diff --git a/src/Libraries/NRefactory/.gitattributes b/src/Libraries/NRefactory/.gitattributes new file mode 100644 index 0000000000..1a15330249 --- /dev/null +++ b/src/Libraries/NRefactory/.gitattributes @@ -0,0 +1,2 @@ +*.sln -crlf +*.csproj -crlf \ No newline at end of file diff --git a/src/Libraries/NRefactory/.gitignore b/src/Libraries/NRefactory/.gitignore new file mode 100644 index 0000000000..a5807eb16d --- /dev/null +++ b/src/Libraries/NRefactory/.gitignore @@ -0,0 +1,2 @@ +/lib/*.dll +/ICSharpCode.NRefactory.Tests/PartCover/* \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/ICSharpCode.Editor.csproj b/src/Libraries/NRefactory/ICSharpCode.Editor/ICSharpCode.Editor.csproj new file mode 100644 index 0000000000..f3baf10f7b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/ICSharpCode.Editor.csproj @@ -0,0 +1,72 @@ + + + + {F054A788-B591-4561-A8BA-AE745BBEB817} + Debug + x86 + Library + ICSharpCode.Editor + ICSharpCode.Editor + v4.0 + Client + Properties + False + False + OnBuildSuccess + bin\Debug\ICSharpCode.Editor.xml + False + False + 4 + false + False + + + x86 + False + Auto + 4194304 + 4096 + + + bin\Debug\ + true + Full + False + True + DEBUG;TRACE + Project + + + bin\Release\ + False + None + True + False + TRACE + + + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/IDocument.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/IDocument.cs new file mode 100644 index 0000000000..925eaee669 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/IDocument.cs @@ -0,0 +1,141 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.Editor +{ + /// + /// A document representing a source code file for refactoring. + /// Line and column counting starts at 1. + /// Offset counting starts at 0. + /// + public interface IDocument : ITextSource, IServiceProvider + { + /// + /// Gets/Sets the text of the whole document.. + /// + new string Text { get; set; } // hides TextBuffer.Text to add the setter + + /// + /// Is raised when the Text property changes. + /// + event EventHandler TextChanged; + + /// + /// Gets the total number of lines in the document. + /// + int TotalNumberOfLines { get; } + + /// + /// Gets the document line with the specified number. + /// + /// The number of the line to retrieve. The first line has number 1. + IDocumentLine GetLine(int lineNumber); + + /// + /// Gets the document line that contains the specified offset. + /// + IDocumentLine GetLineByOffset(int offset); + + /// + /// Gets the offset from a text location. + /// + /// + int GetOffset(int line, int column); + + /// + /// Gets the offset from a text location. + /// + /// + int GetOffset(TextLocation location); + + /// + /// Gets the location from an offset. + /// + /// + TextLocation GetLocation(int offset); + + /// + /// Inserts text. + /// + /// The offset at which the text is inserted. + /// The new text. + /// + /// Anchors positioned exactly at the insertion offset will move according to their movement type. + /// For AnchorMovementType.Default, they will move behind the inserted text. + /// The caret will also move behind the inserted text. + /// + void Insert(int offset, string text); + + /// + /// Inserts text. + /// + /// The offset at which the text is inserted. + /// The new text. + /// + /// Anchors positioned exactly at the insertion offset will move according to the anchor's movement type. + /// For AnchorMovementType.Default, they will move according to the movement type specified by this parameter. + /// The caret will also move according to the parameter. + /// + void Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType); + + /// + /// Removes text. + /// + /// Starting offset of the text to be removed. + /// Length of the text to be removed. + void Remove(int offset, int length); + + /// + /// Replaces text. + /// + /// The starting offset of the text to be replaced. + /// The length of the text to be replaced. + /// The new text. + void Replace(int offset, int length, string newText); + + /// + /// Make the document combine the following actions into a single + /// action for undo purposes. + /// + void StartUndoableAction(); + + /// + /// Ends the undoable action started with . + /// + void EndUndoableAction(); + + /// + /// Creates an undo group. Dispose the returned value to close the undo group. + /// + /// An object that closes the undo group when Dispose() is called. + IDisposable OpenUndoGroup(); + + /// + /// Creates a new at the specified offset. + /// + /// + ITextAnchor CreateAnchor(int offset); + + /// + /// This event is called directly before a change is applied to the document. + /// + /// + /// It is invalid to modify the document within this event handler. + /// Aborting the change (by throwing an exception) is likely to cause corruption of data structures + /// that listen to the Changing and Changed events. + /// + event EventHandler Changing; + + /// + /// This event is called directly after a change is applied to the document. + /// + /// + /// It is invalid to modify the document within this event handler. + /// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures + /// that listen to the Changing and Changed events. + /// + event EventHandler Changed; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/IDocumentLine.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/IDocumentLine.cs new file mode 100644 index 0000000000..982a8cd2be --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/IDocumentLine.cs @@ -0,0 +1,30 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.Editor +{ + /// + /// A line inside a . + /// + public interface IDocumentLine : ISegment + { + /// + /// Gets the length of this line, including the line delimiter. + /// + int TotalLength { get; } + + /// + /// Gets the length of the line terminator. + /// Returns 1 or 2; or 0 at the end of the document. + /// + int DelimiterLength { get; } + + /// + /// Gets the number of this line. + /// The first line has the number 1. + /// + int LineNumber { get; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/ISegment.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/ISegment.cs new file mode 100644 index 0000000000..bf8ac3c089 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/ISegment.cs @@ -0,0 +1,55 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.Editor +{ + /// + /// An (Offset,Length)-pair. + /// + public interface ISegment + { + /// + /// Gets the start offset of the segment. + /// + int Offset { get; } + + /// + /// Gets the length of the segment. + /// + /// Must not be negative. + int Length { get; } + + /// + /// Gets the end offset of the segment. + /// + /// EndOffset = Offset + Length; + int EndOffset { get; } + } + + /// + /// Extension methods for . + /// + public static class ISegmentExtensions + { + /// + /// Gets whether the segment contains the offset. + /// + /// + /// True, if offset is between segment.Start and segment.End (inclusive); otherwise, false. + /// + public static bool Contains (this ISegment segment, int offset) + { + return segment.Offset <= offset && offset <= segment.EndOffset; + } + + /// + /// True, if the segment contains the specified segment, false otherwise. + /// + public static bool Contains (this ISegment thisSegment, ISegment segment) + { + return segment != null && thisSegment.Offset <= segment.Offset && segment.EndOffset <= thisSegment.EndOffset; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/ITextAnchor.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/ITextAnchor.cs new file mode 100644 index 0000000000..dfc95c9e74 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/ITextAnchor.cs @@ -0,0 +1,102 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.Editor +{ + /// + /// The TextAnchor class references an offset (a position between two characters). + /// It automatically updates the offset when text is inserted/removed in front of the anchor. + /// + /// + /// Use the property to get the offset from a text anchor. + /// Use the method to create an anchor from an offset. + /// + /// + /// The document will automatically update all text anchors; and because it uses weak references to do so, + /// the garbage collector can simply collect the anchor object when you don't need it anymore. + /// + /// Moreover, the document is able to efficiently update a large number of anchors without having to look + /// at each anchor object individually. Updating the offsets of all anchors usually only takes time logarithmic + /// to the number of anchors. Retrieving the property also runs in O(lg N). + /// + /// + /// Usage: + /// TextAnchor anchor = document.CreateAnchor(offset); + /// ChangeMyDocument(); + /// int newOffset = anchor.Offset; + /// + /// + public interface ITextAnchor + { + /// + /// Gets the text location of this anchor. + /// + /// Thrown when trying to get the Offset from a deleted anchor. + TextLocation Location { get; } + + /// + /// Gets the offset of the text anchor. + /// + /// Thrown when trying to get the Offset from a deleted anchor. + int Offset { get; } + + /// + /// Controls how the anchor moves. + /// + AnchorMovementType MovementType { get; set; } + + /// + /// Specifies whether the anchor survives deletion of the text containing it. + /// false: The anchor is deleted when the a selection that includes the anchor is deleted. + /// true: The anchor is not deleted. + /// + bool SurviveDeletion { get; set; } + + /// + /// Gets whether the anchor was deleted. + /// + bool IsDeleted { get; } + + /// + /// Occurs after the anchor was deleted. + /// + event EventHandler Deleted; + + /// + /// Gets the line number of the anchor. + /// + /// Thrown when trying to get the Offset from a deleted anchor. + int Line { get; } + + /// + /// Gets the column number of this anchor. + /// + /// Thrown when trying to get the Offset from a deleted anchor. + int Column { get; } + } + + /// + /// Defines how a text anchor moves. + /// + public enum AnchorMovementType + { + /// + /// When text is inserted at the anchor position, the type of the insertion + /// determines where the caret moves to. For normal insertions, the anchor will stay + /// behind the inserted text. + /// + Default, + /// + /// Behaves like a start marker - when text is inserted at the anchor position, the anchor will stay + /// before the inserted text. + /// + BeforeInsertion, + /// + /// Behave like an end marker - when text is insered at the anchor position, the anchor will move + /// after the inserted text. + /// + AfterInsertion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/ITextEditor.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/ITextEditor.cs new file mode 100644 index 0000000000..6d15eb7699 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/ITextEditor.cs @@ -0,0 +1,100 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace ICSharpCode.Editor +{ + /// + /// Interface for text editors. + /// + public interface ITextEditor : IServiceProvider + { + /// + /// Gets the document that is being edited. + /// + IDocument Document { get; } + + /// + /// Gets an object that represents the caret inside this text editor. + /// + ITextEditorCaret Caret { get; } + + /// + /// Sets the caret to the specified line/column and brings the caret into view. + /// + void JumpTo(int line, int column); + + /// + /// Gets the start offset of the selection. + /// + int SelectionStart { get; } + + /// + /// Gets the length of the selection. + /// + int SelectionLength { get; } + + /// + /// Gets/Sets the selected text. + /// + string SelectedText { get; set; } + + /// + /// Sets the selection. + /// + /// Start offset of the selection + /// Length of the selection + void Select(int selectionStart, int selectionLength); + + /// + /// Shows the specified linked elements, and allows the user to edit them. + /// + /// + /// Returns true when the user has finished editing the elements and pressed Return; + /// or false when editing is aborted for any reason. + /// + /// + /// The user can also edit other parts of the document (or other documents) while in link mode. + /// In case of success (true return value), this method will update the offsets of the linked elements + /// to reflect the changes done by the user. + /// If the text editor does not support link mode, it will immediately return false. + /// +// Task ShowLinkedElements(IEnumerable linkedElements); + } + + /// + /// Represents the caret in a text editor. + /// + public interface ITextEditorCaret + { + /// + /// Gets/Sets the caret offset; + /// + int Offset { get; set; } + + /// + /// Gets/Sets the caret line number. + /// Line numbers are counted starting from 1. + /// + int Line { get; set; } + + /// + /// Gets/Sets the caret column number. + /// Column numbers are counted starting from 1. + /// + int Column { get; set; } + + /// + /// Gets/sets the caret location. + /// + TextLocation Location { get; set; } + + /// + /// Is raised whenever the location of the caret has changed. + /// + event EventHandler LocationChanged; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/ITextSource.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/ITextSource.cs new file mode 100644 index 0000000000..d5c6f9e9f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/ITextSource.cs @@ -0,0 +1,147 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.Editor +{ + /// + /// A read-only view on a (potentially mutable) text source. + /// The IDocument interfaces derives from this interface. + /// + public interface ITextSource + { + /// + /// Gets a version identifier for this text source. + /// Returns null for unversioned text sources. + /// + ITextSourceVersion Version { get; } + + /// + /// Creates an immutable snapshot of this text source. + /// Unlike all other methods in this interface, this method is thread-safe. + /// + ITextSource CreateSnapshot(); + + /// + /// Creates an immutable snapshot of a part of this text source. + /// Unlike all other methods in this interface, this method is thread-safe. + /// + ITextSource CreateSnapshot(int offset, int length); + + /// + /// Creates a new TextReader to read from this text source. + /// + TextReader CreateReader(); + + /// + /// Creates a new TextReader to read from this text source. + /// + TextReader CreateReader(int offset, int length); + + /// + /// Gets the total text length. + /// + /// The length of the text, in characters. + /// This is the same as Text.Length, but is more efficient because + /// it doesn't require creating a String object. + int TextLength { get; } + + /// + /// Gets the whole text as string. + /// + string Text { get; } + + /// + /// Gets a character at the specified position in the document. + /// + /// The index of the character to get. + /// Offset is outside the valid range (0 to TextLength-1). + /// The character at the specified position. + /// This is the same as Text[offset], but is more efficient because + /// it doesn't require creating a String object. + char GetCharAt(int offset); + + /// + /// Retrieves the text for a portion of the document. + /// + /// offset or length is outside the valid range. + /// This is the same as Text.Substring, but is more efficient because + /// it doesn't require creating a String object for the whole document. + string GetText(int offset, int length); + + /// + /// Retrieves the text for a portion of the document. + /// + /// offset or length is outside the valid range. + string GetText(ISegment segment); + + /// + /// Gets the index of the first occurrence of any character in the specified array. + /// + /// Characters to search for + /// Start index of the search. + /// Length of the area to search. + /// The first index where any character was found; or -1 if no occurrence was found. + int IndexOfAny(char[] anyOf, int startIndex, int count); + + /* What about: + void Insert (int offset, string value); + void Remove (int offset, int count); + void Remove (ISegment segment); + + void Replace (int offset, int count, string value); + + Or more search operations: + + IEnumerable SearchForward (string pattern, int startIndex); + IEnumerable SearchForwardIgnoreCase (string pattern, int startIndex); + + IEnumerable SearchBackward (string pattern, int startIndex); + IEnumerable SearchBackwardIgnoreCase (string pattern, int startIndex); + */ + } + + /// + /// Represents a version identifier for a text source. + /// + /// + /// Verions can be used to efficiently detect whether a document has changed and needs reparsing; + /// or even to implement incremental parsers. + /// It is a separate class from ITextBuffer to allow the GC to collect the text buffer while + /// the version checkpoint is still in use. + /// + public interface ITextSourceVersion + { + /// + /// Gets whether this checkpoint belongs to the same document as the other checkpoint. + /// + bool BelongsToSameDocumentAs(ITextSourceVersion other); + + /// + /// Compares the age of this checkpoint to the other checkpoint. + /// + /// This method is thread-safe. + /// Raised if 'other' belongs to a different document than this version. + /// -1 if this version is older than . + /// 0 if this version instance represents the same version as . + /// 1 if this version is newer than . + int CompareAge(ITextSourceVersion other); + + /// + /// Gets the changes from this checkpoint to the other checkpoint. + /// If 'other' is older than this checkpoint, reverse changes are calculated. + /// + /// This method is thread-safe. + /// Raised if 'other' belongs to a different document than this checkpoint. + IEnumerable GetChangesTo(ITextSourceVersion other); + + /// + /// Calculates where the offset has moved in the other buffer version. + /// + /// Raised if 'other' belongs to a different document than this checkpoint. + int MoveOffsetTo(ITextSourceVersion other, int oldOffset, AnchorMovementType movement); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/LinkedElement.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/LinkedElement.cs new file mode 100644 index 0000000000..104e53e8a2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/LinkedElement.cs @@ -0,0 +1,68 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.Editor +{ +// I'm not sure if we need this. +// How about a method in the context - this method could wrap the internal representation. +// public void StartTextLinkMode (int linkLength, IEnumerable offsets) +// and maybe then variations taking more than one link element ? + +// /// +// /// Represents an element in the text editor that is either editable, or bound to another editable element. +// /// Used with +// /// +// public class LinkedElement +// { +// LinkedElement boundTo; +// +// /// +// /// Gets/Sets the start offset of this linked element. +// /// +// public int StartOffset { get; set; } +// +// /// +// /// Gets/Sets the end offset of this linked element. +// /// +// public int EndOffset { get; set; } +// +// /// +// /// Gets the linked element to which this element is bound. +// /// +// public LinkedElement BoundTo { +// get { return boundTo; } +// } +// +// /// +// /// Gets whether this element is editable. Returns true if this element is not bound. +// /// +// public bool IsEditable { +// get { return boundTo == null; } +// } +// +// /// +// /// Creates a new editable element. +// /// +// public LinkedElement(int startOffset, int endOffset) +// { +// this.StartOffset = startOffset; +// this.EndOffset = endOffset; +// } +// +// /// +// /// Creates a new element that is bound to . +// /// +// public LinkedElement(int startOffset, int endOffset, LinkedElement boundTo) +// { +// if (boundTo == null) +// throw new ArgumentNullException("boundTo"); +// this.StartOffset = startOffset; +// this.EndOffset = endOffset; +// while (boundTo.boundTo != null) +// boundTo = boundTo.boundTo; +// this.boundTo = boundTo; +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/Properties/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..7d06f87441 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ICSharpCode.Editor")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ICSharpCode.Editor")] +[assembly: AssemblyCopyright("Copyright 2011")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// 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.*")] diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/ReadOnlyDocument.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/ReadOnlyDocument.cs new file mode 100644 index 0000000000..d175cea82a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/ReadOnlyDocument.cs @@ -0,0 +1,321 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.Editor +{ + /// + /// Read-only implementation of . + /// + public sealed class ReadOnlyDocument : IDocument + { + readonly ITextSource textSource; + int[] lines; + + static readonly char[] newline = { '\r', '\n' }; + + /// + /// Creates a new ReadOnlyDocument from the given text source. + /// + public ReadOnlyDocument(ITextSource textSource) + { + if (textSource == null) + throw new ArgumentNullException("textSource"); + // ensure that underlying buffer is immutable + this.textSource = textSource.CreateSnapshot(); + List lines = new List(); + lines.Add(0); + int offset = 0; + int textLength = textSource.TextLength; + while ((offset = textSource.IndexOfAny(newline, offset, textLength - offset)) >= 0) { + offset++; + if (textSource.GetCharAt(offset - 1) == '\r' && offset < textLength && textSource.GetCharAt(offset) == '\n') { + offset++; + } + lines.Add(offset); + } + this.lines = lines.ToArray(); + } + + /// + /// Creates a new ReadOnlyDocument from the given string. + /// + public ReadOnlyDocument(string text) + : this(new StringTextSource(text)) + { + } + + /// + public IDocumentLine GetLine(int lineNumber) + { + if (lineNumber < 1 || lineNumber > lines.Length) + throw new ArgumentOutOfRangeException("lineNumber", lineNumber, "Value must be between 1 and " + lines.Length); + return new ReadOnlyDocumentLine(this, lineNumber); + } + + sealed class ReadOnlyDocumentLine : IDocumentLine + { + readonly ReadOnlyDocument doc; + readonly int lineNumber; + readonly int offset, endOffset; + + public ReadOnlyDocumentLine(ReadOnlyDocument doc, int lineNumber) + { + this.doc = doc; + this.lineNumber = lineNumber; + this.offset = doc.GetStartOffset(lineNumber); + this.endOffset = doc.GetEndOffset(lineNumber); + } + + public int Offset { + get { return offset; } + } + + public int Length { + get { return endOffset - offset; } + } + + public int EndOffset { + get { return endOffset; } + } + + public int TotalLength { + get { + return doc.GetTotalEndOffset(lineNumber) - offset; + } + } + + public int DelimiterLength { + get { + return doc.GetTotalEndOffset(lineNumber) - endOffset; + } + } + + public int LineNumber { + get { return lineNumber; } + } + } + + int GetStartOffset(int lineNumber) + { + return lines[lineNumber-1]; + } + + int GetTotalEndOffset(int lineNumber) + { + return lineNumber < lines.Length ? lines[lineNumber] : textSource.TextLength; + } + + int GetEndOffset(int lineNumber) + { + if (lineNumber == lines.Length) + return textSource.TextLength; + int off = lines[lineNumber] - 1; + if (off > 0 && textSource.GetCharAt(off - 1) == '\r' && textSource.GetCharAt(off) == '\n') + off--; + return off; + } + + /// + public IDocumentLine GetLineByOffset(int offset) + { + return GetLine(GetLineNumberForOffset(offset)); + } + + int GetLineNumberForOffset(int offset) + { + int r = Array.BinarySearch(lines, offset); + return r < 0 ? ~r : r + 1; + } + + /// + public int GetOffset(int line, int column) + { + if (line < 1 || line > lines.Length) + throw new ArgumentOutOfRangeException("line", line, "Value must be between 1 and " + lines.Length); + int lineStart = GetStartOffset(line); + if (column <= 0) + return lineStart; + int lineEnd = GetEndOffset(line); + if (column >= lineEnd - lineStart) + return lineEnd; + return lineStart + column - 1; + } + + /// + public int GetOffset(TextLocation location) + { + return GetOffset(location.Line, location.Column); + } + + /// + public TextLocation GetLocation(int offset) + { + if (offset < 0 || offset > textSource.TextLength) + throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textSource.TextLength); + int line = GetLineNumberForOffset(offset); + return new TextLocation(offset-GetStartOffset(line)+1, line); + } + + /// + public string Text { + get { return textSource.Text; } + set { + throw new NotSupportedException(); + } + } + + /// + public int TotalNumberOfLines { + get { return lines.Length; } + } + + ITextSourceVersion ITextSource.Version { + get { return null; } + } + + /// + public int TextLength { + get { return textSource.TextLength; } + } + + event EventHandler IDocument.Changing { add {} remove {} } + + event EventHandler IDocument.Changed { add {} remove {} } + + event EventHandler IDocument.TextChanged { add {} remove {} } + + void IDocument.Insert(int offset, string text) + { + throw new NotSupportedException(); + } + + void IDocument.Insert(int offset, string text, AnchorMovementType defaultAnchorMovementType) + { + throw new NotSupportedException(); + } + + void IDocument.Remove(int offset, int length) + { + throw new NotSupportedException(); + } + + void IDocument.Replace(int offset, int length, string newText) + { + throw new NotSupportedException(); + } + + void IDocument.StartUndoableAction() + { + } + + void IDocument.EndUndoableAction() + { + } + + IDisposable IDocument.OpenUndoGroup() + { + return null; + } + + /// + public ITextAnchor CreateAnchor(int offset) + { + return new ReadOnlyDocumentTextAnchor(GetLocation(offset), offset); + } + + sealed class ReadOnlyDocumentTextAnchor : ITextAnchor + { + readonly TextLocation location; + readonly int offset; + + public ReadOnlyDocumentTextAnchor(TextLocation location, int offset) + { + this.location = location; + this.offset = offset; + } + + public event EventHandler Deleted { add {} remove {} } + + public TextLocation Location { + get { return location; } + } + + public int Offset { + get { return offset; } + } + + public AnchorMovementType MovementType { get; set; } + + public bool SurviveDeletion { get; set; } + + public bool IsDeleted { + get { return false; } + } + + public int Line { + get { return location.Line; } + } + + public int Column { + get { return location.Column; } + } + } + + /// + public ITextSource CreateSnapshot() + { + return textSource; // textBuffer is immutable + } + + /// + public ITextSource CreateSnapshot(int offset, int length) + { + return textSource.CreateSnapshot(offset, length); + } + + /// + public System.IO.TextReader CreateReader() + { + return textSource.CreateReader(); + } + + /// + public System.IO.TextReader CreateReader(int offset, int length) + { + return textSource.CreateReader(offset, length); + } + + /// + public char GetCharAt(int offset) + { + return textSource.GetCharAt(offset); + } + + /// + public string GetText(int offset, int length) + { + return textSource.GetText(offset, length); + } + + /// + public string GetText(ISegment segment) + { + return textSource.GetText(segment); + } + + /// + public int IndexOfAny(char[] anyOf, int startIndex, int count) + { + return textSource.IndexOfAny(anyOf, startIndex, count); + } + + /// + public object GetService(Type serviceType) + { + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/StringTextSource.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/StringTextSource.cs new file mode 100644 index 0000000000..1d5d3386ff --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/StringTextSource.cs @@ -0,0 +1,91 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.Editor +{ + /// + /// Implements the ITextSource interface using a string. + /// + [Serializable] + public class StringTextSource : ITextSource + { + readonly string text; + + /// + /// Creates a new StringTextSource with the given text. + /// + public StringTextSource(string text) + { + if (text == null) + throw new ArgumentNullException("text"); + this.text = text; + } + + ITextSourceVersion ITextSource.Version { + get { return null; } + } + + /// + public int TextLength { + get { return text.Length; } + } + + /// + public string Text { + get { return text; } + } + + /// + public ITextSource CreateSnapshot() + { + return this; // StringTextBuffer is immutable + } + + /// + public ITextSource CreateSnapshot(int offset, int length) + { + return new StringTextSource(text.Substring(offset, length)); + } + + /// + public TextReader CreateReader() + { + return new StringReader(text); + } + + /// + public TextReader CreateReader(int offset, int length) + { + return new StringReader(text.Substring(offset, length)); + } + + /// + public char GetCharAt(int offset) + { + return text[offset]; + } + + /// + public string GetText(int offset, int length) + { + return text.Substring(offset, length); + } + + /// + public string GetText(ISegment segment) + { + if (segment == null) + throw new ArgumentNullException("segment"); + return text.Substring(segment.Offset, segment.Length); + } + + /// + public int IndexOfAny(char[] anyOf, int startIndex, int count) + { + return text.IndexOfAny(anyOf, startIndex, count); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/TextChangeEventArgs.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/TextChangeEventArgs.cs new file mode 100644 index 0000000000..385f5104a2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/TextChangeEventArgs.cs @@ -0,0 +1,64 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.Editor +{ + /// + /// Describes a change of the document text. + /// This class is thread-safe. + /// + [Serializable] + public class TextChangeEventArgs : EventArgs + { + readonly int offset; + readonly string removedText; + readonly string insertedText; + + /// + /// The offset at which the change occurs. + /// + public int Offset { + get { return offset; } + } + + /// + /// The text that was inserted. + /// + public string RemovedText { + get { return removedText; } + } + + /// + /// The number of characters removed. + /// + public int RemovalLength { + get { return removedText.Length; } + } + + /// + /// The text that was inserted. + /// + public string InsertedText { + get { return insertedText; } + } + + /// + /// The number of characters inserted. + /// + public int InsertionLength { + get { return insertedText.Length; } + } + + /// + /// Creates a new TextChangeEventArgs object. + /// + public TextChangeEventArgs(int offset, string removedText, string insertedText) + { + this.offset = offset; + this.removedText = removedText ?? string.Empty; + this.insertedText = insertedText ?? string.Empty; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.Editor/TextLocation.cs b/src/Libraries/NRefactory/ICSharpCode.Editor/TextLocation.cs new file mode 100644 index 0000000000..12bfe354e3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.Editor/TextLocation.cs @@ -0,0 +1,173 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Globalization; + +namespace ICSharpCode.Editor +{ + /// + /// A line/column position. + /// Text editor lines/columns are counted started from one. + /// + /// + /// The document provides the methods and + /// to convert between offsets and TextLocations. + /// + [Serializable] + public struct TextLocation : IComparable, IEquatable + { + /// + /// Represents no text location (0, 0). + /// + public static readonly TextLocation Empty = new TextLocation(0, 0); + + /// + /// Constant of the minimum line. + /// + public const int MinLine = 1; + + /// + /// Constant of the minimum column. + /// + public const int MinColumn = 1; + + /// + /// Creates a TextLocation instance. + /// + public TextLocation(int line, int column) + { + this.line = line; + this.column = column; + } + + int column, line; + + /// + /// Gets the line number. + /// + public int Line { + get { return line; } + } + + /// + /// Gets the column number. + /// + public int Column { + get { return column; } + } + + /// + /// Gets whether the TextLocation instance is empty. + /// + public bool IsEmpty { + get { + return column < MinLine && line < MinColumn; + } + } + + /// + /// Gets a string representation for debugging purposes. + /// + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "(Line {1}, Col {0})", this.column, this.line); + } + + /// + /// Gets a hash code. + /// + public override int GetHashCode() + { + return unchecked (191 * column.GetHashCode() ^ line.GetHashCode()); + } + + /// + /// Equality test. + /// + public override bool Equals(object obj) + { + if (!(obj is TextLocation)) return false; + return (TextLocation)obj == this; + } + + /// + /// Equality test. + /// + public bool Equals(TextLocation other) + { + return this == other; + } + + /// + /// Equality test. + /// + public static bool operator ==(TextLocation left, TextLocation right) + { + return left.column == right.column && left.line == right.line; + } + + /// + /// Inequality test. + /// + public static bool operator !=(TextLocation left, TextLocation right) + { + return left.column != right.column || left.line != right.line; + } + + /// + /// Compares two text locations. + /// + public static bool operator <(TextLocation left, TextLocation right) + { + if (left.line < right.line) + return true; + else if (left.line == right.line) + return left.column < right.column; + else + return false; + } + + /// + /// Compares two text locations. + /// + public static bool operator >(TextLocation left, TextLocation right) + { + if (left.line > right.line) + return true; + else if (left.line == right.line) + return left.column > right.column; + else + return false; + } + + /// + /// Compares two text locations. + /// + public static bool operator <=(TextLocation left, TextLocation right) + { + return !(left > right); + } + + /// + /// Compares two text locations. + /// + public static bool operator >=(TextLocation left, TextLocation right) + { + return !(left < right); + } + + /// + /// Compares two text locations. + /// + public int CompareTo(TextLocation other) + { + if (this == other) + return 0; + if (this < other) + return -1; + else + return 1; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/.gitignore b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/.gitignore new file mode 100644 index 0000000000..9ce745d95d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs new file mode 100644 index 0000000000..998cee6feb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs @@ -0,0 +1,151 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +namespace ICSharpCode.NRefactory.Demo +{ + partial class CSDemo + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the control. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.csharpCodeTextBox = new System.Windows.Forms.TextBox(); + this.resolveButton = new System.Windows.Forms.Button(); + this.csharpTreeView = new System.Windows.Forms.TreeView(); + this.csharpGenerateCodeButton = new System.Windows.Forms.Button(); + this.csharpParseButton = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.csharpCodeTextBox); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.resolveButton); + this.splitContainer1.Panel2.Controls.Add(this.csharpTreeView); + this.splitContainer1.Panel2.Controls.Add(this.csharpGenerateCodeButton); + this.splitContainer1.Panel2.Controls.Add(this.csharpParseButton); + this.splitContainer1.Size = new System.Drawing.Size(475, 406); + this.splitContainer1.SplitterDistance = 178; + this.splitContainer1.TabIndex = 1; + // + // csharpCodeTextBox + // + this.csharpCodeTextBox.AcceptsReturn = true; + this.csharpCodeTextBox.AcceptsTab = true; + this.csharpCodeTextBox.Dock = System.Windows.Forms.DockStyle.Fill; + this.csharpCodeTextBox.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.csharpCodeTextBox.HideSelection = false; + this.csharpCodeTextBox.Location = new System.Drawing.Point(0, 0); + this.csharpCodeTextBox.Multiline = true; + this.csharpCodeTextBox.Name = "csharpCodeTextBox"; + this.csharpCodeTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.csharpCodeTextBox.Size = new System.Drawing.Size(475, 178); + this.csharpCodeTextBox.TabIndex = 0; + this.csharpCodeTextBox.Text = "using System;\r\nclass Test\r\n{\r\n public void Main(string[] args)\r\n {\r\n " + + " Console.WriteLine(\"Hello, World\");\r\n }\r\n}"; + this.csharpCodeTextBox.WordWrap = false; + this.csharpCodeTextBox.TextChanged += new System.EventHandler(this.CsharpCodeTextBoxTextChanged); + // + // resolveButton + // + this.resolveButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.resolveButton.Location = new System.Drawing.Point(187, 3); + this.resolveButton.Name = "resolveButton"; + this.resolveButton.Size = new System.Drawing.Size(100, 23); + this.resolveButton.TabIndex = 3; + this.resolveButton.Text = "Resolve"; + this.resolveButton.UseVisualStyleBackColor = true; + this.resolveButton.Click += new System.EventHandler(this.ResolveButtonClick); + // + // csharpTreeView + // + this.csharpTreeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.csharpTreeView.HideSelection = false; + this.csharpTreeView.Location = new System.Drawing.Point(3, 32); + this.csharpTreeView.Name = "csharpTreeView"; + this.csharpTreeView.Size = new System.Drawing.Size(467, 189); + this.csharpTreeView.TabIndex = 2; + this.csharpTreeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.CSharpTreeViewAfterSelect); + // + // csharpGenerateCodeButton + // + this.csharpGenerateCodeButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.csharpGenerateCodeButton.Location = new System.Drawing.Point(293, 2); + this.csharpGenerateCodeButton.Name = "csharpGenerateCodeButton"; + this.csharpGenerateCodeButton.Size = new System.Drawing.Size(100, 23); + this.csharpGenerateCodeButton.TabIndex = 1; + this.csharpGenerateCodeButton.Text = "Generate"; + this.csharpGenerateCodeButton.UseVisualStyleBackColor = true; + this.csharpGenerateCodeButton.Click += new System.EventHandler(this.CSharpGenerateCodeButtonClick); + // + // csharpParseButton + // + this.csharpParseButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.csharpParseButton.Location = new System.Drawing.Point(81, 3); + this.csharpParseButton.Name = "csharpParseButton"; + this.csharpParseButton.Size = new System.Drawing.Size(100, 23); + this.csharpParseButton.TabIndex = 0; + this.csharpParseButton.Text = "Parse"; + this.csharpParseButton.UseVisualStyleBackColor = true; + this.csharpParseButton.Click += new System.EventHandler(this.CSharpParseButtonClick); + // + // CSDemo + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "CSDemo"; + this.Size = new System.Drawing.Size(475, 406); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + } + private System.Windows.Forms.Button csharpParseButton; + private System.Windows.Forms.Button csharpGenerateCodeButton; + private System.Windows.Forms.TreeView csharpTreeView; + private System.Windows.Forms.Button resolveButton; + private System.Windows.Forms.TextBox csharpCodeTextBox; + private System.Windows.Forms.SplitContainer splitContainer1; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.cs new file mode 100644 index 0000000000..f589e33252 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.cs @@ -0,0 +1,232 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; + +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.Demo +{ + /// + /// Description of CSDemo. + /// + public partial class CSDemo : UserControl + { + public CSDemo() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + if (LicenseManager.UsageMode != LicenseUsageMode.Designtime) { + csharpCodeTextBox.SelectAll(); + CSharpParseButtonClick(null, null); + resolveButton.UseWaitCursor = true; + ThreadPool.QueueUserWorkItem( + delegate { + builtInLibs.Value.ToString(); + BeginInvoke(new Action(delegate { resolveButton.UseWaitCursor = false; })); + }); + } + } + + CompilationUnit compilationUnit; + + void CSharpParseButtonClick(object sender, EventArgs e) + { + CSharpParser parser = new CSharpParser(); + compilationUnit = parser.Parse(new StringReader(csharpCodeTextBox.Text)); + csharpTreeView.Nodes.Clear(); + foreach (var element in compilationUnit.Children) { + csharpTreeView.Nodes.Add(MakeTreeNode(element)); + } + SelectCurrentNode(csharpTreeView.Nodes); + resolveButton.Enabled = true; + } + + TreeNode MakeTreeNode(AstNode node) + { + TreeNode t = new TreeNode(GetNodeTitle(node)); + t.Tag = node; + foreach (AstNode child in node.Children) { + t.Nodes.Add(MakeTreeNode(child)); + } + return t; + } + + string GetNodeTitle(AstNode node) + { + StringBuilder b = new StringBuilder(); + b.Append(node.Role.ToString()); + b.Append(": "); + b.Append(node.GetType().Name); + bool hasProperties = false; + foreach (PropertyInfo p in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + if (p.Name == "NodeType" || p.Name == "IsNull") + continue; + if (p.PropertyType == typeof(string) || p.PropertyType.IsEnum || p.PropertyType == typeof(bool)) { + if (!hasProperties) { + hasProperties = true; + b.Append(" ("); + } else { + b.Append(", "); + } + b.Append(p.Name); + b.Append(" = "); + try { + object val = p.GetValue(node, null); + b.Append(val != null ? val.ToString() : "**null**"); + } catch (TargetInvocationException ex) { + b.Append("**" + ex.InnerException.GetType().Name + "**"); + } + } + } + if (hasProperties) + b.Append(")"); + return b.ToString(); + } + + bool SelectCurrentNode(TreeNodeCollection c) + { + int selectionStart = csharpCodeTextBox.SelectionStart; + int selectionEnd = selectionStart + csharpCodeTextBox.SelectionLength; + foreach (TreeNode t in c) { + AstNode node = t.Tag as AstNode; + if (node != null + && selectionStart >= GetOffset(csharpCodeTextBox, node.StartLocation) + && selectionEnd <= GetOffset(csharpCodeTextBox, node.EndLocation)) + { + if (selectionStart == selectionEnd + && (selectionStart == GetOffset(csharpCodeTextBox, node.StartLocation) + || selectionStart == GetOffset(csharpCodeTextBox, node.EndLocation))) + { + // caret is on border of this node; don't expand + csharpTreeView.SelectedNode = t; + } else { + t.Expand(); + if (!SelectCurrentNode(t.Nodes)) + csharpTreeView.SelectedNode = t; + } + return true; + } + } + return false; + } + + void CSharpGenerateCodeButtonClick(object sender, EventArgs e) + { + StringWriter w = new StringWriter(); + OutputVisitor output = new OutputVisitor(w, new CSharpFormattingOptions()); + compilationUnit.AcceptVisitor(output, null); + csharpCodeTextBox.Text = w.ToString(); + } + + int GetOffset(TextBox textBox, AstLocation location) + { + return textBox.GetFirstCharIndexFromLine(location.Line - 1) + location.Column - 1; + } + + void CSharpTreeViewAfterSelect(object sender, TreeViewEventArgs e) + { + AstNode node = e.Node.Tag as AstNode; + if (node != null) { + int startOffset = GetOffset(csharpCodeTextBox, node.StartLocation); + int endOffset = GetOffset(csharpCodeTextBox, node.EndLocation); + csharpCodeTextBox.Select(startOffset, endOffset - startOffset); + } + } + + Lazy> builtInLibs = new Lazy>( + delegate { + Assembly[] assemblies = { + typeof(object).Assembly, // mscorlib + typeof(Uri).Assembly, // System.dll + typeof(System.Linq.Enumerable).Assembly, // System.Core.dll +// typeof(System.Xml.XmlDocument).Assembly, // System.Xml.dll +// typeof(System.Drawing.Bitmap).Assembly, // System.Drawing.dll +// typeof(Form).Assembly, // System.Windows.Forms.dll + typeof(ICSharpCode.NRefactory.TypeSystem.IProjectContent).Assembly, + }; + IProjectContent[] projectContents = new IProjectContent[assemblies.Length]; + Stopwatch total = Stopwatch.StartNew(); + Parallel.For( + 0, assemblies.Length, + delegate (int i) { + Stopwatch w = Stopwatch.StartNew(); + CecilLoader loader = new CecilLoader(); + projectContents[i] = loader.LoadAssemblyFile(assemblies[i].Location); + Debug.WriteLine(Path.GetFileName(assemblies[i].Location) + ": " + w.Elapsed); + }); + Debug.WriteLine("Total: " + total.Elapsed); + return projectContents; + }); + + void ResolveButtonClick(object sender, EventArgs e) + { + SimpleProjectContent project = new SimpleProjectContent(); + TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(project, "dummy.cs"); + compilationUnit.AcceptVisitor(convertVisitor, null); + project.UpdateProjectContent(null, convertVisitor.ParsedFile); + + List projects = new List(); + projects.Add(project); + projects.AddRange(builtInLibs.Value); + + using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { + CSharpResolver resolver = new CSharpResolver(context); + + IResolveVisitorNavigator navigator = null; + if (csharpTreeView.SelectedNode != null) { + navigator = new NodeListResolveVisitorNavigator(new[] { (AstNode)csharpTreeView.SelectedNode.Tag }); + } + ResolveVisitor visitor = new ResolveVisitor(resolver, convertVisitor.ParsedFile, navigator); + visitor.Scan(compilationUnit); + csharpTreeView.BeginUpdate(); + ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); + csharpTreeView.EndUpdate(); + } + } + + void ShowResolveResultsInTree(TreeNodeCollection c, ResolveVisitor v) + { + foreach (TreeNode t in c) { + AstNode node = t.Tag as AstNode; + if (node != null) { + ResolveResult rr = v.GetResolveResult(node); + if (rr != null) + t.Text = GetNodeTitle(node) + " " + rr.ToString(); + else + t.Text = GetNodeTitle(node); + } + ShowResolveResultsInTree(t.Nodes, v); + } + } + + void CSharpCodeTextBoxKeyDown(object sender, KeyEventArgs e) + { + if (e.Control && e.KeyCode == Keys.A) { + e.Handled = true; + csharpCodeTextBox.SelectAll(); + } + } + + void CsharpCodeTextBoxTextChanged(object sender, EventArgs e) + { + resolveButton.Enabled = false; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.resx b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/CSDemo.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj new file mode 100644 index 0000000000..841474f597 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj @@ -0,0 +1,82 @@ + + + + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D} + Debug + x86 + WinExe + ICSharpCode.NRefactory.Demo + ICSharpCode.NRefactory.Demo + v4.0 + Client + Properties + + + x86 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + + + bin\Release\ + False + None + True + False + TRACE + + + + + 3.5 + + + + + + + + + CSDemo.cs + + + Form + + + MainForm.cs + + + + + + VBDemo.cs + + + + + {7B82B671-419F-45F4-B778-D9286F996EFA} + ICSharpCode.NRefactory.VB + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + + + + + CSDemo.cs + + + MainForm.cs + + + VBDemo.cs + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs new file mode 100644 index 0000000000..12c38ffb62 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs @@ -0,0 +1,125 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +namespace ICSharpCode.NRefactory.Demo +{ + partial class MainForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.miniToolStrip = new System.Windows.Forms.ToolStrip(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.csDemo1 = new ICSharpCode.NRefactory.Demo.CSDemo(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.vbDemo1 = new ICSharpCode.NRefactory.Demo.VBDemo(); + this.tabPage1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // miniToolStrip + // + this.miniToolStrip.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.miniToolStrip.AutoSize = false; + this.miniToolStrip.CanOverflow = false; + this.miniToolStrip.Dock = System.Windows.Forms.DockStyle.None; + this.miniToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden; + this.miniToolStrip.Location = new System.Drawing.Point(13, 3); + this.miniToolStrip.Name = "miniToolStrip"; + this.miniToolStrip.Size = new System.Drawing.Size(16, 25); + this.miniToolStrip.TabIndex = 3; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.csDemo1); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(507, 458); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "C#"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // csDemo1 + // + this.csDemo1.Dock = System.Windows.Forms.DockStyle.Fill; + this.csDemo1.Location = new System.Drawing.Point(3, 3); + this.csDemo1.Name = "csDemo1"; + this.csDemo1.Size = new System.Drawing.Size(501, 452); + this.csDemo1.TabIndex = 0; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(515, 484); + this.tabControl1.TabIndex = 0; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.vbDemo1); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(507, 458); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "VB"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // vbDemo1 + // + this.vbDemo1.Dock = System.Windows.Forms.DockStyle.Fill; + this.vbDemo1.Location = new System.Drawing.Point(3, 3); + this.vbDemo1.Name = "vbDemo1"; + this.vbDemo1.Size = new System.Drawing.Size(501, 452); + this.vbDemo1.TabIndex = 0; + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(515, 484); + this.Controls.Add(this.tabControl1); + this.Name = "MainForm"; + this.Text = "NRefactory Demo"; + this.tabPage1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.ResumeLayout(false); + } + private ICSharpCode.NRefactory.Demo.VBDemo vbDemo1; + private System.Windows.Forms.TabPage tabPage2; + private ICSharpCode.NRefactory.Demo.CSDemo csDemo1; + private System.Windows.Forms.ToolStrip miniToolStrip; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabControl tabControl1; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.cs new file mode 100644 index 0000000000..9633a00f12 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.Demo +{ + /// + /// Description of MainForm. + /// + public partial class MainForm : Form + { + public MainForm() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.resx b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.resx new file mode 100644 index 0000000000..38d0f5c169 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/Program.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/Program.cs new file mode 100644 index 0000000000..7c176b1aa4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/Program.cs @@ -0,0 +1,25 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Windows.Forms; + +namespace ICSharpCode.NRefactory.Demo +{ + /// + /// Class with program entry point. + /// + internal sealed class Program + { + /// + /// Program entry point. + /// + [STAThread] + private static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/Properties/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..2027632f74 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ICSharpCode.NRefactory.Demo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ICSharpCode.NRefactory.Demo")] +[assembly: AssemblyCopyright("Copyright 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// 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.*")] diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs new file mode 100644 index 0000000000..9cdb323344 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs @@ -0,0 +1,59 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +namespace ICSharpCode.NRefactory.Demo +{ + partial class VBAstView : System.Windows.Forms.UserControl + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the control. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.tree = new System.Windows.Forms.TreeView(); + this.SuspendLayout(); + // + // tree + // + this.tree.Dock = System.Windows.Forms.DockStyle.Fill; + this.tree.HideSelection = false; + this.tree.Location = new System.Drawing.Point(0, 0); + this.tree.Name = "tree"; + this.tree.ShowRootLines = false; + this.tree.Size = new System.Drawing.Size(186, 182); + this.tree.TabIndex = 0; + this.tree.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TreeKeyDown); + // + // AstView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tree); + this.Name = "AstView"; + this.Size = new System.Drawing.Size(186, 182); + this.ResumeLayout(false); + } + private System.Windows.Forms.TreeView tree; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.cs new file mode 100644 index 0000000000..a6e6f58aa5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.cs @@ -0,0 +1,225 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Windows.Forms; +using System.Reflection; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB; + +namespace ICSharpCode.NRefactory.Demo +{ + public partial class VBAstView + { + CompilationUnit unit; + + public CompilationUnit Unit { + get { + return unit; + } + set { + if (value != null) { + unit = value; + UpdateTree(); + } + } + } + + void UpdateTree() + { + tree.Nodes.Clear(); + tree.Nodes.Add(new CollectionNode("CompilationUnit", unit.Children)); + tree.SelectedNode = tree.Nodes[0]; + } + + public VBAstView() + { + InitializeComponent(); + } + +// public void DeleteSelectedNode() +// { +// if (tree.SelectedNode is ElementNode) { +// INode element = (tree.SelectedNode as ElementNode).element; +// if (tree.SelectedNode.Parent is CollectionNode) { +// if (MessageBox.Show("Remove selected node from parent collection?", "Remove node", MessageBoxButtons.YesNo, MessageBoxIcon.Question) +// == DialogResult.Yes) +// { +// IList col = (tree.SelectedNode.Parent as CollectionNode).collection; +// col.Remove(element); +// (tree.SelectedNode.Parent as CollectionNode).Update(); +// } +// } else if (tree.SelectedNode.Parent is ElementNode) { +// if (MessageBox.Show("Set selected property to null?", "Remove node", MessageBoxButtons.YesNo, MessageBoxIcon.Question) +// == DialogResult.Yes) +// { +// // get parent element +// element = (tree.SelectedNode.Parent as ElementNode).element; +// string propertyName = (string)tree.SelectedNode.Tag; +// element.GetType().GetProperty(propertyName).SetValue(element, null, null); +// (tree.SelectedNode.Parent as ElementNode).Update(); +// } +// } +// } else if (tree.SelectedNode is CollectionNode) { +// if (MessageBox.Show("Remove all elements from selected collection?", "Clear collection", MessageBoxButtons.YesNo, MessageBoxIcon.Question) +// == DialogResult.Yes) +// { +// IList col = (tree.SelectedNode as CollectionNode).collection; +// col.Clear(); +// (tree.SelectedNode as CollectionNode).Update(); +// } +// } +// } +// +// public void EditSelectedNode() +// { +// TreeNode node = tree.SelectedNode; +// while (!(node is ElementNode)) { +// if (node == null) { +// return; +// } +// node = node.Parent; +// } +// INode element = ((ElementNode)node).element; +// using (VBEditDialog dlg = new VBEditDialog(element)) { +// dlg.ShowDialog(); +// } +// ((ElementNode)node).Update(); +// } +// +// public void ApplyTransformation(IAstVisitor visitor) +// { +// if (tree.SelectedNode == tree.Nodes[0]) { +// unit.AcceptVisitor(visitor, null); +// UpdateTree(); +// } else { +// string name = visitor.GetType().Name; +// ElementNode elementNode = tree.SelectedNode as ElementNode; +// CollectionNode collectionNode = tree.SelectedNode as CollectionNode; +// if (elementNode != null) { +// if (MessageBox.Show(("Apply " + name + " to selected element '" + elementNode.Text + "'?"), +// "Apply transformation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) +// == DialogResult.Yes) +// { +// elementNode.element.AcceptVisitor(visitor, null); +// elementNode.Update(); +// } +// } else if (collectionNode != null) { +// if (MessageBox.Show(("Apply " + name + " to all elements in selected collection '" + collectionNode.Text + "'?"), +// "Apply transformation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) +// == DialogResult.Yes) +// { +// foreach (TreeNode subNode in collectionNode.Nodes) { +// if (subNode is ElementNode) { +// (subNode as ElementNode).element.AcceptVisitor(visitor, null); +// } +// } +// collectionNode.Update(); +// } +// } +// } +// } +// + static TreeNode CreateNode(object child) + { + if (child == null) { + return new TreeNode("*null reference*"); + } else if (child is INode) { + return new ElementNode(child as INode); + } else { + return new TreeNode(child.ToString()); + } + } + + class CollectionNode : TreeNode + { + internal IList collection; + string baseName; + + public CollectionNode(string text, IList children) : base(text) + { + this.baseName = text; + this.collection = children; + Update(); + } + + public void Update() + { + if (collection.Count == 0) { + Text = baseName + " (empty collection)"; + } else if (collection.Count == 1) { + Text = baseName + " (collection with 1 element)"; + } else { + Text = baseName + " (collection with " + collection.Count + " elements)"; + } + Nodes.Clear(); + foreach (object child in collection) { + Nodes.Add(CreateNode(child)); + } + Expand(); + } + } + + class ElementNode : TreeNode + { + internal AstNode element; + + public ElementNode(AstNode node) + { + this.element = node; + Update(); + } + + public void Update() + { + Nodes.Clear(); + Type type = element.GetType(); + Text = type.Name; + if (Tag != null) { // HACK: after editing property element + Text = Tag.ToString() + " = " + Text; + } + if (!(element is INullable && (element as INullable).IsNull)) { + AddProperties(type, element); + if (element.Children.Count > 0) { + Nodes.Add(new CollectionNode("Children", element.Children)); + } + } + } + + void AddProperties(Type type, AstNode node) + { + if (type == typeof(AbstractNode)) + return; + foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) { + if (pi.DeclaringType != type) // don't add derived properties + continue; + if (pi.Name == "IsNull") + continue; + object value = pi.GetValue(node, null); + if (value is IList) { + Nodes.Add(new CollectionNode(pi.Name, (IList)value)); + } else if (value is string) { + Text += " " + pi.Name + "='" + value + "'"; + } else { + TreeNode treeNode = CreateNode(value); + treeNode.Text = pi.Name + " = " + treeNode.Text; + treeNode.Tag = pi.Name; + Nodes.Add(treeNode); + } + } + AddProperties(type.BaseType, node); + } + } + + void TreeKeyDown(object sender, KeyEventArgs e) + { + if (e.KeyData == Keys.Delete) { + DeleteSelectedNode(); + } else if (e.KeyData == Keys.Space || e.KeyData == Keys.Enter) { + EditSelectedNode(); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.resx b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.resx new file mode 100644 index 0000000000..7080a7d118 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBAstView.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs new file mode 100644 index 0000000000..48641c6694 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs @@ -0,0 +1,134 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +namespace ICSharpCode.NRefactory.Demo +{ + partial class VBDemo + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the control. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.codeView = new System.Windows.Forms.TextBox(); + this.generateCodeButton = new System.Windows.Forms.Button(); + this.parseButton = new System.Windows.Forms.Button(); + this.treeView = new System.Windows.Forms.TreeView(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.codeView); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.generateCodeButton); + this.splitContainer1.Panel2.Controls.Add(this.parseButton); + this.splitContainer1.Panel2.Controls.Add(this.treeView); + this.splitContainer1.Size = new System.Drawing.Size(462, 391); + this.splitContainer1.SplitterDistance = 173; + this.splitContainer1.TabIndex = 1; + // + // codeView + // + this.codeView.AcceptsReturn = true; + this.codeView.AcceptsTab = true; + this.codeView.Dock = System.Windows.Forms.DockStyle.Fill; + this.codeView.Font = new System.Drawing.Font("Courier New", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.codeView.HideSelection = false; + this.codeView.Location = new System.Drawing.Point(0, 0); + this.codeView.Multiline = true; + this.codeView.Name = "codeView"; + this.codeView.ScrollBars = System.Windows.Forms.ScrollBars.Both; + this.codeView.Size = new System.Drawing.Size(462, 173); + this.codeView.TabIndex = 0; + this.codeView.Text = "Option Explicit"; + this.codeView.WordWrap = false; + // + // generateCodeButton + // + this.generateCodeButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.generateCodeButton.Location = new System.Drawing.Point(225, 2); + this.generateCodeButton.Name = "generateCodeButton"; + this.generateCodeButton.Size = new System.Drawing.Size(100, 23); + this.generateCodeButton.TabIndex = 1; + this.generateCodeButton.Text = "Generate"; + this.generateCodeButton.UseVisualStyleBackColor = true; + this.generateCodeButton.Click += new System.EventHandler(this.CSharpGenerateCodeButtonClick); + // + // parseButton + // + this.parseButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.parseButton.Location = new System.Drawing.Point(119, 2); + this.parseButton.Name = "parseButton"; + this.parseButton.Size = new System.Drawing.Size(100, 23); + this.parseButton.TabIndex = 0; + this.parseButton.Text = "Parse"; + this.parseButton.UseVisualStyleBackColor = true; + this.parseButton.Click += new System.EventHandler(this.CSharpParseButtonClick); + // + // treeView + // + this.treeView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.treeView.Location = new System.Drawing.Point(3, 31); + this.treeView.Name = "treeView"; + this.treeView.Size = new System.Drawing.Size(459, 180); + this.treeView.TabIndex = 0; + this.treeView.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.CSharpTreeViewAfterSelect); + // + // VBDemo + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "VBDemo"; + this.Size = new System.Drawing.Size(462, 391); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel1.PerformLayout(); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + } + private System.Windows.Forms.TextBox codeView; + private System.Windows.Forms.TreeView treeView; + private System.Windows.Forms.Button generateCodeButton; + private System.Windows.Forms.Button parseButton; + private System.Windows.Forms.SplitContainer splitContainer1; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.cs new file mode 100644 index 0000000000..beb3308c15 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.cs @@ -0,0 +1,140 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Windows.Forms; + +using ICSharpCode.NRefactory.VB; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; + +namespace ICSharpCode.NRefactory.Demo +{ + /// + /// Description of VBDemo. + /// + public partial class VBDemo : UserControl + { + public VBDemo() + { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + } + + CompilationUnit compilationUnit; + + void CSharpParseButtonClick(object sender, EventArgs e) + { + var parser = new VBParser(); + compilationUnit = parser.Parse(new StringReader(codeView.Text)); + if (parser.HasErrors) + MessageBox.Show(parser.Errors.ErrorOutput); + treeView.Nodes.Clear(); + foreach (var element in compilationUnit.Children) { + treeView.Nodes.Add(MakeTreeNode(element)); + } + SelectCurrentNode(treeView.Nodes); + } + + TreeNode MakeTreeNode(AstNode node) + { + TreeNode t = new TreeNode(GetNodeTitle(node)); + t.Tag = node; + foreach (AstNode child in node.Children) { + t.Nodes.Add(MakeTreeNode(child)); + } + return t; + } + + string GetNodeTitle(AstNode node) + { + StringBuilder b = new StringBuilder(); + b.Append(node.Role.ToString()); + b.Append(": "); + b.Append(node.GetType().Name); + bool hasProperties = false; + foreach (PropertyInfo p in node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { + if (p.Name == "NodeType" || p.Name == "IsNull") + continue; + if (p.PropertyType == typeof(string) || p.PropertyType.IsEnum || p.PropertyType == typeof(bool)) { + if (!hasProperties) { + hasProperties = true; + b.Append(" ("); + } else { + b.Append(", "); + } + b.Append(p.Name); + b.Append(" = "); + try { + object val = p.GetValue(node, null); + b.Append(val != null ? val.ToString() : "**null**"); + } catch (TargetInvocationException ex) { + b.Append("**" + ex.InnerException.GetType().Name + "**"); + } + } + } + if (hasProperties) + b.Append(")"); + return b.ToString(); + } + + bool SelectCurrentNode(TreeNodeCollection c) + { + int selectionStart = codeView.SelectionStart; + int selectionEnd = selectionStart + codeView.SelectionLength; + foreach (TreeNode t in c) { + AstNode node = t.Tag as AstNode; + if (node != null + && selectionStart >= GetOffset(codeView, node.StartLocation) + && selectionEnd <= GetOffset(codeView, node.EndLocation)) + { + if (selectionStart == selectionEnd + && (selectionStart == GetOffset(codeView, node.StartLocation) + || selectionStart == GetOffset(codeView, node.EndLocation))) + { + // caret is on border of this node; don't expand + treeView.SelectedNode = t; + } else { + t.Expand(); + if (!SelectCurrentNode(t.Nodes)) + treeView.SelectedNode = t; + } + return true; + } + } + return false; + } + + void CSharpGenerateCodeButtonClick(object sender, EventArgs e) + { + StringWriter w = new StringWriter(); + OutputVisitor output = new OutputVisitor(w, new VBFormattingOptions()); + compilationUnit.AcceptVisitor(output, null); + codeView.Text = w.ToString(); + } + + int GetOffset(TextBox textBox, AstLocation location) + { + return textBox.GetFirstCharIndexFromLine(location.Line - 1) + location.Column - 1; + } + + void CSharpTreeViewAfterSelect(object sender, TreeViewEventArgs e) + { + AstNode node = e.Node.Tag as AstNode; + if (node != null) { + int startOffset = GetOffset(codeView, node.StartLocation); + int endOffset = GetOffset(codeView, node.EndLocation); + codeView.Select(startOffset, endOffset - startOffset); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.resx b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.resx new file mode 100644 index 0000000000..1af7de150c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBDemo.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs new file mode 100644 index 0000000000..6d4254497d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs @@ -0,0 +1,88 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +namespace ICSharpCode.NRefactory.Demo +{ + partial class VBEditDialog : System.Windows.Forms.Form + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent() + { + this.propertyGrid = new System.Windows.Forms.PropertyGrid(); + this.panel1 = new System.Windows.Forms.Panel(); + this.okButton = new System.Windows.Forms.Button(); + this.panel1.SuspendLayout(); + this.SuspendLayout(); + // + // propertyGrid + // + this.propertyGrid.Dock = System.Windows.Forms.DockStyle.Fill; + this.propertyGrid.HelpVisible = false; + this.propertyGrid.Location = new System.Drawing.Point(0, 0); + this.propertyGrid.Name = "propertyGrid"; + this.propertyGrid.PropertySort = System.Windows.Forms.PropertySort.Alphabetical; + this.propertyGrid.Size = new System.Drawing.Size(477, 436); + this.propertyGrid.TabIndex = 0; + this.propertyGrid.ToolbarVisible = false; + // + // panel1 + // + this.panel1.Controls.Add(this.okButton); + this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel1.Location = new System.Drawing.Point(0, 436); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(477, 38); + this.panel1.TabIndex = 1; + // + // okButton + // + this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK; + this.okButton.Location = new System.Drawing.Point(390, 6); + this.okButton.Name = "okButton"; + this.okButton.Size = new System.Drawing.Size(75, 23); + this.okButton.TabIndex = 0; + this.okButton.Text = "OK"; + this.okButton.UseVisualStyleBackColor = true; + // + // EditDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.CancelButton = this.okButton; + this.ClientSize = new System.Drawing.Size(477, 474); + this.Controls.Add(this.propertyGrid); + this.Controls.Add(this.panel1); + this.Name = "EditDialog"; + this.Text = "EditDialog"; + this.panel1.ResumeLayout(false); + this.ResumeLayout(false); + } + private System.Windows.Forms.PropertyGrid propertyGrid; + private System.Windows.Forms.Button okButton; + private System.Windows.Forms.Panel panel1; + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.cs new file mode 100644 index 0000000000..031ab9971b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.cs @@ -0,0 +1,18 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace ICSharpCode.NRefactory.Demo +{ + public partial class VBEditDialog + { + public VBEditDialog(object element) + { + InitializeComponent(); + propertyGrid.SelectedObject = element; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.resx b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.resx new file mode 100644 index 0000000000..7080a7d118 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Demo/VBEditDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/.gitignore b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/.gitignore new file mode 100644 index 0000000000..9ce745d95d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs new file mode 100644 index 0000000000..10373b84ca --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs @@ -0,0 +1,201 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Analysis +{ + [TestFixture] + public class DefiniteAssignmentTests + { + [Test] + public void TryFinally() + { + BlockStatement block = new BlockStatement { + new TryCatchStatement { + TryBlock = new BlockStatement { + new GotoStatement("LABEL"), + new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(1)) + }, + CatchClauses = { + new CatchClause { + Body = new BlockStatement { + new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(3)) + } + } + }, + FinallyBlock = new BlockStatement { + new AssignmentExpression(new IdentifierExpression("j"), new PrimitiveExpression(5)) + } + }, + new LabelStatement { Label = "LABEL" }, + new EmptyStatement() + }; + TryCatchStatement tryCatchStatement = (TryCatchStatement)block.Statements.First(); + Statement stmt1 = tryCatchStatement.TryBlock.Statements.ElementAt(1); + Statement stmt3 = tryCatchStatement.CatchClauses.Single().Body.Statements.Single(); + Statement stmt5 = tryCatchStatement.FinallyBlock.Statements.Single(); + LabelStatement label = (LabelStatement)block.Statements.ElementAt(1); + + DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(block, CecilLoaderTests.Mscorlib); + da.Analyze("i"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(stmt1)); + Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(stmt1)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt3)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(stmt3)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt5)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(stmt5)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(tryCatchStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(label)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(label)); + + da.Analyze("j"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(tryCatchStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusBefore(stmt1)); + Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(stmt1)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt3)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(stmt3)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(stmt5)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(stmt5)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(tryCatchStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(label)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(label)); + } + + [Test] + public void ConditionalAnd() + { + IfElseStatement ifStmt = new IfElseStatement { + Condition = new BinaryOperatorExpression { + Left = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.GreaterThan, new PrimitiveExpression(0)), + Operator = BinaryOperatorType.ConditionalAnd, + Right = new BinaryOperatorExpression { + Left = new ParenthesizedExpression { + Expression = new AssignmentExpression { + Left = new IdentifierExpression("i"), + Operator = AssignmentOperatorType.Assign, + Right = new IdentifierExpression("y") + } + }, + Operator = BinaryOperatorType.GreaterThanOrEqual, + Right = new PrimitiveExpression(0) + } + }, + TrueStatement = new BlockStatement(), + FalseStatement = new BlockStatement() + }; + DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib); + da.Analyze("i"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.TrueStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt.FalseStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt)); + } + + [Test] + public void ConditionalOr() + { + IfElseStatement ifStmt = new IfElseStatement { + Condition = new BinaryOperatorExpression { + Left = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.GreaterThan, new PrimitiveExpression(0)), + Operator = BinaryOperatorType.ConditionalOr, + Right = new BinaryOperatorExpression { + Left = new ParenthesizedExpression { + Expression = new AssignmentExpression { + Left = new IdentifierExpression("i"), + Operator = AssignmentOperatorType.Assign, + Right = new IdentifierExpression("y") + } + }, + Operator = BinaryOperatorType.GreaterThanOrEqual, + Right = new PrimitiveExpression(0) + } + }, + TrueStatement = new BlockStatement(), + FalseStatement = new BlockStatement() + }; + DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(ifStmt, CecilLoaderTests.Mscorlib); + da.Analyze("i"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(ifStmt.TrueStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(ifStmt.FalseStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(ifStmt)); + } + + [Test] + public void WhileTrue() + { + WhileStatement loop = new WhileStatement { + Condition = new PrimitiveExpression(true), + EmbeddedStatement = new BlockStatement { + new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0)), + new BreakStatement() + } + }; + DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib); + da.Analyze("i"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.CodeUnreachable, da.GetStatusAfter(loop.EmbeddedStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop)); + } + + [Test] + public void ForLoop() + { + ForStatement loop = new ForStatement { + Initializers = { + new ExpressionStatement( + new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(0)) + ) + }, + Condition = new BinaryOperatorExpression(new IdentifierExpression("i"), BinaryOperatorType.LessThan, new PrimitiveExpression(1000)), + Iterators = { + new ExpressionStatement( + new AssignmentExpression { + Left = new IdentifierExpression("i"), + Operator = AssignmentOperatorType.Add, + Right = new IdentifierExpression("j") + } + ) + }, + EmbeddedStatement = new ExpressionStatement( + new AssignmentExpression(new IdentifierExpression("j"), new IdentifierExpression("i")) + )}; + + DefiniteAssignmentAnalysis da = new DefiniteAssignmentAnalysis(loop, CecilLoaderTests.Mscorlib); + da.Analyze("i"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.Initializers.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Initializers.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBeforeLoopCondition(loop)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.EmbeddedStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.EmbeddedStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.Iterators.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Iterators.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop)); + + da.Analyze("j"); + Assert.AreEqual(0, da.UnassignedVariableUses.Count); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.Initializers.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(loop.Initializers.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBeforeLoopCondition(loop)); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusBefore(loop.EmbeddedStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.EmbeddedStatement)); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusBefore(loop.Iterators.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.DefinitelyAssigned, da.GetStatusAfter(loop.Iterators.Single())); + Assert.AreEqual(DefiniteAssignmentStatus.PotentiallyAssigned, da.GetStatusAfter(loop)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs new file mode 100644 index 0000000000..183efacdb2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Reflection; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp +{ + [TestFixture] + public class AstStructureTests + { + [Test] + public void RolesAreStaticReadOnly() + { + foreach (Type type in typeof(AstNode).Assembly.GetExportedTypes()) { + if (type.IsSubclassOf(typeof(AstNode))) { + foreach (FieldInfo field in type.GetFields()) { + if (field.FieldType.IsSubclassOf(typeof(Role))) { + Assert.IsTrue(field.IsPublic); + Assert.IsTrue(field.IsStatic); + Assert.IsTrue(field.IsInitOnly); + Assert.IsTrue(field.Name.EndsWith("Role", StringComparison.Ordinal)); + Assert.IsNotNull(field.GetValue(null)); + } + } + } + } + } + + [Test] + public void AstNodesDoNotDeriveFromEachOther() + { + // Ast nodes should derive only from abstract classes; not from concrete types. + // For example, we want to avoid that an AST consumer doing "if (node is PropertyDeclaration)" + // unknowingly also handles IndexerDeclarations. + foreach (Type type in typeof(AstNode).Assembly.GetExportedTypes()) { + if (type == typeof(CSharpModifierToken)) // CSharpModifierToken is the exception (though I'm not too happy about that) + continue; + if (type.IsSubclassOf(typeof(AstNode))) { + Assert.IsTrue(type.BaseType.IsAbstract, type.FullName); + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs new file mode 100644 index 0000000000..b7f6328f3e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs @@ -0,0 +1,349 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp +{ + [TestFixture] + public class InsertParenthesesVisitorTests + { + CSharpFormattingOptions policy; + + [SetUp] + public void SetUp() + { + policy = new CSharpFormattingOptions(); + } + + string InsertReadable(Expression expr) + { + expr = expr.Clone(); + expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }, null); + StringWriter w = new StringWriter(); + w.NewLine = " "; + expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null); + return w.ToString(); + } + + string InsertRequired(Expression expr) + { + expr = expr.Clone(); + expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = false }, null); + StringWriter w = new StringWriter(); + w.NewLine = " "; + expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null); + return w.ToString(); + } + + [Test] + public void EqualityInAssignment() + { + Expression expr = new AssignmentExpression( + new IdentifierExpression("cond"), + new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.Equality, + new IdentifierExpression("b") + ) + ); + + Assert.AreEqual("cond = a == b", InsertRequired(expr)); + Assert.AreEqual("cond = (a == b)", InsertReadable(expr)); + } + + [Test] + public void TrickyCast1() + { + Expression expr = new UnaryOperatorExpression( + UnaryOperatorType.Minus, new IdentifierExpression("a") + ).CastTo(new PrimitiveType("int")); + + Assert.AreEqual("(int)-a", InsertRequired(expr)); + Assert.AreEqual("(int)(-a)", InsertReadable(expr)); + } + + [Test] + public void TrickyCast2() + { + Expression expr = new UnaryOperatorExpression( + UnaryOperatorType.Minus, new IdentifierExpression("a") + ).CastTo(new SimpleType("MyType")); + + Assert.AreEqual("(MyType)(-a)", InsertRequired(expr)); + Assert.AreEqual("(MyType)(-a)", InsertReadable(expr)); + } + + [Test] + public void TrickyCast3() + { + Expression expr = new UnaryOperatorExpression( + UnaryOperatorType.Not, new IdentifierExpression("a") + ).CastTo(new SimpleType("MyType")); + + Assert.AreEqual("(MyType)!a", InsertRequired(expr)); + Assert.AreEqual("(MyType)(!a)", InsertReadable(expr)); + } + + [Test] + public void TrickyCast4() + { + Expression expr = new PrimitiveExpression(int.MinValue).CastTo(new SimpleType("MyType")); + + Assert.AreEqual("(MyType)(-2147483648)", InsertRequired(expr)); + Assert.AreEqual("(MyType)(-2147483648)", InsertReadable(expr)); + } + + [Test] + public void TrickyCast5() + { + Expression expr = new PrimitiveExpression(-1.0).CastTo(new SimpleType("MyType")); + + Assert.AreEqual("(MyType)(-1.0)", InsertRequired(expr)); + Assert.AreEqual("(MyType)(-1.0)", InsertReadable(expr)); + } + + [Test] + public void TrickyCast6() + { + Expression expr = new PrimitiveExpression(int.MinValue).CastTo(new PrimitiveType("double")); + + Assert.AreEqual("(double)-2147483648", InsertRequired(expr)); + Assert.AreEqual("(double)-2147483648", InsertReadable(expr)); + } + + [Test] + public void CastAndInvoke() + { + Expression expr = new IdentifierExpression("a") + .CastTo(new PrimitiveType("string")) + .Member("Length"); + + Assert.AreEqual("((string)a).Length", InsertRequired(expr)); + Assert.AreEqual("((string)a).Length", InsertReadable(expr)); + } + + [Test] + public void DoubleNegation() + { + Expression expr = new UnaryOperatorExpression( + UnaryOperatorType.Minus, + new UnaryOperatorExpression(UnaryOperatorType.Minus, new IdentifierExpression("a")) + ); + + Assert.AreEqual("- -a", InsertRequired(expr)); + Assert.AreEqual("-(-a)", InsertReadable(expr)); + } + + [Test] + public void AdditionWithConditional() + { + Expression expr = new BinaryOperatorExpression { + Left = new IdentifierExpression("a"), + Operator = BinaryOperatorType.Add, + Right = new ConditionalExpression { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("b"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression(null) + }, + TrueExpression = new IdentifierExpression("c"), + FalseExpression = new IdentifierExpression("d") + } + }; + + Assert.AreEqual("a + (b == null ? c : d)", InsertRequired(expr)); + Assert.AreEqual("a + ((b == null) ? c : d)", InsertReadable(expr)); + } + + [Test] + public void TypeTestInConditional() + { + Expression expr = new ConditionalExpression { + Condition = new IdentifierExpression("a").IsType( + new ComposedType { + BaseType = new PrimitiveType("int"), + HasNullableSpecifier = true + } + ), + TrueExpression = new IdentifierExpression("b"), + FalseExpression = new IdentifierExpression("c") + }; + + Assert.AreEqual("a is int? ? b : c", InsertRequired(expr)); + Assert.AreEqual("(a is int?) ? b : c", InsertReadable(expr)); + + policy.SpaceBeforeConditionalOperatorCondition = false; + policy.SpaceAfterConditionalOperatorCondition = false; + policy.SpaceBeforeConditionalOperatorSeparator = false; + policy.SpaceAfterConditionalOperatorSeparator = false; + + Assert.AreEqual("a is int? ?b:c", InsertRequired(expr)); + Assert.AreEqual("(a is int?)?b:c", InsertReadable(expr)); + } + + [Test] + public void MethodCallOnQueryExpression() + { + Expression expr = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("a").Invoke("c") + } + } + }.Invoke("ToArray"); + + Assert.AreEqual("( from a in b select a.c ()).ToArray ()", InsertRequired(expr)); + Assert.AreEqual("( from a in b select a.c ()).ToArray ()", InsertReadable(expr)); + } + + [Test] + public void SumOfQueries() + { + QueryExpression query = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("a") + } + } + }; + Expression expr = new BinaryOperatorExpression( + query, + BinaryOperatorType.Add, + query.Clone() + ); + + Assert.AreEqual("( from a in b select a) + " + + " from a in b select a", InsertRequired(expr)); + Assert.AreEqual("( from a in b select a) + " + + "( from a in b select a)", InsertReadable(expr)); + } + + [Test] + public void QueryInTypeTest() + { + Expression expr = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("a") + } + } + }.IsType(new PrimitiveType("int")); + + Assert.AreEqual("( from a in b select a) is int", InsertRequired(expr)); + Assert.AreEqual("( from a in b select a) is int", InsertReadable(expr)); + } + + [Test] + public void PrePost() + { + Expression expr = new UnaryOperatorExpression( + UnaryOperatorType.Increment, + new UnaryOperatorExpression( + UnaryOperatorType.PostIncrement, + new IdentifierExpression("a") + ) + ); + + Assert.AreEqual("++a++", InsertRequired(expr)); + Assert.AreEqual("++(a++)", InsertReadable(expr)); + } + + [Test] + public void PostPre() + { + Expression expr = new UnaryOperatorExpression( + UnaryOperatorType.PostIncrement, + new UnaryOperatorExpression( + UnaryOperatorType.Increment, + new IdentifierExpression("a") + ) + ); + + Assert.AreEqual("(++a)++", InsertRequired(expr)); + Assert.AreEqual("(++a)++", InsertReadable(expr)); + } + + [Test] + public void Logical1() + { + Expression expr = new BinaryOperatorExpression( + new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("b") + ), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("c") + ); + + Assert.AreEqual("a && b && c", InsertRequired(expr)); + Assert.AreEqual("a && b && c", InsertReadable(expr)); + } + + [Test] + public void Logical2() + { + Expression expr = new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalAnd, + new BinaryOperatorExpression( + new IdentifierExpression("b"), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("c") + ) + ); + + Assert.AreEqual("a && (b && c)", InsertRequired(expr)); + Assert.AreEqual("a && (b && c)", InsertReadable(expr)); + } + + [Test] + public void Logical3() + { + Expression expr = new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalOr, + new BinaryOperatorExpression( + new IdentifierExpression("b"), + BinaryOperatorType.ConditionalAnd, + new IdentifierExpression("c") + ) + ); + + Assert.AreEqual("a || b && c", InsertRequired(expr)); + Assert.AreEqual("a || (b && c)", InsertReadable(expr)); + } + + [Test] + public void Logical4() + { + Expression expr = new BinaryOperatorExpression( + new IdentifierExpression("a"), + BinaryOperatorType.ConditionalAnd, + new BinaryOperatorExpression( + new IdentifierExpression("b"), + BinaryOperatorType.ConditionalOr, + new IdentifierExpression("c") + ) + ); + + Assert.AreEqual("a && (b || c)", InsertRequired(expr)); + Assert.AreEqual("a && (b || c)", InsertReadable(expr)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs new file mode 100644 index 0000000000..a3ec92054f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs @@ -0,0 +1,53 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class AliasReferenceExpressionTests + { + [Test] + public void GlobalReferenceExpressionTest() + { + CSharpParser parser = new CSharpParser(); + AstType type = parser.ParseTypeReference(new StringReader("global::System")); + Assert.IsTrue( + new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }.IsMatch(type) + ); + } + + [Test] + public void GlobalTypeDeclaration() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("global::System.String a;"); + Assert.IsTrue( + new VariableDeclarationStatement { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }, + IsDoubleColon = false, + MemberName = "String", + }, + Variables = { + new VariableInitializer("a") + } + }.IsMatch(lvd) + ); + } + + // TODO: add tests for aliases other than 'global' + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs new file mode 100644 index 0000000000..710df07ec1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs @@ -0,0 +1,56 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class AnonymousMethodTests + { + AnonymousMethodExpression Parse(string expression) + { + return ParseUtilCSharp.ParseExpression(expression); + } + + [Test] + public void AnonymousMethodWithoutParameterList() + { + AnonymousMethodExpression ame = Parse("delegate {}"); + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + Assert.IsFalse(ame.HasParameterList); + } + + [Test] + public void AnonymousMethodAfterCast() + { + CastExpression c = ParseUtilCSharp.ParseExpression("(ThreadStart)delegate {}"); + AnonymousMethodExpression ame = (AnonymousMethodExpression)c.Expression; + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + } + + [Test] + public void EmptyAnonymousMethod() + { + AnonymousMethodExpression ame = Parse("delegate() {}"); + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + Assert.IsTrue(ame.HasParameterList); + } + + [Test] + public void SimpleAnonymousMethod() + { + AnonymousMethodExpression ame = Parse("delegate(int a, int b) { return a + b; }"); + Assert.IsTrue(ame.HasParameterList); + Assert.AreEqual(2, ame.Parameters.Count()); + Assert.AreEqual(1, ame.Body.Statements.Count()); + Assert.IsTrue(ame.Body.Statements.First() is ReturnStatement); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs new file mode 100644 index 0000000000..a6d3ec0177 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs @@ -0,0 +1,56 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class ArrayObjectCreateExpressionTests + { + [Test] + public void ArrayCreateExpressionTest1() + { + ParseUtilCSharp.AssertExpression( + "new int[5]", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(5) } + }); + } + + [Test] + public void MultidimensionalNestedArray() + { + ParseUtilCSharp.AssertExpression( + "new int[5,2][,,][]", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(5), new PrimitiveExpression(2) }, + AdditionalArraySpecifiers = { + new ArraySpecifier(3), + new ArraySpecifier(1) + } + }); + } + + [Test] + public void ImplicitlyTypedArrayCreateExpression() + { + ParseUtilCSharp.AssertExpression( + "new[] { 1, 10, 100, 1000 }", + new ArrayCreateExpression { + Initializer = new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(10), + new PrimitiveExpression(100), + new PrimitiveExpression(1000) + } + } + }); + + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs new file mode 100644 index 0000000000..065b88bba1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs @@ -0,0 +1,88 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class AssignmentExpressionTests + { + void TestAssignmentExpression(string program, AssignmentOperatorType op) + { + AssignmentExpression ae = ParseUtilCSharp.ParseExpression(program); + + Assert.AreEqual(op, ae.Operator); + + Assert.IsTrue(ae.Left is IdentifierExpression); + Assert.IsTrue(ae.Right is IdentifierExpression); + } + + [Test] + public void AssignTest() + { + TestAssignmentExpression("a = b", AssignmentOperatorType.Assign); + } + + [Test] + public void AddTest() + { + TestAssignmentExpression("a += b", AssignmentOperatorType.Add); + } + + [Test] + public void SubtractTest() + { + TestAssignmentExpression("a -= b", AssignmentOperatorType.Subtract); + } + + [Test] + public void MultiplyTest() + { + TestAssignmentExpression("a *= b", AssignmentOperatorType.Multiply); + } + + [Test] + public void DivideTest() + { + TestAssignmentExpression("a /= b", AssignmentOperatorType.Divide); + } + + [Test] + public void ModulusTest() + { + TestAssignmentExpression("a %= b", AssignmentOperatorType.Modulus); + } + + [Test] + public void ShiftLeftTest() + { + TestAssignmentExpression("a <<= b", AssignmentOperatorType.ShiftLeft); + } + + [Test] + public void ShiftRightTest() + { + TestAssignmentExpression("a >>= b", AssignmentOperatorType.ShiftRight); + } + + [Test] + public void BitwiseAndTest() + { + TestAssignmentExpression("a &= b", AssignmentOperatorType.BitwiseAnd); + } + + [Test] + public void BitwiseOrTest() + { + TestAssignmentExpression("a |= b", AssignmentOperatorType.BitwiseOr); + } + + [Test] + public void ExclusiveOrTest() + { + TestAssignmentExpression("a ^= b", AssignmentOperatorType.ExclusiveOr); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs new file mode 100644 index 0000000000..4bde43b92d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs @@ -0,0 +1,19 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class BaseReferenceExpressionTests + { + [Test] + public void BaseReferenceExpressionTest1() + { + MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("base.myField"); + Assert.IsTrue(fre.Target is BaseReferenceExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs new file mode 100644 index 0000000000..9e133b7637 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs @@ -0,0 +1,227 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class BinaryOperatorExpressionTests + { + #region Precedence Tests + void OperatorPrecedenceTest(string strongOperator, BinaryOperatorType strongOperatorType, + string weakOperator, BinaryOperatorType weakOperatorType, bool vb) + { + string program = "a " + weakOperator + " b " + strongOperator + " c"; + BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression(program); + Assert.AreEqual(weakOperatorType, boe.Operator); + Assert.IsTrue(boe.Left is IdentifierExpression); + boe = (BinaryOperatorExpression)boe.Right; + Assert.AreEqual(strongOperatorType, boe.Operator); + Assert.IsTrue(boe.Left is IdentifierExpression); + Assert.IsTrue(boe.Right is IdentifierExpression); + + program = "a " + strongOperator + " b " + weakOperator + " c"; + + boe = ParseUtilCSharp.ParseExpression(program); + Assert.AreEqual(weakOperatorType, boe.Operator); + Assert.IsTrue(boe.Right is IdentifierExpression); + boe = (BinaryOperatorExpression)boe.Left; + Assert.AreEqual(strongOperatorType, boe.Operator); + Assert.IsTrue(boe.Left is IdentifierExpression); + Assert.IsTrue(boe.Right is IdentifierExpression); + } + + void SameOperatorPrecedenceTest(string firstOperator, BinaryOperatorType firstOperatorType, + string secondOperator, BinaryOperatorType secondOperatorType, bool vb) + { + string program = "a " + secondOperator + " b " + firstOperator + " c"; + BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression(program); + Assert.AreEqual(firstOperatorType, boe.Operator); + Assert.IsTrue(boe.Right is IdentifierExpression); + boe = (BinaryOperatorExpression)boe.Left; + Assert.AreEqual(secondOperatorType, boe.Operator); + Assert.IsTrue(boe.Left is IdentifierExpression); + Assert.IsTrue(boe.Right is IdentifierExpression); + + program = "a " + firstOperator + " b " + secondOperator + " c"; + boe = ParseUtilCSharp.ParseExpression(program); + Assert.AreEqual(secondOperatorType, boe.Operator); + Assert.IsTrue(boe.Right is IdentifierExpression); + boe = (BinaryOperatorExpression)boe.Left; + Assert.AreEqual(firstOperatorType, boe.Operator); + Assert.IsTrue(boe.Left is IdentifierExpression); + Assert.IsTrue(boe.Right is IdentifierExpression); + } + + [Test] + public void OperatorPrecedenceTest() + { + SameOperatorPrecedenceTest("*", BinaryOperatorType.Multiply, "/", BinaryOperatorType.Divide, false); + SameOperatorPrecedenceTest("*", BinaryOperatorType.Multiply, "%", BinaryOperatorType.Modulus, false); + OperatorPrecedenceTest("*", BinaryOperatorType.Multiply, "+", BinaryOperatorType.Add, false); + SameOperatorPrecedenceTest("-", BinaryOperatorType.Subtract, "+", BinaryOperatorType.Add, false); + OperatorPrecedenceTest("+", BinaryOperatorType.Add, "<<", BinaryOperatorType.ShiftLeft, false); + SameOperatorPrecedenceTest(">>", BinaryOperatorType.ShiftRight, "<<", BinaryOperatorType.ShiftLeft, false); + OperatorPrecedenceTest("<<", BinaryOperatorType.ShiftLeft, "==", BinaryOperatorType.Equality, false); + SameOperatorPrecedenceTest("!=", BinaryOperatorType.InEquality, "==", BinaryOperatorType.Equality, false); + OperatorPrecedenceTest("==", BinaryOperatorType.Equality, "&", BinaryOperatorType.BitwiseAnd, false); + OperatorPrecedenceTest("&", BinaryOperatorType.BitwiseAnd, "^", BinaryOperatorType.ExclusiveOr, false); + OperatorPrecedenceTest("^", BinaryOperatorType.ExclusiveOr, "|", BinaryOperatorType.BitwiseOr, false); + OperatorPrecedenceTest("|", BinaryOperatorType.BitwiseOr, "&&", BinaryOperatorType.ConditionalAnd, false); + OperatorPrecedenceTest("&&", BinaryOperatorType.ConditionalAnd, "||", BinaryOperatorType.ConditionalOr, false); + OperatorPrecedenceTest("||", BinaryOperatorType.ConditionalOr, "??", BinaryOperatorType.NullCoalescing, false); + } + #endregion + + void TestBinaryOperatorExpressionTest(string program, BinaryOperatorType op) + { + BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression(program); + Assert.AreEqual(op, boe.Operator); + + Assert.IsTrue(boe.Left is IdentifierExpression); + Assert.IsTrue(boe.Right is IdentifierExpression); + + } + + [Test] + public void SubtractionLeftToRight() + { + BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression("a - b - c"); + Assert.IsTrue(boe.Right is IdentifierExpression); + Assert.IsTrue(boe.Left is BinaryOperatorExpression); + } + + [Test] + public void NullCoalescingRightToLeft() + { + BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression("a ?? b ?? c"); + Assert.IsTrue(boe.Left is IdentifierExpression); + Assert.IsTrue(boe.Right is BinaryOperatorExpression); + } + + [Test] + public void BitwiseAndTest() + { + TestBinaryOperatorExpressionTest("a & b", BinaryOperatorType.BitwiseAnd); + } + + [Test] + public void BitwiseOrTest() + { + TestBinaryOperatorExpressionTest("a | b", BinaryOperatorType.BitwiseOr); + } + + [Test] + public void LogicalAndTest() + { + TestBinaryOperatorExpressionTest("a && b", BinaryOperatorType.ConditionalAnd); + } + + [Test] + public void LogicalOrTest() + { + TestBinaryOperatorExpressionTest("a || b", BinaryOperatorType.ConditionalOr); + } + + [Test] + public void ExclusiveOrTest() + { + TestBinaryOperatorExpressionTest("a ^ b", BinaryOperatorType.ExclusiveOr); + } + + + [Test] + public void GreaterThanTest() + { + TestBinaryOperatorExpressionTest("a > b", BinaryOperatorType.GreaterThan); + } + + [Test] + public void GreaterThanOrEqualTest() + { + TestBinaryOperatorExpressionTest("a >= b", BinaryOperatorType.GreaterThanOrEqual); + } + + [Test] + public void EqualityTest() + { + TestBinaryOperatorExpressionTest("a == b", BinaryOperatorType.Equality); + } + + [Test] + public void InEqualityTest() + { + TestBinaryOperatorExpressionTest("a != b", BinaryOperatorType.InEquality); + } + + [Test] + public void LessThanTest() + { + TestBinaryOperatorExpressionTest("a < b", BinaryOperatorType.LessThan); + } + + [Test] + public void LessThanOrEqualTest() + { + TestBinaryOperatorExpressionTest("a <= b", BinaryOperatorType.LessThanOrEqual); + } + + [Test] + public void AddTest() + { + TestBinaryOperatorExpressionTest("a + b", BinaryOperatorType.Add); + } + + [Test] + public void SubtractTest() + { + TestBinaryOperatorExpressionTest("a - b", BinaryOperatorType.Subtract); + } + + [Test] + public void MultiplyTest() + { + TestBinaryOperatorExpressionTest("a * b", BinaryOperatorType.Multiply); + } + + [Test] + public void DivideTest() + { + TestBinaryOperatorExpressionTest("a / b", BinaryOperatorType.Divide); + } + + [Test] + public void ModulusTest() + { + TestBinaryOperatorExpressionTest("a % b", BinaryOperatorType.Modulus); + } + + [Test] + public void ShiftLeftTest() + { + TestBinaryOperatorExpressionTest("a << b", BinaryOperatorType.ShiftLeft); + } + + [Test] + public void ShiftRightTest() + { + TestBinaryOperatorExpressionTest("a >> b", BinaryOperatorType.ShiftRight); + } + + [Test] + public void NullCoalescingTest() + { + TestBinaryOperatorExpressionTest("a ?? b", BinaryOperatorType.NullCoalescing); + } + + [Test] + public void LessThanOrGreaterTest() + { + const string expr = "i1 < 0 || i1 > (Count - 1)"; + BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression(expr); + Assert.AreEqual(BinaryOperatorType.ConditionalOr, boe.Operator); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs new file mode 100644 index 0000000000..2909f71843 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs @@ -0,0 +1,165 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class CastExpressionTests + { + [Test] + public void SimpleCastExpression() + { + ParseUtilCSharp.AssertExpression( + "(MyObject)o", + new CastExpression { + Type = new SimpleType("MyObject"), + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void ArrayCastExpression() + { + ParseUtilCSharp.AssertExpression( + "(MyType[])o", + new CastExpression { + Type = new SimpleType("MyType").MakeArrayType(1), + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void NullablePrimitiveCastExpression() + { + ParseUtilCSharp.AssertExpression( + "(int?)o", + new CastExpression { + Type = new ComposedType { BaseType = new PrimitiveType("int"), HasNullableSpecifier = true }, + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void NullableCastExpression() + { + ParseUtilCSharp.AssertExpression( + "(MyType?)o", + new CastExpression { + Type = new ComposedType { BaseType = new SimpleType("MyType"), HasNullableSpecifier = true }, + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void NullableTryCastExpression() + { + ParseUtilCSharp.AssertExpression( + "o as int?", + new AsExpression { + Type = new ComposedType { BaseType = new PrimitiveType("int"), HasNullableSpecifier = true }, + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void GenericCastExpression() + { + ParseUtilCSharp.AssertExpression( + "(List)o", + new CastExpression { + Type = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }, + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void GenericArrayCastExpression() + { + ParseUtilCSharp.AssertExpression( + "(List[])o", + new CastExpression { + Type = new ComposedType { + BaseType = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }, + ArraySpecifiers = { new ArraySpecifier(1) } + }, + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void GenericArrayAsCastExpression() + { + ParseUtilCSharp.AssertExpression( + "o as List[]", + new AsExpression { + Type = new ComposedType { + BaseType = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }, + ArraySpecifiers = { new ArraySpecifier(1) } + }, + Expression = new IdentifierExpression("o") + }); + } + + [Test] + public void CastMemberReferenceOnParenthesizedExpression() + { + // yes, we really want to evaluate .Member on expr and THEN cast the result to MyType + ParseUtilCSharp.AssertExpression( + "(MyType)(expr).Member", + new CastExpression { + Type = new SimpleType("MyType"), + Expression = new ParenthesizedExpression { Expression = new IdentifierExpression("expr") }.Member("Member") + }); + } + + [Test] + public void TryCastParenthesizedExpression() + { + ParseUtilCSharp.AssertExpression( + "(o) as string", + new AsExpression { + Expression = new ParenthesizedExpression { Expression = new IdentifierExpression("o") }, + Type = new PrimitiveType("string") + }); + } + + [Test] + public void CastNegation() + { + ParseUtilCSharp.AssertExpression( + "(uint)-negativeValue", + new CastExpression { + Type = new PrimitiveType("uint"), + Expression = new UnaryOperatorExpression( + UnaryOperatorType.Minus, + new IdentifierExpression("negativeValue") + )}); + } + + [Test] + public void SubtractionIsNotCast() + { + ParseUtilCSharp.AssertExpression( + "(BigInt)-negativeValue", + new BinaryOperatorExpression { + Left = new ParenthesizedExpression { Expression = new IdentifierExpression("BigInt") }, + Operator = BinaryOperatorType.Subtract, + Right = new IdentifierExpression("negativeValue") + }); + } + + [Test, Ignore ("TODO")] + public void IntMaxValueToBigInt() + { + ParseUtilCSharp.AssertExpression( + "(BigInt)int.MaxValue", + new CastExpression { + Type = new SimpleType("BigInt"), + Expression = new PrimitiveExpression("int").Member("MaxValue") + }); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs new file mode 100644 index 0000000000..696a28b7a6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs @@ -0,0 +1,26 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class CheckedExpressionTests + { + [Test] + public void CheckedExpressionTest() + { + CheckedExpression ce = ParseUtilCSharp.ParseExpression("checked(a)"); + Assert.IsTrue(ce.Expression is IdentifierExpression); + } + + [Test] + public void UncheckedExpressionTest() + { + UncheckedExpression ce = ParseUtilCSharp.ParseExpression("unchecked(a)"); + Assert.IsTrue(ce.Expression is IdentifierExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs new file mode 100644 index 0000000000..819b16582d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs @@ -0,0 +1,104 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class ConditionalExpressionTests + { + [Test] + public void ConditionalExpressionTest() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a == b ? a() : a.B"); + + Assert.IsTrue(ce.Condition is BinaryOperatorExpression); + Assert.IsTrue(ce.TrueExpression is InvocationExpression); + Assert.IsTrue(ce.FalseExpression is MemberReferenceExpression); + } + + [Test] + public void ConditionalIsExpressionTest() + { + // (as is b?) ERROR (conflict with nullables, SD-419) + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a is b ? a() : a.B"); + + Assert.IsTrue(ce.Condition is IsExpression); + Assert.IsTrue(ce.TrueExpression is InvocationExpression); + Assert.IsTrue(ce.FalseExpression is MemberReferenceExpression); + } + + [Test] + public void ConditionalIsWithNullableExpressionTest() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a is b? ? a() : a.B"); + + Assert.IsTrue(ce.Condition is IsExpression); + Assert.IsTrue(ce.TrueExpression is InvocationExpression); + Assert.IsTrue(ce.FalseExpression is MemberReferenceExpression); + } + + [Test] + public void ConditionalIsExpressionTest2() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a is b ? (a()) : a.B"); + + Assert.IsTrue(ce.Condition is IsExpression); + Assert.IsTrue(ce.TrueExpression is ParenthesizedExpression); + Assert.IsTrue(ce.FalseExpression is MemberReferenceExpression); + } + + [Test] + public void ConditionalExpressionNegativeValue() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("isNegative ? -1 : 1"); + + Assert.IsTrue(ce.Condition is IdentifierExpression); + Assert.IsTrue(ce.TrueExpression is UnaryOperatorExpression); + Assert.IsTrue(ce.FalseExpression is PrimitiveExpression); + } + + + [Test] + public void ConditionalIsWithNegativeValue() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a is b ? -1 : 1"); + + Assert.IsTrue(ce.Condition is IsExpression); + Assert.IsTrue(ce.TrueExpression is UnaryOperatorExpression); + Assert.IsTrue(ce.FalseExpression is PrimitiveExpression); + } + + [Test] + public void ConditionalIsWithExplicitPositiveValue() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a is b ? +1 : 1"); + + Assert.IsTrue(ce.Condition is IsExpression); + Assert.IsTrue(ce.TrueExpression is UnaryOperatorExpression); + Assert.IsTrue(ce.FalseExpression is PrimitiveExpression); + } + + [Test] + public void RepeatedConditionalExpr() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a ? b : c ? d : e"); + + Assert.AreEqual("a", ((IdentifierExpression)ce.Condition).Identifier); + Assert.AreEqual("b", ((IdentifierExpression)ce.TrueExpression).Identifier); + Assert.IsTrue(ce.FalseExpression is ConditionalExpression); + } + + [Test] + public void NestedConditionalExpr() + { + ConditionalExpression ce = ParseUtilCSharp.ParseExpression("a ? b ? c : d : e"); + + Assert.AreEqual("a", ((IdentifierExpression)ce.Condition).Identifier); + Assert.AreEqual("e", ((IdentifierExpression)ce.FalseExpression).Identifier); + Assert.IsTrue(ce.TrueExpression is ConditionalExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs new file mode 100644 index 0000000000..03f5617535 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs @@ -0,0 +1,79 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class DefaultValueExpressionTests + { + [Test] + public void SimpleDefaultValue() + { + DefaultValueExpression toe = ParseUtilCSharp.ParseExpression("default(T)"); + Assert.AreEqual("T", ((SimpleType)toe.Type).Identifier); + } + + [Test] + public void FullQualifiedDefaultValue() + { + ParseUtilCSharp.AssertExpression( + "default(global::MyNamespace.N1.MyType)", + new DefaultValueExpression { + Type = new MemberType { + Target = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "MyNamespace" + }, + MemberName = "N1" + }, + MemberName = "MyType" + } + }); + } + + [Test] + public void GenericDefaultValue() + { + ParseUtilCSharp.AssertExpression( + "default(MyNamespace.N1.MyType)", + new DefaultValueExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "N1" + }, + MemberName = "MyType", + TypeArguments = { new PrimitiveType("string") } + } + }); + } + + [Test] + public void DefaultValueAsIntializer() + { + // This test was problematic (in old NRefactory) because we need a resolver for the "default:" / "default(" conflict. + ParseUtilCSharp.AssertStatement( + "T a = default(T);", + new VariableDeclarationStatement { + Type = new SimpleType("T"), + Variables = { + new VariableInitializer("a", new DefaultValueExpression { Type = new SimpleType("T") }) + }}); + } + + [Test] + public void DefaultValueInReturnStatement() + { + ParseUtilCSharp.AssertStatement( + "return default(T);", + new ReturnStatement { + Expression = new DefaultValueExpression { Type = new SimpleType("T") } + }); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs new file mode 100644 index 0000000000..5a054efe6f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs @@ -0,0 +1,87 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class IdentifierExpressionTests + { + void CheckIdentifier(string sourceCode, string identifier) + { + IdentifierExpression ident = ParseUtilCSharp.ParseExpression(sourceCode); + Assert.AreEqual(identifier, ident.Identifier); + } + + [Test] + public void TestIdentifier() + { + CheckIdentifier("a_Bc05", "a_Bc05"); + } + + [Test] + public void TestIdentifierStartingWithUnderscore() + { + CheckIdentifier("_Bc05", "_Bc05"); + } + + [Test] + public void TestIdentifierStartingWithEscapeSequence() + { + CheckIdentifier(@"\u006cexer", "lexer"); + } + + [Test] + public void TestIdentifierContainingEscapeSequence() + { + CheckIdentifier(@"l\U00000065xer", "lexer"); + } + + [Test, Ignore("The @ should not be part of IdentifierExpression.Identifier")] + public void TestKeyWordAsIdentifier() + { + CheckIdentifier("@int", "int"); + } + + [Test, Ignore("Mono parser bug?")] + public void TestKeywordWithEscapeSequenceIsIdentifier() + { + CheckIdentifier(@"i\u006et", "int"); + } + + [Test, Ignore("The @ should not be part of IdentifierExpression.Identifier")] + public void TestKeyWordAsIdentifierStartingWithUnderscore() + { + CheckIdentifier("@_int", "_int"); + } + + [Test] + public void GenericMethodReference() + { + IdentifierExpression ident = ParseUtilCSharp.ParseExpression("M"); + Assert.IsTrue( + new IdentifierExpression { + Identifier = "M" , + TypeArguments = { + new PrimitiveType("int") + } + }.IsMatch(ident)); + } + + [Test] + public void GenericMethodReference2() + { + IdentifierExpression ident = ParseUtilCSharp.ParseExpression("TargetMethod"); + Assert.IsTrue( + new IdentifierExpression { + Identifier = "TargetMethod" , + TypeArguments = { + new PrimitiveType("string") + } + }.IsMatch(ident)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs new file mode 100644 index 0000000000..1a46dc63ff --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class IndexerExpressionTests + { + [Test] + public void IndexerExpressionTest() + { + IndexerExpression ie = ParseUtilCSharp.ParseExpression("field[1, \"Hello\", 'a']"); + Assert.IsTrue(ie.Target is IdentifierExpression); + + Assert.AreEqual(3, ie.Arguments.Count()); + + Assert.IsTrue(ie.Arguments.ElementAt(0) is PrimitiveExpression); + Assert.AreEqual(1, (int)((PrimitiveExpression)ie.Arguments.ElementAt(0)).Value); + Assert.IsTrue(ie.Arguments.ElementAt(1) is PrimitiveExpression); + Assert.AreEqual("Hello", (string)((PrimitiveExpression)ie.Arguments.ElementAt(1)).Value); + Assert.IsTrue(ie.Arguments.ElementAt(2) is PrimitiveExpression); + Assert.AreEqual('a', (char)((PrimitiveExpression)ie.Arguments.ElementAt(2)).Value); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs new file mode 100644 index 0000000000..53c89bbf89 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs @@ -0,0 +1,172 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class InvocationExpressionTests + { + [Test] + public void SimpleInvocationExpressionTest() + { + var ie = ParseUtilCSharp.ParseExpression("myMethod()"); + Assert.AreEqual(0, ie.Arguments.Count()); + Assert.IsTrue(ie.Target is IdentifierExpression); + Assert.AreEqual("myMethod", ((IdentifierExpression)ie.Target).Identifier); + } + + [Test] + public void GenericInvocationExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "myMethod('a')", + new InvocationExpression { + Target = new IdentifierExpression { + Identifier = "myMethod", + TypeArguments = { new PrimitiveType("char") } + }, + Arguments = { new PrimitiveExpression('a') } + } + ); + } + + [Test] + public void GenericInvocation2ExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "myMethod()", + new InvocationExpression { + Target = new IdentifierExpression { + Identifier = "myMethod", + TypeArguments = { + new SimpleType("T"), + new PrimitiveType("bool") + } + } + } + ); + } + + [Test] + public void AmbiguousGrammarGenericMethodCall() + { + ParseUtilCSharp.AssertExpression( + "F(G(7))", + new InvocationExpression { + Target = new IdentifierExpression("F"), + Arguments = { + new InvocationExpression { + Target = new IdentifierExpression { + Identifier = "G", + TypeArguments = { new SimpleType("A"), new SimpleType("B") } + }, + Arguments = { new PrimitiveExpression(7) } + }}}); + } + + [Test, Ignore("Mono Parser Bug???")] + public void AmbiguousGrammarNotAGenericMethodCall() + { + ParseUtilCSharp.AssertExpression( + "F+y", + new BinaryOperatorExpression { + Left = new BinaryOperatorExpression { + Left = new IdentifierExpression("F"), + Operator = BinaryOperatorType.LessThan, + Right = new IdentifierExpression("A") + }, + Operator = BinaryOperatorType.GreaterThan, + Right = new UnaryOperatorExpression { + Operator = UnaryOperatorType.Plus, + Expression = new IdentifierExpression("y") + }}); + } + + [Test] + public void InvalidNestedInvocationExpressionTest() + { + // this test was written because this bug caused the AbstractASTVisitor to crash + + InvocationExpression expr = ParseUtilCSharp.ParseExpression("WriteLine(myMethod(,))", true); + Assert.IsTrue(expr.Target is IdentifierExpression); + Assert.AreEqual("WriteLine", ((IdentifierExpression)expr.Target).Identifier); + + Assert.AreEqual(1, expr.Arguments.Count); // here a second null parameter was added incorrectly + + Assert.IsTrue(expr.Arguments.Single() is InvocationExpression); + } + + [Test, Ignore("Positions not yet accurate when parsing expression only (because class/method is added around it)")] + public void NestedInvocationPositions() + { + InvocationExpression expr = ParseUtilCSharp.ParseExpression("a.B().C(args)"); + Assert.AreEqual(new AstLocation(1, 8), expr.StartLocation); + Assert.AreEqual(new AstLocation(1, 14), expr.EndLocation); + MemberReferenceExpression mre = (MemberReferenceExpression)expr.Target; + Assert.AreEqual(new AstLocation(1, 6), mre.StartLocation); + Assert.AreEqual(new AstLocation(1, 8), mre.EndLocation); + + Assert.AreEqual(new AstLocation(1, 4), mre.Target.StartLocation); + Assert.AreEqual(new AstLocation(1, 6), mre.Target.EndLocation); + } + + [Test] + public void InvocationOnGenericType() + { + ParseUtilCSharp.AssertExpression( + "A.Foo()", + new IdentifierExpression { + Identifier = "A", + TypeArguments = { new SimpleType("T") } + }.Invoke("Foo") + ); + } + + [Test] + public void InvocationOnInnerClassInGenericType() + { + ParseUtilCSharp.AssertExpression( + "A.B.Foo()", + new IdentifierExpression { + Identifier = "A", + TypeArguments = { new SimpleType("T") } + }.Member("B").Invoke("Foo") + ); + } + + [Test] + public void InvocationOnGenericInnerClassInGenericType() + { + ParseUtilCSharp.AssertExpression( + "A.B.C.Foo()", + new MemberReferenceExpression { + Target = new IdentifierExpression { + Identifier = "A", + TypeArguments = { new SimpleType("T") } + }.Member("B"), + MemberName = "C", + TypeArguments = { new SimpleType("U") } + }.Invoke("Foo")); + } + + [Test] + public void InvocationWithNamedArgument() + { + ParseUtilCSharp.AssertExpression( + "a(arg: ref v)", + new InvocationExpression { + Target = new IdentifierExpression("a"), + Arguments = { + new NamedArgumentExpression { + Identifier = "arg", + Expression = new DirectionExpression { + FieldDirection = FieldDirection.Ref, + Expression = new IdentifierExpression("v") + }}}}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs new file mode 100644 index 0000000000..bbab99a6f4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs @@ -0,0 +1,46 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class IsExpressionTests + { + [Test] + public void GenericArrayIsExpression() + { + ParseUtilCSharp.AssertExpression( + "o is List[]", + new IsExpression { + Expression = new IdentifierExpression("o"), + Type = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }.MakeArrayType(1) + } + ); + } + + [Test] + public void NullableIsExpression() + { + IsExpression ce = ParseUtilCSharp.ParseExpression("o is int?"); + ComposedType type = (ComposedType)ce.Type; + Assert.IsTrue(type.HasNullableSpecifier); + Assert.AreEqual("int", ((PrimitiveType)type.BaseType).Keyword); + Assert.IsTrue(ce.Expression is IdentifierExpression); + } + + [Test] + public void NullableIsExpressionInBinaryOperatorExpression() + { + BinaryOperatorExpression boe; + boe = ParseUtilCSharp.ParseExpression("o is int? == true"); + IsExpression ce = (IsExpression)boe.Left; + ComposedType type = (ComposedType)ce.Type; + Assert.IsTrue(type.HasNullableSpecifier); + Assert.AreEqual("int", ((PrimitiveType)type.BaseType).Keyword); + Assert.IsTrue(ce.Expression is IdentifierExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs new file mode 100644 index 0000000000..d389bac7c1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs @@ -0,0 +1,108 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class LambdaExpressionTests + { + [Test] + public void ImplicitlyTypedExpressionBody() + { + ParseUtilCSharp.AssertExpression( + "(x) => x + 1", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }); + } + + [Test] + public void ImplicitlyTypedExpressionBodyWithoutParenthesis() + { + ParseUtilCSharp.AssertExpression( + "x => x + 1", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }); + } + + [Test] + public void ImplicitlyTypedStatementBody() + { + ParseUtilCSharp.AssertExpression( + "(x) => { return x + 1; }", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BlockStatement { + new ReturnStatement { + Expression = new BinaryOperatorExpression( + new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }}}); + } + + [Test] + public void ImplicitlyTypedStatementBodyWithoutParenthesis() + { + ParseUtilCSharp.AssertExpression( + "x => { return x + 1; }", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BlockStatement { + new ReturnStatement { + Expression = new BinaryOperatorExpression( + new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }}}); + } + + [Test] + public void ExplicitlyTypedStatementBody() + { + ParseUtilCSharp.AssertExpression( + "(int x) => { return x + 1; }", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Type = new PrimitiveType("int"), Name = "x" } }, + Body = new BlockStatement { + new ReturnStatement { + Expression = new BinaryOperatorExpression( + new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }}}); + } + + [Test] + public void ExplicitlyTypedWithRefParameter() + { + ParseUtilCSharp.AssertExpression( + "(ref int i) => i = 1", + new LambdaExpression { + Parameters = { + new ParameterDeclaration { + ParameterModifier = ParameterModifier.Ref, + Type = new PrimitiveType("int"), + Name = "i" + } + }, + Body = new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(1)) + }); + } + + [Test] + public void LambdaExpressionContainingConditionalExpression() + { + ParseUtilCSharp.AssertExpression( + "rr => rr != null ? rr.ResolvedType : null", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "rr" } }, + Body = new ConditionalExpression { + Condition = new BinaryOperatorExpression( + new IdentifierExpression("rr"), BinaryOperatorType.InEquality, new NullReferenceExpression()), + TrueExpression = new IdentifierExpression("rr").Member("ResolvedType"), + FalseExpression = new NullReferenceExpression() + }}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs new file mode 100644 index 0000000000..038b33644d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs @@ -0,0 +1,93 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class MemberReferenceExpressionTests + { + [Test] + public void SimpleFieldReferenceExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "myTargetObject.myField", + new IdentifierExpression("myTargetObject").Member("myField") + ); + } + + [Test, Ignore("parser is broken and produces IdentifierExpression instead of PrimitiveType")] + public void ShortMaxValueTest() + { + ParseUtilCSharp.AssertExpression( + "short.MaxValue", + new PrimitiveType("short").Member("MaxValue") + ); + } + + [Test, Ignore("Parsing of @-identifiers is broken")] + public void IdentShortMaxValueTest() + { + ParseUtilCSharp.AssertExpression( + "@short.MaxValue", + new IdentifierExpression("short").Member("MaxValue") + ); + } + + [Test] + public void GenericFieldReferenceExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "SomeClass.myField", + new IdentifierExpression("SomeClass") { TypeArguments = { new PrimitiveType("string") } }.Member("myField") + ); + } + + [Test] + public void FullNamespaceGenericFieldReferenceExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "Namespace.Subnamespace.SomeClass.myField", + new MemberReferenceExpression { + Target = new IdentifierExpression("Namespace").Member("Subnamespace"), + TypeArguments = { new PrimitiveType("string") } + }.Member("myField") + ); + } + + [Test] + public void GlobalFullNamespaceGenericFieldReferenceExpressionTest() + { + var target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "Namespace" + }.Member("Subnamespace").Member ("SomeClass"); + + target.AddChild (new PrimitiveType("string"), MemberReferenceExpression.Roles.TypeArgument); + + ParseUtilCSharp.AssertExpression( + "global::Namespace.Subnamespace.SomeClass.myField", + new MemberReferenceExpression { + Target = target, + MemberName = "myField" + } + ); + } + + [Test] + public void NestedGenericFieldReferenceExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "MyType.InnerClass.myField", + new MemberReferenceExpression { + Target = new IdentifierExpression("MyType") { TypeArguments = { new PrimitiveType("string") } }, + MemberName = "InnerClass", + TypeArguments = { new PrimitiveType("int") } + }.Member("myField") + ); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ParenthesizedExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ParenthesizedExpressionTests.cs new file mode 100644 index 0000000000..c60bcbf1f9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ParenthesizedExpressionTests.cs @@ -0,0 +1,21 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class ParenthesizedExpressionTests + { + [Test] + public void PrimitiveParenthesizedExpression() + { + ParenthesizedExpression p = ParseUtilCSharp.ParseExpression("((1))"); + Assert.IsTrue(p.Expression is ParenthesizedExpression); + p = (ParenthesizedExpression)p.Expression; + Assert.IsTrue(p.Expression is PrimitiveExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs new file mode 100644 index 0000000000..8104524b91 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs @@ -0,0 +1,33 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class PointerReferenceExpressionTests + { + [Test] + public void PointerReferenceExpressionTest() + { + PointerReferenceExpression pre = ParseUtilCSharp.ParseExpression("myObj.field->b"); + Assert.IsTrue(pre.Target is MemberReferenceExpression); + Assert.AreEqual("b", pre.MemberName); + } + + [Test] + public void PointerReferenceGenericMethodTest() + { + ParseUtilCSharp.AssertExpression( + "ptr->M();", + new InvocationExpression { + Target = new PointerReferenceExpression { + Target = new IdentifierExpression("ptr"), + MemberName = "M", + TypeArguments = { new PrimitiveType("string") } + }}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs new file mode 100644 index 0000000000..9b4b1efcc6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs @@ -0,0 +1,203 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class PrimitiveExpressionTests + { + [Test] + public void HexIntegerTest1() + { + InvocationExpression invExpr = ParseUtilCSharp.ParseExpression("0xAFFE.ToString()"); + Assert.AreEqual(0, invExpr.Arguments.Count()); + Assert.IsTrue(invExpr.Target is MemberReferenceExpression); + MemberReferenceExpression fre = invExpr.Target as MemberReferenceExpression; + Assert.AreEqual("ToString", fre.MemberName); + + Assert.IsTrue(fre.Target is PrimitiveExpression); + PrimitiveExpression pe = fre.Target as PrimitiveExpression; + + Assert.AreEqual(0xAFFE, (int)pe.Value); + + } + + void CheckLiteral(string code, object value) + { + PrimitiveExpression pe = ParseUtilCSharp.ParseExpression(code); + Assert.AreEqual(value.GetType(), pe.Value.GetType()); + Assert.AreEqual(value, pe.Value); + } + + [Test] + public void DoubleTest1() + { + CheckLiteral(".5e-06", .5e-06); + } + + [Test] + public void CharTest1() + { + CheckLiteral("'\\u0356'", '\u0356'); + } + + [Test, Ignore("this special case isn't implemented yet")] + public void IntMinValueTest() + { + CheckLiteral("-2147483648", -2147483648); + } + + [Test] + public void IntMaxValueTest() + { + CheckLiteral("2147483647", 2147483647); // int + CheckLiteral("2147483648", 2147483648); // uint + } + + [Test, Ignore("this special case isn't implemented yet")] + public void LongMinValueTest() + { + CheckLiteral("-9223372036854775808", -9223372036854775808); + } + + [Test] + public void LongMaxValueTest() + { + CheckLiteral("9223372036854775807", 9223372036854775807); // long + CheckLiteral("9223372036854775808", 9223372036854775808); // ulong + } + + [Test] + public void StringTest1() + { + CheckLiteral("\"\\n\\t\\u0005 Hello World !!!\"", "\n\t\u0005 Hello World !!!"); + } + + [Test] + public void TestSingleDigit() + { + CheckLiteral("5", 5); + } + + [Test] + public void TestZero() + { + CheckLiteral("0", 0); + } + + [Test] + public void TestInteger() + { + CheckLiteral("66", 66); + } + + [Test] + public void TestNonOctalInteger() + { + // C# does not have octal integers, so 077 should parse to 77 + Assert.IsTrue(077 == 77); + + CheckLiteral("077", 077); + CheckLiteral("056", 056); + } + + [Test] + public void TestHexadecimalInteger() + { + CheckLiteral("0x99F", 0x99F); + CheckLiteral("0xAB1f", 0xAB1f); + CheckLiteral("0xffffffff", 0xffffffff); + CheckLiteral("0xffffffffL", 0xffffffffL); + CheckLiteral("0xffffffffuL", 0xffffffffuL); + } + + [Test] + public void InvalidHexadecimalInteger() + { + // don't check result, just make sure there is no exception + ParseUtilCSharp.ParseExpression("0x2GF", expectErrors: true); + ParseUtilCSharp.ParseExpression("0xG2F", expectErrors: true); + ParseUtilCSharp.ParseExpression("0x", expectErrors: true); // SD-457 + // hexadecimal integer >ulong.MaxValue + ParseUtilCSharp.ParseExpression("0xfedcba98765432100", expectErrors: true); + } + + [Test] + public void TestLongHexadecimalInteger() + { + CheckLiteral("0x4244636f446c6d58", 0x4244636f446c6d58); + CheckLiteral("0xf244636f446c6d58", 0xf244636f446c6d58); + } + + [Test] + public void TestLongInteger() + { + CheckLiteral("9223372036854775807", 9223372036854775807); // long.MaxValue + CheckLiteral("9223372036854775808", 9223372036854775808); // long.MaxValue+1 + CheckLiteral("18446744073709551615", 18446744073709551615); // ulong.MaxValue + } + + [Test] + public void TestTooLongInteger() + { + // ulong.MaxValue+1 + ParseUtilCSharp.ParseExpression("18446744073709551616", expectErrors: true); + + CheckLiteral("18446744073709551616f", 18446744073709551616f); // ulong.MaxValue+1 as float + CheckLiteral("18446744073709551616d", 18446744073709551616d); // ulong.MaxValue+1 as double + CheckLiteral("18446744073709551616m", 18446744073709551616m); // ulong.MaxValue+1 as decimal + } + + [Test] + public void TestDouble() + { + CheckLiteral("1.0", 1.0); + CheckLiteral("1.1", 1.1); + CheckLiteral("1.1e-2", 1.1e-2); + } + + [Test] + public void TestFloat() + { + CheckLiteral("1f", 1f); + CheckLiteral("1.0f", 1.0f); + CheckLiteral("1.1f", 1.1f); + CheckLiteral("1.1e-2f", 1.1e-2f); + } + + [Test] + public void TestDecimal() + { + CheckLiteral("1m", 1m); + CheckLiteral("1.0m", 1.0m); + CheckLiteral("1.1m", 1.1m); + CheckLiteral("1.1e-2m", 1.1e-2m); + CheckLiteral("2.0e-5m", 2.0e-5m); + } + + [Test] + public void TestString() + { + CheckLiteral(@"@""-->""""<--""", @"-->""<--"); + CheckLiteral(@"""-->\""<--""", "-->\"<--"); + + CheckLiteral(@"""\U00000041""", "\U00000041"); + CheckLiteral(@"""\U00010041""", "\U00010041"); + } + + [Test] + public void TestCharLiteral() + { + CheckLiteral(@"'a'", 'a'); + CheckLiteral(@"'\u0041'", '\u0041'); + CheckLiteral(@"'\x41'", '\x41'); + CheckLiteral(@"'\x041'", '\x041'); + CheckLiteral(@"'\x0041'", '\x0041'); + CheckLiteral(@"'\U00000041'", '\U00000041'); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs new file mode 100644 index 0000000000..35e3f54896 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs @@ -0,0 +1,284 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class QueryExpressionTests + { + [Test] + public void SimpleExpression() + { + ParseUtilCSharp.AssertExpression( + "from c in customers where c.City == \"London\" select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryWhereClause { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("c").Member("City"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression("London") + } + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); + } + + [Test] + public void ExpressionWithType1() + { + ParseUtilCSharp.AssertExpression( + "from Customer c in customers select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Type = new SimpleType("Customer"), + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); + } + + [Test] + public void ExpressionWithType2() + { + ParseUtilCSharp.AssertExpression( + "from int c in customers select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Type = new PrimitiveType("int"), + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); + } + + + [Test] + public void ExpressionWithType3() + { + ParseUtilCSharp.AssertExpression( + "from S? c in customers select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Type = new ComposedType { + BaseType = new SimpleType { + Identifier = "S", + TypeArguments = { + new PrimitiveType("int").MakeArrayType() + } + }, + HasNullableSpecifier = true + }, + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); + } + + [Test] + public void MultipleGenerators() + { + ParseUtilCSharp.AssertExpression( + @" +from c in customers +where c.City == ""London"" +from o in c.Orders +where o.OrderDate.Year == 2005 +select new { c.Name, o.OrderID, o.Total }", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryWhereClause { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("c").Member("City"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression("London") + } + }, + new QueryFromClause { + Identifier = "o", + Expression = new IdentifierExpression("c").Member("Orders") + }, + new QueryWhereClause { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("o").Member("OrderDate").Member("Year"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression(2005) + } + }, + new QuerySelectClause { + Expression = new AnonymousTypeCreateExpression { + Initializer = { + new IdentifierExpression("c").Member("Name"), + new IdentifierExpression("o").Member("OrderID"), + new IdentifierExpression("o").Member("Total") + } + } + } + }}); + } + + [Test] + public void ExpressionWithOrderBy() + { + ParseUtilCSharp.AssertExpression( + "from c in customers orderby c.Name select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryOrderClause { + Orderings = { + new QueryOrdering { + Expression = new IdentifierExpression("c").Member("Name") + } + } + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); + } + + [Test] + public void ExpressionWithOrderByAndLet() + { + ParseUtilCSharp.AssertExpression( + "from c in customers orderby c.Name descending let x = c select x", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryOrderClause { + Orderings = { + new QueryOrdering { + Expression = new IdentifierExpression("c").Member("Name"), + Direction = QueryOrderingDirection.Descending + } + } + }, + new QueryLetClause { + Identifier = "x", + Expression = new IdentifierExpression("c") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("x") + } + }}); + } + + [Test] + public void QueryContinuation() + { + ParseUtilCSharp.AssertExpression( + "from a in b select c into d select e", + new QueryExpression { + Clauses = { + new QueryContinuationClause { + PrecedingQuery = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QuerySelectClause { Expression = new IdentifierExpression("c") } + } + }, + Identifier = "d" + }, + new QuerySelectClause { Expression = new IdentifierExpression("e") } + } + } + ); + } + + + [Test] + public void QueryContinuationWithMultipleFrom() + { + ParseUtilCSharp.AssertExpression( + "from a in b from c in d select e into f select g", + new QueryExpression { + Clauses = { + new QueryContinuationClause { + PrecedingQuery = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("d") + }, + new QuerySelectClause { Expression = new IdentifierExpression("e") } + } + }, + Identifier = "f" + }, + new QuerySelectClause { Expression = new IdentifierExpression("g") } + } + } + ); + } + + [Test] + public void MultipleQueryContinuation() + { + ParseUtilCSharp.AssertExpression( + "from a in b select c into d select e into f select g", + new QueryExpression { + Clauses = { + new QueryContinuationClause { + PrecedingQuery = new QueryExpression { + Clauses = { + new QueryContinuationClause { + PrecedingQuery = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QuerySelectClause { Expression = new IdentifierExpression("c") } + } + }, + Identifier = "d" + }, + new QuerySelectClause { Expression = new IdentifierExpression("e") } + } + }, + Identifier = "f" + }, + new QuerySelectClause { Expression = new IdentifierExpression("g") } + }}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs new file mode 100644 index 0000000000..f6a85fcb3b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs @@ -0,0 +1,19 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class SizeOfExpressionTests + { + [Test] + public void SizeOfExpressionTest() + { + SizeOfExpression soe = ParseUtilCSharp.ParseExpression("sizeof(MyType)"); + Assert.AreEqual("MyType", ((SimpleType)soe.Type).Identifier); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs new file mode 100644 index 0000000000..c28d559fcb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class StackAllocExpressionTests + { + [Test] + public void StackAllocExpressionTest() + { + var vd = ParseUtilCSharp.ParseStatement("int* a = stackalloc int[100];"); + StackAllocExpression sae = (StackAllocExpression)vd.Variables.Single().Initializer; + Assert.AreEqual("int", ((PrimitiveType)sae.Type).Keyword); + Assert.AreEqual(100, ((PrimitiveExpression)sae.CountExpression).Value); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs new file mode 100644 index 0000000000..7c547adeac --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs @@ -0,0 +1,18 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class ThisReferenceExpressionTests + { + [Test] + public void TestMethod() + { + ParseUtilCSharp.ParseExpression("this"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs new file mode 100644 index 0000000000..847b705670 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs @@ -0,0 +1,139 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class TypeOfExpressionTests + { + [Test] + public void SimpleTypeOfExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(MyNamespace.N1.MyType)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "N1" + }, + MemberName = "MyType" + }}); + } + + [Test] + public void GlobalTypeOfExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(global::System.Console)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }, + MemberName = "Console" + }}); + } + + [Test] + public void PrimitiveTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(int)"); + Assert.AreEqual("int", ((PrimitiveType)toe.Type).Keyword); + } + + [Test] + public void VoidTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(void)"); + Assert.AreEqual("void", ((PrimitiveType)toe.Type).Keyword); + } + + [Test] + public void ArrayTypeOfExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(MyType[])", + new TypeOfExpression { + Type = new SimpleType("MyType").MakeArrayType() + }); + } + + [Test] + public void GenericTypeOfExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(MyNamespace.N1.MyType)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "N1" + }, + MemberName = "MyType", + TypeArguments = { new PrimitiveType("string") } + }}); + } + + [Test] + public void NestedGenericTypeOfExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(MyType.InnerClass.InnerInnerClass)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyType") { TypeArguments = { new PrimitiveType("string") } }, + MemberName = "InnerClass", + TypeArguments = { new PrimitiveType("int") } + }, + MemberName = "InnerInnerClass" + }}); + } + + [Test] + public void NullableTypeOfExpressionTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(MyStruct?)", + new TypeOfExpression { + Type = new ComposedType { + BaseType = new SimpleType("MyType"), + HasNullableSpecifier = true + }}); + } + + [Test] + public void UnboundTypeOfExpressionTest() + { + var type = new SimpleType("MyType"); + type.AddChild (new SimpleType (), SimpleType.Roles.TypeArgument); + type.AddChild (new SimpleType (), SimpleType.Roles.TypeArgument); + ParseUtilCSharp.AssertExpression( + "typeof(MyType<,>)", + new TypeOfExpression { + Type = type + }); + } + + [Test] + public void NestedArraysTest() + { + ParseUtilCSharp.AssertExpression( + "typeof(int[,][])", + new TypeOfExpression { + Type = new ComposedType { + BaseType = new PrimitiveType("int"), + ArraySpecifiers = { + new ArraySpecifier(2), + new ArraySpecifier(1) + } + }}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs new file mode 100644 index 0000000000..31f01ce394 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs @@ -0,0 +1,62 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class TypeReferenceExpressionTests + { + [Test] + public void GlobalTypeReferenceExpression() + { + TypeReferenceExpression tr = ParseUtilCSharp.ParseExpression("global::System"); + Assert.IsTrue (tr.IsMatch (new TypeReferenceExpression () { + Type = new MemberType () { + Target = new SimpleType ("global"), + IsDoubleColon = true, + MemberName = "System" + } + })); + } + + [Test, Ignore ("Doesn't work")] + public void GlobalTypeReferenceExpressionWithoutTypeName() + { + TypeReferenceExpression tr = ParseUtilCSharp.ParseExpression("global::", true); + Assert.IsTrue (tr.IsMatch (new TypeReferenceExpression () { + Type = new MemberType () { + Target = new SimpleType ("global"), + IsDoubleColon = true, + } + })); + } + + [Test, Ignore("Primitive types as member reference target are not supported yet")] + public void IntReferenceExpression() + { + MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("int.MaxValue"); + Assert.IsTrue (fre.IsMatch (new MemberReferenceExpression () { + Target = new TypeReferenceExpression () { + Type = new PrimitiveType("int") + }, + MemberName = "MaxValue" + })); + } + + /* [Test] + public void StandaloneIntReferenceExpression() + { + // doesn't work because a = int; gives a compiler error. + // But how do we handle this case for code completion? + TypeReferenceExpression tre = ParseUtilCSharp.ParseExpression("int"); + Assert.IsNotNull (tre.Match (new TypeReferenceExpression () { + Type = new SimpleType ("int") + })); + }*/ + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs new file mode 100644 index 0000000000..a968af1ebd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs @@ -0,0 +1,95 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class UnaryOperatorExpressionTests + { + void TestUnaryOperatorExpressionTest(string program, UnaryOperatorType op) + { + UnaryOperatorExpression uoe = ParseUtilCSharp.ParseExpression(program); + Assert.AreEqual(op, uoe.Operator); + + Assert.IsTrue(uoe.Expression is IdentifierExpression); + } + + [Test] + public void NotTest() + { + TestUnaryOperatorExpressionTest("!a", UnaryOperatorType.Not); + } + + [Test] + public void BitNotTest() + { + TestUnaryOperatorExpressionTest("~a", UnaryOperatorType.BitNot); + } + + [Test] + public void MinusTest() + { + TestUnaryOperatorExpressionTest("-a", UnaryOperatorType.Minus); + } + + [Test] + public void PlusTest() + { + TestUnaryOperatorExpressionTest("+a", UnaryOperatorType.Plus); + } + + [Test] + public void IncrementTest() + { + TestUnaryOperatorExpressionTest("++a", UnaryOperatorType.Increment); + } + + [Test] + public void DecrementTest() + { + TestUnaryOperatorExpressionTest("--a", UnaryOperatorType.Decrement); + } + + [Test] + public void PostIncrementTest() + { + TestUnaryOperatorExpressionTest("a++", UnaryOperatorType.PostIncrement); + } + + [Test] + public void PostDecrementTest() + { + TestUnaryOperatorExpressionTest("a--", UnaryOperatorType.PostDecrement); + } + + [Test] + public void StarTest() + { + TestUnaryOperatorExpressionTest("*a", UnaryOperatorType.Dereference); + } + + [Test] + public void BitWiseAndTest() + { + TestUnaryOperatorExpressionTest("&a", UnaryOperatorType.AddressOf); + } + + [Test] + public void DereferenceAfterCast() + { + UnaryOperatorExpression uoe = ParseUtilCSharp.ParseExpression("*((SomeType*) &w)"); + Assert.AreEqual(UnaryOperatorType.Dereference, uoe.Operator); + ParenthesizedExpression pe = (ParenthesizedExpression)uoe.Expression; + CastExpression ce = (CastExpression)pe.Expression; + ComposedType type = (ComposedType)ce.Type; + Assert.AreEqual("SomeType", ((SimpleType)type.BaseType).Identifier); + Assert.AreEqual(1, type.PointerRank); + + UnaryOperatorExpression adrOf = (UnaryOperatorExpression)ce.Expression; + Assert.AreEqual(UnaryOperatorType.AddressOf, adrOf.Operator); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs new file mode 100644 index 0000000000..15707c51b5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs @@ -0,0 +1,142 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using System.Text.RegularExpressions; + +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope +{ + [TestFixture] + public class AttributeSectionTests + { + [Test] + public void GlobalAttributeCSharp() + { + string program = @"[global::Microsoft.VisualBasic.CompilerServices.DesignerGenerated()] +[someprefix::DesignerGenerated()] +public class Form1 { +}"; + + TypeDeclaration decl = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual(2, decl.Attributes.Count); + Assert.AreEqual("global::Microsoft.VisualBasic.CompilerServices.DesignerGenerated", + decl.Attributes.First().Attributes.Single().Type.ToString()); + Assert.AreEqual("someprefix::DesignerGenerated", decl.Attributes.Last().Attributes.Single().Type.ToString()); + } + + [Test] + public void AssemblyAttributeCSharp() + { + string program = @"[assembly: System.Attribute()]"; + AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual(new AstLocation(1, 1), decl.StartLocation); + Assert.AreEqual("assembly", decl.AttributeTarget); + } + + [Test, Ignore("assembly/module attributes are broken")] + public void AssemblyAttributeCSharpWithNamedArguments() + { + string program = @"[assembly: Foo(1, namedArg: 2, prop = 3)]"; + AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual("assembly", decl.AttributeTarget); + var a = decl.Attributes.Single(); + Assert.AreEqual("Foo", a.Type); + Assert.AreEqual(3, a.Arguments.Count()); + + Assert.IsTrue(a.Arguments.ElementAt(0).IsMatch(new PrimitiveExpression(1))); + Assert.IsTrue(a.Arguments.ElementAt(1).IsMatch(new NamedArgumentExpression { + Identifier = "namedArg", + Expression = new PrimitiveExpression(2) + })); + Assert.IsTrue(a.Arguments.ElementAt(2).IsMatch(new AssignmentExpression { + Left = new IdentifierExpression("prop"), + Operator = AssignmentOperatorType.Assign, + Right = new PrimitiveExpression(3) + })); + } + + [Test, Ignore("assembly/module attributes are broken")] + public void ModuleAttributeCSharp() + { + string program = @"[module: System.Attribute()]"; + AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual(new AstLocation(1, 1), decl.StartLocation); + Assert.AreEqual("module", decl.AttributeTarget); + } + + [Test] + public void TypeAttributeCSharp() + { + string program = @"[type: System.Attribute()] class Test {}"; + TypeDeclaration type = ParseUtilCSharp.ParseGlobal(program); + AttributeSection decl = type.Attributes.Single(); + Assert.AreEqual(new AstLocation(1, 1), decl.StartLocation); + Assert.AreEqual("type", decl.AttributeTarget); + } + + [Test, Ignore("Parser doesn't support attributes on type parameters")] + public void AttributesOnTypeParameter() + { + ParseUtilCSharp.AssertGlobal( + "class Test<[A,B]C> {}", + new TypeDeclaration { + ClassType = ClassType.Class, + Name = "Test", + TypeParameters = { + new TypeParameterDeclaration { + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { Type = new SimpleType("A") }, + new Attribute { Type = new SimpleType("B") } + } + } + }, + Name = "C" + } + }}); + } + + [Test] + public void AttributeOnMethodParameter() + { + ParseUtilCSharp.AssertTypeMember( + "void M([In] int p);", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + Name = "M", + Parameters = { + new ParameterDeclaration { + Attributes = { new AttributeSection(new Attribute { Type = new SimpleType("In") }) }, + Type = new PrimitiveType("int"), + Name = "p" + } + }}); + } + + [Test] + public void AttributeOnSetterValue() + { + ParseUtilCSharp.AssertTypeMember( + "int P { get; [param: In] set; }", + new PropertyDeclaration { + ReturnType = new PrimitiveType("int"), + Name = "P", + Getter = new Accessor(), + Setter = new Accessor { + Attributes = { + new AttributeSection { + AttributeTarget = "param", + Attributes = { new Attribute { Type = new SimpleType("In") } }, + } }, + }}); + } + + // TODO: Tests for other contexts where attributes can appear + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs new file mode 100644 index 0000000000..b41c5e569f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs @@ -0,0 +1,63 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope +{ + [TestFixture] + public class DelegateDeclarationTests + { + [Test] + public void SimpleCSharpDelegateDeclarationTest() + { + ParseUtilCSharp.AssertGlobal( + "public delegate void MyDelegate(int a, int secondParam, MyObj lastParam);", + new DelegateDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new PrimitiveType("void"), + Name = "MyDelegate", + Parameters = { + new ParameterDeclaration(new PrimitiveType("int"), "a"), + new ParameterDeclaration(new PrimitiveType("int"), "secondParam"), + new ParameterDeclaration(new SimpleType("MyObj"), "lastParam") + }}); + } + + [Test] + public void GenericDelegateDeclarationTest() + { + ParseUtilCSharp.AssertGlobal( + "public delegate T CreateObject() where T : ICloneable;", + new DelegateDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new SimpleType("T"), + Name = "CreateObject", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ICloneable") } + } + }}); + } + + [Test] + public void DelegateDeclarationInNamespace() + { + string program = "namespace N { delegate void MyDelegate(); }"; + NamespaceDeclaration nd = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual("MyDelegate", ((DelegateDeclaration)nd.Members.Single()).Name); + } + + [Test] + public void DelegateDeclarationInClass() + { + string program = "class Outer { delegate void Inner(); }"; + TypeDeclaration td = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual("Inner", ((DelegateDeclaration)td.Members.Single()).Name); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs new file mode 100644 index 0000000000..bec5732709 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope +{ + [TestFixture] + public class NamespaceDeclarationTests + { + [Test] + public void SimpleNamespaceTest() + { + string program = "namespace TestNamespace {\n" + + "}\n"; + NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual("TestNamespace", ns.Name); + } + + [Test] + public void NestedNamespaceTest() + { + string program = "namespace N1 {//TestNamespace\n" + + " namespace N2 {// Declares a namespace named N2 within N1.\n" + + " }\n" + + "}\n"; + NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal(program); + + Assert.AreEqual("N1", ns.Name); + + Assert.AreEqual("N2", ns.Children.OfType().Single().Name); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs new file mode 100644 index 0000000000..2c123a5dd6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs @@ -0,0 +1,292 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope +{ + [TestFixture] + public class TypeDeclarationTests + { + [Test] + public void SimpleClassTypeDeclarationTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("class MyClass : My.Base.Class { }"); + + Assert.AreEqual(ClassType.Class, td.ClassType); + Assert.AreEqual("MyClass", td.Name); + Assert.AreEqual("My.Base.Class", td.BaseTypes.First ().ToString ()); + Assert.AreEqual(Modifiers.None, td.Modifiers); + } + + [Test] + public void SimpleClassRegionTest() + { + const string program = "class MyClass\n{\n}\n"; + TypeDeclaration td = ParseUtilCSharp.ParseGlobal(program); + Assert.AreEqual(1, td.StartLocation.Line, "StartLocation.Y"); + Assert.AreEqual(1, td.StartLocation.Column, "StartLocation.X"); + AstLocation bodyStartLocation = td.GetChildByRole(AstNode.Roles.LBrace).PrevSibling.EndLocation; + Assert.AreEqual(1, bodyStartLocation.Line, "BodyStartLocation.Y"); + Assert.AreEqual(14, bodyStartLocation.Column, "BodyStartLocation.X"); + Assert.AreEqual(3, td.EndLocation.Line, "EndLocation.Y"); + Assert.AreEqual(2, td.EndLocation.Column, "EndLocation.Y"); + } + + [Test] + public void SimplePartialClassTypeDeclarationTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("partial class MyClass { }"); + Assert.IsFalse(td.IsNull); + Assert.AreEqual(ClassType.Class, td.ClassType); + Assert.AreEqual("MyClass", td.Name); + Assert.AreEqual(Modifiers.Partial, td.Modifiers); + } + + [Test] + public void NestedClassesTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("class MyClass { partial class P1 {} public partial class P2 {} static class P3 {} internal static class P4 {} }"); + Assert.IsFalse(td.IsNull); + Assert.AreEqual(ClassType.Class, td.ClassType); + Assert.AreEqual("MyClass", td.Name); + Assert.AreEqual(Modifiers.Partial, ((TypeDeclaration)td.Members.ElementAt(0)).Modifiers); + Assert.AreEqual(Modifiers.Partial | Modifiers.Public, ((TypeDeclaration)td.Members.ElementAt(1)).Modifiers); + Assert.AreEqual(Modifiers.Static, ((TypeDeclaration)td.Members.ElementAt(2)).Modifiers); + Assert.AreEqual(Modifiers.Static | Modifiers.Internal, ((TypeDeclaration)td.Members.ElementAt(3)).Modifiers); + } + + [Test] + public void SimpleStaticClassTypeDeclarationTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("static class MyClass { }"); + Assert.IsFalse(td.IsNull); + Assert.AreEqual(ClassType.Class, td.ClassType); + Assert.AreEqual("MyClass", td.Name); + Assert.AreEqual(Modifiers.Static, td.Modifiers); + } + + [Test] + public void GenericClassTypeDeclarationTest() + { + ParseUtilCSharp.AssertGlobal( + "public class G {}", + new TypeDeclaration { + Modifiers = Modifiers.Public, + ClassType = ClassType.Class, + Name = "G", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } } + }); + } + + [Test] + public void GenericClassWithWhere() + { + ParseUtilCSharp.AssertGlobal( + @"public class Test where T : IMyInterface { }", + new TypeDeclaration { + Modifiers = Modifiers.Public, + ClassType = ClassType.Class, + Name = "Test", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("IMyInterface") } + } + }}); + } + + [Test, Ignore ("Mono parser bug.")] + public void ComplexGenericClassTypeDeclarationTest() + { + ParseUtilCSharp.AssertGlobal( + "public class Generic : System.IComparable where S : G, new() where T : MyNamespace.IMyInterface", + new TypeDeclaration { + Modifiers = Modifiers.Public, + ClassType = ClassType.Class, + Name = "Generic", + TypeParameters = { + new TypeParameterDeclaration { Variance = VarianceModifier.Contravariant, Name = "T" }, + new TypeParameterDeclaration { Variance = VarianceModifier.Covariant, Name = "S" } + }, + BaseTypes = { + new MemberType { + Target = new SimpleType("System"), + MemberName = "IComparable" + } + }, + Constraints = { + new Constraint { + TypeParameter = "S", + BaseTypes = { + new SimpleType { + Identifier = "G", + TypeArguments = { new SimpleType("T").MakeArrayType() } + }, + new PrimitiveType("new") + } + }, + new Constraint { + TypeParameter = "T", + BaseTypes = { + new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "IMyInterface" + } + } + } + } + }); + } + + [Test] + public void ComplexClassTypeDeclarationTest() + { + ParseUtilCSharp.AssertGlobal( + @" +[MyAttr()] +public abstract class MyClass : MyBase, Interface1, My.Test.Interface2 +{ +}", + new TypeDeclaration { + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { Type = new SimpleType("MyAttr") } + } + } + }, + Modifiers = Modifiers.Public | Modifiers.Abstract, + ClassType = ClassType.Class, + Name = "MyClass", + BaseTypes = { + new SimpleType("MyBase"), + new SimpleType("Interface1"), + new MemberType { + Target = new MemberType { + Target = new SimpleType("My"), + MemberName = "Test" + }, + MemberName = "Interface2" + } + }}); + } + + [Test] + public void SimpleStructTypeDeclarationTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("struct MyStruct {}"); + + Assert.AreEqual(ClassType.Struct, td.ClassType); + Assert.AreEqual("MyStruct", td.Name); + } + + [Test] + public void SimpleInterfaceTypeDeclarationTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("interface MyInterface {}"); + + Assert.AreEqual(ClassType.Interface, td.ClassType); + Assert.AreEqual("MyInterface", td.Name); + } + + [Test] + public void SimpleEnumTypeDeclarationTest() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("enum MyEnum {}"); + + Assert.AreEqual(ClassType.Enum, td.ClassType); + Assert.AreEqual("MyEnum", td.Name); + } + + [Test, Ignore("Mono parser bug?")] + public void ContextSensitiveKeywordTest() + { + ParseUtilCSharp.AssertGlobal( + "partial class partial<[partial: where] where> where where : partial { }", + new TypeDeclaration { + Modifiers = Modifiers.Partial, + ClassType = ClassType.Class, + Name = "partial", + TypeParameters = { + new TypeParameterDeclaration { + Attributes = { + new AttributeSection { + AttributeTarget = "partial", + Attributes = { new Attribute { Type = new SimpleType("where") } } + } + }, + Name = "where" + } + }, + Constraints = { + new Constraint { + TypeParameter = "where", + BaseTypes = { + new SimpleType { + Identifier = "partial", + TypeArguments = { new SimpleType("where") } + } + } + } + }}); + } + + [Test] + public void TypeInNamespaceTest() + { + NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal("namespace N { class MyClass { } }"); + + Assert.AreEqual("N", ns.Name); + Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name); + } + + [Test] + public void StructInNamespaceTest() + { + NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal("namespace N { struct MyClass { } }"); + + Assert.AreEqual("N", ns.Name); + Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name); + } + + [Test] + public void EnumInNamespaceTest() + { + NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal("namespace N { enum MyClass { } }"); + + Assert.AreEqual("N", ns.Name); + Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name); + } + + [Test] + public void InterfaceInNamespaceTest() + { + NamespaceDeclaration ns = ParseUtilCSharp.ParseGlobal("namespace N { interface MyClass { } }"); + + Assert.AreEqual("N", ns.Name); + Assert.AreEqual("MyClass", ((TypeDeclaration)ns.Members.Single()).Name); + } + + [Test] + public void EnumWithInitializer() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("enum MyEnum { Val1 = 10 }"); + EnumMemberDeclaration member = (EnumMemberDeclaration)td.Members.Single(); + Assert.AreEqual("Val1", member.Name); + Assert.AreEqual(10, ((PrimitiveExpression)member.Initializer).Value); + } + + [Test] + public void EnumWithBaseType() + { + TypeDeclaration td = ParseUtilCSharp.ParseGlobal("enum MyEnum : short { }"); + Assert.AreEqual("MyEnum", td.Name); + Assert.AreEqual("short", ((PrimitiveType)td.BaseTypes.Single()).Keyword); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs new file mode 100644 index 0000000000..e5a82c3ea1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs @@ -0,0 +1,101 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope +{ + [TestFixture] + public class UsingDeclarationTests + { + [Test] + public void WrongUsingTest() + { + string program = "using\n"; + CSharpParser parser = new CSharpParser(); + CompilationUnit cu = parser.Parse(new StringReader(program)); + Assert.AreEqual(0, cu.Children.Count()); + Assert.IsTrue(parser.HasErrors); + } + + [Test] + public void DeclarationTest() + { + string program = "using System;\n" + + "using My.Name.Space;\n"; + CSharpParser parser = new CSharpParser(); + CompilationUnit cu = parser.Parse(new StringReader(program)); + Assert.IsFalse(parser.HasErrors); + + Assert.AreEqual(2, cu.Children.Count()); + Assert.IsTrue(cu.Children.ElementAt(0) is UsingDeclaration); + Assert.IsFalse(cu.Children.ElementAt(0) is UsingAliasDeclaration); + UsingDeclaration ud = (UsingDeclaration)cu.Children.ElementAt(0); + Assert.AreEqual("System", ud.Namespace); + + Assert.IsTrue(cu.Children.ElementAt(1) is UsingDeclaration); + Assert.IsFalse(cu.Children.ElementAt(1) is UsingAliasDeclaration); + ud = (UsingDeclaration)cu.Children.ElementAt(1); + Assert.AreEqual("My.Name.Space", ud.Namespace); + } + + [Test] + public void UsingAliasDeclarationTest() + { + string program = "using TESTME=System;\n" + + "using myAlias=My.Name.Space;\n" + + "using StringCollection = System.Collections.Generic.List;\n"; + CSharpParser parser = new CSharpParser(); + CompilationUnit cu = parser.Parse(new StringReader(program)); + Assert.IsFalse(parser.HasErrors); + + Assert.AreEqual(3, cu.Children.Count()); + + Assert.IsTrue(cu.Children.ElementAt(0) is UsingAliasDeclaration); + UsingAliasDeclaration ud = (UsingAliasDeclaration)cu.Children.ElementAt(0); + Assert.AreEqual("TESTME", ud.Alias); + Assert.AreEqual("System", ud.Import.ToString()); + + Assert.IsTrue(cu.Children.ElementAt(1) is UsingAliasDeclaration); + ud = (UsingAliasDeclaration)cu.Children.ElementAt(1); + Assert.AreEqual("myAlias", ud.Alias); + Assert.AreEqual("My.Name.Space", ud.Import.ToString()); + + Assert.IsTrue(cu.Children.ElementAt(2) is UsingAliasDeclaration); + ud = (UsingAliasDeclaration)cu.Children.ElementAt(2); + Assert.AreEqual("StringCollection", ud.Alias); + Assert.AreEqual("System.Collections.Generic.List", ud.Import.ToString()); + } + + [Test] + public void UsingWithAliasing() + { + string program = "using global::System;\n" + + "using myAlias=global::My.Name.Space;\n" + + "using a::b.c;\n"; + CSharpParser parser = new CSharpParser(); + CompilationUnit cu = parser.Parse(new StringReader(program)); + Assert.IsFalse(parser.HasErrors); + + Assert.AreEqual(3, cu.Children.Count()); + + Assert.IsTrue(cu.Children.ElementAt(0) is UsingDeclaration); + Assert.IsFalse(cu.Children.ElementAt(0) is UsingAliasDeclaration); + UsingDeclaration ud = (UsingDeclaration)cu.Children.ElementAt(0); + Assert.AreEqual("global::System", ud.Namespace); + + Assert.IsTrue(cu.Children.ElementAt(1) is UsingAliasDeclaration); + UsingAliasDeclaration uad = (UsingAliasDeclaration)cu.Children.ElementAt(1); + Assert.AreEqual("myAlias", uad.Alias); + Assert.AreEqual("global::My.Name.Space", uad.Import.ToString()); + + Assert.IsTrue(cu.Children.ElementAt(2) is UsingDeclaration); + Assert.IsFalse(cu.Children.ElementAt(2) is UsingAliasDeclaration); + ud = (UsingDeclaration)cu.Children.ElementAt(2); + Assert.AreEqual("a::b.c", ud.Namespace); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs new file mode 100644 index 0000000000..cef1f56529 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs @@ -0,0 +1,109 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; + +using ICSharpCode.NRefactory.PatternMatching; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser +{ + /// + /// Helper methods for parser unit tests. + /// + public static class ParseUtilCSharp + { + public static T ParseGlobal(string code, bool expectErrors = false) where T : AstNode + { + CSharpParser parser = new CSharpParser(); + CompilationUnit cu = parser.Parse(new StringReader(code)); + + Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); + + AstNode node = cu.Children.Single(); + Type type = typeof(T); + Assert.IsTrue(type.IsAssignableFrom(node.GetType()), String.Format("Parsed node was {0} instead of {1} ({2})", node.GetType(), type, node)); + return (T)node; + } + + public static void AssertGlobal(string code, AstNode expectedNode) + { + var node = ParseGlobal(code); + if (!expectedNode.IsMatch(node)) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedNode), ToCSharp(node)); + } + } + + public static T ParseStatement(string stmt, bool expectErrors = false) where T : AstNode + { + CSharpParser parser = new CSharpParser(); + var statements = parser.ParseStatements(new StringReader(stmt)); + + Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); + + AstNode statement = statements.Single(); + Type type = typeof(T); + Assert.IsTrue(type.IsAssignableFrom(statement.GetType()), String.Format("Parsed statement was {0} instead of {1} ({2})", statement.GetType(), type, statement)); + return (T)statement; + } + + public static void AssertStatement(string code, CSharp.Statement expectedStmt) + { + var stmt = ParseStatement(code); + if (!expectedStmt.IsMatch(stmt)) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedStmt), ToCSharp(stmt)); + } + } + + public static T ParseExpression(string expr, bool expectErrors = false) where T : AstNode + { + CSharpParser parser = new CSharpParser(); + AstNode parsedExpression = parser.ParseExpression(new StringReader(expr)); + + Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); + if (expectErrors && parsedExpression == null) + return default (T); + Type type = typeof(T); + Assert.IsTrue(type.IsAssignableFrom(parsedExpression.GetType()), String.Format("Parsed expression was {0} instead of {1} ({2})", parsedExpression.GetType(), type, parsedExpression)); + return (T)parsedExpression; + } + + public static void AssertExpression(string code, CSharp.Expression expectedExpr) + { + var expr = ParseExpression(code); + if (!expectedExpr.IsMatch(expr)) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedExpr), ToCSharp(expr)); + } + } + + public static T ParseTypeMember(string expr, bool expectErrors = false) where T : AttributedNode + { + CSharpParser parser = new CSharpParser(); + var members = parser.ParseTypeMembers(new StringReader(expr)); + + Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); + + AttributedNode m = members.Single(); + Type type = typeof(T); + Assert.IsTrue(type.IsAssignableFrom(m.GetType()), String.Format("Parsed member was {0} instead of {1} ({2})", m.GetType(), type, m)); + return (T)m; + } + + public static void AssertTypeMember(string code, CSharp.AttributedNode expectedMember) + { + var member = ParseTypeMember(code); + if (!expectedMember.IsMatch(member)) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedMember), ToCSharp(member)); + } + } + + static string ToCSharp(AstNode node) + { + StringWriter w = new StringWriter(); + node.AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); + return w.ToString(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs new file mode 100644 index 0000000000..2aaa2c57bf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs @@ -0,0 +1,42 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class BlockStatementTests + { + [Test] + public void BlockStatementTest() + { + BlockStatement blockStmt = ParseUtilCSharp.ParseStatement("{}"); + Assert.AreEqual(0, blockStmt.Statements.Count()); + } + + [Test] + public void ComplexBlockStatementPositionTest() + { + string code = @"{ + WebClient wc = new WebClient(); + wc.Test(); + wc.UploadStringCompleted += delegate { + output.BeginInvoke((MethodInvoker)delegate { + output.Text += newText; + }); + }; +}"; + BlockStatement blockStmt = ParseUtilCSharp.ParseStatement(code); +// start column gets moved by ParseStatement +// Assert.AreEqual(1, blockStmt.StartLocation.Column); + Assert.AreEqual(1, blockStmt.StartLocation.Line); + Assert.AreEqual(2, blockStmt.EndLocation.Column); + Assert.AreEqual(9, blockStmt.EndLocation.Line); + + Assert.AreEqual(3, blockStmt.Statements.Count()); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs new file mode 100644 index 0000000000..15628db47e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs @@ -0,0 +1,45 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class CheckedStatementTests + { + [Test] + public void CheckedStatementTest() + { + CheckedStatement checkedStatement = ParseUtilCSharp.ParseStatement("checked { }"); + Assert.IsFalse(checkedStatement.Body.IsNull); + } + + [Test] + public void CheckedStatementAndExpressionTest() + { + CheckedStatement checkedStatement = ParseUtilCSharp.ParseStatement("checked { checked(++i).ToString(); }"); + ExpressionStatement es = (ExpressionStatement)checkedStatement.Body.Statements.Single(); + CheckedExpression ce = (CheckedExpression)((MemberReferenceExpression)((InvocationExpression)es.Expression).Target).Target; + Assert.IsTrue(ce.Expression is UnaryOperatorExpression); + } + + [Test] + public void UncheckedStatementTest() + { + UncheckedStatement uncheckedStatement = ParseUtilCSharp.ParseStatement("unchecked { }"); + Assert.IsFalse(uncheckedStatement.Body.IsNull); + } + + [Test] + public void UncheckedStatementAndExpressionTest() + { + UncheckedStatement uncheckedStatement = ParseUtilCSharp.ParseStatement("unchecked { unchecked(++i).ToString(); }"); + ExpressionStatement es = (ExpressionStatement)uncheckedStatement.Body.Statements.Single(); + UncheckedExpression ce = (UncheckedExpression)((MemberReferenceExpression)((InvocationExpression)es.Expression).Target).Target; + Assert.IsTrue(ce.Expression is UnaryOperatorExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs new file mode 100644 index 0000000000..b492b21edd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs @@ -0,0 +1,18 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class EmptyStatementTests + { + [Test] + public void EmptyStatementTest() + { + EmptyStatement emptyStmt = ParseUtilCSharp.ParseStatement(";"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs new file mode 100644 index 0000000000..9489deffc0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs @@ -0,0 +1,26 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class ExpressionStatementTests + { + [Test] + public void StatementExpressionTest() + { + ExpressionStatement stmtExprStmt = ParseUtilCSharp.ParseStatement("a = my.Obj.PropCall;"); + Assert.IsTrue(stmtExprStmt.Expression is AssignmentExpression); + } + + [Test] + public void StatementExpressionTest1() + { + ExpressionStatement stmtExprStmt = ParseUtilCSharp.ParseStatement("yield.yield();"); + Assert.IsTrue(stmtExprStmt.Expression is InvocationExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs new file mode 100644 index 0000000000..374bf760b5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class FixedStatementTests + { + [Test] + public void FixedStatementTest() + { + ParseUtilCSharp.AssertStatement( + "fixed (int* ptr = myIntArr) { }", + new FixedStatement { + Type = new PrimitiveType("int").MakePointerType(), + Variables = { + new VariableInitializer { + Name = "ptr", + Initializer = new IdentifierExpression("myIntArr") + } + }, + EmbeddedStatement = new BlockStatement() + }); + } + + [Test] + public void FixedStatementWithMultipleVariables() + { + ParseUtilCSharp.AssertStatement( + "fixed (int* ptr1 = &myIntArr[1], ptr2 = myIntArr) { }", + new FixedStatement { + Type = new PrimitiveType("int").MakePointerType(), + Variables = { + new VariableInitializer { + Name = "ptr1", + Initializer = new UnaryOperatorExpression( + UnaryOperatorType.AddressOf, + new IndexerExpression { Target = new IdentifierExpression("myIntArr"), Arguments = { new PrimitiveExpression(1) } }) + }, + new VariableInitializer { + Name = "ptr2", + Initializer = new IdentifierExpression("myIntArr") + } + }, + EmbeddedStatement = new BlockStatement() + }); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs new file mode 100644 index 0000000000..44232de5a0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs @@ -0,0 +1,67 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class ForStatementTests + { + [Test] + public void ForeachStatementTest() + { + ParseUtilCSharp.AssertStatement( + "foreach (int i in myColl) {} ", + new ForeachStatement { + VariableType = new PrimitiveType("int"), + VariableName = "i", + InExpression = new IdentifierExpression("myColl"), + EmbeddedStatement = new BlockStatement() + }); + } + + [Test] + public void EmptyForStatementTest() + { + ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (;;) ;"); + Assert.AreEqual(0, forStmt.Initializers.Count()); + Assert.AreEqual(0, forStmt.Iterators.Count()); + Assert.IsTrue(forStmt.Condition.IsNull); + Assert.IsTrue(forStmt.EmbeddedStatement is EmptyStatement); + } + + [Test] + public void ForStatementTest() + { + ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (int i = 5; i < 6; ++i) {} "); + var init = (VariableDeclarationStatement)forStmt.Initializers.Single(); + Assert.AreEqual("i", init.Variables.Single().Name); + + Assert.IsTrue(forStmt.Condition is BinaryOperatorExpression); + + var inc = (ExpressionStatement)forStmt.Iterators.Single(); + Assert.IsTrue(inc.Expression is UnaryOperatorExpression); + } + + [Test] + public void ForStatementTestMultipleInitializers() + { + ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (i = 0, j = 1; i < 6; ++i) {} "); + Assert.AreEqual(2, forStmt.Initializers.Count()); + Assert.IsTrue(forStmt.Iterators.All(i => i is ExpressionStatement)); + } + + [Test] + public void ForStatementTestMultipleIterators() + { + ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (int i = 5, j = 10; i < 6; ++i, j--) {} "); + Assert.AreEqual(1, forStmt.Initializers.Count()); + Assert.AreEqual(2, ((VariableDeclarationStatement)forStmt.Initializers.Single()).Variables.Count()); + Assert.AreEqual(2, forStmt.Iterators.Count()); + Assert.IsTrue(forStmt.Iterators.All(i => i is ExpressionStatement)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs new file mode 100644 index 0000000000..f5a882b0b4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs @@ -0,0 +1,45 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class GotoStatementTests + { + [Test] + public void GotoStatementTest() + { + var gotoStmt = ParseUtilCSharp.ParseStatement("goto myLabel;"); + Assert.AreEqual("myLabel", gotoStmt.Label); + } + + [Test] + public void GotoDefaultStatementTest() + { + var gotoCaseStmt = ParseUtilCSharp.ParseStatement("goto default;"); + } + + [Test] + public void GotoCaseStatementTest() + { + var gotoCaseStmt = ParseUtilCSharp.ParseStatement("goto case 6;"); + Assert.IsTrue(gotoCaseStmt.LabelExpression is PrimitiveExpression); + } + + [Test] + public void BreakStatementTest() + { + BreakStatement breakStmt = ParseUtilCSharp.ParseStatement("break;"); + } + + [Test] + public void ContinueStatementTest() + { + ContinueStatement continueStmt = ParseUtilCSharp.ParseStatement("continue;"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs new file mode 100644 index 0000000000..e0daaba5f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class IfElseStatementTests + { + [Test] + public void SimpleIfStatementTest() + { + IfElseStatement ifElseStatement = ParseUtilCSharp.ParseStatement("if (true) { }"); + Assert.IsTrue(ifElseStatement.Condition is PrimitiveExpression); + Assert.IsTrue(ifElseStatement.TrueStatement is BlockStatement); + Assert.IsTrue(ifElseStatement.FalseStatement.IsNull); + } + + [Test] + public void SimpleIfElseStatementTest() + { + IfElseStatement ifElseStatement = ParseUtilCSharp.ParseStatement("if (true) { } else { }"); + Assert.IsTrue(ifElseStatement.Condition is PrimitiveExpression); + Assert.IsTrue(ifElseStatement.TrueStatement is BlockStatement); + Assert.IsTrue(ifElseStatement.FalseStatement is BlockStatement); + } + + [Test] + public void IfElseIfStatementTest() + { + IfElseStatement ifElseStatement = ParseUtilCSharp.ParseStatement("if (1) { } else if (2) { } else if (3) { } else { }"); + Assert.IsTrue(ifElseStatement.Condition is PrimitiveExpression); + Assert.IsTrue(ifElseStatement.TrueStatement is BlockStatement); + Assert.IsTrue(ifElseStatement.FalseStatement is IfElseStatement); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs new file mode 100644 index 0000000000..3ce3339fdf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class LabelStatementTests + { + [Test] + public void LabelStatementTest() + { + BlockStatement block = ParseUtilCSharp.ParseStatement("{ myLabel: ; }"); + LabelStatement labelStmt = (LabelStatement)block.Statements.First(); + Assert.AreEqual("myLabel", labelStmt.Label); + } + + [Test] + public void Label2StatementTest() + { + BlockStatement block = ParseUtilCSharp.ParseStatement("{ yield: ; }"); + LabelStatement labelStmt = (LabelStatement)block.Statements.First(); + Assert.AreEqual("yield", labelStmt.Label); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs new file mode 100644 index 0000000000..a85dc06c97 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs @@ -0,0 +1,19 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class LockStatementTests + { + [Test] + public void LockStatementTest() + { + LockStatement lockStmt = ParseUtilCSharp.ParseStatement("lock (myObj) {}"); + // TODO : Extend test. + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs new file mode 100644 index 0000000000..3747198eea --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs @@ -0,0 +1,33 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class ReturnStatementTests + { + [Test] + public void EmptyReturnStatementTest() + { + ReturnStatement returnStatement = ParseUtilCSharp.ParseStatement("return;"); + Assert.IsTrue(returnStatement.Expression.IsNull); + } + + [Test] + public void ReturnStatementTest() + { + ReturnStatement returnStatement = ParseUtilCSharp.ParseStatement("return 5;"); + Assert.IsTrue(returnStatement.Expression is PrimitiveExpression); + } + + [Test] + public void ReturnStatementTest1() + { + ReturnStatement returnStatement = ParseUtilCSharp.ParseStatement("return yield;"); + Assert.IsTrue(returnStatement.Expression is IdentifierExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs new file mode 100644 index 0000000000..0800ffb613 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs @@ -0,0 +1,20 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class SwitchStatementTests + { + [Test] + public void SwitchStatementTest() + { + SwitchStatement switchStmt = ParseUtilCSharp.ParseStatement("switch (a) { case 4: case 5: break; case 6: break; default: break; }"); + Assert.AreEqual("a", ((IdentifierExpression)switchStmt.Expression).Identifier); + // TODO: Extend test + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs new file mode 100644 index 0000000000..4ec682f00b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs @@ -0,0 +1,26 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class ThrowStatementTests + { + [Test] + public void EmptyThrowStatementTest() + { + ThrowStatement throwStmt = ParseUtilCSharp.ParseStatement("throw;"); + Assert.IsTrue(throwStmt.Expression.IsNull); + } + + [Test] + public void ThrowStatementTest() + { + ThrowStatement throwStmt = ParseUtilCSharp.ParseStatement("throw new Exception();"); + Assert.IsTrue(throwStmt.Expression is ObjectCreateExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs new file mode 100644 index 0000000000..5854bf904d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs @@ -0,0 +1,74 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class TryCatchStatementTests + { + [Test] + public void SimpleTryCatchStatementTest() + { + TryCatchStatement tryCatchStatement = ParseUtilCSharp.ParseStatement("try { } catch { } "); + Assert.IsTrue(tryCatchStatement.FinallyBlock.IsNull); + Assert.AreEqual(1, tryCatchStatement.CatchClauses.Count()); + Assert.IsTrue(tryCatchStatement.CatchClauses.Single().Type.IsNull); + Assert.AreEqual(string.Empty, tryCatchStatement.CatchClauses.Single().VariableName); + } + + [Test] + public void SimpleTryCatchStatementTest2() + { + ParseUtilCSharp.AssertStatement( + "try { } catch (Exception e) { } ", + new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { + new CatchClause { + Type = new SimpleType("Exception"), + VariableName = "e", + Body = new BlockStatement() + } + }}); + } + + [Test] + public void SimpleTryCatchFinallyStatementTest() + { + ParseUtilCSharp.AssertStatement( + "try { } catch (Exception) { } catch { } finally { } ", + new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { + new CatchClause { + Type = new SimpleType("Exception"), + Body = new BlockStatement() + }, + new CatchClause { Body = new BlockStatement() } + }, + FinallyBlock = new BlockStatement() + }); + } + + [Test] + public void TestEmptyFinallyDoesNotMatchNullFinally() + { + TryCatchStatement c1 = new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { new CatchClause { Body = new BlockStatement() } } + }; + TryCatchStatement c2 = new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { new CatchClause { Body = new BlockStatement() } }, + FinallyBlock = new BlockStatement() + }; + Assert.IsFalse(c1.IsMatch(c2)); + Assert.IsFalse(c2.IsMatch(c1)); // and vice versa + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs new file mode 100644 index 0000000000..bdeed271f7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs @@ -0,0 +1,19 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class UnsafeStatementTests + { + [Test] + public void UnsafeStatementTest() + { + UnsafeStatement unsafeStatement = ParseUtilCSharp.ParseStatement("unsafe { }"); + Assert.IsFalse(unsafeStatement.Body.IsNull); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs new file mode 100644 index 0000000000..db377d0782 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs @@ -0,0 +1,31 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class UsingStatementTests + { + [Test, Ignore("Parser doesn't report the VariableDeclarationStatement")] + public void UsingStatementWithVariableDeclaration() + { + UsingStatement usingStmt = ParseUtilCSharp.ParseStatement("using (MyVar var = new MyVar()) { } "); + VariableDeclarationStatement varDecl = (VariableDeclarationStatement)usingStmt.ResourceAcquisition; + Assert.AreEqual("var", varDecl.Variables.Single().Name); + Assert.IsTrue(varDecl.Variables.Single().Initializer is ObjectCreateExpression); + Assert.AreEqual("MyVar", ((SimpleType)varDecl.Type).Identifier); + Assert.IsTrue(usingStmt.EmbeddedStatement is BlockStatement); + } + + public void UsingStatementWithExpression() + { + UsingStatement usingStmt = ParseUtilCSharp.ParseStatement("using (new MyVar()) { } "); + Assert.IsTrue(usingStmt.ResourceAcquisition is ObjectCreateExpression); + Assert.IsTrue(usingStmt.EmbeddedStatement is BlockStatement); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs new file mode 100644 index 0000000000..74564a6bf8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs @@ -0,0 +1,207 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.NRefactory.PatternMatching; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class VariableDeclarationStatementTests + { + [Test] + public void VariableDeclarationStatementTest() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("int a = 5;"); + Assert.AreEqual(1, lvd.Variables.Count()); + Assert.AreEqual("a", lvd.Variables.First ().Name); + var type = lvd.Type; + Assert.AreEqual("int", type.ToString ()); + Assert.AreEqual(5, ((PrimitiveExpression)lvd.Variables.First ().Initializer).Value); + } + + [Test] + public void VoidPointerVariableDeclarationTest() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("void *a;"); + Assert.IsTrue(new VariableDeclarationStatement(new PrimitiveType("void").MakePointerType(), "a").IsMatch(lvd)); + } + + [Test] + public void ComplexGenericVariableDeclarationStatementTest() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("Generic > where = new Generic>();"); + AstType type = new SimpleType("Generic") { + TypeArguments = { + new MemberType { Target = new SimpleType("Namespace"), MemberName = "Printable" }, + new SimpleType("G") { TypeArguments = { new SimpleType("Printable").MakeArrayType() } } + }}; + Assert.IsTrue(new VariableDeclarationStatement(type, "where", new ObjectCreateExpression { Type = type.Clone() }).IsMatch(lvd)); + } + + [Test] + public void NestedGenericVariableDeclarationStatementTest() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("MyType.InnerClass.InnerInnerClass a;"); + AstType type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyType") { TypeArguments = { new PrimitiveType("string") } }, + MemberName = "InnerClass", + TypeArguments = { new PrimitiveType("int") } + }, + MemberName = "InnerInnerClass" + }; + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void GenericWithArrayVariableDeclarationStatementTest1() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("G[] a;"); + AstType type = new SimpleType("G") { + TypeArguments = { new PrimitiveType("int") } + }.MakeArrayType(); + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void GenericWithArrayVariableDeclarationStatementTest2() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("G a;"); + AstType type = new SimpleType("G") { + TypeArguments = { new PrimitiveType("int").MakeArrayType() } + }; + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void GenericVariableDeclarationStatementTest2() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("G > a;"); + AstType type = new SimpleType("G") { + TypeArguments = { + new SimpleType("G") { TypeArguments = { new PrimitiveType("int") } } + } + }; + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void GenericVariableDeclarationStatementTest2WithoutSpace() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("G> a;"); + AstType type = new SimpleType("G") { + TypeArguments = { + new SimpleType("G") { TypeArguments = { new PrimitiveType("int") } } + } + }; + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void GenericVariableDeclarationStatementTest() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("G a;"); + AstType type = new SimpleType("G") { + TypeArguments = { new PrimitiveType("int") } + }; + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void SimpleVariableDeclarationStatementTest() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("MyVar var = new MyVar();"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("MyVar"), "var", new ObjectCreateExpression { Type = new SimpleType("MyVar") }).IsMatch(lvd)); + } + + [Test] + public void SimpleVariableDeclarationStatementTest1() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("yield yield = new yield();"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("yield"), "yield", new ObjectCreateExpression { Type = new SimpleType("yield") }).IsMatch(lvd)); + } + + [Test] + public void NullableVariableDeclarationStatementTest1() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("int? a;"); + Assert.IsTrue(new VariableDeclarationStatement(new PrimitiveType("int").MakeNullableType(), "a").IsMatch(lvd)); + } + + [Test] + public void NullableVariableDeclarationStatementTest2() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime? a;"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakeNullableType(), "a").IsMatch(lvd)); + } + + [Test, Ignore("The parser creates nested ComposedTypes while MakeArrayType() adds the specifier to the existing ComposedType")] + public void NullableVariableDeclarationStatementTest3() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime?[] a;"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakeNullableType().MakeArrayType(), "a").IsMatch(lvd)); + } + + [Test] + public void NullableVariableDeclarationStatementTest4() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("SomeStruct? a;"); + AstType type = new SimpleType("SomeStruct") { + TypeArguments = { new PrimitiveType("int").MakeNullableType() } + }.MakeNullableType(); + Assert.IsTrue(new VariableDeclarationStatement(type, "a").IsMatch(lvd)); + } + + [Test] + public void PositionTestWithoutModifier() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("\ndouble w = 7;"); + Assert.AreEqual(2, lvd.StartLocation.Line); + Assert.AreEqual(1, lvd.StartLocation.Column); + Assert.AreEqual(2, lvd.EndLocation.Line); + Assert.AreEqual(14, lvd.EndLocation.Column); + } + + [Test] + public void PositionTestWithModifier() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("\nconst double w = 7;"); + Assert.AreEqual(Modifiers.Const, lvd.Modifiers); + Assert.AreEqual(2, lvd.StartLocation.Line); + Assert.AreEqual(1, lvd.StartLocation.Column); + Assert.AreEqual(2, lvd.EndLocation.Line); + Assert.AreEqual(20, lvd.EndLocation.Column); + } + + [Test, Ignore("Nested arrays are broken in the parser")] + public void NestedArray() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime[,][] a;"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakeArrayType(1).MakeArrayType(2), "a").IsMatch(lvd)); + } + + [Test, Ignore("Nested pointers are broken in the parser")] + public void NestedPointers() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime*** a;"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakePointerType().MakePointerType().MakePointerType(), "a").IsMatch(lvd)); + } + + [Test, Ignore("The parser creates nested ComposedTypes while MakeArrayType() adds the specifier to the existing ComposedType")] + public void ArrayOfPointers() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime*[] a;"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakePointerType().MakeArrayType(), "a").IsMatch(lvd)); + } + + [Test, Ignore("The parser creates nested ComposedTypes while MakeArrayType() adds the specifier to the existing ComposedType")] + public void ArrayOfNullables() + { + VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime?[] a;"); + Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakeNullableType().MakeArrayType(), "a").IsMatch(lvd)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs new file mode 100644 index 0000000000..689eb05845 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs @@ -0,0 +1,28 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class WhileStatementTests + { + [Test] + public void WhileStatementTest() + { + WhileStatement loopStmt = ParseUtilCSharp.ParseStatement("while (true) { }"); + Assert.IsTrue(loopStmt.Condition is PrimitiveExpression); + Assert.IsTrue(loopStmt.EmbeddedStatement is BlockStatement); + } + + [Test] + public void DoWhileStatementTest() + { + DoWhileStatement loopStmt = ParseUtilCSharp.ParseStatement("do { } while (true);"); + Assert.IsTrue(loopStmt.Condition is PrimitiveExpression); + Assert.IsTrue(loopStmt.EmbeddedStatement is BlockStatement); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs new file mode 100644 index 0000000000..ae4d75d933 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs @@ -0,0 +1,40 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Statements +{ + [TestFixture] + public class YieldStatementTests + { + [Test] + public void YieldReturnStatementTest() + { + YieldStatement yieldStmt = ParseUtilCSharp.ParseStatement("yield return \"Foo\";"); + PrimitiveExpression expr = (PrimitiveExpression)yieldStmt.Expression; + Assert.AreEqual("Foo", expr.Value); + } + + [Test] + public void YieldBreakStatementTest() + { + ParseUtilCSharp.ParseStatement("yield break;"); + } + + [Test] + public void YieldAsVariableTest() + { + ExpressionStatement se = ParseUtilCSharp.ParseStatement("yield = 3;"); + AssignmentExpression ae = se.Expression as AssignmentExpression; + + Assert.AreEqual(AssignmentOperatorType.Assign, ae.Operator); + + Assert.IsTrue(ae.Left is IdentifierExpression); + Assert.AreEqual("yield", ((IdentifierExpression)ae.Left).Identifier); + Assert.IsTrue(ae.Right is PrimitiveExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs new file mode 100644 index 0000000000..3d3124a39e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class ConstructorDeclarationTests + { + [Test] + public void ConstructorDeclarationTest1() + { + ConstructorDeclaration cd = ParseUtilCSharp.ParseTypeMember("MyClass() {}"); + Assert.IsTrue(cd.Initializer.IsNull); + } + + [Test] + public void ConstructorDeclarationTest2() + { + ConstructorDeclaration cd = ParseUtilCSharp.ParseTypeMember("MyClass() : this(5) {}"); + Assert.AreEqual(ConstructorInitializerType.This, cd.Initializer.ConstructorInitializerType); + Assert.AreEqual(1, cd.Initializer.Arguments.Count()); + } + + [Test] + public void ConstructorDeclarationTest3() + { + ConstructorDeclaration cd = ParseUtilCSharp.ParseTypeMember("MyClass() : base(1, 2, 3) {}"); + Assert.AreEqual(ConstructorInitializerType.Base, cd.Initializer.ConstructorInitializerType); + Assert.AreEqual(3, cd.Initializer.Arguments.Count()); + } + + [Test] + public void StaticConstructorDeclarationTest1() + { + ConstructorDeclaration cd = ParseUtilCSharp.ParseTypeMember("static MyClass() {}"); + Assert.IsTrue(cd.Initializer.IsNull); + Assert.AreEqual(Modifiers.Static, cd.Modifiers); + } + + [Test] + public void ExternStaticConstructorDeclarationTest() + { + ConstructorDeclaration cd = ParseUtilCSharp.ParseTypeMember("extern static MyClass();"); + Assert.IsTrue(cd.Initializer.IsNull); + Assert.AreEqual(Modifiers.Static | Modifiers.Extern, cd.Modifiers); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs new file mode 100644 index 0000000000..25ba714f74 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs @@ -0,0 +1,32 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class DestructorDeclarationTests + { + [Test] + public void DestructorDeclarationTest() + { + DestructorDeclaration dd = ParseUtilCSharp.ParseTypeMember("~MyClass() {}"); + } + + [Test] + public void ExternDestructorDeclarationTest() + { + DestructorDeclaration dd = ParseUtilCSharp.ParseTypeMember("extern ~MyClass();"); + Assert.AreEqual(Modifiers.Extern, dd.Modifiers); + } + + [Test] + public void UnsafeDestructorDeclarationTest() + { + DestructorDeclaration dd = ParseUtilCSharp.ParseTypeMember("unsafe ~MyClass() {}"); + Assert.AreEqual(Modifiers.Unsafe, dd.Modifiers); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs new file mode 100644 index 0000000000..35c98a4a19 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class EventDeclarationTests + { + [Test] + public void SimpleEventDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "event EventHandler MyEvent;", + new EventDeclaration { + ReturnType = new SimpleType("EventHandler"), + Variables = { + new VariableInitializer { + Name = "MyEvent" + } + }}); + } + + [Test] + public void MultipleEventDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "public event EventHandler A = null, B = delegate {};", + new EventDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new SimpleType("EventHandler"), + Variables = { + new VariableInitializer { + Name = "A", + Initializer = new NullReferenceExpression() + }, + new VariableInitializer { + Name = "B", + Initializer = new AnonymousMethodExpression() { Body = new BlockStatement ()} + } + }}); + } + + [Test] + public void AddRemoveEventDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "public event System.EventHandler MyEvent { add { } remove { } }", + new CustomEventDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new MemberType { + Target = new SimpleType("System"), + MemberName = "EventHandler" + }, + Name = "MyEvent", + AddAccessor = new Accessor { Body = new BlockStatement() }, + RemoveAccessor = new Accessor { Body = new BlockStatement() } + }); + } + + [Test] + public void EventImplementingGenericInterfaceDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "event EventHandler MyInterface.MyEvent { add { } [Attr] remove {} }", + new CustomEventDeclaration { + ReturnType = new SimpleType("EventHandler"), + PrivateImplementationType = new SimpleType{ + Identifier = "MyInterface", + TypeArguments = { new PrimitiveType("string") } + }, + Name = "MyEvent", + AddAccessor = new Accessor { Body = new BlockStatement() }, + RemoveAccessor = new Accessor { + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { Type = new SimpleType("Attr") } + } + } + }, + Body = new BlockStatement() + } + }); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs new file mode 100644 index 0000000000..1ed04478b4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs @@ -0,0 +1,76 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class FieldDeclarationTests + { + [Test] + public void SimpleFieldDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "int[,,,] myField;", + new FieldDeclaration { + ReturnType = new PrimitiveType("int").MakeArrayType(4), + Variables = { new VariableInitializer("myField") } + }); + } + + [Test] + public void MultipleFieldDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "int a = 1, b = 2;", + new FieldDeclaration { + ReturnType = new PrimitiveType("int"), + Variables = { + new VariableInitializer("a", new PrimitiveExpression(1)), + new VariableInitializer("b", new PrimitiveExpression(2)), + } + }); + } + + [Test] + public void FieldWithArrayInitializer() + { + ParseUtilCSharp.AssertTypeMember( + "public static readonly int[] arr = { 1, 2, 3 };", + new FieldDeclaration { + Modifiers = Modifiers.Public | Modifiers.Static | Modifiers.Readonly, + ReturnType = new PrimitiveType("int").MakeArrayType(), + Variables = { + new VariableInitializer { + Name = "arr", + Initializer = new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(2), + new PrimitiveExpression(3) + } + } + } + }}); + } + + [Test] + public void FieldWithFixedSize() + { + ParseUtilCSharp.AssertTypeMember( + "public unsafe fixed int Field[100];", + new FixedFieldDeclaration() { + Modifiers = Modifiers.Public | Modifiers.Unsafe, + ReturnType = new PrimitiveType("int"), + Variables = { + new FixedVariableInitializer { + Name = "Field", + CountExpression = new PrimitiveExpression(100) + } + } + }); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs new file mode 100644 index 0000000000..a324c51b1f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class IndexerDeclarationTests + { + [Test] + public void IndexerDeclarationTest() + { + IndexerDeclaration id = ParseUtilCSharp.ParseTypeMember("public int this[int a, string b] { get { } protected set { } }"); + Assert.AreEqual(2, id.Parameters.Count()); + Assert.IsNotNull(id.Getter, "No get region found!"); + Assert.IsNotNull(id.Setter, "No set region found!"); + Assert.AreEqual(Modifiers.Public, id.Modifiers); + Assert.AreEqual(Modifiers.None, id.Getter.Modifiers); + Assert.AreEqual(Modifiers.Protected, id.Setter.Modifiers); + } + + [Test] + public void IndexerImplementingInterfaceTest() + { + IndexerDeclaration id = ParseUtilCSharp.ParseTypeMember("int MyInterface.this[int a, string b] { get { } set { } }"); + Assert.AreEqual(2, id.Parameters.Count()); + Assert.IsNotNull(id.Getter, "No get region found!"); + Assert.IsNotNull(id.Setter, "No set region found!"); + + Assert.AreEqual("MyInterface", ((SimpleType)id.PrivateImplementationType).Identifier); + } + + [Test] + public void IndexerImplementingGenericInterfaceTest() + { + ParseUtilCSharp.AssertTypeMember( + "int MyInterface.this[int a, string b] { get { } [Attr] set { } }", + new IndexerDeclaration { + ReturnType = new PrimitiveType("int"), + PrivateImplementationType = new SimpleType { + Identifier = "MyInterface", + TypeArguments = { new PrimitiveType("string") } + }, + Parameters = { + new ParameterDeclaration(new PrimitiveType("int"), "a"), + new ParameterDeclaration(new PrimitiveType("string"), "b") + }, + Getter = new Accessor { Body = new BlockStatement() }, + Setter = new Accessor { + Attributes = { new AttributeSection(new Attribute { Type = new SimpleType("Attr") }) }, + Body = new BlockStatement() + }}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs new file mode 100644 index 0000000000..c0a8ab3c3f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs @@ -0,0 +1,344 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class MethodDeclarationTests + { + [Test] + public void SimpleMethodDeclarationTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyMethod() {} "); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); + Assert.AreEqual(0, md.Parameters.Count()); + Assert.IsFalse(md.IsExtensionMethod); + } + + [Test] + public void AbstractMethodDeclarationTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("abstract void MyMethod();"); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); + Assert.AreEqual(0, md.Parameters.Count()); + Assert.IsFalse(md.IsExtensionMethod); + Assert.IsTrue(md.Body.IsNull); + Assert.AreEqual(Modifiers.Abstract, md.Modifiers); + } + + [Test] + public void DefiningPartialMethodDeclarationTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("partial void MyMethod();"); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); + Assert.AreEqual(0, md.Parameters.Count()); + Assert.IsFalse(md.IsExtensionMethod); + Assert.IsTrue(md.Body.IsNull); + Assert.AreEqual(Modifiers.Partial, md.Modifiers); + } + + [Test] + public void ImplementingPartialMethodDeclarationTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("partial void MyMethod() { }"); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); + Assert.AreEqual(0, md.Parameters.Count()); + Assert.IsFalse(md.IsExtensionMethod); + Assert.IsFalse(md.Body.IsNull); + Assert.AreEqual(Modifiers.Partial, md.Modifiers); + } + + [Test] + public void SimpleMethodRegionTest() + { + const string program = @" + void MyMethod() + { + OtherMethod(); + } +"; + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember(program); + Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y"); + Assert.AreEqual(5, md.EndLocation.Line, "EndLocation.Y"); + Assert.AreEqual(3, md.StartLocation.Column, "StartLocation.X"); + Assert.AreEqual(4, md.EndLocation.Column, "EndLocation.X"); + } + + [Test] + public void MethodWithModifiersRegionTest() + { + const string program = @" + public static void MyMethod() + { + OtherMethod(); + } +"; + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember(program); + Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y"); + Assert.AreEqual(5, md.EndLocation.Line, "EndLocation.Y"); + Assert.AreEqual(3, md.StartLocation.Column, "StartLocation.X"); + Assert.AreEqual(4, md.EndLocation.Column, "EndLocation.X"); + } + + [Test] + public void MethodWithUnnamedParameterDeclarationTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyMethod(int) {} ", true); + Assert.AreEqual("void", md.ReturnType.ToString ()); + Assert.AreEqual(1, md.Parameters.Count()); + Assert.AreEqual("int", ((PrimitiveType)md.Parameters.Single().Type).Keyword); + } + + [Test] + public void GenericVoidMethodDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "void MyMethod(T a) {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Body = new BlockStatement() + }); + } + + [Test] + public void GenericMethodDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "T MyMethod(T a) {} ", + new MethodDeclaration { + ReturnType = new SimpleType("T"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Body = new BlockStatement() + }); + } + + [Test] + public void GenericMethodDeclarationWithConstraintTest() + { + ParseUtilCSharp.AssertTypeMember( + "T MyMethod(T a) where T : ISomeInterface {} ", + new MethodDeclaration { + ReturnType = new SimpleType("T"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ISomeInterface") } + } + }, + Body = new BlockStatement() + }); + } + + [Test] + public void GenericMethodInInterface() + { + ParseUtilCSharp.AssertGlobal( + @"interface MyInterface { + T MyMethod(T a) where T : ISomeInterface; +} +", + new TypeDeclaration { + ClassType = ClassType.Interface, + Members = { + new MethodDeclaration { + ReturnType = new SimpleType("T"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ISomeInterface") } + } + } + }}}); + } + + [Test] + public void GenericVoidMethodInInterface() + { + ParseUtilCSharp.AssertGlobal( + @"interface MyInterface { + void MyMethod(T a) where T : ISomeInterface; +} +", + new TypeDeclaration { + ClassType = ClassType.Interface, + Members = { + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ISomeInterface") } + } + } + }}}); + } + + [Test] + public void ShadowingMethodInInterface() + { + ParseUtilCSharp.AssertGlobal( + @"interface MyInterface : IDisposable { + new void Dispose(); +} +", + new TypeDeclaration { + ClassType = ClassType.Interface, + Name = "MyInterface", + BaseTypes = { new SimpleType("IDisposable") }, + Members = { + new MethodDeclaration { + Modifiers = Modifiers.New, + ReturnType = new PrimitiveType("void"), + Name = "Dispose" + }}}); + } + + [Test] + public void MethodImplementingInterfaceTest() + { + ParseUtilCSharp.AssertTypeMember( + "int MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("int"), + PrivateImplementationType = new SimpleType("MyInterface"), + Name = "MyMethod", + Body = new BlockStatement() + }); + } + + [Test] + public void MethodImplementingGenericInterfaceTest() + { + ParseUtilCSharp.AssertTypeMember( + "int MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("int"), + PrivateImplementationType = new SimpleType("MyInterface") { TypeArguments = { new PrimitiveType("string") } }, + Name = "MyMethod", + Body = new BlockStatement() + }); + } + + [Test] + public void VoidMethodImplementingInterfaceTest() + { + ParseUtilCSharp.AssertTypeMember ( + "void MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + PrivateImplementationType = new SimpleType("MyInterface"), + Name = "MyMethod", + Body = new BlockStatement() + }); + } + + [Test] + public void VoidMethodImplementingGenericInterfaceTest() + { + ParseUtilCSharp.AssertTypeMember ( + "void MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + PrivateImplementationType = new SimpleType("MyInterface") { TypeArguments = { new PrimitiveType("string") } }, + Name = "MyMethod", + Body = new BlockStatement() + }); + } + + [Test] + public void IncompleteConstraintsTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember( + "void a() where T { }", true // expect errors + ); + Assert.AreEqual("a", md.Name); + Assert.AreEqual(1, md.TypeParameters.Count); + Assert.AreEqual("T", md.TypeParameters.Single().Name); + Assert.AreEqual(0, md.Constraints.Count()); + } + + [Test] + public void ExtensionMethodTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember( + "public static int ToInt32(this string s) { return int.Parse(s); }" + ); + Assert.AreEqual("ToInt32", md.Name); + Assert.AreEqual("s", md.Parameters.First().Name); + Assert.AreEqual(ParameterModifier.This, md.Parameters.First().ParameterModifier); + Assert.AreEqual("string", ((PrimitiveType)md.Parameters.First().Type).Keyword); + Assert.IsTrue(md.IsExtensionMethod); + } + + [Test] + public void VoidExtensionMethodTest() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember( + "public static void Print(this string s) { Console.WriteLine(s); }" + ); + Assert.AreEqual("Print", md.Name); + Assert.AreEqual("s", md.Parameters.First().Name); + Assert.AreEqual(ParameterModifier.This, md.Parameters.First().ParameterModifier); + Assert.AreEqual("string", ((PrimitiveType)md.Parameters.First().Type).Keyword); + Assert.IsTrue(md.IsExtensionMethod); + } + + [Test] + public void MethodWithEmptyAssignmentErrorInBody() + { + MethodDeclaration md = ParseUtilCSharp.ParseTypeMember( + "void A ()\n" + + "{\n" + + "int a = 3;\n" + + " = 4;\n" + + "}", true // expect errors + ); + Assert.AreEqual("A", md.Name); + Assert.AreEqual(new AstLocation(2, 1), md.Body.StartLocation); + Assert.AreEqual(new AstLocation(5, 2), md.Body.EndLocation); + } + + [Test] + public void OptionalParameterTest() + { + ParseUtilCSharp.AssertTypeMember( + "public void Foo(string bar = null, int baz = 0) { }", + new MethodDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new PrimitiveType("void"), + Name = "Foo", + Body = new BlockStatement(), + Parameters = { + new ParameterDeclaration { + Type = new PrimitiveType("string"), + Name = "bar", + DefaultExpression = new NullReferenceExpression() + }, + new ParameterDeclaration { + Type = new PrimitiveType("int"), + Name = "baz", + DefaultExpression = new PrimitiveExpression(0) + } + }}); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs new file mode 100644 index 0000000000..4956d374aa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs @@ -0,0 +1,53 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class OperatorDeclarationTests + { + [Test] + public void ImplictOperatorDeclarationTest() + { + OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static implicit operator double(MyObject f) { return 0.5d; }"); + Assert.AreEqual(OperatorType.Implicit, od.OperatorType); + Assert.AreEqual(1, od.Parameters.Count()); + Assert.AreEqual("double", ((PrimitiveType)od.ReturnType).Keyword); + Assert.AreEqual("op_Implicit", od.Name); + } + + [Test] + public void ExplicitOperatorDeclarationTest() + { + OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static explicit operator double(MyObject f) { return 0.5d; }"); + Assert.AreEqual(OperatorType.Explicit, od.OperatorType); + Assert.AreEqual(1, od.Parameters.Count()); + Assert.AreEqual("double", ((PrimitiveType)od.ReturnType).Keyword); + Assert.AreEqual("op_Explicit", od.Name); + } + + [Test] + public void BinaryPlusOperatorDeclarationTest() + { + OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static MyObject operator +(MyObject a, MyObject b) {}"); + Assert.AreEqual(OperatorType.Addition, od.OperatorType); + Assert.AreEqual(2, od.Parameters.Count()); + Assert.AreEqual("MyObject", ((SimpleType)od.ReturnType).Identifier); + Assert.AreEqual("op_Addition", od.Name); + } + + [Test] + public void UnaryPlusOperatorDeclarationTest() + { + OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static MyObject operator +(MyObject a) {}"); + Assert.AreEqual(OperatorType.UnaryPlus, od.OperatorType); + Assert.AreEqual(1, od.Parameters.Count()); + Assert.AreEqual("MyObject", ((SimpleType)od.ReturnType).Identifier); + Assert.AreEqual("op_UnaryPlus", od.Name); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs new file mode 100644 index 0000000000..a9d0711d4d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs @@ -0,0 +1,92 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; +using NUnit.Framework; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers +{ + [TestFixture] + public class PropertyDeclarationTests + { + [Test] + public void SimpleGetSetPropertyDeclarationTest() + { + PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyProperty { get {} set {} } "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.Getter.IsNull); + Assert.IsFalse(pd.Setter.IsNull); + } + + [Test] + public void GetSetPropertyDeclarationWithAccessorModifiers() + { + PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyProperty { private get {} protected internal set {} } "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.Getter.IsNull); + Assert.IsFalse(pd.Setter.IsNull); + } + + [Test] + public void SimpleGetPropertyDeclarationTest() + { + PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyProperty { get {} } "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.Getter.IsNull); + Assert.IsTrue(pd.Setter.IsNull); + } + + [Test] + public void SimpleSetPropertyDeclarationTest() + { + PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyProperty { set {} } "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsTrue(pd.Getter.IsNull); + Assert.IsFalse(pd.Setter.IsNull); + } + + [Test] + public void PropertyRegionTest() + { + const string code = "class T {\n\tint Prop {\n\t\tget { return f; }\n\t\tset { f = value; }\n\t}\n}\n"; + int line2Pos = code.IndexOf("\tint Prop"); + int line3Pos = code.IndexOf("\t\tget"); + int line4Pos = code.IndexOf("\t\tset"); + + CSharpParser parser = new CSharpParser(); + CompilationUnit cu = parser.Parse(new StringReader(code)); + PropertyDeclaration pd = (PropertyDeclaration)cu.Children.Single().GetChildByRole(TypeDeclaration.MemberRole); + Assert.AreEqual(new AstLocation(2, code.IndexOf("{\n\t\tget") - line2Pos + 1), pd.GetChildByRole(AstNode.Roles.LBrace).StartLocation); + Assert.AreEqual(new AstLocation(5, 3), pd.EndLocation); + Assert.AreEqual(new AstLocation(3, code.IndexOf("{ return") - line3Pos + 1), pd.Getter.Body.StartLocation); + Assert.AreEqual(new AstLocation(3, code.IndexOf("}\n\t\tset") + 1 - line3Pos + 1), pd.Getter.Body.EndLocation); + Assert.AreEqual(new AstLocation(4, code.IndexOf("{ f =") - line4Pos + 1), pd.Setter.Body.StartLocation); + Assert.AreEqual(new AstLocation(4, code.IndexOf("}\n\t}") + 1 - line4Pos + 1), pd.Setter.Body.EndLocation); + } + + [Test] + public void PropertyImplementingInterfaceTest() + { + PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyInterface.MyProperty { get {} } "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.Getter.IsNull); + Assert.IsTrue(pd.Setter.IsNull); + + Assert.AreEqual("MyInterface", ((SimpleType)pd.PrivateImplementationType).Identifier); + } + + [Test] + public void PropertyImplementingGenericInterfaceTest() + { + PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyInterface.MyProperty { get {} } "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.Getter.IsNull); + Assert.IsTrue(pd.Setter.IsNull); + + Assert.IsTrue(new SimpleType { Identifier = "MyInterface", TypeArguments = { new PrimitiveType("string") } }.IsMatch(pd.PrivateImplementationType)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs new file mode 100644 index 0000000000..9606e32471 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + + +using System; +using System.IO; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser +{ + [TestFixture] + public class TypeSystemConvertVisitorTests : TypeSystemTests + { + ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; + + [TestFixtureSetUp] + public void FixtureSetUp() + { + const string fileName = "TypeSystemTests.TestCase.cs"; + + CSharpParser parser = new CSharpParser(); + CompilationUnit cu; + using (Stream s = typeof(TypeSystemTests).Assembly.GetManifestResourceStream(typeof(TypeSystemTests), fileName)) { + cu = parser.Parse(s); + } + + testCasePC = new SimpleProjectContent(); + TypeSystemConvertVisitor visitor = new TypeSystemConvertVisitor(testCasePC, fileName); + cu.AcceptVisitor(visitor, null); + ParsedFile parsedFile = visitor.ParsedFile; + ((SimpleProjectContent)testCasePC).UpdateProjectContent(null, parsedFile); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreationTests.cs new file mode 100644 index 0000000000..335b42e7c5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreationTests.cs @@ -0,0 +1,63 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + [Ignore("Parser produces incorrect positions")] + public class ArrayCreationTests : ResolverTestBase + { + [Test] + public void SimpleArrayCreation() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new int[] { 42 }$; + } +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int32[]", result.Type.ReflectionName); + } + + [Test] + public void NestedArrayCreation() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new int[2][,][,,]$; + } +} +"; + var result = Resolve(program); + // a one-dimensional array of two-dimensional arrays of three-dimensional arrays + ArrayType a1 = (ArrayType)result.Type; + Assert.AreEqual(1, a1.Dimensions); + ArrayType a2 = (ArrayType)a1.ElementType; + Assert.AreEqual(2, a2.Dimensions); + ArrayType a3 = (ArrayType)a2.ElementType; + Assert.AreEqual(3, a3.Dimensions); + Assert.AreEqual("System.Int32", a3.ElementType.ReflectionName); + } + + [Test] + public void InferredType() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new [] { 1, 1L }$; + } +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int64[]", result.Type.ReflectionName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs new file mode 100644 index 0000000000..bca4362542 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs @@ -0,0 +1,96 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class AttributeTests : ResolverTestBase + { + [Test] + public void NamespaceInAttributeContext() + { + string program = "using System; [$System.Runtime$.CompilerServices.IndexerName(\"bla\")] class Test { }"; + NamespaceResolveResult result = Resolve(program); + Assert.AreEqual("System.Runtime", result.NamespaceName); + } + + [Test] + public void AttributeWithShortName() + { + string program = "using System; [$Obsolete$] class Test {}"; + + TypeResolveResult result = Resolve(program); + Assert.AreEqual("System.ObsoleteAttribute", result.Type.FullName); + } + + [Test] + public void QualifiedAttributeWithShortName() + { + string program = "using System; [$System.Obsolete$] class Test {}"; + + TypeResolveResult result = Resolve(program); + Assert.AreEqual("System.ObsoleteAttribute", result.Type.FullName); + } + + [Test] + public void AttributeConstructor1() + { + string program = "using System; [$LoaderOptimization(3)$] class Test { }"; + var mrr = Resolve(program); + Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); + Assert.AreEqual("System.Byte", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName); + } + + [Test] + public void AttributeConstructor2() + { + string program = "using System; [$LoaderOptimization(LoaderOptimization.NotSpecified)$] class Test { }"; + var mrr = Resolve(program); + Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); + Assert.AreEqual("System.LoaderOptimization", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName); + } + + [Test] + public void AttributeArgumentInClassContext1() + { + string program = @"using System; +[AttributeUsage($XXX$)] class MyAttribute : Attribute { + public const AttributeTargets XXX = AttributeTargets.All; +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("MyAttribute.XXX", result.Member.FullName); + } + + [Test] + public void AttributeArgumentInClassContext2() + { + string program = @"using System; namespace MyNamespace { +[SomeAttribute($E.A$)] class Test { } +enum E { A, B } +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("MyNamespace.E.A", result.Member.FullName); + } + + [Test, Ignore("Not implemented in type system.")] + public void SD_1384() + { + string program = @"using System; +class Flags { + [Flags] + enum $Test$ { } +}"; + TypeResolveResult result = Resolve(program); + Assert.AreEqual("Flags.Test", result.Type.FullName); + + var rt = result.Type.GetDefinition().Attributes[0].AttributeType.Resolve(context); + Assert.AreEqual("System.FlagsAttribute", rt.FullName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs new file mode 100644 index 0000000000..250c2619e4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs @@ -0,0 +1,449 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + // assign short name to the fake reflection type + using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; + + [TestFixture] + public unsafe class BinaryOperatorTests : ResolverTestBase + { + [Test] + public void Multiplication() + { + AssertType(typeof(int), resolver.ResolveBinaryOperator( + BinaryOperatorType.Multiply, MakeResult(typeof(int)), MakeResult(typeof(int)))); + + AssertType(typeof(float), resolver.ResolveBinaryOperator( + BinaryOperatorType.Multiply, MakeResult(typeof(int)), MakeConstant(0.0f))); + + AssertConstant(3.0f, resolver.ResolveBinaryOperator( + BinaryOperatorType.Multiply, MakeConstant(1.5f), MakeConstant(2))); + + AssertConstant(6, resolver.ResolveBinaryOperator( + BinaryOperatorType.Multiply, MakeConstant((byte)2), MakeConstant((byte)3))); + + AssertType(typeof(long?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Multiply, MakeResult(typeof(uint?)), MakeResult(typeof(int?)))); + + AssertError(typeof(decimal), resolver.ResolveBinaryOperator( + BinaryOperatorType.Multiply, MakeResult(typeof(float)), MakeResult(typeof(decimal)))); + } + + [Test] + public void Addition() + { + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(short)), MakeResult(typeof(byte?)))); + + AssertConstant(3.0, resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(1.0f), MakeConstant(2.0))); + + AssertConstant(StringComparison.Ordinal, resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(StringComparison.InvariantCulture), MakeConstant(2))); + + AssertConstant(StringComparison.OrdinalIgnoreCase, resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant((short)3), MakeConstant(StringComparison.InvariantCulture))); + + AssertConstant("Text", resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant("Te"), MakeConstant("xt"))); + + AssertConstant("", resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(null), resolver.ResolveCast(ResolveType(typeof(string)), MakeConstant(null)))); + + AssertError(typeof(ReflectionHelper.Null), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(null), MakeConstant(null))); + + AssertType(typeof(Action), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + + AssertType(typeof(Action), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action))).IsError); + + AssertType(typeof(StringComparison?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(StringComparison?)), MakeResult(typeof(int)))); + + AssertType(typeof(StringComparison?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(int?)), MakeResult(typeof(StringComparison)))); + + AssertType(typeof(long?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(int?)), MakeResult(typeof(uint?)))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(ushort?)), MakeResult(typeof(ushort?)))); + + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(null), MakeConstant(null)).IsError); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(1), MakeConstant(null))); + + AssertType(typeof(int*), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(int*)), MakeConstant(1))); + + AssertType(typeof(byte*), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(long)), MakeResult(typeof(byte*)))); + } + + [Test] + public void AdditionWithOverflow() + { + resolver.CheckForOverflow = false; + AssertConstant(int.MinValue, resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(int.MaxValue), MakeConstant(1))); + + resolver.CheckForOverflow = true; + AssertError(typeof(int), resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(int.MaxValue), MakeConstant(1))); + } + + + [Test] + public void Subtraction() + { + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(short)), MakeResult(typeof(byte?)))); + + AssertConstant(-1.0, resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeConstant(1.0f), MakeConstant(2.0))); + + AssertConstant(StringComparison.InvariantCulture, resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeConstant(StringComparison.Ordinal), MakeConstant(2))); + + AssertConstant(3, resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeConstant(StringComparison.OrdinalIgnoreCase), MakeConstant(StringComparison.InvariantCulture))); + + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeConstant("Te"), MakeConstant("xt")).IsError); + + AssertType(typeof(Action), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + + AssertType(typeof(Action), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(Action)), MakeResult(typeof(Action))).IsError); + + AssertType(typeof(StringComparison?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(StringComparison?)), MakeResult(typeof(int)))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(StringComparison?)), MakeResult(typeof(StringComparison)))); + + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(int?)), MakeResult(typeof(StringComparison))).IsError); + + AssertType(typeof(byte*), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(byte*)), MakeResult(typeof(uint)))); + + AssertType(typeof(long), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(byte*)), MakeResult(typeof(byte*)))); + } + + [Test] + public void ShiftTest() + { + AssertConstant(6, resolver.ResolveBinaryOperator( + BinaryOperatorType.ShiftLeft, MakeConstant(3), MakeConstant(1))); + + AssertConstant(ulong.MaxValue >> 2, resolver.ResolveBinaryOperator( + BinaryOperatorType.ShiftRight, MakeConstant(ulong.MaxValue), MakeConstant(2))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.ShiftLeft, MakeResult(typeof(ushort?)), MakeConstant(1))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.ShiftLeft, MakeConstant(null), MakeConstant(1))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.ShiftLeft, MakeConstant(null), MakeConstant(null))); + } + + [Test] + public void Equality() + { + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(3), MakeConstant(3))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(3), MakeConstant(3.0))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(2.9), MakeConstant(3))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(double.NaN), MakeConstant(double.NaN))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(float.NaN), MakeConstant(float.NaN))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant("A"), MakeConstant("B"))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant("A"), MakeConstant("A"))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(""), MakeConstant(null))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(null), MakeConstant(null))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(1), MakeConstant(null))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(null), MakeConstant('a'))); + + AssertType(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeResult(typeof(int*)), MakeResult(typeof(uint*)))); + } + + [Test] + public void Inequality() + { + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(3), MakeConstant(3))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(3), MakeConstant(3.0))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(2.9), MakeConstant(3))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(double.NaN), MakeConstant(double.NaN))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(float.NaN), MakeConstant(double.NaN))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(float.NaN), MakeConstant(float.NaN))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant("A"), MakeConstant("B"))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant("A"), MakeConstant("A"))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(""), MakeConstant(null))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(null), MakeConstant(null))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(1), MakeConstant(null))); + + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeConstant(null), MakeConstant('a'))); + + AssertType(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.InEquality, MakeResult(typeof(int*)), MakeResult(typeof(uint*)))); + } + + [Test] + public void EqualityEnum() + { + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(0), MakeConstant(StringComparison.Ordinal))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(0), MakeConstant(StringComparison.Ordinal))); + + Assert.IsFalse(resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(StringComparison.Ordinal), MakeConstant(1)).IsCompileTimeConstant); + } + + [Test] + public void RelationalOperators() + { + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.LessThan, MakeConstant(0), MakeConstant(0))); + + AssertType(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.LessThan, MakeResult(typeof(int*)), MakeResult(typeof(uint*)))); + } + + [Test] + public void RelationalEnum() + { + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.LessThan, MakeConstant(0), MakeConstant(StringComparison.Ordinal))); + + AssertError(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.LessThanOrEqual, MakeConstant(1), MakeConstant(StringComparison.Ordinal))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.GreaterThan, MakeConstant(StringComparison.CurrentCultureIgnoreCase), MakeConstant(StringComparison.Ordinal))); + + AssertType(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.GreaterThan, MakeResult(typeof(StringComparison?)), MakeResult(typeof(StringComparison?)))); + } + + [Test] + public void BitAnd() + { + AssertConstant(5, resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeConstant(7), MakeConstant(13))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeConstant(null), MakeConstant((short)13))); + + AssertType(typeof(long?), resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeResult(typeof(uint?)), MakeConstant((short)13))); + + AssertType(typeof(uint?), resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeResult(typeof(uint?)), MakeConstant((int)13))); + + AssertType(typeof(ulong?), resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeResult(typeof(ulong?)), MakeConstant((long)13))); + + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeResult(typeof(ulong?)), MakeConstant((short)13)).IsError); + } + + [Test] + public void BitXor() + { + AssertConstant(6L ^ 3, resolver.ResolveBinaryOperator( + BinaryOperatorType.ExclusiveOr, MakeConstant(6L), MakeConstant(3))); + + AssertConstant(6UL ^ 3L, resolver.ResolveBinaryOperator( + BinaryOperatorType.ExclusiveOr, MakeConstant(6UL), MakeConstant(3L))); + + AssertError(typeof(ulong), resolver.ResolveBinaryOperator( + BinaryOperatorType.ExclusiveOr, MakeConstant(6UL), MakeConstant(-3L))); + } + + [Test] + public void BitwiseEnum() + { + AssertConstant(AttributeTargets.Field | AttributeTargets.Property, resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseOr, MakeConstant(AttributeTargets.Field), MakeConstant(AttributeTargets.Property))); + + AssertConstant(AttributeTargets.Field & AttributeTargets.All, resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeConstant(AttributeTargets.Field), MakeConstant(AttributeTargets.All))); + + AssertConstant(AttributeTargets.Field & 0, resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseAnd, MakeConstant(AttributeTargets.Field), MakeConstant(0))); + + AssertConstant(0 | AttributeTargets.Field, resolver.ResolveBinaryOperator( + BinaryOperatorType.BitwiseOr, MakeConstant(0), MakeConstant(AttributeTargets.Field))); + } + + [Test] + public void LogicalAnd() + { + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.ConditionalAnd, MakeConstant(true), MakeConstant(true))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.ConditionalAnd, MakeConstant(false), MakeConstant(true))); + + AssertError(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.ConditionalAnd, MakeConstant(false), MakeResult(typeof(bool?)))); + } + + [Test] + public void LogicalOr() + { + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.ConditionalOr, MakeConstant(false), MakeConstant(true))); + + AssertConstant(false, resolver.ResolveBinaryOperator( + BinaryOperatorType.ConditionalOr, MakeConstant(false), MakeConstant(false))); + + AssertError(typeof(bool), resolver.ResolveBinaryOperator( + BinaryOperatorType.ConditionalOr, MakeConstant(false), MakeResult(typeof(bool?)))); + } + + [Test] + public void NullCoalescing() + { + AssertType(typeof(int), resolver.ResolveBinaryOperator( + BinaryOperatorType.NullCoalescing, MakeResult(typeof(int?)), MakeResult(typeof(short)))); + + AssertType(typeof(int?), resolver.ResolveBinaryOperator( + BinaryOperatorType.NullCoalescing, MakeResult(typeof(int?)), MakeResult(typeof(short?)))); + + AssertType(typeof(object), resolver.ResolveBinaryOperator( + BinaryOperatorType.NullCoalescing, MakeResult(typeof(string)), MakeResult(typeof(object)))); + + AssertError(typeof(string), resolver.ResolveBinaryOperator( + BinaryOperatorType.NullCoalescing, MakeResult(typeof(string)), MakeResult(typeof(int)))); + + AssertType(typeof(dynamic), resolver.ResolveBinaryOperator( + BinaryOperatorType.NullCoalescing, MakeResult(typeof(dynamic)), MakeResult(typeof(string)))); + + AssertType(typeof(dynamic), resolver.ResolveBinaryOperator( + BinaryOperatorType.NullCoalescing, MakeResult(typeof(string)), MakeResult(typeof(dynamic)))); + } + + [Test, Ignore("user-defined operators not yet implemented")] + public void LiftedUserDefined() + { + AssertType(typeof(TimeSpan), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(DateTime)), MakeResult(typeof(DateTime)))); + AssertType(typeof(TimeSpan?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(DateTime?)), MakeResult(typeof(DateTime)))); + AssertType(typeof(TimeSpan?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(DateTime)), MakeResult(typeof(DateTime?)))); + AssertType(typeof(TimeSpan?), resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeResult(typeof(DateTime?)), MakeResult(typeof(DateTime?)))); + } + + [Test, Ignore("user-defined operators not yet implemented")] + public void UserDefinedNeedsLiftingDueToImplicitConversion() + { + string program = @"struct S {} +struct A { + public static implicit operator S?(A a) { return null; } + + public static S operator +(A a, S s) { return s; } +} +class Test { + void M(A a) { + var s = $a + a$; + } +} +"; + MemberResolveResult trr = Resolve(program); + Assert.IsFalse(trr.IsError); + Assert.AreEqual("A.op_Addition", trr.Member.FullName); + // even though we're calling the lifted operator, trr.Member should be the original operator method + Assert.AreEqual("S", trr.Member.ReturnType.Resolve(context).ReflectionName); + Assert.AreEqual("System.Nullable`1[[S]]", trr.Type.ReflectionName); + } + + [Test, Ignore("user-defined operators not yet implemented")] + public void ThereIsNoLiftedOperatorsForClasses() + { + string program = @"struct S {} +class A { + public static implicit operator S?(A a) { return null; } + + public static S operator +(A a, S s) { return s; } +} +class Test { + void M(A a) { + var s = $a + a$; + } +} +"; + MemberResolveResult trr = Resolve(program); + Assert.IsTrue(trr.IsError); // cannot convert from A to S + Assert.AreEqual("A.op_Addition", trr.Member.FullName); + Assert.AreEqual("S", trr.Type.ReflectionName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs new file mode 100644 index 0000000000..a961a9b8c3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs @@ -0,0 +1,57 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + // assign short name to the fake reflection type + using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; + + [TestFixture] + public class CastTests : ResolverTestBase + { + [Test] + public void SimpleCast() + { + AssertType(typeof(int), resolver.ResolveCast(ResolveType(typeof(int)), MakeResult(typeof(float)))); + AssertType(typeof(string), resolver.ResolveCast(ResolveType(typeof(string)), MakeResult(typeof(object)))); + AssertType(typeof(byte), resolver.ResolveCast(ResolveType(typeof(byte)), MakeResult(typeof(dynamic)))); + AssertType(typeof(dynamic), resolver.ResolveCast(ResolveType(typeof(dynamic)), MakeResult(typeof(double)))); + } + + [Test] + public void ConstantValueCast() + { + AssertConstant("Hello", resolver.ResolveCast(ResolveType(typeof(string)), MakeConstant("Hello"))); + AssertConstant((byte)1L, resolver.ResolveCast(ResolveType(typeof(byte)), MakeConstant(1L))); + AssertConstant(3, resolver.ResolveCast(ResolveType(typeof(int)), MakeConstant(3.1415))); + AssertConstant(3, resolver.ResolveCast(ResolveType(typeof(int)), MakeConstant(3.99))); + AssertConstant((short)-3, resolver.ResolveCast(ResolveType(typeof(short)), MakeConstant(-3.99f))); + AssertConstant(-3L, resolver.ResolveCast(ResolveType(typeof(long)), MakeConstant(-3.5))); + } + + [Test] + public void OverflowingCast() + { + resolver.CheckForOverflow = false; + AssertConstant(uint.MaxValue, resolver.ResolveCast(ResolveType(typeof(uint)), MakeConstant(-1.6))); + resolver.CheckForOverflow = true; + AssertError(typeof(uint), resolver.ResolveCast(ResolveType(typeof(uint)), MakeConstant(-1.6))); + } + + [Test] + public void FailingStringCast() + { + AssertError(typeof(string), resolver.ResolveCast(ResolveType(typeof(string)), MakeConstant(1))); + } + + [Test] + public void OverflowingCastToEnum() + { + resolver.CheckForOverflow = true; + AssertError(typeof(StringComparison), resolver.ResolveCast(ResolveType(typeof(StringComparison)), MakeConstant(long.MaxValue))); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs new file mode 100644 index 0000000000..d1178757eb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs @@ -0,0 +1,85 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + // assign short name to the fake reflection type + using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; + + [TestFixture] + public class ConditionalOperatorTests : ResolverTestBase + { + [Test] + public void PickMoreGeneralOfTheTypes() + { + AssertType(typeof(object), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeResult(typeof(object)))); + AssertType(typeof(long), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(int)), MakeResult(typeof(long)))); + } + + [Test] + public void Null() + { + AssertType(typeof(string), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeConstant(null))); + AssertType(typeof(string), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeConstant(null), MakeResult(typeof(string)))); + } + + [Test] + public void DynamicInArguments() + { + AssertType(typeof(dynamic), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(dynamic)), MakeResult(typeof(double)))); + + AssertType(typeof(dynamic), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(double)), MakeResult(typeof(dynamic)))); + } + + [Test] + public void DynamicInCondition() + { + AssertType(typeof(double), resolver.ResolveConditional( + MakeResult(typeof(dynamic)), MakeResult(typeof(float)), MakeResult(typeof(double)))); + } + + [Test] + public void AllDynamic() + { + AssertType(typeof(dynamic), resolver.ResolveConditional( + MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)))); + } + + [Test] + public void ListOfDynamicAndListOfObject() + { + AssertError(typeof(List), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(List)), MakeResult(typeof(List)))); + + AssertError(typeof(List), resolver.ResolveConditional( + MakeResult(typeof(bool)), MakeResult(typeof(List)), MakeResult(typeof(List)))); + } + + [Test] + public void Constant() + { + AssertConstant(1L, resolver.ResolveConditional( + MakeConstant(true), MakeConstant(1), MakeConstant(2L))); + + AssertConstant(2L, resolver.ResolveConditional( + MakeConstant(false), MakeConstant(1), MakeConstant(2L))); + } + + [Test] + public void NotConstantIfFalsePortionNotConstant() + { + AssertType(typeof(long), resolver.ResolveConditional( + MakeConstant(true), MakeConstant(1), MakeResult(typeof(long)))); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs new file mode 100644 index 0000000000..f1d2703980 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs @@ -0,0 +1,421 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + // assign short names to the fake reflection types + using Null = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Null; + using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; + + [TestFixture] + public unsafe class ConversionsTest + { + ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; + Conversions conversions = new Conversions(CecilLoaderTests.Mscorlib); + + bool ImplicitConversion(Type from, Type to) + { + IType from2 = from.ToTypeReference().Resolve(ctx); + IType to2 = to.ToTypeReference().Resolve(ctx); + return conversions.ImplicitConversion(from2, to2); + } + + [Test] + public void IdentityConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(char), typeof(char))); + Assert.IsTrue(ImplicitConversion(typeof(string), typeof(string))); + Assert.IsTrue(ImplicitConversion(typeof(object), typeof(object))); + Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(char))); + + Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Dynamic, SharedTypes.Dynamic)); + Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.UnknownType, SharedTypes.UnknownType)); + Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, SharedTypes.Null)); + } + + [Test] + public void DynamicIdentityConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(object), typeof(ReflectionHelper.Dynamic))); + Assert.IsTrue(ImplicitConversion(typeof(ReflectionHelper.Dynamic), typeof(object))); + } + + [Test] + public void ComplexDynamicIdentityConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(List), typeof(List))); + Assert.IsTrue(ImplicitConversion(typeof(List), typeof(List))); + Assert.IsFalse(ImplicitConversion(typeof(List), typeof(List))); + Assert.IsFalse(ImplicitConversion(typeof(List), typeof(List))); + + Assert.IsTrue(ImplicitConversion(typeof(List[]>), typeof(List[]>))); + Assert.IsTrue(ImplicitConversion(typeof(List[]>), typeof(List[]>))); + Assert.IsFalse(ImplicitConversion(typeof(List[,]>), typeof(List[]>))); + } + + [Test] + public void PrimitiveConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(char), typeof(ushort))); + Assert.IsFalse(ImplicitConversion(typeof(byte), typeof(char))); + Assert.IsTrue(ImplicitConversion(typeof(int), typeof(long))); + Assert.IsFalse(ImplicitConversion(typeof(long), typeof(int))); + Assert.IsTrue(ImplicitConversion(typeof(int), typeof(float))); + Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(float))); + Assert.IsTrue(ImplicitConversion(typeof(float), typeof(double))); + Assert.IsFalse(ImplicitConversion(typeof(float), typeof(decimal))); + Assert.IsTrue(ImplicitConversion(typeof(char), typeof(long))); + Assert.IsTrue(ImplicitConversion(typeof(uint), typeof(long))); + } + + [Test] + public void NullableConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(char), typeof(ushort?))); + Assert.IsFalse(ImplicitConversion(typeof(byte), typeof(char?))); + Assert.IsTrue(ImplicitConversion(typeof(int), typeof(long?))); + Assert.IsFalse(ImplicitConversion(typeof(long), typeof(int?))); + Assert.IsTrue(ImplicitConversion(typeof(int), typeof(float?))); + Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(float?))); + Assert.IsTrue(ImplicitConversion(typeof(float), typeof(double?))); + Assert.IsFalse(ImplicitConversion(typeof(float), typeof(decimal?))); + } + + [Test] + public void NullableConversions2() + { + Assert.IsTrue(ImplicitConversion(typeof(char?), typeof(ushort?))); + Assert.IsFalse(ImplicitConversion(typeof(byte?), typeof(char?))); + Assert.IsTrue(ImplicitConversion(typeof(int?), typeof(long?))); + Assert.IsFalse(ImplicitConversion(typeof(long?), typeof(int?))); + Assert.IsTrue(ImplicitConversion(typeof(int?), typeof(float?))); + Assert.IsFalse(ImplicitConversion(typeof(bool?), typeof(float?))); + Assert.IsTrue(ImplicitConversion(typeof(float?), typeof(double?))); + Assert.IsFalse(ImplicitConversion(typeof(float?), typeof(decimal?))); + } + + [Test] + public void NullLiteralConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int?))); + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(char?))); + Assert.IsFalse(ImplicitConversion(typeof(Null), typeof(int))); + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(object))); + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(dynamic))); + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(string))); + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int[]))); + } + + [Test] + public void SimpleReferenceConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(string), typeof(object))); + Assert.IsTrue(ImplicitConversion(typeof(BitArray), typeof(ICollection))); + Assert.IsTrue(ImplicitConversion(typeof(IList), typeof(IEnumerable))); + Assert.IsFalse(ImplicitConversion(typeof(object), typeof(string))); + Assert.IsFalse(ImplicitConversion(typeof(ICollection), typeof(BitArray))); + Assert.IsFalse(ImplicitConversion(typeof(IEnumerable), typeof(IList))); + } + + [Test] + public void SimpleDynamicConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(string), typeof(dynamic))); + Assert.IsTrue(ImplicitConversion(typeof(dynamic), typeof(string))); + Assert.IsTrue(ImplicitConversion(typeof(int), typeof(dynamic))); + Assert.IsTrue(ImplicitConversion(typeof(dynamic), typeof(int))); + } + + [Test] + public void ParameterizedTypeConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(List), typeof(ICollection))); + Assert.IsTrue(ImplicitConversion(typeof(IList), typeof(ICollection))); + Assert.IsFalse(ImplicitConversion(typeof(List), typeof(ICollection))); + Assert.IsFalse(ImplicitConversion(typeof(IList), typeof(ICollection))); + } + + [Test] + public void ArrayConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(object[]))); + Assert.IsTrue(ImplicitConversion(typeof(string[,]), typeof(object[,]))); + Assert.IsFalse(ImplicitConversion(typeof(string[]), typeof(object[,]))); + Assert.IsFalse(ImplicitConversion(typeof(object[]), typeof(string[]))); + + Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(IList))); + Assert.IsFalse(ImplicitConversion(typeof(string[,]), typeof(IList))); + Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(IList))); + + Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(Array))); + Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(ICloneable))); + Assert.IsFalse(ImplicitConversion(typeof(Array), typeof(string[]))); + Assert.IsFalse(ImplicitConversion(typeof(object), typeof(object[]))); + } + + [Test] + public void VarianceConversions() + { + Assert.IsTrue(ImplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.IsFalse(ImplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.IsTrue(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); + Assert.IsFalse(ImplicitConversion(typeof(ICollection), typeof(ICollection))); + + Assert.IsTrue(ImplicitConversion(typeof(Comparer), typeof(IComparer))); + Assert.IsTrue(ImplicitConversion(typeof(Comparer), typeof(IComparer))); + Assert.IsFalse(ImplicitConversion(typeof(Comparer), typeof(Comparer))); + + Assert.IsFalse(ImplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.IsTrue(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); + + Assert.IsTrue(ImplicitConversion(typeof(Func), typeof(Func))); + Assert.IsTrue(ImplicitConversion(typeof(Func), typeof(Func))); + Assert.IsFalse(ImplicitConversion(typeof(Func), typeof(Func))); + Assert.IsFalse(ImplicitConversion(typeof(Func), typeof(Func))); + } + + [Test] + public void PointerConversion() + { + Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int*))); + Assert.IsTrue(ImplicitConversion(typeof(int*), typeof(void*))); + } + + [Test] + public void NoConversionFromPointerTypeToObject() + { + Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(object))); + Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(dynamic))); + } + + [Test] + public void UnconstrainedTypeParameter() + { + DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); + DefaultTypeParameter t2 = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "T2"); + DefaultTypeParameter tm = new DefaultTypeParameter(EntityType.Method, 0, "TM"); + + Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + + Assert.IsTrue(conversions.ImplicitConversion(t, t)); + Assert.IsFalse(conversions.ImplicitConversion(t2, t)); + Assert.IsFalse(conversions.ImplicitConversion(t, t2)); + Assert.IsFalse(conversions.ImplicitConversion(t, tm)); + Assert.IsFalse(conversions.ImplicitConversion(tm, t)); + } + + [Test] + public void TypeParameterWithReferenceTypeConstraint() + { + DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); + t.HasReferenceTypeConstraint = true; + + Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + } + + [Test] + public void TypeParameterWithValueTypeConstraint() + { + DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); + t.HasValueTypeConstraint = true; + + Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + } + + [Test] + public void TypeParameterWithClassConstraint() + { + DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); + t.Constraints.Add(ctx.GetTypeDefinition(typeof(StringComparer))); + + Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer)))); + Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer)))); + Assert.IsFalse(conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); + Assert.IsTrue(conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); + } + + [Test] + public void TypeParameterWithInterfaceConstraint() + { + DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); + t.Constraints.Add(ctx.GetTypeDefinition(typeof(IList))); + + Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList)))); + Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable)))); + } + + [Test] + public void UserDefinedImplicitConversion() + { + Assert.IsTrue(ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset))); + Assert.IsFalse(ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime))); + } + + [Test] + public void UserDefinedImplicitNullableConversion() + { + // User-defined conversion followed by nullable conversion + Assert.IsTrue(ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset?))); + // Lifted user-defined conversion + Assert.IsTrue(ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset?))); + // User-defined conversion doesn't drop the nullability + Assert.IsFalse(ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset))); + } + + bool IntegerLiteralConversion(object value, Type to) + { + IType fromType = value.GetType().ToTypeReference().Resolve(ctx); + ConstantResolveResult crr = new ConstantResolveResult(fromType, value); + IType to2 = to.ToTypeReference().Resolve(ctx); + return conversions.ImplicitConversion(crr, to2); + } + + [Test] + public void IntegerLiteralToEnumConversions() + { + Assert.IsTrue(IntegerLiteralConversion(0, typeof(LoaderOptimization))); + Assert.IsTrue(IntegerLiteralConversion(0L, typeof(LoaderOptimization))); + Assert.IsTrue(IntegerLiteralConversion(0, typeof(LoaderOptimization?))); + Assert.IsFalse(IntegerLiteralConversion(0, typeof(string))); + Assert.IsFalse(IntegerLiteralConversion(1, typeof(LoaderOptimization))); + } + + [Test] + public void ImplicitConstantExpressionConversion() + { + Assert.IsTrue(IntegerLiteralConversion(0, typeof(int))); + Assert.IsTrue(IntegerLiteralConversion(0, typeof(ushort))); + Assert.IsTrue(IntegerLiteralConversion(0, typeof(sbyte))); + + Assert.IsTrue (IntegerLiteralConversion(-1, typeof(int))); + Assert.IsFalse(IntegerLiteralConversion(-1, typeof(ushort))); + Assert.IsTrue (IntegerLiteralConversion(-1, typeof(sbyte))); + + Assert.IsTrue (IntegerLiteralConversion(200, typeof(int))); + Assert.IsTrue (IntegerLiteralConversion(200, typeof(ushort))); + Assert.IsFalse(IntegerLiteralConversion(200, typeof(sbyte))); + } + + [Test] + public void ImplicitLongConstantExpressionConversion() + { + Assert.IsFalse(IntegerLiteralConversion(0L, typeof(int))); + Assert.IsTrue(IntegerLiteralConversion(0L, typeof(long))); + Assert.IsTrue(IntegerLiteralConversion(0L, typeof(ulong))); + + Assert.IsTrue(IntegerLiteralConversion(-1L, typeof(long))); + Assert.IsFalse(IntegerLiteralConversion(-1L, typeof(ulong))); + } + + [Test] + public void ImplicitConstantExpressionConversionToNullable() + { + Assert.IsTrue(IntegerLiteralConversion(0, typeof(uint?))); + Assert.IsTrue(IntegerLiteralConversion(0, typeof(short?))); + Assert.IsTrue(IntegerLiteralConversion(0, typeof(byte?))); + + Assert.IsFalse(IntegerLiteralConversion(-1, typeof(uint?))); + Assert.IsTrue (IntegerLiteralConversion(-1, typeof(short?))); + Assert.IsFalse(IntegerLiteralConversion(-1, typeof(byte?))); + + Assert.IsTrue(IntegerLiteralConversion(200, typeof(uint?))); + Assert.IsTrue(IntegerLiteralConversion(200, typeof(short?))); + Assert.IsTrue(IntegerLiteralConversion(200, typeof(byte?))); + + Assert.IsFalse(IntegerLiteralConversion(0L, typeof(uint?))); + Assert.IsTrue (IntegerLiteralConversion(0L, typeof(long?))); + Assert.IsTrue (IntegerLiteralConversion(0L, typeof(ulong?))); + + Assert.IsTrue(IntegerLiteralConversion(-1L, typeof(long?))); + Assert.IsFalse(IntegerLiteralConversion(-1L, typeof(ulong?))); + } + + [Test] + public void ImplicitConstantExpressionConversionNumberInterfaces() + { + Assert.IsTrue(IntegerLiteralConversion(0, typeof(IFormattable))); + Assert.IsTrue(IntegerLiteralConversion(0, typeof(IComparable))); + Assert.IsFalse(IntegerLiteralConversion(0, typeof(IComparable))); + Assert.IsFalse(IntegerLiteralConversion(0, typeof(IComparable))); + } + + int BetterConversion(Type s, Type t1, Type t2) + { + IType sType = s.ToTypeReference().Resolve(ctx); + IType t1Type = t1.ToTypeReference().Resolve(ctx); + IType t2Type = t2.ToTypeReference().Resolve(ctx); + return conversions.BetterConversion(sType, t1Type, t2Type); + } + + int BetterConversion(object value, Type t1, Type t2) + { + IType fromType = value.GetType().ToTypeReference().Resolve(ctx); + ConstantResolveResult crr = new ConstantResolveResult(fromType, value); + IType t1Type = t1.ToTypeReference().Resolve(ctx); + IType t2Type = t2.ToTypeReference().Resolve(ctx); + return conversions.BetterConversion(crr, t1Type, t2Type); + } + + [Test] + public void BetterConversion() + { + Assert.AreEqual(1, BetterConversion(typeof(string), typeof(string), typeof(object))); + Assert.AreEqual(2, BetterConversion(typeof(string), typeof(object), typeof(IComparable))); + Assert.AreEqual(0, BetterConversion(typeof(string), typeof(IEnumerable), typeof(IComparable))); + } + + [Test] + public void BetterPrimitiveConversion() + { + Assert.AreEqual(1, BetterConversion(typeof(short), typeof(int), typeof(long))); + Assert.AreEqual(1, BetterConversion(typeof(short), typeof(int), typeof(uint))); + Assert.AreEqual(2, BetterConversion(typeof(ushort), typeof(uint), typeof(int))); + Assert.AreEqual(1, BetterConversion(typeof(char), typeof(short), typeof(int))); + Assert.AreEqual(1, BetterConversion(typeof(char), typeof(ushort), typeof(int))); + Assert.AreEqual(1, BetterConversion(typeof(sbyte), typeof(long), typeof(ulong))); + Assert.AreEqual(2, BetterConversion(typeof(byte), typeof(ushort), typeof(short))); + + Assert.AreEqual(1, BetterConversion(1, typeof(sbyte), typeof(byte))); + Assert.AreEqual(2, BetterConversion(1, typeof(ushort), typeof(sbyte))); + } + + [Test] + public void BetterNullableConversion() + { + Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(int), typeof(uint?))); + Assert.AreEqual(0, BetterConversion(typeof(byte?), typeof(int?), typeof(uint?))); + Assert.AreEqual(1, BetterConversion(typeof(byte), typeof(ushort?), typeof(uint?))); + Assert.AreEqual(2, BetterConversion(typeof(byte?), typeof(ulong?), typeof(uint?))); + Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ushort?), typeof(uint))); + Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ushort?), typeof(int))); + Assert.AreEqual(2, BetterConversion(typeof(byte), typeof(ulong?), typeof(uint))); + Assert.AreEqual(0, BetterConversion(typeof(byte), typeof(ulong?), typeof(int))); + Assert.AreEqual(2, BetterConversion(typeof(ushort?), typeof(long?), typeof(int?))); + Assert.AreEqual(0, BetterConversion(typeof(sbyte), typeof(int?), typeof(uint?))); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs new file mode 100644 index 0000000000..3a9f0a7396 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class ExtensionMethodTests : ResolverTestBase + { + [Test] + public void ExtensionMethodsTest() + { + string program = @"using XN; +class TestClass { + static void Test(A a, B b, C c) { + $; + } +} +class A { } +class B { + public void F(int i) { } +} +class C { + public void F(object obj) { } +} +namespace XN { + public static class XC { + public static void F(this object obj, int i) { } + public static void F(this object obj, string s) { } + } +} +"; + MemberResolveResult mrr; + + mrr = Resolve(program.Replace("$", "$a.F(1)$")); + Assert.AreEqual("XN.XC.F", mrr.Member.FullName); + Assert.AreEqual("System.Int32", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); + + mrr = Resolve(program.Replace("$", "$a.F(\"text\")$")); + Assert.AreEqual("XN.XC.F", mrr.Member.FullName); + Assert.AreEqual("System.String", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); + + mrr = Resolve(program.Replace("$", "$b.F(1)$")); + Assert.AreEqual("B.F", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$b.F(\"text\")$")); + Assert.AreEqual("XN.XC.F", mrr.Member.FullName); + Assert.AreEqual("System.String", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); + + mrr = Resolve(program.Replace("$", "$c.F(1)$")); + Assert.AreEqual("C.F", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$c.F(\"text\")$")); + Assert.AreEqual("C.F", mrr.Member.FullName); + } + + [Test, Ignore("Anonymous methods not yet implemented")] + public void ExtensionMethodsTest2() + { + string program = @"using System; using System.Collections.Generic; +class TestClass { + static void Test(string[] args) { + $; + } +} +public static class XC { + public static int ToInt32(this string s) { return int.Parse(s); } + public static T[] Slice(this T[] source, int index, int count) { throw new NotImplementedException(); } + public static IEnumerable Filter(this IEnumerable source, Predicate predicate) { throw new NotImplementedException(); } +} +"; + MemberResolveResult mrr; + + mrr = Resolve(program.Replace("$", "$\"text\".ToInt32()$")); + Assert.AreEqual("XC.ToInt32", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$args.Slice(1, 2)$")); + Assert.AreEqual("XC.Slice", mrr.Member.FullName); + Assert.AreEqual("System.String[]", mrr.Type.ReflectionName); + + mrr = Resolve(program.Replace("$", "$args.Filter(delegate { return true; })$")); + Assert.AreEqual("XC.Filter", mrr.Member.FullName); + Assert.AreEqual("System.Collections.Generic.IEnumerable{System.String}", mrr.Type.ReflectionName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs new file mode 100644 index 0000000000..b59b2941e9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs @@ -0,0 +1,268 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class InvocationTests : ResolverTestBase + { + // TODO: do we want to return the MemberResolveResult for the InvocationExpression, or only for it's target? + + [Test] + public void MethodCallTest() + { + string program = @"class A { + void Method() { + $TargetMethod()$; + } + + int TargetMethod() { + return 3; + } +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("A.TargetMethod", result.Member.FullName); + Assert.AreEqual("System.Int32", result.Type.ReflectionName); + } + + [Test] + public void InvalidMethodCall() + { + string program = @"class A { + void Method(string b) { + $b.ThisMethodDoesNotExistOnString(b)$; + } +} +"; + UnknownMethodResolveResult result = Resolve(program); + Assert.AreEqual("ThisMethodDoesNotExistOnString", result.MemberName); + Assert.AreEqual("System.String", result.TargetType.FullName); + Assert.AreEqual(1, result.Parameters.Count); + Assert.AreEqual("b", result.Parameters[0].Name); + Assert.AreEqual("System.String", result.Parameters[0].Type.Resolve(context).ReflectionName); + + Assert.AreSame(SharedTypes.UnknownType, result.Type); + } + + [Test, Ignore("Resolver returns the member from the base class, which is correct according to C# spec, but not what we want to show in tooltips")] + public void OverriddenMethodCall() + { + string program = @"class A { + void Method() { + $new B().GetRandomNumber()$; + } + + public abstract int GetRandomNumber(); +} +class B : A { + public override int GetRandomNumber() { + return 4; // chosen by fair dice roll. + // guaranteed to be random + } +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("B.GetRandomNumber", result.Member.FullName); + } + + [Test, Ignore("Resolver returns the member from the base class, which is correct according to C# spec, but not what we want to show in tooltips")] + public void OverriddenMethodCall2() + { + string program = @"class A { + void Method() { + $new B().GetRandomNumber(""x"", this)$; + } + + public abstract int GetRandomNumber(string a, A b); +} +class B : A { + public override int GetRandomNumber(string b, A a) { + return 4; // chosen by fair dice roll. + // guaranteed to be random + } +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("B.GetRandomNumber", result.Member.FullName); + } + + [Test] + public void ThisMethodCallTest() + { + string program = @"class A { + void Method() { + $this.TargetMethod()$; + } + + int TargetMethod() { + return 3; + } +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("A.TargetMethod", result.Member.FullName); + Assert.AreEqual("System.Int32", result.Type.ReflectionName); + } + + [Test] + public void VoidTest() + { + string program = @"using System; +class A { + void TestMethod() { + $TestMethod()$; + } +} +"; + Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName); + } + + [Test] + public void EventCallTest() + { + string program = @"using System; +class A { + void Method() { + $TestEvent(this, EventArgs.Empty)$; + } + + public event EventHandler TestEvent; +} +"; + Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName); + } + + [Test] + public void DelegateCallTest() + { + string program = @"using System; using System.Reflection; +class A { + void Method(ModuleResolveEventHandler eh) { + $eh(this, new ResolveEventArgs())$; + } +} +"; + Assert.AreEqual("System.Reflection.Module", Resolve(program).Type.ReflectionName); + } + + [Test] + public void DelegateReturnedFromMethodCallTest() + { + string program = @"using System; +class A { + void Method() { + $GetHandler()(abc)$; + } + abstract Predicate GetHandler(); +} +"; + Assert.AreEqual("System.Boolean", Resolve(program).Type.ReflectionName); + } + + /* TODO + [Test] + public void MethodGroupResolveTest() + { + string program = @"class A { + void Method() { + + } + + void TargetMethod(int a) { } + void TargetMethod(T a) { } +} +"; + MethodGroupResolveResult result = Resolve(program, "TargetMethod", 3); + Assert.AreEqual("TargetMethod", result.Name); + Assert.AreEqual(2, result.Methods.Count); + + result = Resolve(program, "TargetMethod", 3); + Assert.AreEqual("TargetMethod", result.Name); + Assert.AreEqual(1, result.Methods[0].Count); + Assert.AreEqual("System.String", result.GetMethodIfSingleOverload().Parameters[0].ReturnType.FullyQualifiedName); + } + */ + + [Test] + public void TestOverloadingByRef() + { + string program = @"using System; +class Program { + public static void Main() { + int a = 42; + T(a); + T(ref a); + } + static void T(int x) {} + static void T(ref int y) {} +}"; + + MemberResolveResult mrr = Resolve(program, "T(a)"); + Assert.IsFalse(((IMethod)mrr.Member).Parameters[0].IsRef); + + mrr = Resolve(program, "T(ref a)"); + Assert.IsTrue(((IMethod)mrr.Member).Parameters[0].IsRef); + } + + [Test, Ignore("Grouping by declaring type not yet implemented")] + public void AddedOverload() + { + string program = @"class BaseClass { + static void Main(DerivedClass d) { + $d.Test(3)$; + } + public void Test(int a) { } +} +class DerivedClass : BaseClass { + public void Test(object a) { } +}"; + MemberResolveResult mrr = Resolve(program); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + } + + [Test] + public void AddedNonApplicableOverload() + { + string program = @"class BaseClass { + static void Main(DerivedClass d) { + $d.Test(3)$; + } + public void Test(int a) { } +} +class DerivedClass : BaseClass { + public void Test(string a) { } +}"; + MemberResolveResult mrr = Resolve(program); + Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); + + mrr = Resolve(program.Replace("(3)", "(\"3\")")); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + } + + [Test, Ignore("Grouping by declaring type not yet implemented")] + public void OverrideShadowed() + { + string program = @"using System; +class BaseClass { + static void Main() { + $new DerivedClass().Test(3)$; + } + public virtual void Test(int a) { } +} +class MiddleClass : BaseClass { + public void Test(object a) { } +} +class DerivedClass : MiddleClass { + public override void Test(int a) { } +}"; + + MemberResolveResult mrr = Resolve(program); + Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs new file mode 100644 index 0000000000..4a21067048 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -0,0 +1,292 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture, Ignore("Lambdas not supported by resolver")] + public class LambdaTests : ResolverTestBase + { + [Test] + public void SimpleLambdaTest() + { + string program = @"using System; +class TestClass { + static void Main() { + Test(i => Console.WriteLine(i)); + } + public void Test(Action ac) { ac(42); } +}"; + var lrr = Resolve(program.Replace("(i)", "($i$)")); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + + lrr = Resolve(program.Replace("i =>", "$i$ =>")); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInConstructorTest() + { + string program = @"using System; +class TestClass { + static void Main() { + TestClass t = new TestClass(i => Console.WriteLine($i$)); + } + public TestClass(Action ac) { ac(42); } +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInGenericConstructorTest() + { + string program = @"using System; +class TestClass { + static void Main() { + var t = new SomeClass(i => Console.WriteLine($i$)); + } +} +class SomeClass { + public SomeClass(Action ac) { } +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + } + + #region Lambda In Initializer + [Test] + public void LambdaInCollectionInitializerTest1() + { + string program = @"using System; +class TestClass { + static void Main() { + Converter[] arr = { + i => $i$.ToString() + }; + } +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInCollectionInitializerTest2() + { + string program = @"using System; using System.Collections.Generic; +class TestClass { + static void Main() { + a = new List> { + i => $i$.ToString() + }; + } +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInCollectionInitializerTest3() + { + string program = @"using System; +class TestClass { + static void Main() { + a = new Converter[] { + i => $i$.ToString() + }; + } +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInCollectionInitializerTest4() + { + string program = @"using System; +class TestClass { + Converter[] field = new Converter[] { + i => $i$.ToString() + }; +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInCollectionInitializerTest5() + { + string program = @"using System; +class TestClass { + Converter[] field = { + i => $i$.ToString() + }; +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInObjectInitializerTest() + { + string program = @"using System; +class X { + void SomeMethod() { + Helper h = new Helper { + F = i => $i$.ToString() + }; + } +} +class Helper { + public Converter F; +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + #endregion + + [Test] + public void LambdaExpressionInCastExpression() + { + string program = @"using System; +static class TestClass { + static void Main(string[] args) { + var f = (Func) ( i => $i$ ); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaExpressionInReturnStatement() + { + string program = @"using System; +static class TestClass { + static Converter GetToString() { + return i => $i$.ToString(); + } +}"; + var lrr = Resolve(program, "i"); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaExpressionInReturnStatementInStatementLambda() + { + string program = @"using System; +static class TestClass { + static void SomeMethod() { + Func> getStringTransformer = () => { + return s => $s$.ToUpper(); + }; + } + public delegate R Func(T arg); + public delegate R Func(); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaExpressionInReturnStatementInAnonymousMethod() + { + string program = @"using System; +static class TestClass { + static void SomeMethod() { + Func> getStringTransformer = delegate { + return s => $s$.ToUpper(); + }; + } + public delegate R Func(T arg); + public delegate R Func(); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + } + + [Test] + public void CurriedLambdaExpressionInCastExpression() + { + string program = @"using System; +static class TestClass { + static void Main(string[] args) { + var f = (Func>) ( a => b => 0 ); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program.Replace("a =>", "$a$ =>")); + Assert.AreEqual("System.Char", lrr.Type.ReflectionName); + + lrr = Resolve(program.Replace("b =>", "$b$ =>")); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaExpressionInVariableInitializer() + { + string program = @"using System; +static class TestClass { + static void Main() { + Func f = $i$ => i.ToString(); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaExpressionInVariableAssignment() + { + string program = @"using System; +static class TestClass { + static void Main() { + Func f; + f = $i$ => i.ToString(); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInDelegateCall() + { + string program = @"using System; +class TestClass { + static void Main() { + Func, char> f; + f($i$ => i.ToString()); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + /* TODO write test for this +class A +{ + static void Foo(string x, Action y) { Console.WriteLine(1); } + static void Foo(object x, Func, int> y) { Console.WriteLine(2); } + + static void Main() + { + Foo(null, x => x()); // Prints 1 + Foo(null, x => (x())); // Prints 2 + } +} + */ + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs new file mode 100644 index 0000000000..9f5f4eaeff --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs @@ -0,0 +1,136 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture, Ignore("LINQ not yet implemented")] + public class LinqTests : ResolverTestBase + { + [Test] + public void SimpleLinqTest() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + var r = from e in input + where e.StartsWith(""/"") + select e.Trim(); + r.ToString(); + } +} +"; + LocalResolveResult lrr = Resolve(program.Replace("where e", "where $e$")); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + lrr = Resolve(program.Replace("select e", "select $e$")); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + lrr = Resolve(program.Replace("from e", "from $e$")); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + + lrr = Resolve(program.Replace("r.ToString", "$r$.ToString")); + Assert.AreEqual("System.Collections.Generic.IEnumerable", lrr.Type.FullName); + Assert.AreEqual("System.String", ((ParameterizedType)lrr.Type).TypeArguments[0].FullName); + } + + [Test] + public void LinqGroupTest() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + var r = from e in input + group e.ToUpper() by e.Length; + $r$.ToString(); + } +} +"; + LocalResolveResult lrr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable", lrr.Type.FullName); + ParameterizedType rt = (ParameterizedType)((ParameterizedType)lrr.Type).TypeArguments[0]; + Assert.AreEqual("System.Linq.IGrouping", rt.FullName); + Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullName); + Assert.AreEqual("System.String", rt.TypeArguments[1].FullName); + } + + [Test] + public void LinqQueryableGroupTest() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(IQueryable input) { + var r = from e in input + group e.ToUpper() by e.Length; + $r$.ToString(); + } +} +"; + LocalResolveResult lrr = Resolve(program); + Assert.AreEqual("System.Linq.IQueryable", lrr.Type.FullName); + ParameterizedType rt = (ParameterizedType)((ParameterizedType)lrr.Type).TypeArguments[0]; + Assert.AreEqual("System.Linq.IGrouping", rt.FullName); + Assert.AreEqual("System.Int32", rt.TypeArguments[0].FullName); + Assert.AreEqual("System.String", rt.TypeArguments[1].FullName); + } + + [Test] + public void ParenthesizedLinqTest() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $(from e in input select e.Length)$.ToArray(); + } +} +"; + ResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName); + Assert.AreEqual("System.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName); + } + + [Test] + public void LinqSelectReturnTypeTest() + { + string program = @"using System; +class TestClass { static void M() { + $(from a in new XYZ() select a.ToUpper())$.ToString(); +}} +class XYZ { + public int Select(Func f) { return 42; } +}"; + ResolveResult rr = Resolve(program); + Assert.AreEqual("System.Int32", rr.Type.FullName); + } + + [Test] + public void LinqQueryContinuationTest() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + var r = from x in input + select x.GetHashCode() into x + where x == 42 + select x * x; + r.ToString(); + } +} +"; + LocalResolveResult lrr = Resolve(program.Replace("from x", "from $x$")); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + lrr = Resolve(program.Replace("select x.G", "select $x$.G")); + Assert.AreEqual("System.String", lrr.Type.ReflectionName); + lrr = Resolve(program.Replace("into x", "into $x$")); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + lrr = Resolve(program.Replace("where x", "where $x$")); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + lrr = Resolve(program.Replace("select x * x", "select x * $x$")); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + + lrr = Resolve(program.Replace("r.ToString", "$r$.ToString")); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32]]", lrr.Type.ReflectionName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs new file mode 100644 index 0000000000..def97c563f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs @@ -0,0 +1,55 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class LocalTypeInferenceTests : ResolverTestBase + { + [Test] + public void TypeInferenceTest() + { + string program = @"class TestClass { + static void Test() { + var a = 3; + $a$.ToString(); + } +} +"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.FullName); + } + + [Test] + public void TypeInferenceCycleTest() + { + string program = @"class TestClass { + static void Test() { + var a = a; + $a$.ToString(); + } +} +"; + var lrr = Resolve(program); + Assert.AreSame(SharedTypes.UnknownType, lrr.Type); + } + + [Test] + public void InvalidAnonymousTypeDeclaration() + { + // see SD-1393 + string program = @"using System; +class TestClass { + static void Main() { + var contact = {id = 54321}; + $contact$.ToString(); + } }"; + var lrr = Resolve(program); + Assert.AreEqual(SharedTypes.UnknownType, lrr.Type); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs new file mode 100644 index 0000000000..f3836eaaf8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs @@ -0,0 +1,809 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class NameLookupTests : ResolverTestBase + { + [Test] + public void SimpleNameLookupWithoutContext() + { + // nothing should be found without specifying any UsingScope - however, the resolver also must not crash + resolver.UsingScope = null; + Assert.IsTrue(resolver.ResolveSimpleName("System", new IType[0]).IsError); + } + + [Test] + public void SimpleNamespaceLookup() + { + NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("System", new IType[0]); + Assert.AreEqual("System", nrr.NamespaceName); + Assert.AreSame(SharedTypes.UnknownType, nrr.Type); + } + + [Test] + public void NamespaceInParentNamespaceLookup() + { + resolver.UsingScope = MakeUsingScope("System.Collections.Generic"); + NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("Text", new IType[0]); + Assert.AreEqual("System.Text", nrr.NamespaceName); + } + + [Test] + public void NamespacesAreNotImported() + { + AddUsing("System"); + Assert.IsTrue(resolver.ResolveSimpleName("Collections", new IType[0]).IsError); + } + + [Test] + public void ImportedType() + { + AddUsing("System"); + TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("String", new IType[0]); + Assert.AreEqual("System.String", trr.Type.FullName); + } + + [Test] + public void UnknownIdentifierTest() + { + UnknownIdentifierResolveResult uirr = (UnknownIdentifierResolveResult)resolver.ResolveSimpleName("xyz", new IType[0]); + Assert.IsTrue(uirr.IsError); + Assert.AreEqual("xyz", uirr.Identifier); + } + + [Test] + public void GlobalIsUnknownIdentifier() + { + Assert.IsTrue(resolver.ResolveSimpleName("global", new IType[0]).IsError); + } + + [Test] + public void GlobalIsAlias() + { + NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveAlias("global"); + Assert.AreEqual("", nrr.NamespaceName); + } + + [Test] + public void AliasToImportedType() + { + AddUsing("System"); + AddUsingAlias("x", "String"); + TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); + // Unknown type (as String isn't looked up in System) + Assert.AreSame(SharedTypes.UnknownType, trr.Type); + } + + [Test] + public void AliasToImportedType2() + { + AddUsing("System"); + resolver.UsingScope = new UsingScope(resolver.UsingScope, "SomeNamespace"); + AddUsingAlias("x", "String"); + TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); + Assert.AreEqual("System.String", trr.Type.FullName); + } + + [Test] + public void AliasOperatorOnTypeAlias() + { + AddUsingAlias("x", "System.String"); + Assert.IsTrue(resolver.ResolveAlias("x").IsError); + } + + [Test] + public void AliasOperatorOnNamespaceAlias() + { + AddUsingAlias("x", "System.Collections.Generic"); + NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveAlias("x"); + Assert.AreEqual("System.Collections.Generic", nrr.NamespaceName); + } + + [Test] + public void AliasOperatorOnNamespace() + { + Assert.IsTrue(resolver.ResolveAlias("System").IsError); + } + + [Test] + public void FindClassInCurrentNamespace() + { + resolver.UsingScope = MakeUsingScope("System.Collections"); + TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("String", new IType[0]); + Assert.AreEqual("System.String", trr.Type.FullName); + } + + [Test] + public void FindNeighborNamespace() + { + resolver.UsingScope = MakeUsingScope("System.Collections"); + NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("Text", new IType[0]); + Assert.AreEqual("System.Text", nrr.NamespaceName); + } + + [Test] + public void FindTypeParameters() + { + resolver.UsingScope = MakeUsingScope("System.Collections.Generic"); + resolver.CurrentTypeDefinition = context.GetTypeDefinition(typeof(List<>)); + resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.Single(m => m.Name == "ConvertAll"); + + TypeResolveResult trr; + trr = (TypeResolveResult)resolver.ResolveSimpleName("TOutput", new IType[0]); + Assert.AreSame(((IMethod)resolver.CurrentMember).TypeParameters[0], trr.Type); + + trr = (TypeResolveResult)resolver.ResolveSimpleName("T", new IType[0]); + Assert.AreSame(resolver.CurrentTypeDefinition.TypeParameters[0], trr.Type); + } + + [Test] + public void SimpleParameter() + { + string program = @"class A { + void Method(string a) { + string b = $a$; + } +} +"; + LocalResolveResult result = Resolve(program); + Assert.AreEqual("a", result.Variable.Name); + Assert.IsTrue(result.IsParameter); + Assert.AreEqual("System.String", result.Type.FullName); + } + + [Test] + public void SimpleLocalVariable() + { + string program = @"class A { + void Method() { + string a; + string b = $a$; + } +} +"; + LocalResolveResult result = Resolve(program); + Assert.AreEqual("a", result.Variable.Name); + Assert.IsFalse(result.IsParameter); + + Assert.AreEqual("System.String", result.Type.FullName); + } + + [Test] + public void UnknownTypeTest() + { + string program = @"class A { + void Method($StringBuilder$ b) { + } +} +"; + UnknownIdentifierResolveResult result = Resolve(program); + Assert.AreEqual("StringBuilder", result.Identifier); + + Assert.AreSame(SharedTypes.UnknownType, result.Type); + } + + [Test] + public void PropertyNameAmbiguousWithTypeName() + { + string program = @"class A { + public Color Color { get; set; } + + void Method() { + $ + } +} +class Color { public static readonly Color Empty = null; } +"; + TypeResolveResult trr = Resolve(program.Replace("$", "$Color$ c;")); + Assert.AreEqual("Color", trr.Type.Name); + + MemberResolveResult mrr = Resolve(program.Replace("$", "x = $Color$;")); + Assert.AreEqual("Color", mrr.Member.Name); + + Resolve(program.Replace("$", "$Color$ = Color.Empty;")); + Resolve(program.Replace("$", "Color = $Color$.Empty;")); + Resolve(program.Replace("$", "x = $Color$.ToString();")); + } + + [Test] + public void ValueInsideSetterTest() + { + string program = @"class A { + public string Property { + set { + var a = $value$; + } + } +} +"; + LocalResolveResult result = Resolve(program); + Assert.AreEqual("System.String", result.Type.FullName); + Assert.AreEqual("value", result.Variable.Name); + } + + [Test] + public void ValueInsideEventTest() + { + string program = @"using System; class A { + public event EventHandler Ev { + add { + var a = $value$; + } + remove {} + } +} +"; + LocalResolveResult result = Resolve(program); + Assert.AreEqual("System.EventHandler", result.Type.FullName); + Assert.AreEqual("value", result.Variable.Name); + } + + [Test] + public void ValueInsideIndexerSetterTest() + { + string program = @"using System; class A { + public string this[int arg] { + set { + var a = $value$; + } + } +} +"; + LocalResolveResult result = Resolve(program); + Assert.AreEqual("System.String", result.Type.FullName); + Assert.AreEqual("value", result.Variable.Name); + } + + [Test, Ignore("Anonymous methods not supported in resolver")] + public void AnonymousMethodParameters() + { + string program = @"using System; +class A { + void Method() { + SomeEvent += delegate(object sender, EventArgs e) { + $e$.ToString(); + }; + } } +"; + LocalResolveResult result = Resolve(program); + Assert.AreEqual("System.EventArgs", result.Type.FullName); + Assert.AreEqual("e", result.Variable.Name); + } + + [Test] + public void DefaultTypeCSharp() + { + string program = @"class A { + void Method() { + $int$ a; + } } +"; + TypeResolveResult result = Resolve(program); + Assert.AreEqual("System.Int32", result.Type.FullName); + } + + [Test] + public void LoopVariableScopeTest() + { + string program = @"using System; +class TestClass { + void Test() { + for (int i = 0; i < 10; i++) { + $1$.ToString(); + } + for (long i = 0; i < 10; i++) { + $2$.ToString(); + } + } +} +"; + LocalResolveResult lr = Resolve(program.Replace("$1$", "$i$").Replace("$2$", "i")); + Assert.AreEqual("System.Int32", lr.Type.ReflectionName); + + lr = Resolve(program.Replace("$1$", "i").Replace("$2$", "$i$")); + Assert.AreEqual("System.Int64", lr.Type.ReflectionName); + } + + [Test] + public void NamespacePreferenceTest() + { + // Classes in the current namespace are preferred over classes from + // imported namespaces + string program = @"using System; +namespace Testnamespace { +class A { + $Activator$ a; +} + +class Activator { + +} +} +"; + var result = Resolve(program); + Assert.AreEqual("Testnamespace.Activator", result.Type.FullName); + } + + [Test] + public void ParentNamespaceTypeLookup() + { + string program = @"using System; +namespace Root { + class Alpha {} +} +namespace Root.Child { + class Beta { + $Alpha$ a; + } +} +"; + var result = Resolve(program); + Assert.AreEqual("Root.Alpha", result.Type.FullName); + } + + [Test] + public void ImportAliasTest() + { + string program = @"using COL = System.Collections; +class TestClass { + COL.ArrayList ff; +} +"; + TypeResolveResult type = Resolve(program, "COL.ArrayList"); + Assert.IsNotNull(type, "COL.ArrayList should resolve to a type"); + Assert.AreEqual("System.Collections.ArrayList", type.Type.FullName, "TypeResolveResult"); + + MemberResolveResult member = Resolve(program, "ff"); + Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved"); + } + + [Test] + public void ImportAliasNamespaceResolveTest() + { + NamespaceResolveResult ns; + string program = "using COL = System.Collections;\r\nclass A {\r\n$.ArrayList a;\r\n}\r\n"; + ns = Resolve(program.Replace("$", "$COL$")); + Assert.AreEqual("System.Collections", ns.NamespaceName, "COL"); + ns = Resolve(program.Replace("$", "$COL.Generic$")); + Assert.AreEqual("System.Collections.Generic", ns.NamespaceName, "COL.Generic"); + } + + [Test] + public void ImportAliasClassResolveTest() + { + string program = @"using COL = System.Collections.ArrayList; +class TestClass { + void Test() { + COL a = new COL(); + + } +} +"; + TypeResolveResult trr = Resolve(program.Replace("COL a", "$COL$ a")); + Assert.AreEqual("System.Collections.ArrayList", trr.Type.FullName, "COL"); + ResolveResult rr = Resolve(program.Replace("new COL()", "$new COL()$")); + Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a"); + } + + [Test] + public void ImportSubnamespaceWithAliasTest() + { + string program = @"namespace PC +{ + // Define an alias for the nested namespace. + using Project = PC.MyCompany.Project; + class A + { + Project.MyClass M() + { + // Use the alias + $Project.MyClass$ mc = new Project.MyClass(); + return mc; + } + } + namespace MyCompany + { + namespace Project + { + public class MyClass { } + } + } +} +"; + var mrr = Resolve(program); + Assert.AreEqual("PC.MyCompany.Project.MyClass", mrr.Type.FullName); + } + + [Test] + public void ResolveNamespaceSD_863() + { + string program = @"using System; +namespace A.C { class D {} } +namespace A.B.C { class D {} } +namespace A.B { + class TestClass { + void Test() { + C.D x; + } + } +} +"; + NamespaceResolveResult nrr = Resolve(program.Replace("C.D", "$C$.D")); + Assert.AreEqual("A.B.C", nrr.NamespaceName, "nrr.Name"); + TypeResolveResult trr = Resolve(program.Replace("C.D", "$C.D$")); + Assert.AreEqual("A.B.C.D", trr.Type.FullName); + } + + [Test] + public void ResolveTypeSD_863() + { + string program = @"using System; +namespace A { class C {} } +namespace A.B { + class C {} + class TestClass { + void Test() { + $C$ a; + } + } +} +"; + TypeResolveResult trr = Resolve(program); + Assert.AreEqual("A.B.C", trr.Type.FullName); + } + + + [Test] + public void InnerTypeResolve () + { + string program = @"public class C { public class Inner { } } +class TestClass { + void Test() { + $C.Inner$ a; + } +} +"; + TypeResolveResult trr = Resolve(program); + Assert.AreEqual("C.Inner", trr.Type.FullName); + + program = @"public class C { public class D { public class Inner { } }} +class TestClass { + void Test() { + $C.D.Inner$ a; + } +} +"; + trr = Resolve(program); + Assert.AreEqual("C.D.Inner", trr.Type.FullName); + } + + [Test, Ignore("parser is broken and produces IdentifierExpression instead of PrimitiveType")] + public void ShortMaxValueTest() + { + string program = @"using System; +class TestClass { + object a = $short.MaxValue$; +} +"; + MemberResolveResult rr = Resolve(program); + Assert.AreEqual("System.Int16", rr.Type.FullName); + Assert.AreEqual("System.Int16.MaxValue", rr.Member.FullName); + Assert.AreEqual(short.MaxValue, rr.ConstantValue); + } + + [Test] + public void ClassWithSameNameAsNamespace() + { + string program = @"using System; namespace XX { + class Test { + static void X() { + a = $; + } + } + class XX { + public static void Test() {} + } }"; + TypeResolveResult trr = Resolve(program.Replace("$", "$XX$")); + Assert.AreEqual("XX.XX", trr.Type.FullName); + + NamespaceResolveResult nrr = Resolve(program.Replace("$", "$global::XX$.T")); + Assert.AreEqual("XX", nrr.NamespaceName); + + trr = Resolve(program.Replace("$", "$global::XX.XX$")); + Assert.AreEqual("XX.XX", trr.Type.FullName); + + MemberResolveResult mrr = Resolve(program.Replace("$", "$XX.Test()$")); + Assert.AreEqual("XX.XX.Test", mrr.Member.FullName); + } + + [Test] + public void ClassNameLookup1() + { + string program = @"namespace MainNamespace { + using Test.Subnamespace; + class Program { + static void M($Test.TheClass$ c) {} + } +} + +namespace Test { public class TheClass { } } +namespace Test.Subnamespace { + public class Test { public class TheClass { } } +} +"; + TypeResolveResult trr = Resolve(program); + Assert.AreEqual("Test.Subnamespace.Test.TheClass", trr.Type.FullName); + } + + [Test] + public void ClassNameLookup2() + { + string program = @"using Test.Subnamespace; +namespace MainNamespace { + class Program { + static void M($Test.TheClass$ c) {} + } +} + +namespace Test { public class TheClass { } } +namespace Test.Subnamespace { + public class Test { public class TheClass { } } +} +"; + TypeResolveResult trr = Resolve(program); + Assert.AreEqual("Test.TheClass", trr.Type.FullName); + } + + [Test] + public void ClassNameLookup3() + { + string program = @"namespace MainNamespace { + using Test.Subnamespace; + class Program { + static void M($Test$ c) {} + } +} + +namespace Test { public class TheClass { } } +namespace Test.Subnamespace { + public class Test { public class TheClass { } } +} +"; + TypeResolveResult trr = Resolve(program); + Assert.AreEqual("Test.Subnamespace.Test", trr.Type.FullName); + } + + [Test] + public void ClassNameLookup4() + { + string program = @"using Test.Subnamespace; +namespace MainNamespace { + class Program { + static void M($Test$ c) {} + } +} + +namespace Test { public class TheClass { } } +namespace Test.Subnamespace { + public class Test { public class TheClass { } } +} +"; + NamespaceResolveResult nrr = Resolve(program); + Assert.AreEqual("Test", nrr.NamespaceName); + } + + [Test] + public void ClassNameLookup5() + { + string program = @"namespace MainNamespace { + using A; + + class M { + void X($Test$ a) {} + } + namespace Test { class B {} } +} + +namespace A { + class Test {} +}"; + NamespaceResolveResult nrr = Resolve(program); + Assert.AreEqual("MainNamespace.Test", nrr.NamespaceName); + } + + [Test] + public void InvocableRule() + { + string program = @"using System; + class DerivedClass : BaseClass { + static void X() { + a = $; + } + private static new int Test; + } + class BaseClass { + public static string Test() {} + }"; + MemberResolveResult mrr = Resolve(program.Replace("$", "$BaseClass.Test()$")); + Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$Test$")); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$DerivedClass.Test$")); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + + // returns BaseClass.Test because DerivedClass.Test is not invocable + mrr = Resolve(program.Replace("$", "$DerivedClass.Test()$")); + Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); + } + + [Test] + public void InvocableRule2() + { + string program = @"using System; + class DerivedClass : BaseClass { + static void X() { + a = $; + } + private static new int Test; + } + delegate string SomeDelegate(); + class BaseClass { + public static SomeDelegate Test; + }"; + MemberResolveResult mrr = Resolve(program.Replace("$", "$BaseClass.Test$()")); + Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$Test$")); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$DerivedClass.Test$")); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + + // returns BaseClass.Test because DerivedClass.Test is not invocable + mrr = Resolve(program.Replace("$", "$DerivedClass.Test$()")); + Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); + } + + [Test] + public void AccessibleRule() + { + string program = @"using System; + class BaseClass { + static void X() { + a = $DerivedClass.Test$; + } + public static int Test; + } + class DerivedClass : BaseClass { + private static new int Test; + } + "; + // returns BaseClass.Test because DerivedClass.Test is not accessible + MemberResolveResult mrr = Resolve(program); + Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); + } + + [Test] + public void FieldHidingProperty() + { + string program = @"using System; + class DerivedClass : BaseClass { + static void X() { + a = $Test$; + } + public static new int Test; + } + class BaseClass { + public static int Test { get { return 0; } } + } + "; + MemberResolveResult mrr = Resolve(program); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + } + + [Test] + public void PropertyHidingField() + { + string program = @"using System; + class DerivedClass : BaseClass { + static void X() { + a = $Test$; + } + public static new int Test { get { return 0; } } + } + class BaseClass { + public static int Test; + } + "; + MemberResolveResult mrr = Resolve(program); + Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); + } + + [Test, Ignore("Resolver Bug")] + public void SD_1487() + { + string program = @"using System; +class C2 : C1 { + public static void M() { + a = $; + } +} +class C1 { + protected static int Field; +}"; + MemberResolveResult mrr; + mrr = Resolve(program.Replace("$", "$Field$")); + Assert.AreEqual("C1.Field", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$C1.Field$")); + Assert.AreEqual("C1.Field", mrr.Member.FullName); + + mrr = Resolve(program.Replace("$", "$C2.Field$")); + Assert.AreEqual("C1.Field", mrr.Member.FullName); + } + + [Test] + public void NullableValue() + { + string program = @"using System; +class Test { + public static void M(int? a) { + $a.Value$.ToString(); + } +}"; + MemberResolveResult rr = Resolve(program); + Assert.AreEqual("System.Nullable.Value", rr.Member.FullName); + Assert.AreEqual("System.Int32", rr.Member.ReturnType.Resolve(context).FullName); + } + + [Test, Ignore("Resolver bug")] + public void MethodHidesEvent() + { + // see SD-1542 + string program = @"using System; +class Test : Form { + public Test() { + a = $base.KeyDown$; + } + void KeyDown(object sender, EventArgs e) {} +} +class Form { + public event EventHandler KeyDown; +}"; + var mrr = Resolve(program); + Assert.AreEqual("Form.KeyDown", mrr.Member.FullName); + + var mgrr = Resolve(program.Replace("base", "this")); + Assert.AreEqual("Test.KeyDown", mgrr.Methods.Single().FullName); + } + + [Test, Ignore("partial classes not yet supported")] + public void ProtectedMemberVisibleWhenBaseTypeReferenceIsInOtherPart() + { + string program = @"using System; +partial class A { + void M1() { + $x$ = 0; + } +} +partial class A : B { } +class B +{ + protected int x; +}"; + var mrr = Resolve(program); + Assert.AreEqual("B.x", mrr.Member.FullName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs new file mode 100644 index 0000000000..d3a130212c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -0,0 +1,135 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class ObjectCreationTests : ResolverTestBase + { + [Test] + public void GenericObjectCreation() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new List()$; + } +} +"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("System.Collections.Generic.List..ctor", result.Member.FullName); + + Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", result.Type.ReflectionName); + } + + [Test] + public void NonExistingClass() + { + string program = @"class A { + void Method() { + var a = $new ThisClassDoesNotExist()$; + } +} +"; + ResolveResult result = Resolve(program); + Assert.AreSame(SharedTypes.UnknownType, result.Type); + } + + [Test] + public void NonExistingClassTypeName() + { + string program = @"class A { + void Method() { + var a = new $ThisClassDoesNotExist$(); + } +} +"; + UnknownIdentifierResolveResult result = Resolve(program); + Assert.AreEqual("ThisClassDoesNotExist", result.Identifier); + Assert.AreSame(SharedTypes.UnknownType, result.Type); + } + + [Test] + public void CTorOverloadLookupTest() + { + string program = @"class A { + void Method() { + $; + } + + static A() {} + A() {} + A(int intVal) {} + A(double dblVal) {} +} +"; + MemberResolveResult result = Resolve(program.Replace("$", "$new A()$")); + IMethod m = (IMethod)result.Member; + Assert.IsFalse(m.IsStatic, "new A() is static"); + Assert.AreEqual(0, m.Parameters.Count, "new A() parameter count"); + Assert.AreEqual("A", result.Type.FullName); + + result = Resolve(program.Replace("$", "$new A(10)$")); + m = (IMethod)result.Member; + Assert.AreEqual(1, m.Parameters.Count, "new A(10) parameter count"); + Assert.AreEqual("intVal", m.Parameters[0].Name, "new A(10) parameter"); + + result = Resolve(program.Replace("$", "$new A(11.1)$")); + m = (IMethod)result.Member; + Assert.AreEqual(1, m.Parameters.Count, "new A(11.1) parameter count"); + Assert.AreEqual("dblVal", m.Parameters[0].Name, "new A(11.1) parameter"); + } + + [Test] + public void DefaultCTorOverloadLookupTest() + { + string program = @"class A { + void Method() { + $new A()$; + } +} +"; + MemberResolveResult result = Resolve(program); + IMethod m = (IMethod)result.Member; + Assert.IsNotNull(m); + Assert.AreEqual("A", result.Type.ReflectionName); + Assert.AreEqual(0, m.Parameters.Count); + } + + [Test, Ignore("Not implemented")] + public void ChainedConstructorCall() + { + string program = @"using System; +class A { + public A(int a) {} +} +class B : A { + public B(int b) + : base(b) + {} +} +class C : B { + public C(int c) + : base(c) + {} + + public C() + : this(0) + {} +} +"; + MemberResolveResult mrr = Resolve(program, "base(b)"); + Assert.AreEqual("A..ctor", mrr.Member.FullName); + + mrr = Resolve(program, "base(c)"); + Assert.AreEqual("B..ctor", mrr.Member.FullName); + + mrr = Resolve(program, "this(0)"); + Assert.AreEqual("C..ctor", mrr.Member.FullName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs new file mode 100644 index 0000000000..f1701156ce --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs @@ -0,0 +1,185 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class OverloadResolutionTests + { + readonly ITypeResolveContext context = CecilLoaderTests.Mscorlib; + readonly DefaultTypeDefinition dummyClass = new DefaultTypeDefinition(CecilLoaderTests.Mscorlib, string.Empty, "DummyClass"); + + ResolveResult[] MakeArgumentList(params Type[] argumentTypes) + { + return argumentTypes.Select(t => new ResolveResult(t.ToTypeReference().Resolve(context))).ToArray(); + } + + DefaultMethod MakeMethod(params object[] parameterTypesOrDefaultValues) + { + DefaultMethod m = new DefaultMethod(dummyClass, "Method"); + foreach (var typeOrDefaultValue in parameterTypesOrDefaultValues) { + Type type = typeOrDefaultValue as Type; + if (type != null) + m.Parameters.Add(new DefaultParameter(type.ToTypeReference(), string.Empty)); + else if (Type.GetTypeCode(typeOrDefaultValue.GetType()) > TypeCode.Object) + m.Parameters.Add(new DefaultParameter(typeOrDefaultValue.GetType().ToTypeReference(), string.Empty) { + DefaultValue = new SimpleConstantValue(typeOrDefaultValue.GetType().ToTypeReference(), typeOrDefaultValue) + }); + else + throw new ArgumentException(typeOrDefaultValue.ToString()); + } + return m; + } + + DefaultMethod MakeParamsMethod(params object[] parameterTypesOrDefaultValues) + { + DefaultMethod m = MakeMethod(parameterTypesOrDefaultValues); + ((DefaultParameter)m.Parameters.Last()).IsParams = true; + return m; + } + + DefaultParameter MakeOptionalParameter(IType type, string name) + { + return new DefaultParameter(type, name) { + DefaultValue = new SimpleConstantValue(type, null) + }; + } + + [Test] + public void PreferIntOverUInt() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(ushort))); + var c1 = MakeMethod(typeof(int)); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(c1)); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint)))); + Assert.IsFalse(r.IsAmbiguous); + Assert.AreSame(c1, r.BestCandidate); + } + + [Test] + public void NullableIntAndNullableUIntIsAmbiguous() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(ushort?))); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(int?)))); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(uint?)))); + Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors); + + // then adding a matching overload solves the ambiguity: + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeMethod(typeof(ushort?)))); + Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); + Assert.IsNull(r.BestCandidateAmbiguousWith); + } + + [Test] + public void ParamsMethodMatchesEmptyArgumentList() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList()); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); + Assert.IsTrue(r.BestCandidateIsExpandedForm); + } + + [Test] + public void ParamsMethodMatchesOneArgumentInExpandedForm() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int))); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); + Assert.IsTrue(r.BestCandidateIsExpandedForm); + } + + [Test] + public void ParamsMethodMatchesInUnexpandedForm() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int[]))); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); + Assert.IsFalse(r.BestCandidateIsExpandedForm); + } + + [Test] + public void LessArgumentsPassedToParamsIsBetter() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int), typeof(int), typeof(int))); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int[])))); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(MakeParamsMethod(typeof(int), typeof(int[])))); + Assert.IsFalse(r.IsAmbiguous); + Assert.AreEqual(2, r.BestCandidate.Parameters.Count); + } + + [Test] + public void CallInvalidParamsDeclaration() + { + OverloadResolution r = new OverloadResolution(context, MakeArgumentList(typeof(int[,]))); + Assert.AreEqual(OverloadResolutionErrors.ArgumentTypeMismatch, r.AddCandidate(MakeParamsMethod(typeof(int)))); + Assert.IsFalse(r.BestCandidateIsExpandedForm); + } + + [Test] + public void PreferMethodWithoutOptionalParameters() + { + var m1 = MakeMethod(); + var m2 = MakeMethod(1); + + OverloadResolution r = new OverloadResolution(context, MakeArgumentList()); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); + Assert.IsFalse(r.IsAmbiguous); + Assert.AreSame(m1, r.BestCandidate); + } + + [Test] + public void SkeetEvilOverloadResolution() + { + // http://msmvps.com/blogs/jon_skeet/archive/2010/11/02/evil-code-overload-resolution-workaround.aspx + + // static void Foo(T? ignored = default(T?)) where T : struct + var m1 = MakeMethod(); + m1.TypeParameters.Add(new DefaultTypeParameter(EntityType.Method, 0, "T") { HasValueTypeConstraint = true }); + m1.Parameters.Add(MakeOptionalParameter( + NullableType.Create(m1.TypeParameters[0], context), + "ignored" + )); + + // class ClassConstraint where T : class {} + DefaultTypeDefinition classConstraint = new DefaultTypeDefinition(dummyClass, "ClassConstraint"); + classConstraint.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T") { HasReferenceTypeConstraint = true }); + + // static void Foo(ClassConstraint ignored = default(ClassConstraint)) + // where T : class + var m2 = MakeMethod(); + m2.TypeParameters.Add(new DefaultTypeParameter(EntityType.Method, 0, "T") { HasReferenceTypeConstraint = true }); + m2.Parameters.Add(MakeOptionalParameter( + new ParameterizedType(classConstraint, new[] { m2.TypeParameters[0] }), + "ignored" + )); + + // static void Foo() + var m3 = MakeMethod(); + m3.TypeParameters.Add(new DefaultTypeParameter(EntityType.Method, 0, "T")); + + // Call: Foo(); + OverloadResolution o; + o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(int).ToTypeReference().Resolve(context) }); + Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m2)); + Assert.AreSame(m1, o.BestCandidate); + + // Call: Foo(); + o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(string).ToTypeReference().Resolve(context) }); + Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m2)); + Assert.AreSame(m2, o.BestCandidate); + + // Call: Foo(); + o = new OverloadResolution(context, new ResolveResult[0], typeArguments: new[] { typeof(int?).ToTypeReference().Resolve(context) }); + Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint, o.AddCandidate(m2)); + Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m3)); + Assert.AreSame(m3, o.BestCandidate); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs new file mode 100644 index 0000000000..e93bcce1b1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs @@ -0,0 +1,207 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using ICSharpCode.NRefactory.CSharp.Parser; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Base class with helper functions for resolver unit tests. + /// + public abstract class ResolverTestBase + { + protected readonly IProjectContent mscorlib = CecilLoaderTests.Mscorlib; + protected SimpleProjectContent project; + protected ITypeResolveContext context; + protected CSharpResolver resolver; + + [SetUp] + public virtual void SetUp() + { + project = new SimpleProjectContent(); + context = new CompositeTypeResolveContext(new [] { project, mscorlib }); + resolver = new CSharpResolver(context); + resolver.UsingScope = MakeUsingScope(""); + } + + protected UsingScope MakeUsingScope(string namespaceName) + { + UsingScope u = new UsingScope(project); + if (!string.IsNullOrEmpty(namespaceName)) { + foreach (string element in namespaceName.Split('.')) { + u = new UsingScope(u, string.IsNullOrEmpty(u.NamespaceName) ? element : u.NamespaceName + "." + element); + } + } + return u; + } + + /// + /// Adds a using to the current using scope. + /// + protected void AddUsing(string namespaceName) + { + resolver.UsingScope.Usings.Add(MakeReference(namespaceName)); + } + + /// + /// Adds a using alias to the current using scope. + /// + protected void AddUsingAlias(string alias, string target) + { + resolver.UsingScope.UsingAliases.Add(new KeyValuePair(alias, MakeReference(target))); + } + + protected ITypeOrNamespaceReference MakeReference(string namespaceName) + { + string[] nameParts = namespaceName.Split('.'); + ITypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.UsingScope, true); + for (int i = 1; i < nameParts.Length; i++) { + r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.UsingScope); + } + return r; + } + + protected IType ResolveType(Type type) + { + IType t = type.ToTypeReference().Resolve(context); + if (t == SharedTypes.UnknownType) + throw new InvalidOperationException("Could not resolve type"); + return t; + } + + protected ConstantResolveResult MakeConstant(object value) + { + if (value == null) + return new ConstantResolveResult(SharedTypes.Null, null); + IType type = ResolveType(value.GetType()); + if (type.IsEnum()) + value = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())); + return new ConstantResolveResult(type, value); + } + + protected ResolveResult MakeResult(Type type) + { + return new ResolveResult(ResolveType(type)); + } + + protected void AssertConstant(object expectedValue, ResolveResult rr) + { + Assert.IsFalse(rr.IsError, rr.ToString() + " is an error"); + Assert.IsTrue(rr.IsCompileTimeConstant, rr.ToString() + " is not a compile-time constant"); + Type expectedType = expectedValue.GetType(); + Assert.AreEqual(ResolveType(expectedType), rr.Type, "ResolveResult.Type is wrong"); + if (expectedType.IsEnum) { + Assert.AreEqual(Enum.GetUnderlyingType(expectedType), rr.ConstantValue.GetType(), "ResolveResult.ConstantValue has wrong Type"); + Assert.AreEqual(Convert.ChangeType(expectedValue, Enum.GetUnderlyingType(expectedType)), rr.ConstantValue); + } else { + Assert.AreEqual(expectedType, rr.ConstantValue.GetType(), "ResolveResult.ConstantValue has wrong Type"); + Assert.AreEqual(expectedValue, rr.ConstantValue); + } + } + + protected void AssertType(Type expectedType, ResolveResult rr) + { + Assert.IsFalse(rr.IsError, rr.ToString() + " is an error"); + Assert.IsFalse(rr.IsCompileTimeConstant, rr.ToString() + " is a compile-time constant"); + Assert.AreEqual(expectedType.ToTypeReference().Resolve(context), rr.Type); + } + + protected void AssertError(Type expectedType, ResolveResult rr) + { + Assert.IsTrue(rr.IsError, rr.ToString() + " is not an error, but an error was expected"); + Assert.IsFalse(rr.IsCompileTimeConstant, rr.ToString() + " is a compile-time constant"); + Assert.AreEqual(expectedType.ToTypeReference().Resolve(context), rr.Type); + } + + IEnumerable FindDollarSigns(string code) + { + int line = 1; + int col = 1; + foreach (char c in code) { + if (c == '$') { + yield return new AstLocation(line, col); + } else if (c == '\n') { + line++; + col = 1; + } else { + col++; + } + } + } + + protected ResolveResult Resolve(string code) + { + CompilationUnit cu = new CSharpParser().Parse(new StringReader(code.Replace("$", ""))); + + AstLocation[] dollars = FindDollarSigns(code).ToArray(); + Assert.AreEqual(2, dollars.Length, "Expected 2 dollar signs marking start+end of desired node"); + + UsingScope rootUsingScope = resolver.UsingScope; + while (rootUsingScope.Parent != null) + rootUsingScope = rootUsingScope.Parent; + + ParsedFile parsedFile = new ParsedFile("test.cs", rootUsingScope); + TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.UsingScope, null); + cu.AcceptVisitor(convertVisitor, null); + project.UpdateProjectContent(null, convertVisitor.ParsedFile); + + FindNodeVisitor fnv = new FindNodeVisitor(dollars[0], dollars[1]); + cu.AcceptVisitor(fnv, null); + Assert.IsNotNull(fnv.ResultNode, "Did not find DOM node at the specified location"); + + var navigator = new NodeListResolveVisitorNavigator(new[] { fnv.ResultNode }); + ResolveResult rr; + using (var context = this.context.Synchronize()) { + ResolveVisitor rv = new ResolveVisitor(new CSharpResolver(context), convertVisitor.ParsedFile, navigator); + rv.Scan(cu); + rr = rv.GetResolveResult(fnv.ResultNode); + } + Assert.IsNotNull(rr, "ResolveResult is null - did something go wrong while navigating to the target node?"); + return rr; + } + + protected T Resolve(string code) where T : ResolveResult + { + ResolveResult rr = Resolve(code); + Assert.IsTrue(rr is T, "Resolve should be " + typeof(T).Name + ", but was " + (rr != null ? rr.GetType().Name : "null")); + return (T)rr; + } + + protected T Resolve(string code, string exprToResolve) where T : ResolveResult + { + return Resolve(code.Replace(exprToResolve, "$" + exprToResolve + "$")); + } + + sealed class FindNodeVisitor : DepthFirstAstVisitor + { + readonly AstLocation start; + readonly AstLocation end; + public AstNode ResultNode; + + public FindNodeVisitor(AstLocation start, AstLocation end) + { + this.start = start; + this.end = end; + } + + protected override object VisitChildren(AstNode node, object data) + { + if (node.StartLocation == start && node.EndLocation == end) { + if (ResultNode != null) + throw new InvalidOperationException("found multiple nodes with same start+end"); + return ResultNode = node; + } else { + return base.VisitChildren(node, data); + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs new file mode 100644 index 0000000000..21911d656d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs @@ -0,0 +1,201 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class TypeInferenceTests + { + readonly ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; + TypeInference ti; + + [SetUp] + public void Setup() + { + ti = new TypeInference(ctx); + } + + #region Type Inference + IType[] Resolve(params Type[] types) + { + IType[] r = new IType[types.Length]; + for (int i = 0; i < types.Length; i++) { + r[i] = types[i].ToTypeReference().Resolve(CecilLoaderTests.Mscorlib); + Assert.AreNotSame(r[i], SharedTypes.UnknownType); + } + Array.Sort(r, (a,b)=>a.ReflectionName.CompareTo(b.ReflectionName)); + return r; + } + + [Test] + public void ArrayToEnumerable() + { + ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); + IType stringType = KnownTypeReference.String.Resolve(ctx); + ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>)); + + bool success; + Assert.AreEqual( + new [] { stringType }, + ti.InferTypeArguments(new [] { tp }, + new [] { new ResolveResult(new ArrayType(stringType)) }, + new [] { new ParameterizedType(enumerableType, new [] { tp }) }, + out success)); + Assert.IsTrue(success); + } + + [Test] + public void EnumerableToArrayInContravariantType() + { + ITypeParameter tp = new DefaultTypeParameter(EntityType.Method, 0, "T"); + IType stringType = KnownTypeReference.String.Resolve(ctx); + ITypeDefinition enumerableType = ctx.GetTypeDefinition(typeof(IEnumerable<>)); + ITypeDefinition comparerType = ctx.GetTypeDefinition(typeof(IComparer<>)); + + var comparerOfIEnumerableOfString = new ParameterizedType(comparerType, new [] { new ParameterizedType(enumerableType, new [] { stringType} ) }); + var comparerOfTpArray = new ParameterizedType(comparerType, new [] { new ArrayType(tp) }); + + bool success; + Assert.AreEqual( + new [] { stringType }, + ti.InferTypeArguments(new [] { tp }, + new [] { new ResolveResult(comparerOfIEnumerableOfString) }, + new [] { comparerOfTpArray }, + out success)); + Assert.IsTrue(success); + } + #endregion + + #region FindTypeInBounds + IType[] FindAllTypesInBounds(IList lowerBounds, IList upperBounds = null) + { + ti.Algorithm = TypeInferenceAlgorithm.ImprovedReturnAllResults; + IType type = ti.FindTypeInBounds(lowerBounds, upperBounds ?? new IType[0]); + return ExpandIntersections(type).OrderBy(t => t.ReflectionName).ToArray(); + } + + static IEnumerable ExpandIntersections(IType type) + { + IntersectionType it = type as IntersectionType; + if (it != null) { + return it.Types.SelectMany(t => ExpandIntersections(t)); + } + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + IType[][] typeArguments = new IType[pt.TypeArguments.Count][]; + for (int i = 0; i < typeArguments.Length; i++) { + typeArguments[i] = ExpandIntersections(pt.TypeArguments[i]).ToArray(); + } + return AllCombinations(typeArguments).Select(ta => new ParameterizedType(pt.GetDefinition(), ta)); + } + return new [] { type }; + } + + /// + /// Performs the combinatorial explosion. + /// + static IEnumerable AllCombinations(IType[][] typeArguments) + { + int[] index = new int[typeArguments.Length]; + index[typeArguments.Length - 1] = -1; + while (true) { + int i; + for (i = index.Length - 1; i >= 0; i--) { + if (++index[i] == typeArguments[i].Length) + index[i] = 0; + else + break; + } + if (i < 0) + break; + IType[] r = new IType[typeArguments.Length]; + for (i = 0; i < r.Length; i++) { + r[i] = typeArguments[i][index[i]]; + } + yield return r; + } + } + + [Test] + public void ListOfShortAndInt() + { + Assert.AreEqual( + Resolve(typeof(IList)), + FindAllTypesInBounds(Resolve(typeof(List), typeof(List)))); + } + + [Test] + public void ListOfStringAndObject() + { + Assert.AreEqual( + Resolve(typeof(IList), typeof(IEnumerable)), + FindAllTypesInBounds(Resolve(typeof(List), typeof(List)))); + } + + [Test] + public void ListOfListOfStringAndObject() + { + Assert.AreEqual( + Resolve(typeof(IList), typeof(IEnumerable), typeof(IEnumerable>)), + FindAllTypesInBounds(Resolve(typeof(List>), typeof(List>)))); + } + + [Test] + public void ShortAndInt() + { + Assert.AreEqual( + Resolve(typeof(int)), + FindAllTypesInBounds(Resolve(typeof(short), typeof(int)))); + } + + [Test] + public void StringAndVersion() + { + Assert.AreEqual( + Resolve(typeof(ICloneable), typeof(IComparable)), + FindAllTypesInBounds(Resolve(typeof(string), typeof(Version)))); + } + + [Test] + public void CommonSubTypeClonableComparable() + { + Assert.AreEqual( + Resolve(typeof(string), typeof(Version)), + FindAllTypesInBounds(Resolve(), Resolve(typeof(ICloneable), typeof(IComparable)))); + } + + [Test] + public void EnumerableOfStringAndVersion() + { + Assert.AreEqual( + Resolve(typeof(IEnumerable), typeof(IEnumerable)), + FindAllTypesInBounds(Resolve(typeof(IList), typeof(IList)))); + } + + [Test] + public void CommonSubTypeIEnumerableClonableIEnumerableComparable() + { + Assert.AreEqual( + Resolve(typeof(IEnumerable), typeof(IEnumerable)), + FindAllTypesInBounds(Resolve(), Resolve(typeof(IEnumerable), typeof(IEnumerable)))); + } + + [Test] + public void CommonSubTypeIEnumerableClonableIEnumerableComparableList() + { + Assert.AreEqual( + Resolve(typeof(List), typeof(List), typeof(Collection), typeof(Collection), typeof(ReadOnlyCollection), typeof(ReadOnlyCollection)), + FindAllTypesInBounds(Resolve(), Resolve(typeof(IEnumerable), typeof(IEnumerable), typeof(IList)))); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs new file mode 100644 index 0000000000..7793efc31c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs @@ -0,0 +1,147 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + // assign short name to the fake reflection type + using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; + + [TestFixture] + public unsafe class UnaryOperatorTests : ResolverTestBase + { + [Test] + public void TestAddressOf() + { + AssertType(typeof(int*), resolver.ResolveUnaryOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(int)))); + AssertType(typeof(byte**), resolver.ResolveUnaryOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(byte*)))); + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(dynamic)))); + } + + [Test] + public void TestDereference() + { + AssertType(typeof(int), resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(int*)))); + AssertType(typeof(long*), resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(long**)))); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(int))).IsError); + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(dynamic)))); + } + + [Test] + public void TestIncrementDecrement() + { + AssertType(typeof(byte), resolver.ResolveUnaryOperator(UnaryOperatorType.Increment, MakeResult(typeof(byte)))); + AssertType(typeof(ulong), resolver.ResolveUnaryOperator(UnaryOperatorType.Decrement, MakeResult(typeof(ulong)))); + AssertType(typeof(short?), resolver.ResolveUnaryOperator(UnaryOperatorType.PostDecrement, MakeResult(typeof(short?)))); + AssertType(typeof(TypeCode), resolver.ResolveUnaryOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(TypeCode)))); + AssertType(typeof(TypeCode?), resolver.ResolveUnaryOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(TypeCode?)))); + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(dynamic)))); + AssertError(typeof(object), resolver.ResolveUnaryOperator(UnaryOperatorType.Increment, MakeResult(typeof(object)))); + + AssertType(typeof(int*), resolver.ResolveUnaryOperator(UnaryOperatorType.Increment, MakeResult(typeof(int*)))); + AssertType(typeof(uint*), resolver.ResolveUnaryOperator(UnaryOperatorType.PostDecrement, MakeResult(typeof(uint*)))); + } + + [Test] + public void TestUnaryPlus() + { + AssertConstant(1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((sbyte)1))); + AssertConstant(1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((byte)1))); + AssertConstant(1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((short)1))); + AssertConstant(1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((ushort)1))); + AssertConstant(65, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant('A'))); + AssertConstant(1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant(1))); + AssertConstant((uint)1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((uint)1))); + AssertConstant(1L, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((long)1))); + AssertConstant((ulong)1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((ulong)1))); + + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeResult(typeof(dynamic)))); + AssertType(typeof(int?), resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeResult(typeof(ushort?)))); + } + + [Test] + public void TestUnaryMinus() + { + AssertConstant(-1, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(1))); + AssertConstant(-1L, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant((uint)1))); + AssertConstant(-2147483648L, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(2147483648))); + AssertConstant(-1.0f, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(1.0f))); + AssertConstant(-1.0, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(1.0))); + AssertConstant(1m, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(-1m))); + AssertConstant(-65, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant('A'))); + + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeResult(typeof(dynamic)))); + AssertType(typeof(long?), resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeResult(typeof(uint?)))); + } + + [Test] + public void TestUnaryMinusUncheckedOverflow() + { + AssertConstant(-2147483648, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(-2147483648))); + } + + [Test] + public void TestUnaryMinusCheckedOverflow() + { + resolver.CheckForOverflow = true; + AssertError(typeof(int), resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(-2147483648))); + } + + [Test] + public void TestBitwiseNot() + { + AssertConstant(1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant(-2))); + AssertConstant(~'A', resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant('A'))); + AssertConstant(~(sbyte)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((sbyte)1))); + AssertConstant(~(byte)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((byte)1))); + AssertConstant(~(short)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((short)1))); + AssertConstant(~(ushort)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((ushort)1))); + AssertConstant(~(uint)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((uint)1))); + AssertConstant(~(long)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((long)1))); + AssertConstant(~(ulong)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((ulong)1))); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant(1.0)).IsError); + + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(dynamic)))); + AssertType(typeof(uint), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(uint)))); + AssertType(typeof(int?), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(ushort?)))); + } + + [Test] + public void TestLogicalNot() + { + AssertConstant(true, resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeConstant(false))); + AssertConstant(false, resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeConstant(true))); + AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(dynamic)))); + AssertType(typeof(bool), resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(bool)))); + AssertType(typeof(bool?), resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(bool?)))); + } + + [Test] + public void TestInvalidUnaryOperatorsOnEnum() + { + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeConstant(StringComparison.Ordinal)).IsError); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant(StringComparison.Ordinal)).IsError); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(StringComparison.Ordinal)).IsError); + + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(StringComparison))).IsError); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeResult(typeof(StringComparison))).IsError); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeResult(typeof(StringComparison))).IsError); + + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(StringComparison?))).IsError); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeResult(typeof(StringComparison?))).IsError); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeResult(typeof(StringComparison?))).IsError); + } + + [Test] + public void TestBitwiseNotOnEnum() + { + AssertConstant(~StringComparison.Ordinal, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant(StringComparison.Ordinal))); + AssertConstant(~StringComparison.CurrentCultureIgnoreCase, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant(StringComparison.CurrentCultureIgnoreCase))); + AssertType(typeof(StringComparison), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(StringComparison)))); + AssertType(typeof(StringComparison?), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(StringComparison?)))); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs new file mode 100644 index 0000000000..a336cd23c0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class UnsafeCodeTests : ResolverTestBase + { + [Test, Ignore("Parser returns incorrect positions")] + public void FixedStatement() + { + string program = @"using System; +class TestClass { + static void Main(byte[] a) { + fixed (byte* p = a) { + a = $p$; + } } }"; + + var lrr = Resolve(program); + Assert.AreEqual("System.Byte*", lrr.Type.ReflectionName); + + var rr = Resolve(program.Replace("$p$", "$*p$")); + Assert.AreEqual("System.Byte", lrr.Type.ReflectionName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs new file mode 100644 index 0000000000..7557859e6d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs @@ -0,0 +1,286 @@ +// +// TastBlankLineFormatting.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + [Ignore ("TODO")] + [TestFixture()] + public class TestBlankLineFormatting : TestBase + { + [Test()] + public void TestBlankLinesAfterUsings () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesAfterUsings = 2; + + var adapter = Test (policy, @"using System; +using System.Text; +namespace Test +{ +}", +@"using System; +using System.Text; + + +namespace Test +{ +}"); + + policy.BlankLinesAfterUsings = 0; + Continue (policy, adapter, +@"using System; +using System.Text; +namespace Test +{ +}"); + } + + [Test()] + public void TestBlankLinesBeforeUsings () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesAfterUsings = 0; + policy.BlankLinesBeforeUsings = 2; + + var adapter = Test (policy, @"using System; +using System.Text; +namespace Test +{ +}", +@" + +using System; +using System.Text; +namespace Test +{ +}"); + + policy.BlankLinesBeforeUsings = 0; + Continue (policy, adapter, +@"using System; +using System.Text; +namespace Test +{ +}"); + } + + [Test()] + public void TestBlankLinesBeforeFirstDeclaration () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesBeforeFirstDeclaration = 2; + + var adapter = Test (policy, @"namespace Test +{ + class Test + { + } +}", +@"namespace Test +{ + + + class Test + { + } +}"); + + policy.BlankLinesBeforeFirstDeclaration = 0; + Continue (policy, adapter, +@"namespace Test +{ + class Test + { + } +}"); + } + + [Test()] + public void TestBlankLinesBetweenTypes () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesBetweenTypes = 1; + + var adapter = Test (policy, @"namespace Test +{ + class Test1 + { + } + class Test2 + { + } + class Test3 + { + } +}", +@"namespace Test +{ + class Test1 + { + } + + class Test2 + { + } + + class Test3 + { + } +}"); + + policy.BlankLinesBetweenTypes = 0; + Continue (policy, adapter, @"namespace Test +{ + class Test1 + { + } + class Test2 + { + } + class Test3 + { + } +}"); + } + + [Test()] + public void TestBlankLinesBetweenFields () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesBetweenFields = 1; + + var adapter = Test (policy, @"class Test +{ + int a; + int b; + int c; +}", +@"class Test +{ + int a; + + int b; + + int c; +}"); + + policy.BlankLinesBetweenFields = 0; + Continue (policy, adapter, @"class Test +{ + int a; + int b; + int c; +}"); + } + + [Test()] + public void TestBlankLinesBetweenEventFields () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesBetweenEventFields = 1; + + var adapter = Test (policy, @"class Test +{ + public event EventHandler a; + public event EventHandler b; + public event EventHandler c; +}", +@"class Test +{ + public event EventHandler a; + + public event EventHandler b; + + public event EventHandler c; +}"); + + policy.BlankLinesBetweenEventFields = 0; + Continue (policy, adapter, +@"class Test +{ + public event EventHandler a; + public event EventHandler b; + public event EventHandler c; +}"); + } + + [Test()] + public void TestBlankLinesBetweenMembers () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.BlankLinesBetweenMembers = 1; + + var adapter = Test (policy,@"class Test +{ + void AMethod () + { + } + void BMethod () + { + } + void CMethod () + { + } +}", @"class Test +{ + void AMethod () + { + } + + void BMethod () + { + } + + void CMethod () + { + } +}"); + + policy.BlankLinesBetweenMembers = 0; + Continue (policy, adapter, @"class Test +{ + void AMethod () + { + } + void BMethod () + { + } + void CMethod () + { + } +}"); + } + + + + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs new file mode 100644 index 0000000000..3746b3b0fa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs @@ -0,0 +1,416 @@ +// +// TestBraceStyle.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + [TestFixture()] + public class TestBraceStyle : TestBase + { + [Ignore ("TODO")] + [Test()] + public void TestNamespaceBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.NamespaceBraceStyle = BraceStyle.EndOfLine; + policy.ClassBraceStyle = BraceStyle.DoNotChange; + + var adapter = Test (policy, @"namespace A +{ +namespace B { + class Test {} +} +}", +@"namespace A { + namespace B { + class Test {} + } +}"); + + policy.NamespaceBraceStyle = BraceStyle.NextLineShifted; + Continue (policy, adapter, +@"namespace A + { + namespace B + { + class Test {} + } + }"); + } + + [Test()] + public void TestClassBraceStlye () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, +@"class Test {}", +@"class Test { +}"); + } + + [Test()] + public void TestStructBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.StructBraceStyle = BraceStyle.NextLine; + + Test (policy, +@"struct Test {}", +@"struct Test +{ +}"); + } + + [Test()] + public void TestInterfaceBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.InterfaceBraceStyle = BraceStyle.NextLine; + + Test (policy, +@"interface Test {}", +@"interface Test +{ +}"); + } + + [Test()] + public void TestEnumBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.EnumBraceStyle = BraceStyle.NextLineShifted; + + Test (policy, @"enum Test { + A +}", +@"enum Test + { + A + }"); + } + + [Test()] + public void TestMethodBraceStlye () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.MethodBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + Test MyMethod() {} +}", +@"class Test +{ + Test MyMethod () + { + } +}"); + } + + [Test()] + public void TestConstructorBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ConstructorBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + Test() {} +}", +@"class Test +{ + Test () + { + } +}"); + } + + [Test()] + public void TestDestructorBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.DestructorBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + ~Test() {} +}", +@"class Test +{ + ~Test () + { + } +}"); + } + + [Test()] + public void TestPropertyBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + Test A { + get; + set; + } +}", +@"class Test +{ + Test A + { + get; + set; + } +}"); + } + + [Test()] + public void TestPropertyGetBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyGetBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + Test A { + get { + return null; + } + set; + } +}", +@"class Test +{ + Test A { + get + { + return null; + } + set; + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestAllowPropertyGetBlockInline () + { + + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyBraceStyle = BraceStyle.DoNotChange; + policy.AllowPropertyGetBlockInline = true; + policy.AllowPropertySetBlockInline = false; + + var adapter = Test (policy, @"class Test +{ + Test A { + get { return null; } + set { ; } + } +}", +@"class Test +{ + Test A { + get { return null; } + set { + ; + } + } +}"); + + policy.AllowPropertyGetBlockInline = false; + Continue (policy, adapter, +@"class Test +{ + Test A { + get { + return null; + } + set { + ; + } + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestAllowPropertySetBlockInline () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyBraceStyle = BraceStyle.DoNotChange; + policy.AllowPropertyGetBlockInline = false; + policy.AllowPropertySetBlockInline = true; + + var adapter = Test (policy, @"class Test +{ + Test A { + get { return null; } + set { ; } + } +}", +@"class Test +{ + Test A { + get { + return null; + } + set { ; } + } +}"); + + policy.AllowPropertySetBlockInline = false; + Continue (policy, adapter, +@"class Test +{ + Test A { + get { + return null; + } + set { + ; + } + } +}"); + } + + [Test()] + public void TestPropertySetBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertySetBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + Test A { + get; + set { + ; + } + } +}", +@"class Test +{ + Test A { + get; + set + { + ; + } + } +}"); + } + + [Test()] + public void TestEventBraceStyle () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.EventBraceStyle = BraceStyle.NextLine; + policy.EventAddBraceStyle = BraceStyle.NextLine; + policy.EventRemoveBraceStyle = BraceStyle.NextLine; + + Test (policy, @"class Test +{ + public event EventHandler Handler { + add { +} + remove { +} + } +}", +@"class Test +{ + public event EventHandler Handler + { + add + { + } + remove + { + } + } +}"); + } + + [Test()] + public void TestAllowEventAddBlockInline () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.AllowEventAddBlockInline = true; + policy.AllowEventRemoveBlockInline = false; + + Test (policy, @"class Test +{ + public event EventHandler Handler { + add { ; } + remove { ; } + } +}", +@"class Test +{ + public event EventHandler Handler { + add { ; } + remove { + ; + } + } +}"); + } + + [Test()] + public void TestAllowEventRemoveBlockInline () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.AllowEventAddBlockInline = false; + policy.AllowEventRemoveBlockInline = true; + + Test (policy, @"class Test +{ + public event EventHandler Handler { + add { ; } + remove { ; } + } +}", +@"class Test +{ + public event EventHandler Handler { + add { + ; + } + remove { ; } + } +}"); + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs new file mode 100644 index 0000000000..8e667542e7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs @@ -0,0 +1,198 @@ +// +// TestFormattingBugs.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + [Ignore()] + [TestFixture()] + public class TestFormattingBugs : TestBase + { + /// + /// Bug 325187 - Bug in smart indent + /// + [Test()] + public void TestBug325187 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PlaceElseOnNewLine = true; + + TestStatementFormatting (policy, +@"foreach (int i in myints) +if (i == 6) +Console.WriteLine (""Yeah""); +else +Console.WriteLine (""Bad indent"");", +@"foreach (int i in myints) + if (i == 6) + Console.WriteLine (""Yeah""); + else + Console.WriteLine (""Bad indent"");"); + } + + /// + /// Bug 415469 - return ternary in a switch is not tabbed properly + /// + [Test()] + public void TestBug415469 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + TestStatementFormatting (policy, +@"switch (condition) { +case CONDITION1: +return foo != null ? foo.Bar : null; +case CONDITION2: +string goo = foo != null ? foo.Bar : null; +return ""Should be indented like this""; +}", @"switch (condition) { +case CONDITION1: + return foo != null ? foo.Bar : null; +case CONDITION2: + string goo = foo != null ? foo.Bar : null; + return ""Should be indented like this""; +}"); + } + + /// + /// Bug 540043 - Format option for alignment of using-statements + /// + [Test()] + public void TestBug540043 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + TestStatementFormatting (policy, +@"using (IDisposable a = null) + using (IDisposable b = null) { + int c; + } +", @"using (IDisposable a = null) +using (IDisposable b = null) { + int c; +}"); + } + + /// + /// Bug 655635 - Auto format document doesn't indent comments as well + /// + [Test()] + public void TestBug655635 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + TestStatementFormatting (policy, +@"try { + // Comment 1 + myObject.x = Run (); +} catch (InvalidOperationException e) { + Console.WriteLine (e.Message); +}", @"try { + // Comment 1 + myObject.x = Run (); +} catch (InvalidOperationException e) { + Console.WriteLine (e.Message); +}"); + } + + void TestStatementFormatting (CSharpFormattingOptions policy, string input, string expectedOutput) + { + var result = GetResult (policy, @"class Test +{ + MyType TestMethod () + { + " + input + @" + } +}"); + int start = result.GetLineOffset (5); + int end = result.GetLineOffset (result.LineCount - 1); + string text = result.GetTextAt (start, end - start).Trim (); + expectedOutput = expectedOutput.Replace ("\n", "\n\t\t"); + Assert.AreEqual (expectedOutput, text); + } + + /// + /// Bug 659675 - on-the-fly code formatting breaks @-prefixed identifiers + /// + [Test()] + public void TestBug659675 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + TestStatementFormatting (policy, "@string=@int;", "@string = @int;"); + } + + /// + /// Bug 670213 - Document formatter deletes valid text! + /// + [Test()] + public void TestBug670213 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.MethodBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test MyMethod() // Comment + { + } +}", +@"class Test +{ + Test MyMethod () { // Comment + } +}"); + } + + + /// + /// Bug 677261 - Format Document with constructor with over-indented opening curly brace + /// + [Test()] + public void TestBug677261 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ConstructorBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test () + { + } +}", +@"class Test +{ + Test () { + } +}"); + } + + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs new file mode 100644 index 0000000000..87d61ee511 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs @@ -0,0 +1,1602 @@ +// +// TestFormattingVisitor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + [TestFixture()] + public class TestSpacingVisitor : TestBase + { + [Test()] + public void TestFieldSpacesBeforeComma1 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + policy.SpaceBeforeFieldDeclarationComma = false; + policy.SpaceAfterFieldDeclarationComma = false; + + Test (policy, @"class Test { + int a , b, c; +}", +@"class Test { + int a,b,c; +}"); + } + + [Test()] + public void TestFieldSpacesBeforeComma2 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + policy.SpaceBeforeFieldDeclarationComma = true; + policy.SpaceAfterFieldDeclarationComma = true; + + Test (policy, @"class Test { + int a , b, c; +}", +@"class Test { + int a , b , c; +}"); + } + + [Test()] + public void TestFixedFieldSpacesBeforeComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + policy.SpaceAfterFieldDeclarationComma = true; + policy.SpaceBeforeFieldDeclarationComma = true; + + Test (policy, @"class Test { + fixed int a[10] , b[10], c[10]; +}", + @"class Test { + fixed int a[10] , b[10] , c[10]; +}"); + } + + [Test()] + public void TestConstFieldSpacesBeforeComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + policy.SpaceAfterFieldDeclarationComma = false; + policy.SpaceBeforeFieldDeclarationComma = false; + + Test (policy, @"class Test { + const int a = 1 , b = 2, c = 3; +}", +@"class Test { + const int a = 1,b = 2,c = 3; +}"); + } + + [Test()] + public void TestBeforeMethodDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodDeclarationParentheses = true; + + Test (policy, @"public abstract class Test +{ + public abstract Test TestMethod(); +}", +@"public abstract class Test +{ + public abstract Test TestMethod (); +}"); + } + + [Test()] + public void TestBeforeConstructorDeclarationParenthesesDestructorCase () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeConstructorDeclarationParentheses = true; + + Test (policy, @"class Test +{ + ~Test() + { + } +}", +@"class Test +{ + ~Test () + { + } +}"); + } + + static void TestBinaryOperator (CSharpFormattingOptions policy, string op) + { + var result = GetResult (policy, "class Test { void TestMe () { result = left" + op + "right; } }"); + + int i1 = result.Text.IndexOf ("left"); + int i2 = result.Text.IndexOf ("right") + "right".Length; + if (i1 < 0 || i2 < 0) + Assert.Fail ("text invalid:" + result.Text); + Assert.AreEqual ("left " + op + " right", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestSpacesAroundMultiplicativeOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundMultiplicativeOperator = true; + + TestBinaryOperator (policy, "*"); + TestBinaryOperator (policy, "/"); + } + + [Test()] + public void TestSpacesAroundShiftOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundShiftOperator = true; + TestBinaryOperator (policy, "<<"); + TestBinaryOperator (policy, ">>"); + } + + [Test()] + public void TestSpacesAroundAdditiveOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundAdditiveOperator = true; + + TestBinaryOperator (policy, "+"); + TestBinaryOperator (policy, "-"); + } + + [Test()] + public void TestSpacesAroundBitwiseOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundBitwiseOperator = true; + + TestBinaryOperator (policy, "&"); + TestBinaryOperator (policy, "|"); + TestBinaryOperator (policy, "^"); + } + + [Test()] + public void TestSpacesAroundRelationalOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundRelationalOperator = true; + + TestBinaryOperator (policy, "<"); + TestBinaryOperator (policy, "<="); + TestBinaryOperator (policy, ">"); + TestBinaryOperator (policy, ">="); + } + + [Test()] + public void TestSpacesAroundEqualityOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundEqualityOperator = true; + + TestBinaryOperator (policy, "=="); + TestBinaryOperator (policy, "!="); + } + + [Test()] + public void TestSpacesAroundLogicalOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundLogicalOperator = true; + + TestBinaryOperator (policy, "&&"); + TestBinaryOperator (policy, "||"); + } + + [Test()] + public void TestConditionalOperator () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeConditionalOperatorCondition = true; + policy.SpaceAfterConditionalOperatorCondition = true; + policy.SpaceBeforeConditionalOperatorSeparator = true; + policy.SpaceAfterConditionalOperatorSeparator = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + result = condition?trueexpr:falseexpr; + } +}"); + int i1 = result.Text.IndexOf ("condition"); + int i2 = result.Text.IndexOf ("falseexpr") + "falseexpr".Length; + Assert.AreEqual (@"condition ? trueexpr : falseexpr", result.GetTextAt (i1, i2 - i1)); + + + policy.SpaceBeforeConditionalOperatorCondition = false; + policy.SpaceAfterConditionalOperatorCondition = false; + policy.SpaceBeforeConditionalOperatorSeparator = false; + policy.SpaceAfterConditionalOperatorSeparator = false; + + result = GetResult (policy, @"class Test { + void TestMe () + { + result = true ? trueexpr : falseexpr; + } +}"); + i1 = result.Text.IndexOf ("true"); + i2 = result.Text.IndexOf ("falseexpr") + "falseexpr".Length; + Assert.AreEqual (@"true?trueexpr:falseexpr", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeMethodCallParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodCallParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + MethodCall(); + } +}"); + + int i1 = result.Text.IndexOf ("MethodCall"); + int i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"MethodCall ();", result.GetTextAt (i1, i2 - i1)); + + + result = GetResult (policy, @"class Test { + void TestMe () + { + MethodCall (); + } +}"); + policy.SpaceBeforeMethodCallParentheses = false; + + result = GetResult (policy, result.Text); + i1 = result.Text.IndexOf ("MethodCall"); + i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"MethodCall();", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinMethodCallParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceWithinMethodCallParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + MethodCall(true); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + + + policy.SpaceWithinMethodCallParentheses = false; + result = GetResult (policy, @"class Test { + void TestMe () + { + MethodCall( true ); + } +}"); + + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(true)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeIfParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeIfParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + if(true); + } +}"); + int i1 = result.Text.IndexOf ("if"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"if (true)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinIfParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinIfParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + if (true); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeWhileParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeWhileParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + while(true); + } +}"); + int i1 = result.Text.IndexOf ("while"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"while (true)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinWhileParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinWhileParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + while (true); + } +}"); + + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeForParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeForParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + for(;;); + } +}"); + int i1 = result.Text.IndexOf ("for"); + int i2 = result.Text.LastIndexOf ("(") + "(".Length; + Assert.AreEqual (@"for (", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinForParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinForParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + for(;;); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( ;; )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeForeachParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeForeachParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + foreach(var o in list); + } +}"); + int i1 = result.Text.IndexOf ("foreach"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"foreach (var o in list)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinForeachParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinForeachParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + foreach(var o in list); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( var o in list )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeCatchParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeCatchParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + try {} catch(Exception) {} + } +}"); + int i1 = result.Text.IndexOf ("catch"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"catch (Exception)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinCatchParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinCatchParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + try {} catch(Exception) {} + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( Exception )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeLockParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeLockParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + lock(this) {} + } +}"); + int i1 = result.Text.IndexOf ("lock"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"lock (this)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinLockParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinLockParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + lock(this) {} + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( this )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestSpacesAfterForSemicolon () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAfterForSemicolon = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + for (int i;true;i++) ; + } +}"); + int i1 = result.Text.LastIndexOf ("for"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + + Assert.AreEqual (@"for (int i; true; i++)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestSpacesBeforeForSemicolon () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeForSemicolon = true; + policy.SpaceAfterForSemicolon = false; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + for (int i;true;i++) ; + } +}"); + int i1 = result.Text.LastIndexOf ("for"); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + + Assert.AreEqual (@"for (int i ;true ;i++)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestSpacesAfterTypecast () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAfterTypecast = true; + + var result = GetResult (policy, @"class Test { + Test TestMe () + { +return (Test)null; + } +}"); + int i1 = result.Text.LastIndexOf ("return"); + int i2 = result.Text.LastIndexOf ("null") + "null".Length; + + Assert.AreEqual (@"return (Test) null", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeUsingParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeUsingParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + using(a) {} + } +}"); + int i1 = result.Text.IndexOf ("using"); + int i2 = result.Text.LastIndexOf ("(") + "(".Length; + Assert.AreEqual (@"using (", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinUsingParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinUsingParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + using(a) {} + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( a )", result.GetTextAt (i1, i2 - i1)); + } + + static void TestAssignmentOperator (CSharpFormattingOptions policy, string op) + { + var result = GetResult (policy, "class Test { void TestMe () { left" + op + "right; } }"); + + int i1 = result.Text.IndexOf ("left"); + int i2 = result.Text.IndexOf ("right") + "right".Length; + if (i1 < 0 || i2 < 0) + Assert.Fail ("text invalid:" + result.Text); + Assert.AreEqual ("left " + op + " right", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAroundAssignmentSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundAssignment = true; + + TestAssignmentOperator (policy, "="); + TestAssignmentOperator (policy, "*="); + TestAssignmentOperator (policy, "/="); + TestAssignmentOperator (policy, "+="); + TestAssignmentOperator (policy, "%="); + TestAssignmentOperator (policy, "-="); + TestAssignmentOperator (policy, "<<="); + TestAssignmentOperator (policy, ">>="); + TestAssignmentOperator (policy, "&="); + TestAssignmentOperator (policy, "|="); + TestAssignmentOperator (policy, "^="); + } + + [Test()] + public void TestAroundAssignmentSpaceInDeclarations () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAroundAssignment = true; + var result = GetResult (policy, @"class Test { + void TestMe () + { + int left=right; + } +}"); + + int i1 = result.Text.LastIndexOf ("left"); + int i2 = result.Text.LastIndexOf ("right") + "right".Length; + Assert.AreEqual (@"left = right", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeSwitchParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeSwitchParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + switch (test) { default: break; } + } +}"); + int i1 = result.Text.IndexOf ("switch"); + int i2 = result.Text.LastIndexOf ("(") + "(".Length; + Assert.AreEqual (@"switch (", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinSwitchParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinSwitchParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + switch (test) { default: break; } + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( test )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + c = (test); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( test )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinMethodDeclarationParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceWithinMethodDeclarationParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe (int a) + { + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinCastParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinCastParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + a = (int)b; + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinSizeOfParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinSizeOfParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + a = sizeof(int); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeSizeOfParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeSizeOfParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + a = sizeof(int); + } +}"); + int i1 = result.Text.LastIndexOf ("sizeof"); + int i2 = result.Text.LastIndexOf ("(") + "(".Length; + Assert.AreEqual (@"sizeof (", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinTypeOfParenthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinTypeOfParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + a = typeof(int); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeTypeOfParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeTypeOfParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + a = typeof(int); + } +}"); + + int i1 = result.Text.LastIndexOf ("typeof"); + int i2 = result.Text.LastIndexOf ("(") + "(".Length; + Assert.AreEqual (@"typeof (", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinCheckedExpressionParanthesesSpace () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinCheckedExpressionParantheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + a = checked(a + b); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( a + b )", result.GetTextAt (i1, i2 - i1)); + + result = GetResult (policy, @"class Test { + void TestMe () + { + a = unchecked(a + b); + } +}"); + + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( a + b )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestSpaceBeforeNewParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeNewParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + new Test(); + } +}"); + int i1 = result.Text.LastIndexOf ("new"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"new Test ();", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinNewParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinNewParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + new Test (1); + } +}"); + int i1 = result.Text.LastIndexOf ("new"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"new Test ( 1 );", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBetweenEmptyNewParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesBetweenEmptyNewParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + new Test (); + } +}"); + int i1 = result.Text.LastIndexOf ("new"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"new Test ( );", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeNewParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeNewParameterComma = true; + policy.SpaceAfterNewParameterComma = false; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + new Test (1,2); + } +}"); + int i1 = result.Text.LastIndexOf ("new"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"new Test (1 ,2);", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAfterNewParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAfterNewParameterComma = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + new Test (1,2); + } +}"); + int i1 = result.Text.LastIndexOf ("new"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"new Test (1, 2);", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestFieldDeclarationComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeFieldDeclarationComma = false; + policy.SpaceAfterFieldDeclarationComma = true; + + var result = GetResult (policy, @"class Test { + int a,b,c; +}"); + int i1 = result.Text.LastIndexOf ("int"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"int a, b, c;", result.GetTextAt (i1, i2 - i1)); + policy.SpaceBeforeFieldDeclarationComma = true; + + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("int"); + i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"int a , b , c;", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceBeforeFieldDeclarationComma = false; + policy.SpaceAfterFieldDeclarationComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("int"); + i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"int a,b,c;", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeMethodDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodDeclarationParameterComma = true; + policy.SpaceAfterMethodDeclarationParameterComma = false; + + var result = GetResult (policy, @"class Test { + public void Foo (int a,int b,int c) {} +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceBeforeMethodDeclarationParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAfterMethodDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodDeclarationParameterComma = false; + policy.SpaceAfterMethodDeclarationParameterComma = true; + + var result = GetResult (policy, @"class Test { + public void Foo (int a,int b,int c) {} +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceAfterMethodDeclarationParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestSpacesInLambdaExpression () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinWhileParentheses = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + var v = x=>x!=null; + } +}"); + int i1 = result.Text.IndexOf ("x"); + int i2 = result.Text.LastIndexOf ("null") + "null".Length; + Assert.AreEqual (@"x => x != null", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBeforeLocalVariableDeclarationComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeLocalVariableDeclarationComma = true; + policy.SpaceAfterLocalVariableDeclarationComma = false; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + int a,b,c; + } +}"); + int i1 = result.Text.IndexOf ("int"); + int i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"int a ,b ,c;", result.GetTextAt (i1, i2 - i1)); + + result = GetResult (policy, result.Text); + + policy.SpaceBeforeLocalVariableDeclarationComma = false; + + result = GetResult (policy, result.Text); + i1 = result.Text.IndexOf ("int"); + i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"int a,b,c;", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestLocalVariableDeclarationComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeLocalVariableDeclarationComma = true; + policy.SpaceAfterLocalVariableDeclarationComma = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + int a = 5,b = 6,c; + } +}"); + int i1 = result.Text.IndexOf ("int"); + int i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"int a = 5 , b = 6 , c;", result.GetTextAt (i1, i2 - i1)); + + result = GetResult (policy, result.Text); + + policy.SpaceBeforeLocalVariableDeclarationComma = false; + policy.SpaceAfterLocalVariableDeclarationComma = false; + + result = GetResult (policy, result.Text); + i1 = result.Text.IndexOf ("int"); + i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"int a = 5,b = 6,c;", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestLocalVariableWithGenerics () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeLocalVariableDeclarationComma = true; + policy.SpaceAfterLocalVariableDeclarationComma = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + List a; + } +}"); + int i1 = result.Text.IndexOf ("List"); + int i2 = result.Text.IndexOf (";") + ";".Length; + Assert.AreEqual (@"List a;", result.GetTextAt (i1, i2 - i1)); + + } + + #region Constructors + + [Test()] + public void TestBeforeConstructorDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeConstructorDeclarationParentheses = true; + + var result = GetResult (policy, @"class Test +{ + Test() + { + } +}"); + + Assert.AreEqual (@"class Test +{ + Test () + { + } +}", result.Text); + } + + [Test()] + public void TestBeforeConstructorDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeConstructorDeclarationParameterComma = true; + policy.SpaceAfterConstructorDeclarationParameterComma = false; + + var result = GetResult (policy, @"class Test { + public Test (int a,int b,int c) {} +}"); + + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceBeforeConstructorDeclarationParameterComma = false; + result = GetResult (policy, result.Text); + + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAfterConstructorDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeConstructorDeclarationParameterComma = false; + policy.SpaceAfterConstructorDeclarationParameterComma = true; + + var result = GetResult (policy, @"class Test { + public Test (int a,int b,int c) {} +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceAfterConstructorDeclarationParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinConstructorDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceWithinConstructorDeclarationParentheses = true; + + var result = GetResult (policy, @"class Test { + Test (int a) + { + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBetweenEmptyConstructorDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBetweenEmptyConstructorDeclarationParentheses = true; + + var result = GetResult (policy, @"class Test { + Test () + { + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + } + + #endregion + + #region Delegates + [Test()] + public void TestBeforeDelegateDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeDelegateDeclarationParentheses = true; + + var result = GetResult (policy, @"delegate void Test();"); + + Assert.AreEqual (@"delegate void Test ();", result.Text); + } + + [Test()] + public void TestBeforeDelegateDeclarationParenthesesComplex () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeDelegateDeclarationParentheses = true; + + var result = GetResult (policy, "delegate void TestDelegate\t\t\t();"); + + Assert.AreEqual (@"delegate void TestDelegate ();", result.Text); + } + + [Test()] + public void TestBeforeDelegateDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeDelegateDeclarationParameterComma = true; + policy.SpaceAfterDelegateDeclarationParameterComma = false; + + var result = GetResult (policy, @"delegate void Test (int a,int b,int c);"); + + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceBeforeDelegateDeclarationParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAfterDelegateDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeDelegateDeclarationParameterComma = false; + policy.SpaceAfterDelegateDeclarationParameterComma = true; + + var result = GetResult (policy, @"delegate void Test (int a,int b,int c);"); + + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceAfterDelegateDeclarationParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinDelegateDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceWithinDelegateDeclarationParentheses = true; + var result = GetResult (policy, @"delegate void Test (int a);"); + + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBetweenEmptyDelegateDeclarationParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBetweenEmptyDelegateDeclarationParentheses = true; + var result = GetResult (policy, @"delegate void Test();"); + + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + } + + #endregion + + #region Method invocations + [Test()] + public void TestBeforeMethodCallParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodCallParentheses = true; + + var result = GetResult (policy, @"class FooBar +{ + public void Foo () + { + Test(); + } +}"); + + Assert.AreEqual (@"class FooBar +{ + public void Foo () + { + Test (); + } +}", result.Text); + } + + [Test()] + public void TestBeforeMethodCallParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodCallParameterComma = true; + policy.SpaceAfterMethodCallParameterComma = false; + + var result = GetResult (policy, @"class FooBar +{ + public void Foo () + { + Test(a,b,c); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(a ,b ,c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceBeforeMethodCallParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(a,b,c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAfterMethodCallParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeMethodCallParameterComma = false; + policy.SpaceAfterMethodCallParameterComma = true; + + var result = GetResult (policy, @"class FooBar +{ + public void Foo () + { + Test(a,b,c); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(a, b, c)", result.GetTextAt (i1, i2 - i1)); + + policy.SpaceAfterMethodCallParameterComma = false; + result = GetResult (policy, result.Text); + i1 = result.Text.LastIndexOf ("("); + i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"(a,b,c)", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinMethodCallParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceWithinMethodCallParentheses = true; + + var result = GetResult (policy, @"class FooBar +{ + public void Foo () + { + Test(a); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( a )", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestBetweenEmptyMethodCallParentheses () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBetweenEmptyMethodCallParentheses = true; + + var result = GetResult (policy, @"class FooBar +{ + public void Foo () + { + Test(); + } +}"); + int i1 = result.Text.LastIndexOf ("("); + int i2 = result.Text.LastIndexOf (")") + ")".Length; + Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + } + + #endregion + + #region Indexer declarations + [Test()] + public void TestBeforeIndexerDeclarationBracket () + { + + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeIndexerDeclarationBracket = true; + + var result = GetResult (policy, @"class FooBar +{ + public int this[int a, int b] { + get { + return a + b; + } + } +}"); + Assert.AreEqual (@"class FooBar +{ + public int this [int a, int b] { + get { + return a + b; + } + } +}", result.Text); + } + + [Test()] + public void TestBeforeIndexerDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeIndexerDeclarationParameterComma = true; + policy.SpaceAfterIndexerDeclarationParameterComma = false; + + var result = GetResult (policy, @"class FooBar +{ + public int this[int a,int b] { + get { + return a + b; + } + } +}"); + int i1 = result.Text.LastIndexOf ("["); + int i2 = result.Text.LastIndexOf ("]") + "]".Length; + Assert.AreEqual (@"[int a ,int b]", result.GetTextAt (i1, i2 - i1)); + + } + + [Test()] + public void TestAfterIndexerDeclarationParameterComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAfterIndexerDeclarationParameterComma = true; + + var result = GetResult (policy, @"class FooBar +{ + public int this[int a,int b] { + get { + return a + b; + } + } +}"); + int i1 = result.Text.LastIndexOf ("["); + int i2 = result.Text.LastIndexOf ("]") + "]".Length; + Assert.AreEqual (@"[int a, int b]", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestWithinIndexerDeclarationBracket () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceWithinIndexerDeclarationBracket = true; + + var result = GetResult (policy, @"class FooBar +{ + public int this[int a, int b] { + get { + return a + b; + } + } +}"); + int i1 = result.Text.LastIndexOf ("["); + int i2 = result.Text.LastIndexOf ("]") + "]".Length; + Assert.AreEqual (@"[ int a, int b ]", result.GetTextAt (i1, i2 - i1)); + } + + #endregion + + #region Brackets + + [Test()] + public void TestSpacesWithinBrackets () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesWithinBrackets = true; + policy.SpacesBeforeBrackets = false; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + this[0] = 5; + } +}"); + Assert.AreEqual (@"class Test +{ + void TestMe () + { + this[ 0 ] = 5; + } +}", result.Text); + + + } + + [Test()] + public void TestSpacesBeforeBrackets () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpacesBeforeBrackets = true; + + var result = GetResult (policy, @"class Test +{ + void TestMe () + { + this[0] = 5; + } +}"); + Assert.AreEqual (@"class Test +{ + void TestMe () + { + this [0] = 5; + } +}", result.Text); + + + } + + [Test()] + public void TestBeforeBracketComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeBracketComma = true; + policy.SpaceAfterBracketComma = false; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + this[1,2,3] = 5; + } +}"); + + int i1 = result.Text.LastIndexOf ("["); + int i2 = result.Text.LastIndexOf ("]") + "]".Length; + Assert.AreEqual (@"[1 ,2 ,3]", result.GetTextAt (i1, i2 - i1)); + } + + [Test()] + public void TestAfterBracketComma () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceAfterBracketComma = true; + + var result = GetResult (policy, @"class Test { + void TestMe () + { + this[1,2,3] = 5; + } +}"); + + int i1 = result.Text.LastIndexOf ("["); + int i2 = result.Text.LastIndexOf ("]") + "]".Length; + Assert.AreEqual (@"[1, 2, 3]", result.GetTextAt (i1, i2 - i1)); + } + + #endregion + + [Test()] + public void TestSpacesBeforeArrayDeclarationBrackets () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.SpaceBeforeArrayDeclarationBrackets = true; + + var result = GetResult (policy, @"class Test { + int[] a; + int[][] b; +}"); + + Assert.AreEqual (@"class Test +{ + int [] a; + int [][] b; +}", result.Text); + + + } + + [Test()] + public void TestRemoveWhitespacesBeforeSemicolon () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + var result = GetResult (policy, @"class Test { + void TestMe () + { + Foo () ; + } +}"); + int i1 = result.Text.IndexOf ("Foo"); + int i2 = result.Text.LastIndexOf (";") + ";".Length; + Assert.AreEqual (@"Foo ();", result.GetTextAt (i1, i2 - i1)); + } + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs new file mode 100644 index 0000000000..96d06c1c27 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs @@ -0,0 +1,1687 @@ +// +// TestStatementIndentation.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + [TestFixture()] + public class TestStatementIndentation : TestBase + { + [Test()] + public void TestInvocationIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, +@"class Test { + Test TestMethod () + { +this.TestMethod (); + } +}", +@"class Test { + Test TestMethod () + { + this.TestMethod (); + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestIndentBlocks () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentBlocks = true; + + var adapter = Test (policy, +@"class Test { + Test TestMethod () + { +{ +{} +} + } +}", +@"class Test +{ + Test TestMethod () + { + { + {} + } + } +}"); + policy.IndentBlocks = false; + Continue (policy, adapter, @"class Test +{ + Test TestMethod () + { + { + {} + } + } +}"); + } + + [Test()] + public void TestBreakIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, +@"class Test { + Test TestMethod () + { + break; + } +}", +@"class Test { + Test TestMethod () + { + break; + } +}"); + } + + [Test()] + public void TestCheckedIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + + Test (policy, @"class Test { + Test TestMethod () + { +checked { +} + } +}", @"class Test { + Test TestMethod () + { + checked { + } + } +}"); + } + + [Test()] + public void TestBaseIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { + base.FooBar(); + } +}", @"class Test { + Test TestMethod () + { + base.FooBar (); + } +}"); + } + + [Test()] + public void TestUncheckedIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +unchecked { +} + } +}", +@"class Test { + Test TestMethod () + { + unchecked { + } + } +}"); + } + + [Test()] + public void TestContinueIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +continue; + } +}", +@"class Test { + Test TestMethod () + { + continue; + } +}"); + } + + [Test()] + public void TestEmptyStatementIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +; + } +}", @"class Test { + Test TestMethod () + { + ; + } +}"); + } + + [Test()] + public void TestFixedStatementIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +fixed (object* obj = &obj) +; + } +}", +@"class Test { + Test TestMethod () + { + fixed (object* obj = &obj) + ; + } +}"); + } + + [Test()] + public void TestFixedForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.FixedBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + Test TestMethod () + { + fixed (object* obj = &obj) { + } + fixed (object* obj = &obj) ; + } +}", +@"class Test +{ + Test TestMethod () + { + fixed (object* obj = &obj) { + } + fixed (object* obj = &obj) { + ; + } + } +}"); + } + + [Test()] + public void TestForeachIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { +foreach (var obj in col) { +} + } +}", @"class Test +{ + Test TestMethod () + { + foreach (var obj in col) { + } + } +}"); + } + + [Test()] + public void TestForIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +for (;;) { +} + } +}", @"class Test { + Test TestMethod () + { + for (;;) { + } + } +}"); + } + + [Test()] + public void TestGotoIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +goto label; + } +}", +@"class Test { + Test TestMethod () + { + goto label; + } +}"); + } + + [Test()] + public void TestReturnIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +return; + } +}", +@"class Test { + Test TestMethod () + { + return; + } +}"); + } + + [Test()] + public void TestLockIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +lock (this) { +} + } +}", +@"class Test { + Test TestMethod () + { + lock (this) { + } + } +}"); + } + + [Test()] + public void TestThrowIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +throw new NotSupportedException (); + } +}", +@"class Test { + Test TestMethod () + { + throw new NotSupportedException (); + } +}"); + } + + [Test()] + public void TestUnsafeIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +unsafe { +} + } +}", +@"class Test { + Test TestMethod () + { + unsafe { + } + } +}"); + } + + [Test()] + public void TestUsingIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +using (var o = new MyObj()) { +} + } +}", @"class Test { + Test TestMethod () + { + using (var o = new MyObj()) { + } + } +}"); + } + + [Test()] + public void TestUsingForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.UsingBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + Test TestMethod () + { + using (var o = new MyObj()) { + } + using (var o = new MyObj()) ; + } +}", +@"class Test +{ + Test TestMethod () + { + using (var o = new MyObj()) { + } + using (var o = new MyObj()) { + ; + } + } +}"); + } + + [Test()] + public void TestUsingForcementDoNotChange () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.UsingBraceForcement = BraceForcement.DoNotChange; + + Test (policy, @"class Test +{ + Test TestMethod () + { + using (var o = new MyObj()) { + } + using (var o = new MyObj()) ; + } +}", +@"class Test +{ + Test TestMethod () + { + using (var o = new MyObj()) { + } + using (var o = new MyObj()) + ; + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestUsingAlignment () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.AlignEmbeddedUsingStatements = true; + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + var adapter = Test (policy, @"class Test { + Test TestMethod () + { +using (var p = new MyObj()) +using (var o = new MyObj()) { +} + } +}", +@"class Test { + Test TestMethod () + { + using (var p = new MyObj()) + using (var o = new MyObj()) { + } + } +}"); + policy.AlignEmbeddedUsingStatements = false; + Continue (policy, adapter, @"class Test { + Test TestMethod () + { + using (var p = new MyObj()) + using (var o = new MyObj()) { + } + } +}"); + } + + [Test()] + public void TestVariableDeclarationIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +Test a; + } +}", +@"class Test { + Test TestMethod () + { + Test a; + } +}"); + } + + [Test()] + public void TestConstantVariableDeclarationIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +const int a = 5; + } +}", +@"class Test { + Test TestMethod () + { + const int a = 5; + } +}"); + } + + [Test()] + public void TestYieldIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + Test (policy, @"class Test { + Test TestMethod () + { +yield return null; + } +}", +@"class Test { + Test TestMethod () + { + yield return null; + } +}"); + } + + [Test()] + public void TestWhileIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test { + Test TestMethod () + { +while (true) +; + } +}", +@"class Test { + Test TestMethod () + { + while (true) + ; + } +}"); + } + + [Test()] + public void TestDoWhileIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.ClassBraceStyle = BraceStyle.EndOfLine; + Test (policy, @"class Test { + Test TestMethod () + { +do { +} while (true); + } +}", +@"class Test { + Test TestMethod () + { + do { + } while (true); + } +}"); + } + + [Test()] + public void TestForeachBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + Test (policy, @"class Test +{ + Test TestMethod () + { + foreach (var obj in col) {} + } +}", +@"class Test +{ + Test TestMethod () + { + foreach (var obj in col) { + } + } +}"); + } + + [Test()] + public void TestForeachBracketPlacement2 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLineShifted2; + Test (policy, @"class Test +{ + Test TestMethod () + { + foreach (var obj in col) {;} + } +}", +@"class Test +{ + Test TestMethod () + { + foreach (var obj in col) + { + ; + } + } +}"); + } + + [Test()] + public void TestForEachBraceForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLine; + policy.ForEachBraceForcement = BraceForcement.AddBraces; + Test (policy, @"class Test +{ + Test TestMethod () + { + foreach (var obj in col) + { + } + foreach (var obj in col) ; + } +}", +@"class Test +{ + Test TestMethod () + { + foreach (var obj in col) + { + } + foreach (var obj in col) + { + ; + } + } +}"); + } + + [Test()] + public void TestForBraceForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLine; + policy.ForBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + Test TestMethod () + { + for (;;) + { + } + for (;;) ; + } +}", +@"class Test +{ + Test TestMethod () + { + for (;;) + { + } + for (;;) + { + ; + } + } +}"); + } + + [Test()] + public void TestForEachBraceForcementRemove () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLine; + policy.ForEachBraceForcement = BraceForcement.RemoveBraces; + Test (policy, @"class Test +{ + Test TestMethod () + { + foreach (var obj in col) + { + ; + ; + } + foreach (var obj in col) + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + foreach (var obj in col) + { + ; + ; + } + foreach (var obj in col) + ; + } +}"); + } + + [Test()] + public void TestIfBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) {} + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) { + } + } +}"); + } + + [Test()] + public void TestAllowIfBlockInline () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.AllowIfBlockInline = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) {} + } +}", @"class Test +{ + Test TestMethod () + { + if (true) {} + } +}"); + + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) { Foo (); } + } +}", @"class Test +{ + Test TestMethod () + { + if (true) { Foo (); } + } +}"); + + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) Foo (); + } +}", @"class Test +{ + Test TestMethod () + { + if (true) Foo (); + } +}"); + + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) + Foo (); + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) + Foo (); + } +}"); + } + + [Test()] + public void TestIfElseBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) {} else {} + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) { + } else { + } + } +}"); + } + + [Test()] + public void TestIfForcementRemove () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLine; + policy.IfElseBraceForcement = BraceForcement.RemoveBraces; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) + { + ; + ; + } + if (true) + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) + { + ; + ; + } + if (true) + ; + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestIfAlignment () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.AlignEmbeddedIfStatements = true; + policy.ClassBraceStyle = BraceStyle.EndOfLine; + + var adapter = Test (policy, @"class Test { + Test TestMethod () + { +if (a) +if (b) { +} + } +}", +@"class Test { + Test TestMethod () + { + if (a) + if (b) { + } + } +}"); + policy.AlignEmbeddedIfStatements = false; + Continue (policy, adapter, @"class Test { + Test TestMethod () + { + if (a) + if (b) { + } + } +}"); + } + + [Test()] + public void TestIfForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.IfElseBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + void TestMethod () + { + if (true) + Call (); + } +}", +@"class Test +{ + void TestMethod () + { + if (true) { + Call (); + } + } +}"); + } + + [Test()] + public void TestIfForcementWithComment () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.IfElseBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + void TestMethod () + { + if (true) // TestComment + Call (); + } +}", +@"class Test +{ + void TestMethod () + { + if (true) { + // TestComment + Call (); + } + } +}"); + } + + [Test()] + public void TestIfElseForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.IfElseBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + void TestMethod () + { + if (true) + Call (); + else + Call2 (); + } +}", +@"class Test +{ + void TestMethod () + { + if (true) { + Call (); + } else { + Call2 (); + } + } +}"); + } + + [Test()] + public void TestIfElseIFForcementAdd () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.IfElseBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + void TestMethod () + { + if (true) + Call (); + else if (false) + Call2 (); + } +}", +@"class Test +{ + void TestMethod () + { + if (true) { + Call (); + } else if (false) { + Call2 (); + } + } +}"); + } + + [Test()] + public void TestElseOnNewLine () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PlaceElseOnNewLine = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) { + ; + } else if (false) { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) { + ; + } + else if (false) { + ; + } + } +}"); + } + + [Test()] + public void TestElseIfOnNewLine () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PlaceElseIfOnNewLine = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) { + ; + } else if (false) { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) { + ; + } else + if (false) { + ; + } + } +}"); + } + + [Test()] + public void TestElseOnNewLineOff () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PlaceElseOnNewLine = false; + + Test (policy, @"class Test +{ + Test TestMethod () + { + if (true) { + ; + } + else if (false) { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + if (true) { + ; + } else if (false) { + ; + } + } +}"); + } + + [Test()] + public void TestSimpleIfElseComment () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + policy.PlaceElseIfOnNewLine = false; // for simple statements it must be new line. + + Test (policy, @"class Test +{ + void TestMethod () + { + if (true) Call (); else Call (); + } +}", +@"class Test +{ + void TestMethod () + { + if (true) + Call (); + else + Call (); + } +}"); + } + + [Test()] + public void TestWhileForcementRemove () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLine; + policy.WhileBraceForcement = BraceForcement.RemoveBraces; + + Test (policy, @"class Test +{ + Test TestMethod () + { + while (true) + { + ; + ; + } + while (true) + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + while (true) + { + ; + ; + } + while (true) + ; + } +}"); + } + + [Test()] + public void TestFixedBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.NextLineShifted; + policy.FixedBraceForcement = BraceForcement.AddBraces; + + Test (policy, @"class Test +{ + Test TestMethod () + { + fixed (object* obj = &obj) + +; + } +}", +@"class Test +{ + Test TestMethod () + { + fixed (object* obj = &obj) + { + ; + } + } +}"); + } + + [Test()] + public void TestForBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLineWithoutSpace; + Test (policy, @"class Test +{ + Test TestMethod () + { + for (;;) {;} + } +}", +@"class Test +{ + Test TestMethod () + { + for (;;){ + ; + } + } +}"); + } + + [Test()] + public void TestCheckedBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLineWithoutSpace; + + Test (policy, @"class Test +{ + Test TestMethod () + { + checked {;} + } +}", +@"class Test +{ + Test TestMethod () + { + checked{ + ; + } + } +}"); + } + + [Test()] + public void TestUncheckedBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLineWithoutSpace; + + Test (policy, @"class Test +{ + Test TestMethod () + { + unchecked {;} + } +}", +@"class Test +{ + Test TestMethod () + { + unchecked{ + ; + } + } +}"); + } + + [Test()] + public void TestLockBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + lock (this) + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + lock (this) { + ; + } + } +}"); + } + + [Test()] + public void TestUnsafeBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + unsafe + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + unsafe { + ; + } + } +}"); + } + + [Test()] + public void TestUsingBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + using (var e = new E()) + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + using (var e = new E()) { + ; + } + } +}"); + } + + [Test()] + public void TestWhileBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + while (true) + { + ; + } + } +}", +@"class Test +{ + Test TestMethod () + { + while (true) { + ; + } + } +}"); + } + + [Test()] + public void TestDoWhileBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + do + { + ; + } while (true); + } +}", +@"class Test +{ + Test TestMethod () + { + do { + ; + } while (true); + } +}"); + } + + [Test()] + public void TestSwitchFormatting1 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.IndentSwitchBody = true; + policy.IndentCaseBody = true; + policy.IndentBreakStatements = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + switch (a) { case 1: case 2: DoSomething(); break; default: Foo (); break;} + } +}", +@"class Test +{ + Test TestMethod () + { + switch (a) { + case 1: + case 2: + DoSomething (); + break; + default: + Foo (); + break; + } + } +}"); + } + + [Test()] + public void TestSwitchFormatting2 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.IndentSwitchBody = false; + policy.IndentCaseBody = false; + policy.IndentBreakStatements = false; + + Test (policy, @"class Test +{ + Test TestMethod () + { + switch (a) { case 1: case 2: DoSomething(); break; default: Foo (); break;} + } +}", +@"class Test +{ + Test TestMethod () + { + switch (a) { + case 1: + case 2: + DoSomething (); + break; + default: + Foo (); + break; + } + } +}"); + } + + [Test()] + public void TestTryCatchBracketPlacement () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.StatementBraceStyle = BraceStyle.EndOfLine; + + Test (policy, @"class Test +{ + Test TestMethod () + { + try { ; } catch (Exception e) { } finally { } + } +}", +@"class Test +{ + Test TestMethod () + { + try { + ; + } catch (Exception e) { + } finally { + } + } +}"); + } + + [Test()] + public void TestPlaceCatchOnNewLine () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.PlaceCatchOnNewLine = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + try { + ; + } catch (Exception e) { + } finally { + } + } +}", +@"class Test +{ + Test TestMethod () + { + try { + ; + } + catch (Exception e) { + } finally { + } + } +}"); + } + + [Test()] + public void TestPlaceFinallyOnNewLine () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PlaceFinallyOnNewLine = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + try { + ; + } catch (Exception e) { + } finally { + } + } +}", + @"class Test +{ + Test TestMethod () + { + try { + ; + } catch (Exception e) { + } + finally { + } + } +}"); + } + + [Test()] + public void TestPlaceWhileOnNewLine () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + policy.PlaceWhileOnNewLine = true; + + Test (policy, @"class Test +{ + Test TestMethod () + { + do { + ; + } while (true); + } +}", + @"class Test +{ + Test TestMethod () + { + do { + ; + } + while (true); + } +}"); + } + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs new file mode 100644 index 0000000000..1ba5ef5f53 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs @@ -0,0 +1,563 @@ +// +// TestTypeLevelIndentation.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + [TestFixture()] + public class TestTypeLevelIndentation : TestBase + { + [Test()] + public void TestClassIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.DoNotChange; + + Test (policy, +@" class Test {}", +@"class Test {}"); + } + + + [Test()] + public void TestClassIndentationInNamespaces () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.NamespaceBraceStyle = BraceStyle.EndOfLine; + policy.ClassBraceStyle = BraceStyle.DoNotChange; + + Test (policy, +@"namespace A { class Test {} }", +@"namespace A { + class Test {} +}"); + } + + [Test()] + public void TestNoIndentationInNamespaces () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.NamespaceBraceStyle = BraceStyle.EndOfLine; + policy.ClassBraceStyle = BraceStyle.DoNotChange; + policy.IndentNamespaceBody = false; + + Test (policy, +@"namespace A { class Test {} }", +@"namespace A { +class Test {} +}"); + } + + [Test()] + public void TestClassIndentationInNamespacesCase2 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.NamespaceBraceStyle = BraceStyle.NextLine; + policy.ClassBraceStyle = BraceStyle.NextLine; + policy.ConstructorBraceStyle = BraceStyle.NextLine; + + Test (policy, +@"using System; + +namespace MonoDevelop.CSharp.Formatting { + public class FormattingProfileService { + public FormattingProfileService () { + } + } +}", +@"using System; + +namespace MonoDevelop.CSharp.Formatting +{ + public class FormattingProfileService + { + public FormattingProfileService () + { + } + } +}"); + } + + [Test()] + public void TestIndentClassBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentClassBody = true; + Test (policy, +@"class Test +{ + Test a; +}", @"class Test +{ + Test a; +}"); + + policy.IndentClassBody = false; + Test (policy, +@"class Test +{ + Test a; +}", +@"class Test +{ +Test a; +}"); + } + + [Test()] + public void TestIndentInterfaceBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentInterfaceBody = true; + + Test (policy, +@"interface Test +{ + Test Foo (); +}", @"interface Test +{ + Test Foo (); +}"); + policy.IndentInterfaceBody = false; + Test (policy, +@"interface Test +{ + Test Foo (); +}", @"interface Test +{ +Test Foo (); +}"); + } + + [Test()] + public void TestIndentStructBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentStructBody = true; + + Test (policy, +@"struct Test +{ + Test Foo (); +}", @"struct Test +{ + Test Foo (); +}"); + policy.IndentStructBody = false; + Test (policy, +@"struct Test +{ + Test Foo (); +}", @"struct Test +{ +Test Foo (); +}"); + } + + [Test()] + public void TestIndentEnumBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentEnumBody = true; + + Test (policy, +@"enum Test +{ + A +}", @"enum Test +{ + A +}"); + policy.IndentEnumBody = false; + Test (policy, +@"enum Test +{ + A +}", @"enum Test +{ +A +}"); + } + + [Test()] + public void TestIndentMethodBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentMethodBody = true; + + Test (policy, +@"class Test +{ + Test Foo () + { +; + ; + } +}", +@"class Test +{ + Test Foo () + { + ; + ; + } +}"); + policy.IndentMethodBody = false; + Test (policy, +@"class Test +{ + Test Foo () + { + ; + ; + } +}", +@"class Test +{ + Test Foo () + { + ; + ; + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestIndentMethodBodyOperatorCase () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentMethodBody = true; + + var adapter = Test (policy, +@"class Test +{ + static Test operator+(Test left, Test right) + { +; + ; + } +}", +@"class Test +{ + static Test operator+ (Test left, Test right) + { + ; + ; + } +}"); + policy.IndentMethodBody = false; + Continue (policy, adapter, @"class Test +{ + static Test operator+ (Test left, Test right) + { + ; + ; + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestIndentPropertyBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentPropertyBody = true; + + var adapter = Test (policy, +@"class Test +{ + Test TestMe { + get; +set; + } +}", +@"class Test +{ + Test TestMe { + get; + set; + } +}"); + policy.IndentPropertyBody = false; + + Continue (policy, adapter, +@"class Test +{ + Test TestMe { + get; + set; + } +}"); + } + + [Test()] + public void TestIndentPropertyOneLine () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyFormatting = PropertyFormatting.AllowOneLine; + policy.AllowPropertyGetBlockInline = true; + policy.AllowPropertySetBlockInline = true; + + Test (policy, +@"class Test +{ + Test TestMe { get;set; } +}", +@"class Test +{ + Test TestMe { get; set; } +}"); + } + + [Test()] + public void TestIndentPropertyOneLineCase2 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyFormatting = PropertyFormatting.AllowOneLine; + policy.AllowPropertyGetBlockInline = true; + policy.AllowPropertySetBlockInline = true; + + Test (policy, +@"class Test +{ + Test TestMe { get { ; }set{;} } +}", +@"class Test +{ + Test TestMe { get { ; } set { ; } } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestIndentPropertyBodyIndexerCase () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentPropertyBody = true; + + var adapter = Test (policy, +@"class Test +{ + Test this[int a] { + get { + return null; +} +set { + ; +} + } +}", +@"class Test +{ + Test this [int a] { + get { + return null; + } + set { + ; + } + } +}"); + policy.IndentPropertyBody = false; + Continue (policy, adapter, +@"class Test +{ + Test this [int a] { + get { + return null; + } + set { + ; + } + } +}"); + } + + [Ignore ("TODO")] + [Test()] + public void TestPropertyAlignment () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyFormatting = PropertyFormatting.AllowOneLine; + var adapter = Test (policy, +@"class Test +{ + Test TestMe { get; set; } +}", +@"class Test +{ + Test TestMe { get; set; } +}"); + policy.PropertyFormatting = PropertyFormatting.ForceNewLine; + Continue (policy, adapter, +@"class Test +{ + Test TestMe { + get; + set; + } +}"); + policy.PropertyFormatting = PropertyFormatting.ForceOneLine; + + Continue (policy, adapter, +@"class Test +{ + Test TestMe { get; set; } +}"); + } + + + [Ignore ("TODO")] + [Test()] + public void TestIndentNamespaceBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.DoNotChange; + policy.NamespaceBraceStyle = BraceStyle.EndOfLine; + policy.IndentNamespaceBody = true; + var adapter = Test (policy, +@" namespace Test { +class FooBar {} + }", +@"namespace Test { + class FooBar {} +}"); + + policy.IndentNamespaceBody = false; + Continue (policy, adapter, +@"namespace Test { +class FooBar {} +}"); + } + + + [Test()] + public void TestMethodIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.MethodBraceStyle = BraceStyle.DoNotChange; + + Test (policy, +@"class Test +{ +MyType TestMethod () {} +}", +@"class Test +{ + MyType TestMethod () {} +}"); + } + + [Test()] + public void TestPropertyIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.PropertyBraceStyle = BraceStyle.DoNotChange; + + Test (policy, +@"class Test +{ + public int Prop { get; set; } +}",@"class Test +{ + public int Prop { get; set; } +}"); + } + + [Test()] + public void TestPropertyIndentationCase2 () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + + Test (policy, +@"class Test +{ + public int Prop { + get; +set; +} +}", +@"class Test +{ + public int Prop { + get; + set; + } +}"); + } + + + [Ignore ("TODO")] + [Test()] + public void TestIndentEventBody () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.IndentEventBody = true; + + var adapter = Test (policy, +@"class Test +{ + public event EventHandler TestMe { + add { + ; + } +remove { + ; +} + } +}", +@"class Test +{ + public event EventHandler TestMe { + add { + ; + } + remove { + ; + } + } +}"); + policy.IndentEventBody = false; + Continue (policy, adapter, +@"class Test +{ + public event EventHandler TestMe { + add { + ; + } + remove { + ; + } + } +}"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs new file mode 100644 index 0000000000..a9cef844fb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.CSharp.Refactoring; + +namespace ICSharpCode.NRefactory.FormattingTests +{ + /// + /// Text editor test adapter. Only implemented for testing purposes. Don't use in production code. + /// + class TextEditorTestAdapter : ITextEditorAdapter + { + string text; + + public string Text { + get { + return this.text; + } + } + + List delimiters; + + struct Delimiter + { + public readonly int Offset; + public readonly int Length; + + public int EndOffset { + get { return Offset + Length; } + } + + public Delimiter (int offset, int length) + { + Offset = offset; + Length = length; + } + + public override string ToString () + { + return string.Format ("[Delimiter: Offset={0}, Length={1}]", Offset, Length); + } + } + public void Replace (int offset, int count, string value) + { + this.text = this.text.Substring (0, offset) + value + this.text.Substring (offset + count); + } + static IEnumerable FindDelimiter (string text) + { + for (int i = 0; i < text.Length; i++) { + switch (text [i]) { + case '\r': + if (i + 1 < text.Length && text [i + 1] == '\n') { + yield return new Delimiter (i, 2); + i++; + } else { + yield return new Delimiter (i, 1); + } + break; + case '\n': + yield return new Delimiter (i, 1); + break; + } + } + } + + public TextEditorTestAdapter (string text) + { + this.text = text; + delimiters = new List (FindDelimiter (text)); + } + + class Segment + { + public readonly int Offset; + public readonly int Length; + public readonly int DelimiterLength; + + public Segment (int offset, int length, int delimiterLength) + { + this.Offset = offset; + this.Length = length; + this.DelimiterLength = delimiterLength; + } + + public override string ToString () + { + return string.Format ("[Segment: Offset={0}, Length={1}, DelimiterLength={2}]", Offset, Length, DelimiterLength); + } + } + + Segment Get (int number) + { + number--; + if (number < 0 || number - 1 >= delimiters.Count) + return null; + int startOffset = number > 0 ? delimiters [number - 1].EndOffset : 0; + int endOffset; + int delimiterLength; + if (number < delimiters.Count) { + endOffset = delimiters [number].EndOffset; + delimiterLength = delimiters [number].Length; + } else { + endOffset = text.Length; + delimiterLength = 0; + } + return new Segment (startOffset, endOffset - startOffset, delimiterLength); + } + + #region ITextEditorAdapter implementation + public int LocationToOffset (int line, int col) + { + Segment seg = Get (line); + if (seg == null) + return 0; + return seg.Offset + col - 1; + } + + public char GetCharAt (int offset) + { + if (offset < 0 || offset >= text.Length) + return '\0'; + return text [offset]; + } + + public string GetTextAt (int offset, int length) + { + if (offset < 0 || offset + length >= text.Length) + return ""; + if (length <= 0) + return ""; + + return text.Substring (offset, length); + } + + public int GetEditableLength (int lineNumber) + { + var seg = Get (lineNumber); + if (seg == null) + return 0; + return seg.Length - seg.DelimiterLength; + } + + public string GetIndentation (int lineNumber) + { + var seg = Get (lineNumber); + if (seg == null) + return ""; + int start = seg.Offset; + int end = seg.Offset; + int endOffset = seg.Offset + seg.Length - seg.DelimiterLength; + + while (end < endOffset && (text[end] == ' ' || text[end] == '\t')) + end++; + + return start < end ? text.Substring (start, end - start) : ""; + } + + public int GetLineOffset (int lineNumber) + { + var seg = Get (lineNumber); + if (seg == null) + return 0; + return seg.Offset; + } + + public int GetLineLength (int lineNumber) + { + var seg = Get (lineNumber); + if (seg == null) + return 0; + return seg.Length; + } + + public int GetLineEndOffset (int lineNumber) + { + var seg = Get (lineNumber); + if (seg == null) + return 0; + return seg.Offset + seg.Length; + } + + public bool TabsToSpaces { + get { + return false; + } + } + + public int TabSize { + get { + return 4; + } + } + + public string EolMarker { + get { + return Environment.NewLine; + } + } + + public int Length { + get { + return text.Length; + } + } + + public int LineCount { + get { + return delimiters.Count + 1; + } + } + #endregion + } + + public abstract class TestBase + { + static IActionFactory factory = new TestFactory (); + + class TestTextReplaceAction : TextReplaceAction + { + public TestTextReplaceAction (int offset, int removedChars, string insertedText) : base (offset, removedChars, insertedText) + { + } + + public override void Perform (Script script) + { + } + } + + class TestFactory : AbstractActionFactory + { + public override TextReplaceAction CreateTextReplaceAction (int offset, int removedChars, string insertedText) + { + return new TestTextReplaceAction (offset, removedChars, insertedText); + } + } + + static void ApplyChanges (TextEditorTestAdapter adapter, List changes) + { + changes.Sort ((x, y) => y.Offset.CompareTo (x.Offset)); + foreach (var change in changes) { +// Console.WriteLine ("---- apply:" + change); +// Console.WriteLine (adapter.Text); + if (change.Offset > adapter.Length) + continue; + adapter.Replace (change.Offset, change.RemovedChars, change.InsertedText); + } +// Console.WriteLine ("---result:"); +// Console.WriteLine (adapter.Text); + } + + protected static ITextEditorAdapter GetResult (CSharpFormattingOptions policy, string input) + { + var adapter = new TextEditorTestAdapter (input); + var visitior = new AstFormattingVisitor (policy, adapter, factory); + + var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); + compilationUnit.AcceptVisitor (visitior, null); + + ApplyChanges (adapter, visitior.Changes); + + return adapter; + } + + protected static ITextEditorAdapter Test (CSharpFormattingOptions policy, string input, string expectedOutput) + { + var adapter = new TextEditorTestAdapter (input); + var visitior = new AstFormattingVisitor (policy, adapter, factory); + + var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); + compilationUnit.AcceptVisitor (visitior, null); + ApplyChanges (adapter, visitior.Changes); + if (expectedOutput != adapter.Text) { + Console.WriteLine (adapter.Text); + } + Assert.AreEqual (expectedOutput, adapter.Text); + return adapter; + } + + protected static void Continue (CSharpFormattingOptions policy, ITextEditorAdapter adapter, string expectedOutput) + { + var visitior = new AstFormattingVisitor (policy, adapter, factory); + + var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); + compilationUnit.AcceptVisitor (visitior, null); + ApplyChanges (((TextEditorTestAdapter)adapter), visitior.Changes); + if (expectedOutput != adapter.Text) { + Console.WriteLine (adapter.Text); + } + Assert.AreEqual (expectedOutput, adapter.Text); + } + + + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj new file mode 100644 index 0000000000..dd21e09282 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -0,0 +1,173 @@ + + + + {63D3B27A-D966-4902-90B3-30290E1692F1} + Debug + AnyCPU + Library + ICSharpCode.NRefactory + ICSharpCode.NRefactory.Tests + v4.0 + Properties + 10.0.0 + 2.0 + + + x86 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + + + bin\Release\ + False + None + True + False + TRACE + + + 4 + true + ..\ICSharpCode.NRefactory\bin\Debug\ + + + 4 + true + ..\ICSharpCode.NRefactory\bin\Release\ + + + + + + + + + + + ..\..\Mono.Cecil\Test\libs\nunit-2.4.8\nunit.framework.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Properties/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..4d1c475589 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ICSharpCode.NRefactory.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// 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.*")] diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs new file mode 100644 index 0000000000..e64e1f7535 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs @@ -0,0 +1,247 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [TestFixture] + public class CecilLoaderTests : TypeSystemTests + { + public static readonly IProjectContent Mscorlib = new CecilLoader().LoadAssemblyFile(typeof(object).Assembly.Location); + ITypeResolveContext ctx = Mscorlib; + + [TestFixtureSetUp] + public void FixtureSetUp() + { + // use "IncludeInternalMembers" so that Cecil results match C# parser results + CecilLoader loader = new CecilLoader() { IncludeInternalMembers = true }; + testCasePC = loader.LoadAssemblyFile(typeof(TestCase.SimplePublicClass).Assembly.Location); + } + + [Test] + public void InheritanceTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(SystemException)); + ITypeDefinition c2 = Mscorlib.GetTypeDefinition(typeof(Exception)); + Assert.IsNotNull(c, "c is null"); + Assert.IsNotNull(c2, "c2 is null"); + //Assert.AreEqual(3, c.BaseTypes.Count); // Inherited interfaces are not reported by Cecil + // which matches the behaviour of our C#/VB parsers + Assert.AreEqual("System.Exception", c.BaseTypes[0].Resolve(ctx).FullName); + Assert.AreSame(c2, c.BaseTypes[0]); + + string[] superTypes = c.GetAllBaseTypes(ctx).Select(t => t.ToString()).ToArray(); + Assert.AreEqual(new string[] { + "System.SystemException", "System.Exception", "System.Object", + "System.Runtime.Serialization.ISerializable", "System.Runtime.InteropServices._Exception" + }, superTypes); + } + + [Test] + public void GenericPropertyTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Comparer<>)); + IProperty def = c.Properties.Single(p => p.Name == "Default"); + ParameterizedType pt = (ParameterizedType)def.ReturnType.Resolve(ctx); + Assert.AreEqual("System.Collections.Generic.Comparer", pt.FullName); + Assert.AreSame(c.TypeParameters[0], pt.TypeArguments[0]); + } + + [Test] + public void PointerTypeTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(IntPtr)); + IMethod toPointer = c.Methods.Single(p => p.Name == "ToPointer"); + Assert.AreEqual("System.Void*", toPointer.ReturnType.Resolve(ctx).ReflectionName); + Assert.IsTrue (toPointer.ReturnType.Resolve(ctx) is PointerType); + Assert.AreEqual("System.Void", ((PointerType)toPointer.ReturnType.Resolve(ctx)).ElementType.FullName); + } + + [Test] + public void DateTimeDefaultConstructor() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(DateTime)); + Assert.IsFalse(c.Methods.Any(m => m.IsConstructor && m.Parameters.Count == 0)); // struct ctor isn't declared + // but it is implicit: + Assert.IsTrue(c.GetConstructors(ctx).Any(m => m.Parameters.Count == 0)); + } + + [Test] + public void NoEncodingInfoDefaultConstructor() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(EncodingInfo)); + // EncodingInfo only has an internal constructor + Assert.IsFalse(c.Methods.Any(m => m.IsConstructor)); + // and no implicit ctor should be added: + Assert.AreEqual(0, c.GetConstructors(ctx).Count()); + } + + [Test] + public void StaticModifierTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment)); + Assert.IsNotNull(c, "System.Environment not found"); + Assert.IsTrue(c.IsAbstract, "class should be abstract"); + Assert.IsTrue(c.IsSealed, "class should be sealed"); + Assert.IsTrue(c.IsStatic, "class should be static"); + } + + [Test] + public void InnerClassReferenceTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment)); + Assert.IsNotNull(c, "System.Environment not found"); + ITypeReference rt = c.Methods.First(m => m.Name == "GetFolderPath").Parameters[0].Type; + Assert.AreSame(c.NestedTypes.Single(ic => ic.Name == "SpecialFolder"), rt.Resolve(ctx)); + } + + [Test] + public void NestedTypesTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(Environment.SpecialFolder)); + Assert.IsNotNull(c, "c is null"); + Assert.AreEqual("System.Environment.SpecialFolder", c.FullName); + Assert.AreEqual("System.Environment+SpecialFolder", c.ReflectionName); + } + + [Test] + public void VoidTest() + { + ITypeDefinition c = Mscorlib.GetTypeDefinition(typeof(void)); + Assert.IsNotNull(c, "System.Void not found"); + Assert.AreEqual(0, c.GetMethods(ctx).Count()); + Assert.AreEqual(0, c.GetProperties(ctx).Count()); + Assert.AreEqual(0, c.GetEvents(ctx).Count()); + Assert.AreEqual(0, c.GetFields(ctx).Count()); + Assert.AreEqual( + new string[] { + "[System.SerializableAttribute]", + "[System.Runtime.InteropServices.StructLayoutAttribute(0, Size=1)]", + "[System.Runtime.InteropServices.ComVisibleAttribute(true)]" + }, + c.Attributes.Select(a => a.ToString()).ToArray()); + } + + [Test] + public void NestedClassInGenericClassTest() + { + ITypeDefinition dictionary = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); + Assert.IsNotNull(dictionary); + ITypeDefinition valueCollection = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>.ValueCollection)); + Assert.IsNotNull(valueCollection); + var dictionaryRT = new ParameterizedType(dictionary, new[] { Mscorlib.GetTypeDefinition(typeof(string)), Mscorlib.GetTypeDefinition(typeof(int)) }); + IProperty valueProperty = dictionaryRT.GetProperties(ctx).Single(p => p.Name == "Values"); + IType parameterizedValueCollection = valueProperty.ReturnType.Resolve(ctx); + Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection[[System.String],[System.Int32]]", parameterizedValueCollection.ReflectionName); + Assert.AreSame(valueCollection, parameterizedValueCollection.GetDefinition()); + } + + [Test] + public void ValueCollectionCountModifiers() + { + ITypeDefinition valueCollection = Mscorlib.GetTypeDefinition(typeof(Dictionary<,>.ValueCollection)); + Assert.AreEqual(Accessibility.Public, valueCollection.Accessibility); + Assert.IsTrue(valueCollection.IsSealed); + Assert.IsFalse(valueCollection.IsAbstract); + Assert.IsFalse(valueCollection.IsStatic); + + IProperty count = valueCollection.Properties.Single(p => p.Name == "Count"); + Assert.AreEqual(Accessibility.Public, count.Accessibility); + // It's sealed on the IL level; but in C# it's just a normal non-virtual method that happens to implement an interface + Assert.IsFalse(count.IsSealed); + Assert.IsFalse(count.IsVirtual); + Assert.IsFalse(count.IsAbstract); + } + + [Test] + public void MathAcosModifiers() + { + ITypeDefinition math = Mscorlib.GetTypeDefinition(typeof(Math)); + Assert.AreEqual(Accessibility.Public, math.Accessibility); + Assert.IsTrue(math.IsSealed); + Assert.IsTrue(math.IsAbstract); + Assert.IsTrue(math.IsStatic); + + IMethod acos = math.Methods.Single(p => p.Name == "Acos"); + Assert.AreEqual(Accessibility.Public, acos.Accessibility); + Assert.IsTrue(acos.IsStatic); + Assert.IsFalse(acos.IsAbstract); + Assert.IsFalse(acos.IsSealed); + Assert.IsFalse(acos.IsVirtual); + Assert.IsFalse(acos.IsOverride); + } + + [Test] + public void EncodingModifiers() + { + ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(Encoding)); + Assert.AreEqual(Accessibility.Public, encoding.Accessibility); + Assert.IsFalse(encoding.IsSealed); + Assert.IsTrue(encoding.IsAbstract); + + IMethod getDecoder = encoding.Methods.Single(p => p.Name == "GetDecoder"); + Assert.AreEqual(Accessibility.Public, getDecoder.Accessibility); + Assert.IsFalse(getDecoder.IsStatic); + Assert.IsFalse(getDecoder.IsAbstract); + Assert.IsFalse(getDecoder.IsSealed); + Assert.IsTrue(getDecoder.IsVirtual); + Assert.IsFalse(getDecoder.IsOverride); + + IMethod getMaxByteCount = encoding.Methods.Single(p => p.Name == "GetMaxByteCount"); + Assert.AreEqual(Accessibility.Public, getMaxByteCount.Accessibility); + Assert.IsFalse(getMaxByteCount.IsStatic); + Assert.IsTrue(getMaxByteCount.IsAbstract); + Assert.IsFalse(getMaxByteCount.IsSealed); + Assert.IsFalse(getMaxByteCount.IsVirtual); + Assert.IsFalse(getMaxByteCount.IsOverride); + + IProperty encoderFallback = encoding.Properties.Single(p => p.Name == "EncoderFallback"); + Assert.AreEqual(Accessibility.Public, encoderFallback.Accessibility); + Assert.IsFalse(encoderFallback.IsStatic); + Assert.IsFalse(encoderFallback.IsAbstract); + Assert.IsFalse(encoderFallback.IsSealed); + Assert.IsFalse(encoderFallback.IsVirtual); + Assert.IsFalse(encoderFallback.IsOverride); + } + + [Test] + public void UnicodeEncodingModifiers() + { + ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(UnicodeEncoding)); + Assert.AreEqual(Accessibility.Public, encoding.Accessibility); + Assert.IsFalse(encoding.IsSealed); + Assert.IsFalse(encoding.IsAbstract); + + IMethod getDecoder = encoding.Methods.Single(p => p.Name == "GetDecoder"); + Assert.AreEqual(Accessibility.Public, getDecoder.Accessibility); + Assert.IsFalse(getDecoder.IsStatic); + Assert.IsFalse(getDecoder.IsAbstract); + Assert.IsFalse(getDecoder.IsSealed); + Assert.IsFalse(getDecoder.IsVirtual); + Assert.IsTrue(getDecoder.IsOverride); + } + + [Test] + public void UTF32EncodingModifiers() + { + ITypeDefinition encoding = Mscorlib.GetTypeDefinition(typeof(UTF32Encoding)); + Assert.AreEqual(Accessibility.Public, encoding.Accessibility); + Assert.IsTrue(encoding.IsSealed); + Assert.IsFalse(encoding.IsAbstract); + + IMethod getDecoder = encoding.Methods.Single(p => p.Name == "GetDecoder"); + Assert.AreEqual(Accessibility.Public, getDecoder.Accessibility); + Assert.IsFalse(getDecoder.IsStatic); + Assert.IsFalse(getDecoder.IsAbstract); + Assert.IsFalse(getDecoder.IsSealed); + Assert.IsFalse(getDecoder.IsVirtual); + Assert.IsTrue(getDecoder.IsOverride); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs new file mode 100644 index 0000000000..095e455ca9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs @@ -0,0 +1,148 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [TestFixture] + public class GetAllBaseTypesTest + { + IProjectContent mscorlib = CecilLoaderTests.Mscorlib; + ITypeResolveContext context = CecilLoaderTests.Mscorlib; + + IType[] GetAllBaseTypes(Type type) + { + return type.ToTypeReference().Resolve(context).GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray(); + } + + IType[] GetTypes(params Type[] types) + { + return types.Select(t => t.ToTypeReference().Resolve(context)).OrderBy(t => t.ReflectionName).ToArray();; + } + + [Test] + public void ObjectBaseTypes() + { + Assert.AreEqual(GetTypes(typeof(object)), GetAllBaseTypes(typeof(object))); + } + + [Test] + public void StringBaseTypes() + { + Assert.AreEqual(GetTypes(typeof(string), typeof(object), typeof(IComparable), typeof(ICloneable), typeof(IConvertible), + typeof(IComparable), typeof(IEquatable), typeof(IEnumerable), typeof(IEnumerable)), + GetAllBaseTypes(typeof(string))); + } + + [Test] + public void ArrayOfString() + { + Assert.AreEqual(GetTypes(typeof(string[]), typeof(Array), typeof(object), + typeof(IList), typeof(ICollection), typeof(IEnumerable), + typeof(IList), typeof(ICollection), typeof(IEnumerable), + typeof(IStructuralEquatable), typeof(IStructuralComparable), typeof(ICloneable)), + GetAllBaseTypes(typeof(string[]))); + } + + [Test] + public void MultidimensionalArrayOfString() + { + Assert.AreEqual(GetTypes(typeof(string[,]), typeof(Array), typeof(object), + typeof(IList), typeof(ICollection), typeof(IEnumerable), + typeof(IStructuralEquatable), typeof(IStructuralComparable), typeof(ICloneable)), + GetAllBaseTypes(typeof(string[,]))); + } + + [Test] + public void ClassDerivingFromItself() + { + // class C : C {} + DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + c.BaseTypes.Add(c); + Assert.AreEqual(new [] { c }, c.GetAllBaseTypes(context).ToArray()); + } + + [Test] + public void TwoClassesDerivingFromEachOther() + { + // class C1 : C2 {} class C2 : C1 {} + DefaultTypeDefinition c1 = new DefaultTypeDefinition(mscorlib, string.Empty, "C1"); + DefaultTypeDefinition c2 = new DefaultTypeDefinition(mscorlib, string.Empty, "C2"); + c1.BaseTypes.Add(c2); + c2.BaseTypes.Add(c1); + Assert.AreEqual(new [] { c1, c2 }, c1.GetAllBaseTypes(context).ToArray()); + } + + [Test] + public void ClassDerivingFromParameterizedVersionOfItself() + { + // class C : C> {} + DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + c.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X")); + c.BaseTypes.Add(new ParameterizedType(c, new [] { new ParameterizedType(c, new [] { c.TypeParameters[0] }) })); + Assert.AreEqual(new [] { c }, c.GetAllBaseTypes(context).ToArray()); + } + + [Test] + public void ClassDerivingFromTwoInstanciationsOfIEnumerable() + { + // class C : IEnumerable, IEnumerable {} + DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + c.BaseTypes.Add(typeof(IEnumerable).ToTypeReference()); + c.BaseTypes.Add(typeof(IEnumerable).ToTypeReference()); + IType[] expected = { + c, + c.BaseTypes[0].Resolve(context), + c.BaseTypes[1].Resolve(context), + mscorlib.GetTypeDefinition(typeof(IEnumerable)), + mscorlib.GetTypeDefinition(typeof(object)) + }; + Assert.AreEqual(expected, + c.GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray()); + } + + [Test] + public void StructImplementingIEquatable() + { + // struct S : IEquatable {} + // don't use a Cecil-loaded struct for this test; we're testing the implicit addition of System.ValueType + DefaultTypeDefinition s = new DefaultTypeDefinition(mscorlib, string.Empty, "S"); + s.ClassType = ClassType.Struct; + s.BaseTypes.Add(new ParameterizedType(mscorlib.GetTypeDefinition(typeof(IEquatable<>)), new[] { s })); + IType[] expected = { + s, + s.BaseTypes[0].Resolve(context), + mscorlib.GetTypeDefinition(typeof(object)), + mscorlib.GetTypeDefinition(typeof(ValueType)) + }; + Assert.AreEqual(expected, + s.GetAllBaseTypes(context).OrderBy(t => t.ReflectionName).ToArray()); + } + + [Test] + public void BaseTypesOfListOfString() + { + Assert.AreEqual( + GetTypes(typeof(List), typeof(object), + typeof(IList), typeof(ICollection), typeof(IEnumerable), + typeof(IEnumerable), typeof(ICollection), typeof(IList)), + GetAllBaseTypes(typeof(List))); + } + + [Test] + public void BaseTypeDefinitionsOfListOfString() + { + Assert.AreEqual( + GetTypes(typeof(List<>), typeof(object), + typeof(IList), typeof(ICollection), typeof(IEnumerable), + typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)), + typeof(List).ToTypeReference().Resolve(context).GetAllBaseTypeDefinitions(context).OrderBy(t => t.ReflectionName).ToArray()); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs new file mode 100644 index 0000000000..6e0d9dc8ba --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs @@ -0,0 +1,75 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [TestFixture] + public class GetMembersTests + { + IProjectContent mscorlib = CecilLoaderTests.Mscorlib; + + [Test] + public void EmptyClassHasToString() + { + DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + Assert.AreEqual("System.Object.ToString", c.GetMethods(mscorlib, m => m.Name == "ToString").Single().FullName); + } + + [Test] + public void MultipleInheritanceTest() + { + DefaultTypeDefinition b1 = new DefaultTypeDefinition(mscorlib, string.Empty, "B1"); + b1.ClassType = ClassType.Interface; + b1.Properties.Add(new DefaultProperty(b1, "P1")); + + DefaultTypeDefinition b2 = new DefaultTypeDefinition(mscorlib, string.Empty, "B1"); + b2.ClassType = ClassType.Interface; + b2.Properties.Add(new DefaultProperty(b1, "P2")); + + DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); + c.ClassType = ClassType.Interface; + c.BaseTypes.Add(b1); + c.BaseTypes.Add(b2); + + Assert.AreEqual(new[] { "P1", "P2" }, c.GetProperties(mscorlib).Select(p => p.Name).ToArray()); + // Test that there's only one copy of ToString(): + Assert.AreEqual(1, c.GetMethods(mscorlib, m => m.Name == "ToString").Count()); + } + + [Test] + public void ArrayType() + { + IType arrayType = typeof(string[]).ToTypeReference().Resolve(mscorlib); + // Array inherits ToString() from System.Object + Assert.AreEqual("System.Object.ToString", arrayType.GetMethods(mscorlib, m => m.Name == "ToString").Single().FullName); + Assert.AreEqual("System.Array.GetLowerBound", arrayType.GetMethods(mscorlib, m => m.Name == "GetLowerBound").Single().FullName); + Assert.AreEqual("System.Array.Length", arrayType.GetProperties(mscorlib, p => p.Name == "Length").Single().FullName); + + // test indexer + IProperty indexer = arrayType.GetProperties(mscorlib, p => p.IsIndexer).Single(); + Assert.AreEqual("System.Array.Items", indexer.FullName); + Assert.AreEqual("System.String", indexer.ReturnType.Resolve(mscorlib).ReflectionName); + Assert.AreEqual(1, indexer.Parameters.Count); + Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.Resolve(mscorlib).ReflectionName); + } + + [Test] + public void MultidimensionalArrayType() + { + IType arrayType = typeof(string[,][]).ToTypeReference().Resolve(mscorlib); + + // test indexer + IProperty indexer = arrayType.GetProperties(mscorlib, p => p.IsIndexer).Single(); + Assert.AreEqual("System.Array.Items", indexer.FullName); + Assert.AreEqual("System.String[]", indexer.ReturnType.Resolve(mscorlib).ReflectionName); + Assert.AreEqual(2, indexer.Parameters.Count); + Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.Resolve(mscorlib).ReflectionName); + Assert.AreEqual("System.Int32", indexer.Parameters[1].Type.Resolve(mscorlib).ReflectionName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs new file mode 100644 index 0000000000..537ed2319a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs @@ -0,0 +1,279 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [TestFixture] + public unsafe class ReflectionHelperTests + { + ITypeResolveContext context = CecilLoaderTests.Mscorlib; + + void TestGetClass(Type type) + { + ITypeDefinition t = CecilLoaderTests.Mscorlib.GetTypeDefinition(type); + Assert.IsNotNull(t, type.FullName); + Assert.AreEqual(type.FullName, t.ReflectionName); + } + + [Test] + public void TestGetInnerClass() + { + TestGetClass(typeof(Environment.SpecialFolder)); + } + + [Test] + public void TestGetGenericClass1() + { + TestGetClass(typeof(Action<>)); + } + + [Test] + public void TestGetGenericClass2() + { + TestGetClass(typeof(Action<,>)); + } + + [Test] + public void TestGetInnerClassInGenericClass1() + { + TestGetClass(typeof(Dictionary<,>.ValueCollection)); + } + + [Test] + public void TestGetInnerClassInGenericClass2() + { + TestGetClass(typeof(Dictionary<,>.ValueCollection.Enumerator)); + } + + [Test] + public void TestToTypeReferenceInnerClass() + { + Assert.AreEqual("System.Environment+SpecialFolder", + typeof(Environment.SpecialFolder).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceUnboundGenericClass() + { + Assert.AreEqual("System.Action`1", + typeof(Action<>).ToTypeReference().Resolve(context).ReflectionName); + Assert.AreEqual("System.Action`2", + typeof(Action<,>).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceBoundGenericClass() + { + Assert.AreEqual("System.Action`1[[System.String]]", + typeof(Action).ToTypeReference().Resolve(context).ReflectionName); + Assert.AreEqual("System.Action`2[[System.Int32],[System.Int16]]", + typeof(Action).ToTypeReference().Resolve(context).ReflectionName); + } + + + [Test] + public void TestToTypeReferenceNullableType() + { + Assert.AreEqual("System.Nullable`1[[System.Int32]]", + typeof(int?).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceInnerClassInUnboundGenericType() + { + Assert.AreEqual("System.Collections.Generic.Dictionary`2+ValueCollection", + typeof(Dictionary<,>.ValueCollection).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceInnerClassInBoundGenericType() + { + Assert.AreEqual("System.Collections.Generic.Dictionary`2+KeyCollection[[System.String],[System.Int32]]", + typeof(Dictionary.KeyCollection).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceArrayType() + { + Assert.AreEqual(typeof(int[]).FullName, + typeof(int[]).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceMultidimensionalArrayType() + { + Assert.AreEqual(typeof(int[,]).FullName, + typeof(int[,]).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceJaggedMultidimensionalArrayType() + { + Assert.AreEqual(typeof(int[,][,,]).FullName, + typeof(int[,][,,]).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferencePointerType() + { + Assert.AreEqual(typeof(int*).FullName, + typeof(int*).ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceByReferenceType() + { + Assert.AreEqual(typeof(int).MakeByRefType().FullName, + typeof(int).MakeByRefType().ToTypeReference().Resolve(context).ReflectionName); + } + + [Test] + public void TestToTypeReferenceGenericType() + { + MethodInfo convertAllInfo = typeof(List<>).GetMethod("ConvertAll"); + Type parameterType = convertAllInfo.GetParameters()[0].ParameterType; // Converter[[`0],[``0]] + // cannot resolve generic types without knowing the parent entity: + Assert.AreEqual("System.Converter`2[[?],[?]]", + parameterType.ToTypeReference().Resolve(context).ReflectionName); + // now try with parent entity: + IMethod convertAll = context.GetTypeDefinition(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll"); + Assert.AreEqual("System.Converter`2[[`0],[``0]]", + parameterType.ToTypeReference(entity: convertAll).Resolve(context).ReflectionName); + } + + [Test] + public void ParseReflectionName() + { + Assert.AreEqual("System.Int32", ReflectionHelper.ParseReflectionName("System.Int32").Resolve(context).ReflectionName); + Assert.AreEqual("System.Int32&", ReflectionHelper.ParseReflectionName("System.Int32&").Resolve(context).ReflectionName); + Assert.AreEqual("System.Int32*&", ReflectionHelper.ParseReflectionName("System.Int32*&").Resolve(context).ReflectionName); + Assert.AreEqual("System.Int32", ReflectionHelper.ParseReflectionName(typeof(int).AssemblyQualifiedName).Resolve(context).ReflectionName); + Assert.AreEqual("System.Action`1[[System.String]]", ReflectionHelper.ParseReflectionName("System.Action`1[[System.String]]").Resolve(context).ReflectionName); + Assert.AreEqual("System.Action`1[[System.String]]", ReflectionHelper.ParseReflectionName("System.Action`1[[System.String, mscorlib]]").Resolve(context).ReflectionName); + Assert.AreEqual("System.Int32[,,][,]", ReflectionHelper.ParseReflectionName(typeof(int[,][,,]).AssemblyQualifiedName).Resolve(context).ReflectionName); + Assert.AreEqual("System.Environment+SpecialFolder", ReflectionHelper.ParseReflectionName("System.Environment+SpecialFolder").Resolve(context).ReflectionName); + } + + [Test] + public void ParseOpenGenericReflectionName() + { + IMethod convertAll = context.GetTypeDefinition(typeof(List<>)).Methods.Single(m => m.Name == "ConvertAll"); + Assert.AreEqual("System.Converter`2[[?],[?]]", ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]").Resolve(context).ReflectionName); + Assert.AreEqual("System.Converter`2[[`0],[``0]]", ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]", convertAll).Resolve(context).ReflectionName); + } + + [Test, ExpectedException(typeof(ArgumentNullException))] + public void ParseNullReflectionName() + { + ReflectionHelper.ParseReflectionName(null); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName1() + { + ReflectionHelper.ParseReflectionName(string.Empty); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName2() + { + ReflectionHelper.ParseReflectionName("`"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName3() + { + ReflectionHelper.ParseReflectionName("``"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName4() + { + ReflectionHelper.ParseReflectionName("System.Action`A"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName5() + { + ReflectionHelper.ParseReflectionName("System.Environment+"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName5b() + { + ReflectionHelper.ParseReflectionName("System.Environment+`"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName6() + { + ReflectionHelper.ParseReflectionName("System.Int32["); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName7() + { + ReflectionHelper.ParseReflectionName("System.Int32[`]"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName8() + { + ReflectionHelper.ParseReflectionName("System.Int32[,"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName9() + { + ReflectionHelper.ParseReflectionName("System.Int32]"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName10() + { + ReflectionHelper.ParseReflectionName("System.Int32*a"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName11() + { + ReflectionHelper.ParseReflectionName("System.Action`1[[]]"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName12() + { + ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32]a]"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName13() + { + ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32],]"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName14() + { + ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32]"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName15() + { + ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32"); + } + + [Test, ExpectedException(typeof(ReflectionNameParseException))] + public void ParseInvalidReflectionName16() + { + ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32],[System.String"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs new file mode 100644 index 0000000000..f4931bc33a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [TestFixture] + public class StructureTests + { + [Test] + public void ClasesThatSupportInterningAreSealed() + { + foreach (Type type in typeof(ISupportsInterning).Assembly.GetTypes()) { + if (typeof(ISupportsInterning).IsAssignableFrom(type) && !type.IsInterface) { + Assert.IsTrue(type.IsSealed, type.FullName); + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs new file mode 100644 index 0000000000..11d53549a3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs @@ -0,0 +1,192 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Serialization; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /* Not a real unit test + [TestFixture] + public class TestInterningProvider + { + sealed class ReferenceComparer : IEqualityComparer + { + public new bool Equals(object a, object b) + { + return ReferenceEquals(a, b); + } + + public int GetHashCode(object obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } + + sealed class InterningComparer : IEqualityComparer + { + public bool Equals(ISupportsInterning x, ISupportsInterning y) + { + return x.EqualsForInterning(y); + } + + public int GetHashCode(ISupportsInterning obj) + { + return obj.GetHashCodeForInterning(); + } + } + + sealed class ListComparer : IEqualityComparer> + { + public bool Equals(IEnumerable a, IEnumerable b) + { + if (a.GetType() != b.GetType()) + return false; + return Enumerable.SequenceEqual(a, b, new ReferenceComparer()); + } + + public int GetHashCode(IEnumerable obj) + { + int hashCode = obj.GetType().GetHashCode(); + unchecked { + foreach (object o in obj) { + hashCode *= 27; + hashCode += RuntimeHelpers.GetHashCode(o); + } + } + return hashCode; + } + } + + sealed class InterningProvider : IInterningProvider + { + internal HashSet uniqueObjectsPreIntern = new HashSet(new ReferenceComparer()); + internal HashSet uniqueObjectsPostIntern = new HashSet(new ReferenceComparer()); + internal Dictionary byValueDict = new Dictionary(); + internal Dictionary supportsInternDict = new Dictionary(new InterningComparer()); + internal Dictionary, IEnumerable> listDict = new Dictionary, IEnumerable>(new ListComparer()); + + public T Intern(T obj) where T : class + { + if (obj == null) + return null; + uniqueObjectsPreIntern.Add(obj); + ISupportsInterning s = obj as ISupportsInterning; + if (s != null) { + ISupportsInterning output; + if (supportsInternDict.TryGetValue(s, out output)) { + obj = (T)output; + } else { + s.PrepareForInterning(this); + if (supportsInternDict.TryGetValue(s, out output)) + obj = (T)output; + else + supportsInternDict.Add(s, s); + } + } else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { + object output; + if (byValueDict.TryGetValue(obj, out output)) + obj = (T)output; + else + byValueDict.Add(obj, obj); + } + uniqueObjectsPostIntern.Add(obj); + return obj; + } + + public IList InternList(IList list) where T : class + { + if (list == null) + return null; + uniqueObjectsPreIntern.Add(list); + for (int i = 0; i < list.Count; i++) { + T oldItem = list[i]; + T newItem = Intern(oldItem); + if (oldItem != newItem) { + if (list.IsReadOnly) + list = new T[list.Count]; + list[i] = newItem; + } + } + if (!list.IsReadOnly) + list = new ReadOnlyCollection(list); + IEnumerable output; + if (listDict.TryGetValue(list, out output)) + list = (IList)output; + else + listDict.Add(list, list); + uniqueObjectsPostIntern.Add(list); + return list; + } + + public void InternProject(IProjectContent pc) + { + foreach (var c in TreeTraversal.PreOrder(pc.GetClasses(), c => c.NestedTypes)) { + Intern(c.Namespace); + Intern(c.Name); + foreach (IMember m in c.Members) { + Intern(m); + } + } + } + } + + IProjectContent[] LoadProjects(CecilLoader loader) + { + const string dir = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\"; + return new IProjectContent[] { + loader.LoadAssemblyFile(dir + "mscorlib.dll"), + loader.LoadAssemblyFile(dir + "System.dll"), + loader.LoadAssemblyFile(dir + "System.Core.dll"), + loader.LoadAssemblyFile(dir + "System.Xml.dll"), + loader.LoadAssemblyFile(dir + "System.Xml.Linq.dll"), + loader.LoadAssemblyFile(dir + "System.Data.dll"), + loader.LoadAssemblyFile(dir + "System.Drawing.dll"), + loader.LoadAssemblyFile(dir + "System.Windows.Forms.dll"), + loader.LoadAssemblyFile(dir + "WindowsBase.dll"), + loader.LoadAssemblyFile(dir + "PresentationCore.dll"), + loader.LoadAssemblyFile(dir + "PresentationFramework.dll") + }; + } + + [Test] + public void PrintStatistics() + { + long startMemory = GC.GetTotalMemory(true); + IProjectContent[] pc = LoadProjects(new CecilLoader()); + long memoryWithFullPC = GC.GetTotalMemory(true) - startMemory; + InterningProvider p = new InterningProvider(); + CecilLoader loader = new CecilLoader(); + loader.InterningProvider = p; + pc = LoadProjects(loader); + PrintStatistics(p); + loader = null; + p = null; + long memoryWithInternedPC = GC.GetTotalMemory(true) - startMemory; + GC.KeepAlive(pc); + Console.WriteLine(memoryWithInternedPC / 1024 + " KB / " + memoryWithFullPC / 1024 + " KB"); + } + + void PrintStatistics(InterningProvider p) + { + var stats = + from obj in p.uniqueObjectsPreIntern + group 1 by obj.GetType() into g + join g2 in (from obj in p.uniqueObjectsPostIntern group 1 by obj.GetType()) on g.Key equals g2.Key + orderby g.Key.FullName + select new { Type = g.Key, PreCount = g.Count(), PostCount = g2.Count() }; + foreach (var element in stats) { + Console.WriteLine(element.Type + ": " + element.PostCount + "/" + element.PreCount); + } + } + }//*/ +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs new file mode 100644 index 0000000000..edb0bce50b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -0,0 +1,98 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +[assembly: ICSharpCode.NRefactory.TypeSystem.TestCase.TypeTestAttribute( + 42, typeof(System.Action<>), typeof(IDictionary>))] + +namespace ICSharpCode.NRefactory.TypeSystem.TestCase +{ + public delegate S GenericDelegate(T input) where T : S where S : class; + + public class SimplePublicClass + { + public void Method() {} + } + + public class TypeTestAttribute : Attribute + { + public TypeTestAttribute(int a1, Type a2, Type a3) {} + } + + public unsafe class DynamicTest + { + public dynamic SimpleProperty { get; set; } + + public List DynamicGenerics1(Action param) { return null; } + public void DynamicGenerics2(Action param) { } + public void DynamicGenerics3(Action param) { } + public void DynamicGenerics4(Action param) { } + public void DynamicGenerics5(Action param) { } + public void DynamicGenerics6(ref Action param) { } + public void DynamicGenerics7(Action param) { } + } + + public class GenericClass where A : B + { + public void TestMethod(string param) where V: K where K: IComparable {} + public void GetIndex(T element) where T : IEquatable {} + } + + public class PropertyTest + { + public int PropertyWithProtectedSetter { get; protected set; } + + public object PropertyWithPrivateSetter { get; private set; } + + public string this[int index] { get { return "Test"; } } + } + + public enum MyEnum : short + { + First, + Second, + Flag1 = 0x10, + Flag2 = 0x20, + CombinedFlags = Flag1 | Flag2 + } + + public class Base { + public class Nested {} + } + public class Derived : Base {} + + public struct MyStructWithCtor + { + public MyStructWithCtor(int a) {} + } + + [Serializable] + public class NonCustomAttributes + { + [NonSerialized] + public readonly int NonSerializedField; + + [DllImport("unmanaged.dll", CharSet = CharSet.Unicode)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool DllMethod([In, Out] ref int p); + } + + [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8)] + public struct ExplicitFieldLayoutStruct + { + [FieldOffset(0)] + public int Field0; + + [FieldOffset(100)] + public int Field100; + } + + public class ParameterTests + { + public void MethodWithOutParameter(out int x) { x = 0; } + public void MethodWithParamsArray(params object[] x) {} + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs new file mode 100644 index 0000000000..80e4071ba0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -0,0 +1,398 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; +using System.Runtime.InteropServices; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.TypeSystem.TestCase; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Base class for the type system tests. + /// Test fixtures for specific APIs (Cecil, C# Parser) derive from this class. + /// + public abstract class TypeSystemTests + { + protected IProjectContent testCasePC; + + ITypeResolveContext ctx; + + [SetUpAttribute] + public void SetUp() + { + ctx = CompositeTypeResolveContext.Combine(testCasePC, CecilLoaderTests.Mscorlib); + } + + ITypeDefinition GetClass(Type type) + { + return testCasePC.GetTypeDefinition(type); + } + + [Test] + public void SimplePublicClassTest() + { + ITypeDefinition c = testCasePC.GetTypeDefinition(typeof(SimplePublicClass)); + Assert.AreEqual(typeof(SimplePublicClass).Name, c.Name); + Assert.AreEqual(typeof(SimplePublicClass).FullName, c.FullName); + Assert.AreEqual(typeof(SimplePublicClass).Namespace, c.Namespace); + Assert.AreEqual(typeof(SimplePublicClass).FullName, c.ReflectionName); + + Assert.AreEqual(Accessibility.Public, c.Accessibility); + Assert.IsFalse(c.IsAbstract); + Assert.IsFalse(c.IsSealed); + Assert.IsFalse(c.IsStatic); + Assert.IsFalse(c.IsShadowing); + } + + [Test] + public void SimplePublicClassMethodTest() + { + ITypeDefinition c = testCasePC.GetTypeDefinition(typeof(SimplePublicClass)); + + IMethod method = c.Methods.Single(m => m.Name == "Method"); + Assert.AreEqual(typeof(SimplePublicClass).FullName + ".Method", method.FullName); + Assert.AreSame(c, method.DeclaringType); + Assert.AreEqual(Accessibility.Public, method.Accessibility); + Assert.AreEqual(EntityType.Method, method.EntityType); + Assert.IsFalse(method.IsVirtual); + Assert.IsFalse(method.IsStatic); + Assert.IsTrue(method.IsFrozen); + Assert.AreEqual(0, method.Parameters.Count); + Assert.AreEqual(0, method.Attributes.Count); + } + + [Test] + public void DynamicType() + { + ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); + Assert.AreSame(SharedTypes.Dynamic, testClass.Properties.Single().ReturnType.Resolve(ctx)); + Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count); + } + + [Test] + public void DynamicTypeInGenerics() + { + ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); + + IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); + Assert.AreEqual("System.Collections.Generic.List`1[[dynamic]]", m1.ReturnType.Resolve(ctx).ReflectionName); + Assert.AreEqual("System.Action`3[[System.Object],[dynamic[]],[System.Object]]", m1.Parameters[0].Type.Resolve(ctx).ReflectionName); + + IMethod m2 = testClass.Methods.Single(me => me.Name == "DynamicGenerics2"); + Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]", m2.Parameters[0].Type.Resolve(ctx).ReflectionName); + + IMethod m3 = testClass.Methods.Single(me => me.Name == "DynamicGenerics3"); + Assert.AreEqual("System.Action`3[[System.Int32],[dynamic],[System.Object]]", m3.Parameters[0].Type.Resolve(ctx).ReflectionName); + + IMethod m4 = testClass.Methods.Single(me => me.Name == "DynamicGenerics4"); + Assert.AreEqual("System.Action`3[[System.Int32[]],[dynamic],[System.Object]]", m4.Parameters[0].Type.Resolve(ctx).ReflectionName); + + IMethod m5 = testClass.Methods.Single(me => me.Name == "DynamicGenerics5"); + Assert.AreEqual("System.Action`3[[System.Int32*[]],[dynamic],[System.Object]]", m5.Parameters[0].Type.Resolve(ctx).ReflectionName); + + IMethod m6 = testClass.Methods.Single(me => me.Name == "DynamicGenerics6"); + Assert.AreEqual("System.Action`3[[System.Object],[dynamic],[System.Object]]&", m6.Parameters[0].Type.Resolve(ctx).ReflectionName); + + IMethod m7 = testClass.Methods.Single(me => me.Name == "DynamicGenerics7"); + Assert.AreEqual("System.Action`3[[System.Int32[][,]],[dynamic],[System.Object]]", m7.Parameters[0].Type.Resolve(ctx).ReflectionName); + } + + [Test] + public void DynamicParameterHasNoAttributes() + { + ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); + IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); + Assert.AreEqual(0, m1.Parameters[0].Attributes.Count); + } + + [Test] + public void AssemblyAttribute() + { + var attributes = testCasePC.AssemblyAttributes; + var typeTest = attributes.First(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName); + var posArgs = typeTest.GetPositionalArguments(ctx); + Assert.AreEqual(3, posArgs.Count); + // first argument is (int)42 + Assert.AreEqual(42, (int)posArgs[0].GetValue(ctx)); + // second argument is typeof(System.Action<>) + IType rt = (IType)posArgs[1].GetValue(ctx); + Assert.IsFalse(rt is ParameterizedType); // rt must not be constructed - it's just an unbound type + Assert.AreEqual("System.Action", rt.FullName); + Assert.AreEqual(1, rt.TypeParameterCount); + // third argument is typeof(IDictionary>) + ParameterizedType crt = (ParameterizedType)posArgs[2].GetValue(ctx); + Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); + Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); + // ? for NUnit.TestAttribute (because that assembly isn't in ctx) + Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName); + } + + [Test] + public void TestClassTypeParameters() + { + var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>)); + Assert.AreEqual(EntityType.TypeDefinition, testClass.TypeParameters[0].OwnerType); + Assert.AreEqual(EntityType.TypeDefinition, testClass.TypeParameters[1].OwnerType); + Assert.AreSame(testClass.TypeParameters[1], testClass.TypeParameters[0].Constraints[0].Resolve(ctx)); + } + + [Test] + public void TestMethod() + { + var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>)); + + IMethod m = testClass.Methods.Single(me => me.Name == "TestMethod"); + Assert.AreEqual("K", m.TypeParameters[0].Name); + Assert.AreEqual("V", m.TypeParameters[1].Name); + Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType); + Assert.AreEqual(EntityType.Method, m.TypeParameters[1].OwnerType); + + Assert.AreEqual("System.IComparable`1[[``1]]", m.TypeParameters[0].Constraints[0].Resolve(ctx).ReflectionName); + Assert.AreSame(m.TypeParameters[0], m.TypeParameters[1].Constraints[0].Resolve(ctx)); + } + + [Test] + public void GetIndex() + { + var testClass = testCasePC.GetTypeDefinition(typeof(GenericClass<,>)); + + IMethod m = testClass.Methods.Single(me => me.Name == "GetIndex"); + Assert.AreEqual("T", m.TypeParameters[0].Name); + Assert.AreEqual(EntityType.Method, m.TypeParameters[0].OwnerType); + + ParameterizedType constraint = (ParameterizedType)m.TypeParameters[0].Constraints[0].Resolve(ctx); + Assert.AreEqual("IEquatable", constraint.Name); + Assert.AreEqual(1, constraint.TypeParameterCount); + Assert.AreEqual(1, constraint.TypeArguments.Count); + Assert.AreSame(m.TypeParameters[0], constraint.TypeArguments[0]); + } + + [Test] + public void PropertyWithProtectedSetter() + { + var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); + IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithProtectedSetter"); + Assert.IsTrue(p.CanGet); + Assert.IsTrue(p.CanSet); + Assert.AreEqual(Accessibility.Public, p.Accessibility); + Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); + Assert.AreEqual(Accessibility.Protected, p.Setter.Accessibility); + } + + [Test] + public void PropertyWithPrivateSetter() + { + var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); + IProperty p = testClass.Properties.Single(pr => pr.Name == "PropertyWithPrivateSetter"); + Assert.IsTrue(p.CanGet); + Assert.IsTrue(p.CanSet); + Assert.AreEqual(Accessibility.Public, p.Accessibility); + Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); + Assert.AreEqual(Accessibility.Private, p.Setter.Accessibility); + } + + [Test] + public void Indexer() + { + var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); + IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); + Assert.IsTrue(p.CanGet); + Assert.AreEqual(Accessibility.Public, p.Accessibility); + Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); + Assert.IsFalse(p.CanSet); + Assert.IsNull(p.Setter); + } + + [Test] + public void EnumTest() + { + var e = testCasePC.GetTypeDefinition(typeof(MyEnum)); + Assert.AreEqual(ClassType.Enum, e.ClassType); + Assert.AreEqual(false, e.IsReferenceType(ctx)); + Assert.AreEqual("System.Int16", e.BaseTypes[0].Resolve(ctx).ReflectionName); + Assert.AreEqual(new[] { "System.Enum" }, e.GetBaseTypes(ctx).Select(t => t.ReflectionName).ToArray()); + } + + [Test] + public void EnumFieldsTest() + { + var e = testCasePC.GetTypeDefinition(typeof(MyEnum)); + Assert.AreEqual(5, e.Fields.Count); + + foreach (IField f in e.Fields) { + Assert.IsTrue(f.IsStatic); + Assert.IsTrue(f.IsConst); + Assert.AreEqual(Accessibility.Public, f.Accessibility); + Assert.AreSame(e, f.ConstantValue.GetValueType(ctx)); + Assert.AreEqual(typeof(short), f.ConstantValue.GetValue(ctx).GetType()); + } + + Assert.AreEqual("First", e.Fields[0].Name); + Assert.AreEqual(0, e.Fields[0].ConstantValue.GetValue(ctx)); + + Assert.AreEqual("Second", e.Fields[1].Name); + Assert.AreSame(e, e.Fields[1].ConstantValue.GetValueType(ctx)); + Assert.AreEqual(1, e.Fields[1].ConstantValue.GetValue(ctx)); + + Assert.AreEqual("Flag1", e.Fields[2].Name); + Assert.AreEqual(0x10, e.Fields[2].ConstantValue.GetValue(ctx)); + + Assert.AreEqual("Flag2", e.Fields[3].Name); + Assert.AreEqual(0x20, e.Fields[3].ConstantValue.GetValue(ctx)); + + Assert.AreEqual("CombinedFlags", e.Fields[4].Name); + Assert.AreEqual(0x30, e.Fields[4].ConstantValue.GetValue(ctx)); + } + + [Test] + public void ParameterizedTypeGetNestedTypesFromBaseClassTest() + { + var d = typeof(Derived).ToTypeReference().Resolve(ctx); + Assert.AreEqual(new[] { typeof(Base<>.Nested).FullName + "[[System.Int32]]" }, + d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); + } + + [Test] + public void DefaultConstructorAddedToStruct() + { + var ctors = typeof(MyStructWithCtor).ToTypeReference().Resolve(ctx).GetConstructors(ctx); + Assert.AreEqual(2, ctors.Count()); + Assert.IsFalse(ctors.Any(c => c.IsStatic)); + } + + [Test] + public void SerializableAttribute() + { + IAttribute attr = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Attributes.Single(); + Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.Resolve(ctx).FullName); + } + + [Test] + public void NonSerializedAttribute() + { + IField field = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField"); + Assert.AreEqual("System.NonSerializedAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); + } + + [Test] + public void ExplicitStructLayoutAttribute() + { + IAttribute attr = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single(); + Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName); + IConstantValue arg1 = attr.GetPositionalArguments(ctx).Single(); + Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.GetValueType(ctx).FullName); + Assert.AreEqual((int)LayoutKind.Explicit, arg1.GetValue(ctx)); + + var namedArgs = attr.GetNamedArguments(ctx); + var arg2 = namedArgs[0]; + Assert.AreEqual("CharSet", arg2.Key); + Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.GetValueType(ctx).FullName); + Assert.AreEqual((int)CharSet.Unicode, arg2.Value.GetValue(ctx)); + + var arg3 = namedArgs[1]; + Assert.AreEqual("Pack", arg3.Key); + Assert.AreEqual("System.Int32", arg3.Value.GetValueType(ctx).FullName); + Assert.AreEqual(8, arg3.Value.GetValue(ctx)); + } + + [Test] + public void FieldOffsetAttribute() + { + IField field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); + Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); + IConstantValue arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); + Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName); + Assert.AreEqual(0, arg.GetValue(ctx)); + + field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); + Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); + arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); + Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName); + Assert.AreEqual(100, arg.GetValue(ctx)); + } + + [Test] + public void DllImportAttribute() + { + IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); + IAttribute dllImport = method.Attributes.Single(); + Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName); + Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].GetValue(ctx)); + Assert.AreEqual((int)CharSet.Unicode, dllImport.GetNamedArguments(ctx).Single().Value.GetValue(ctx)); + } + + [Test] + public void InOutParametersOnRefMethod() + { + IParameter p = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single(); + Assert.IsTrue(p.IsRef); + Assert.IsFalse(p.IsOut); + Assert.AreEqual(2, p.Attributes.Count); + Assert.AreEqual("System.Runtime.InteropServices.InAttribute", p.Attributes[0].AttributeType.Resolve(ctx).FullName); + Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", p.Attributes[1].AttributeType.Resolve(ctx).FullName); + } + + [Test] + public void MarshalAsAttributeOnMethod() + { + IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); + IAttribute marshalAs = method.ReturnTypeAttributes.Single(); + Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().GetValue(ctx)); + } + + [Test] + public void MethodWithOutParameter() + { + IParameter p = ctx.GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOutParameter").Parameters.Single(); + Assert.IsFalse(p.IsRef); + Assert.IsTrue(p.IsOut); + Assert.AreEqual(0, p.Attributes.Count); + Assert.IsTrue(p.Type is ByReferenceTypeReference); + } + + [Test] + public void MethodWithParamsArray() + { + IParameter p = ctx.GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithParamsArray").Parameters.Single(); + Assert.IsFalse(p.IsRef); + Assert.IsFalse(p.IsOut); + Assert.IsTrue(p.IsParams); + Assert.AreEqual(0, p.Attributes.Count); + Assert.IsTrue(p.Type is ArrayTypeReference); + } + + [Test, Ignore("C# Parser does not set the variance")] + public void GenericDelegate_Variance() + { + ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>)); + Assert.AreEqual(VarianceModifier.Contravariant, type.TypeParameters[0].Variance); + Assert.AreEqual(VarianceModifier.Covariant, type.TypeParameters[1].Variance); + + Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].Constraints[0]); + } + + [Test] + public void GenericDelegate_ReferenceTypeConstraints() + { + ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>)); + Assert.IsFalse(type.TypeParameters[0].HasReferenceTypeConstraint); + Assert.IsTrue(type.TypeParameters[1].HasReferenceTypeConstraint); + + Assert.IsTrue(type.TypeParameters[0].IsReferenceType(ctx) == true); + Assert.IsTrue(type.TypeParameters[1].IsReferenceType(ctx) == true); + } + + [Test] + public void GenericDelegate_GetInvokeMethod() + { + IType type = typeof(GenericDelegate).ToTypeReference().Resolve(ctx); + IMethod m = type.GetDelegateInvokeMethod(); + Assert.AreEqual("Invoke", m.Name); + Assert.AreEqual("System.Object", m.ReturnType.Resolve(ctx).FullName); + Assert.AreEqual("System.String", m.Parameters[0].Type.Resolve(ctx).FullName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Untested.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Untested.cs new file mode 100644 index 0000000000..3555418c47 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Untested.cs @@ -0,0 +1,41 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory +{ + // This file contains unit tests from SharpDevelop 4.0 which are not (yet) ported to NRefactory + + /* + + class ReflectionOrCecilLayerTests { + [Test] + public void ParameterComparisonTest() + { + DefaultParameter p1 = new DefaultParameter("a", mscorlib.GetClass("System.String", 0).DefaultReturnType, DomRegion.Empty); + DefaultParameter p2 = new DefaultParameter("b", new GetClassReturnType(mscorlib, "System.String", 0), DomRegion.Empty); + IList a1 = new List(); + IList a2 = new List(); + a1.Add(p1); + a2.Add(p2); + Assert.AreEqual(0, DiffUtility.Compare(a1, a2)); + } + + [Test] + public void GenericDocumentationTagNamesTest() + { + DefaultClass c = (DefaultClass)mscorlib.GetClass("System.Collections.Generic.List", 1); + Assert.AreEqual("T:System.Collections.Generic.List`1", + c.DocumentationTag); + Assert.AreEqual("M:System.Collections.Generic.List`1.Add(`0)", + GetMethod(c, "Add").DocumentationTag); + Assert.AreEqual("M:System.Collections.Generic.List`1.AddRange(System.Collections.Generic.IEnumerable{`0})", + GetMethod(c, "AddRange").DocumentationTag); + Assert.AreEqual("M:System.Collections.Generic.List`1.ConvertAll``1(System.Converter{`0,``0})", + GetMethod(c, "ConvertAll").DocumentationTag); + } + } + + */ +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs new file mode 100644 index 0000000000..fc73adcd71 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs @@ -0,0 +1,68 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.Utils +{ + [TestFixture] + public class CSharpPrimitiveCastTests + { + // I know, these tests aren't really clever, more of a way to fake code coverage... + // Well, at least they should ensure the 'tables' in CSharpPrimitiveCast don't contain any typos. + + [Test] + public void FloatToInteger() + { + for (int checkedMode = 0; checkedMode < 2; checkedMode++) { + for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { + object val = CSharpPrimitiveCast.Cast(to, 3.9f, checkedMode == 1); + Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); + Assert.AreEqual(3, Convert.ToInt64(val)); + } + } + } + + [Test] + public void DoubleToInteger() + { + for (int checkedMode = 0; checkedMode < 2; checkedMode++) { + for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { + object val = CSharpPrimitiveCast.Cast(to, 3.9, checkedMode == 1); + Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); + Assert.AreEqual(3, Convert.ToInt64(val)); + } + } + } + + [Test] + public void DecimalToInteger() + { + for (int checkedMode = 0; checkedMode < 2; checkedMode++) { + for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { + object val = CSharpPrimitiveCast.Cast(to, 3.9m, checkedMode == 1); + Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); + Assert.AreEqual(3, Convert.ToInt64(val)); + } + } + } + + [Test] + public void IntegerToInteger() + { + for (int checkedMode = 0; checkedMode < 2; checkedMode++) { + for (TypeCode to = TypeCode.Char; to <= TypeCode.UInt64; to++) { + for (TypeCode to2 = TypeCode.Char; to2 <= TypeCode.Decimal; to2++) { + object val = CSharpPrimitiveCast.Cast(to, 3, checkedMode == 1); + Assert.AreEqual(to, Type.GetTypeCode(val.GetType())); + Assert.AreEqual(3, Convert.ToInt64(val)); + object val2 = CSharpPrimitiveCast.Cast(to2, val, checkedMode == 1); + Assert.AreEqual(to2, Type.GetTypeCode(val2.GetType())); + Assert.AreEqual(3, Convert.ToInt64(val2)); + } + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs new file mode 100644 index 0000000000..dae0f43c81 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.Utils +{ + [TestFixture] + public class TreeTraversalTests + { + sealed class Node + { + public int Data; + public List Children = new List(); + } + + Node tree = new Node { + Data = 1, + Children = { + new Node { Data = 2 }, + new Node { Data = 3, + Children = { + new Node { Data = 4 }, + new Node { Data = 5 } + } }, + new Node { Data = 6, Children = null } + } + }; + + [Test] + public void PreOrder() + { + Assert.AreEqual(new int[] { 1, 2, 3, 4, 5, 6 }, + TreeTraversal.PreOrder(tree, n => n.Children).Select(n => n.Data).ToArray()); + } + + [Test] + public void PostOrder() + { + Assert.AreEqual(new int[] { 2, 4, 5, 3, 6, 1 }, + TreeTraversal.PostOrder(tree, n => n.Children).Select(n => n.Data).ToArray()); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/.gitignore b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/.gitignore new file mode 100644 index 0000000000..9ce745d95d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/AssemblyInfo.cs new file mode 100644 index 0000000000..065e001fe5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/AssemblyInfo.cs @@ -0,0 +1,35 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly: AssemblyTitle("NRefactory Test")] +[assembly: AssemblyDescription("Unit tests for the parser and refactoring library for C# and VB.NET")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ic#code")] +[assembly: AssemblyProduct("SharpDevelop")] +[assembly: AssemblyCopyright("2004-2006 AlphaSierraPapa")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly: AssemblyVersion("2.0.0.1")] + +// The following attributes specify the key for the sign of your assembly. See the +// .NET Framework documentation for more information about signing. +// This is not required, if you don't want signing let these attributes like they're. +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/General/UnitTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/General/UnitTest.cs new file mode 100644 index 0000000000..def7d7d0f5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/General/UnitTest.cs @@ -0,0 +1,102 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Reflection; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; + +namespace ICSharpCode.NRefactory.VB.Tests +{ + [TestFixture] + public class StructuralTest + { +// [Test] +// public void TestToStringMethods() +// { +// Type[] allTypes = typeof(INode).Assembly.GetTypes(); +// +// foreach (Type type in allTypes) { +// if (type.IsClass && !type.IsAbstract && !type.IsNested && type.GetInterface(typeof(INode).FullName) != null) { +// MethodInfo methodInfo = type.GetMethod("ToString", BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public); +// Assert.IsNotNull(methodInfo, "ToString() not found in " + type.FullName); +// } +// } +// } +// +// [Test] +// public void TestUnitTests() +// { +// Type[] allTypes = typeof(StructuralTest).Assembly.GetTypes(); +// +// foreach (Type type in allTypes) { +// if (type.GetCustomAttributes(typeof(TestFixtureAttribute), true).Length > 0) { +// foreach (MethodInfo m in type.GetMethods()) { +// if (m.IsPublic && m.ReturnType == typeof(void) && m.GetParameters().Length == 0) { +// if (m.GetCustomAttributes(typeof(TestAttribute), true).Length == 0) { +// Assert.Fail(type.Name + "." + m.Name + " should have the [Test] attribute!"); +// } +// } +// } +// } +// } +// } +// +// [Test] +// public void TestAcceptVisitorMethods() +// { +// Type[] allTypes = typeof(AbstractNode).Assembly.GetTypes(); +// +// foreach (Type type in allTypes) { +// if (type.IsClass && !type.IsAbstract && type.GetInterface(typeof(INode).FullName) != null) { +// MethodInfo methodInfo = type.GetMethod("AcceptVisitor", BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public); +// Assertion.AssertNotNull("AcceptVisitor() not found in " + type.FullName, methodInfo); +// } +// } +// } +// +// [Test] +// public void TestIAstVisitor() +// { +// Type[] allTypes = typeof(AbstractNode).Assembly.GetTypes(); +// Type visitor = typeof(IAstVisitor); +// +// foreach (Type type in allTypes) { +// if (type.IsClass && !type.IsAbstract && !type.IsNested && type.GetInterface(typeof(INode).FullName) != null && !type.Name.StartsWith("Null")) { +// MethodInfo methodInfo = visitor.GetMethod("Visit" + type.Name, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.ExactBinding, null, new Type[] {type, typeof(object)}, null); +// Assert.IsNotNull(methodInfo, "Visit with parameter " + type.FullName + " not found"); +// Assert.AreEqual(2, methodInfo.GetParameters().Length); +// ParameterInfo first = methodInfo.GetParameters()[0]; +// Assert.AreEqual(Char.ToLower(first.ParameterType.Name[0]) + first.ParameterType.Name.Substring(1), first.Name); +// +// ParameterInfo second = methodInfo.GetParameters()[1]; +// Assert.AreEqual(typeof(System.Object), second.ParameterType); +// Assert.AreEqual("data", second.Name); +// } +// } +// } +// +// [Test] +// public void TestAbstractAstVisitorVisitor() +// { +// Type[] allTypes = typeof(AbstractNode).Assembly.GetTypes(); +// Type visitor = typeof(AbstractAstVisitor); +// +// foreach (Type type in allTypes) { +// if (type.IsClass && !type.IsAbstract && !type.IsNested && type.GetInterface(typeof(INode).FullName) != null && !type.Name.StartsWith("Null")) { +// MethodInfo methodInfo = visitor.GetMethod("Visit" + type.Name, BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.ExactBinding, null, new Type[] {type, typeof(object)}, null); +// Assert.IsNotNull(methodInfo, "Visit with parameter " + type.FullName + " not found"); +// +// Assert.AreEqual(2, methodInfo.GetParameters().Length); +// ParameterInfo first = methodInfo.GetParameters()[0]; +// Assert.AreEqual(Char.ToLower(first.ParameterType.Name[0]) + first.ParameterType.Name.Substring(1), first.Name); +// +// ParameterInfo second = methodInfo.GetParameters()[1]; +// Assert.AreEqual(typeof(System.Object), second.ParameterType); +// Assert.AreEqual("data", second.Name); +// } +// } +// } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj new file mode 100644 index 0000000000..f0da0835c5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj @@ -0,0 +1,88 @@ + + + + Debug + AnyCPU + 8.0.50215 + 2.0 + {870115DD-960A-4406-A6B9-600BCDC36A03} + ICSharpCode.NRefactory.VB.Tests + ICSharpCode.NRefactory.VB.Tests + Library + False + False + OnBuildSuccess + Library + ..\..\..\..\bin\UnitTests\ + False + x86 + 4 + v4.0 + false + Client + + + True + DEBUG + False + + + True + False + + + Full + true + Project + + + False + + + False + Auto + 4194304 + 4096 + + + + ..\lib\nunit.framework.dll + True + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + {7B82B671-419F-45F4-B778-D9286F996EFA} + ICSharpCode.NRefactory.VB + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/CustomLexerTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/CustomLexerTests.cs new file mode 100644 index 0000000000..c37cf1b02d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/CustomLexerTests.cs @@ -0,0 +1,118 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class CustomLexerTests + { + VBLexer GenerateLexer(StringReader sr) + { + return new VBLexer(sr); + } + + [Test] + public void TestSingleEOLForMulitpleLines() + { + VBLexer lexer = GenerateLexer(new StringReader("Stop\n\n\nEnd")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Stop)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.End)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void TestSingleEOLForMulitpleLinesWithContinuation() + { + VBLexer lexer = GenerateLexer(new StringReader("Stop\n _\n\nEnd")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Stop)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.End)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void EscapedIdentifier() + { + VBLexer lexer = GenerateLexer(new StringReader("[Stop]")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void IdentifierWithTypeCharacter() + { + VBLexer lexer = GenerateLexer(new StringReader("Stop$")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void ExclamationMarkIsTypeCharacter() + { + VBLexer lexer = GenerateLexer(new StringReader("a!=b")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Assign)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void ExclamationMarkIsTypeCharacter2() + { + VBLexer lexer = GenerateLexer(new StringReader("a! b")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void ExclamationMarkIsIdentifier() + { + VBLexer lexer = GenerateLexer(new StringReader("a!b")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.ExclamationMark)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void ExclamationMarkIsIdentifier2() + { + VBLexer lexer = GenerateLexer(new StringReader("a![b]")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.ExclamationMark)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void RemCommentTest() + { + VBLexer lexer = GenerateLexer(new StringReader("a rem b")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.Identifier)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOL)); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + + [Test] + public void RemCommentTest2() + { + VBLexer lexer = GenerateLexer(new StringReader("REM c")); + Assert.That(lexer.NextToken().Kind, Is.EqualTo(Tokens.EOF)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/ImplicitLineContinuationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/ImplicitLineContinuationTests.cs new file mode 100644 index 0000000000..8e5bcdb71d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/ImplicitLineContinuationTests.cs @@ -0,0 +1,230 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class ImplicitLineContinuationTests + { + [Test] + public void Example1() + { + string code = @"Module Test + Sub Print( + Param1 As Integer, + Param2 As Integer) + + If (Param1 < Param2) Or + (Param1 > Param2) Then + Console.WriteLine(""Not equal"") + End If + End Sub +End Module"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL, + Tokens.Sub, Tokens.Identifier, Tokens.OpenParenthesis, + Tokens.Identifier, Tokens.As, Tokens.Integer, Tokens.Comma, + Tokens.Identifier, Tokens.As, Tokens.Integer, Tokens.CloseParenthesis, Tokens.EOL, + Tokens.If, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.LessThan, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.Or, + Tokens.OpenParenthesis, Tokens.Identifier, Tokens.GreaterThan, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.Then, Tokens.EOL, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString, Tokens.CloseParenthesis, Tokens.EOL, + Tokens.End, Tokens.If, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Module); + } + + [Test] + public void QualifierInWith() + { + string code = @"Module Test + Sub Print + With xml + Dim a = b. + d + Dim c = . + Count + End With + End Sub +End Module"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL, + Tokens.Sub, Tokens.Identifier, Tokens.EOL, + Tokens.With, Tokens.Identifier, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Dot, Tokens.EOL, + Tokens.Identifier, Tokens.EOL, + Tokens.End, Tokens.With, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Module); + } + + [Test] + public void Example2() + { + string code = @"Module Test + Sub Print + Dim a = _ + + y + End Sub +End Module"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL, + Tokens.Sub, Tokens.Identifier, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.EOL, Tokens.Identifier, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Module); + } + + [Test] + public void Query() + { + string code = @"Module Test + Sub A + Dim q = From x In a + Select x + End Sub +End Module"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL, + Tokens.Sub, Tokens.Identifier, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, + Tokens.Select, Tokens.Identifier, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Module); + } + + [Test] + public void Query1() + { + string code = @"Module Test + Sub A + Dim actions = From a in b Select Sub() + Dim i = 1 + Select Case i + End Select + End Sub + End Sub +End Module"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens(lexer, Tokens.Module, Tokens.Identifier, Tokens.EOL, + Tokens.Sub, Tokens.Identifier, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Select, Tokens.Sub, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.LiteralInteger, Tokens.EOL, + Tokens.Select, Tokens.Case, Tokens.Identifier, Tokens.EOL, + Tokens.End, Tokens.Select, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Module); + } + + /// tests http://community.sharpdevelop.net/forums/p/12068/32893.aspx#32893 + [Test] + public void Bug_Thread12068() + { + string code = @"Class MainClass + Public Shared Sub Main() + Dim categoryNames = From p In AList _ + Select p.AFunction(1,2,3) _ + Distinct + End Sub +End Class"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens( + lexer, Tokens.Class, Tokens.Identifier, Tokens.EOL, + Tokens.Public, Tokens.Shared, Tokens.Sub, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, + Tokens.Select, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralInteger, + Tokens.Comma, Tokens.LiteralInteger, Tokens.Comma, Tokens.LiteralInteger, Tokens.CloseParenthesis, + Tokens.Distinct, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Class + ); + } + + [Test] + public void LineContinuationAfterAttributes() + { + string code = @" +Public Class TestContinuation + + Public Sub TestMethod + Assert.Fail + End Sub + + _ + Public Sub TestMethod2 + Assert.Fail + End Sub +End Class"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens( + lexer, Tokens.LessThan, Tokens.Identifier, Tokens.GreaterThan, + Tokens.Public, Tokens.Class, Tokens.Identifier, Tokens.EOL, + Tokens.LessThan, Tokens.Identifier, Tokens.GreaterThan, + Tokens.Public, Tokens.Sub, Tokens.Identifier, Tokens.EOL, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.LessThan, Tokens.Identifier, Tokens.GreaterThan, + Tokens.Public, Tokens.Sub, Tokens.Identifier, Tokens.EOL, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL, + Tokens.End, Tokens.Sub, Tokens.EOL, + Tokens.End, Tokens.Class + ); + } + + [Test] + public void NoILCAfterGlobalAttributes() + { + string code = "" + Environment.NewLine + + ""; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens( + lexer, Tokens.LessThan, Tokens.Assembly, Tokens.Colon, + Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString, + Tokens.CloseParenthesis, Tokens.GreaterThan, Tokens.EOL, + Tokens.LessThan, Tokens.Assembly, Tokens.Colon, + Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString, + Tokens.CloseParenthesis, Tokens.GreaterThan + ); + } + + #region Helpers + VBLexer GenerateLexer(StringReader sr) + { + return new VBLexer(sr); + } + + void CheckTokens(VBLexer lexer, params int[] tokens) + { + for (int i = 0; i < tokens.Length; i++) { + int token = tokens[i]; + Token t = lexer.NextToken(); + int next = t.Kind; + Assert.AreEqual(token, next, "{2} of {3}: {0} != {1}; at {4}", Tokens.GetTokenString(token), Tokens.GetTokenString(next), i + 1, tokens.Length, t.Location); + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LATextReaderTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LATextReaderTests.cs new file mode 100644 index 0000000000..2671dad2ea --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LATextReaderTests.cs @@ -0,0 +1,35 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class LATextReaderTests + { + [Test] + public void TestPeek() + { + LATextReader reader = new LATextReader(new StringReader("abcd")); + + CheckPeek(reader, 0, 'a'); + CheckPeek(reader, 2, 'c'); + CheckPeek(reader, 3, 'd'); + CheckPeek(reader, 1, 'b'); + CheckPeek(reader, 0, 'a'); + Assert.AreEqual((int)'a', reader.Read()); + CheckPeek(reader, 1, 'c'); + CheckPeek(reader, 2, 'd'); + CheckPeek(reader, 0, 'b'); + } + + void CheckPeek(LATextReader reader, int num1, char char2) + { + Assert.AreEqual((int)char2, reader.Peek(num1)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs new file mode 100644 index 0000000000..f04ab84692 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerContextTests.cs @@ -0,0 +1,574 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class LexerContextTests + { + [Test] + public void SimpleGlobal() + { + RunTest( + @"Option Explicit", + @"enter Global +exit Global +" + ); + } + + [Test] + public void VariableWithXmlLiteral() + { + RunTest( + @"Class Test + Public Sub New() + Dim x = + End Sub +End Class +", + @"enter Global + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Body + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + enter Xml + enter Xml + exit Xml + exit Xml + exit Expression + exit Expression + exit Expression + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void MemberWithXmlLiteral() + { + RunTest( + @"Class Test + Private xml As XElement = + + Public Sub New() + Dim x = + End Sub +End Class +", + @"enter Global + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Type + exit Type + enter Expression + enter Expression + enter Expression + enter Xml + enter Xml + exit Xml + exit Xml + exit Expression + exit Expression + exit Expression + exit Member + enter Member + enter Identifier + exit Identifier + enter Body + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + enter Xml + enter Xml + exit Xml + exit Xml + exit Expression + exit Expression + exit Expression + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void GlobalAttributeTest() + { + RunTest( + @" +Class Test + Public Sub New() + Dim x = 5 + End Sub +End Class +", + @"enter Global + enter Attribute + exit Attribute + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Body + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void ClassAttributeTest() + { + RunTest( + @" +Class Test + Public Sub New() + Dim x = 5 + End Sub +End Class +", + @"enter Global + enter Attribute + exit Attribute + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Body + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void MethodAttributeTest() + { + RunTest( + @"Class Test + + Public Sub New() + Dim x = 5 + End Sub +End Class +", + @"enter Global + enter TypeDeclaration + enter Identifier + exit Identifier + enter Attribute + exit Attribute + enter Member + enter Identifier + exit Identifier + enter Body + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void WithBlockTest() + { + RunTest( + @"Class Test + Public Sub New() + With x + + End With + End Sub +End Class +", + @"enter Global + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Body + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Body + exit Body + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void StatementsTest() + { + RunTest( + @"Class Test + Public Sub New() + For i As Integer = 0 To 10 + + Next + + For Each x As Integer In list + + Next + + Try + + Catch e As Exception + + End Try + End Sub +End Class +", + @"enter Global + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Body + enter Identifier + enter Expression + exit Expression + exit Identifier + enter Type + exit Type + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Body + exit Body + enter Identifier + enter Expression + exit Expression + exit Identifier + enter Type + exit Type + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Body + exit Body + enter Body + exit Body + enter Identifier + exit Identifier + enter Type + exit Type + enter Body + exit Body + exit Body + exit Member + exit TypeDeclaration +exit Global +" + ); + } + + [Test] + public void ClassTest() + { + RunTest( + @"Class MainClass ' a comment + Dim under_score_field As Integer + Sub SomeMethod() + simple += 1 + For Each loopVarName In collection + Next + End Sub +End Class", + @"enter Global + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Type + exit Type + exit Member + enter Member + enter Identifier + exit Identifier + enter Body + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Identifier + enter Expression + exit Expression + exit Identifier + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Body + exit Body + exit Body + exit Member + exit TypeDeclaration +exit Global +"); + } + + [Test] + public void CollectionInitializer() + { + RunTest(@"' +' Created by SharpDevelop. +' User: Siegfried +' Date: 22.06.2010 +' Time: 21:29 +' +' To change this template use Tools | Options | Coding | Edit Standard Headers. +' + +Option Infer On + +Imports System.Linq +Imports System.Xml.Linq + +Module Program + Sub Main() + Console.WriteLine(""Hello World!"") + + Dim name = ""Test"" + Dim content = { 4, 5, New XAttribute(""a"", 3) } + + Dim xml = <<%= name %> <%= content %> /> + + Console.ReadKey() + End Sub +End Module", + @"enter Global + enter Importable + exit Importable + enter Importable + exit Importable + enter TypeDeclaration + enter Identifier + exit Identifier + enter Member + enter Identifier + exit Identifier + enter Body + enter Expression + enter Expression + enter Expression + exit Expression + enter Expression + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Expression + exit Expression + exit Expression + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Expression + enter Expression + enter ObjectCreation + enter Expression + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Expression + exit ObjectCreation + exit Expression + exit Expression + exit Expression + exit Expression + enter Identifier + exit Identifier + enter Expression + enter Expression + enter Expression + enter Xml + enter Xml + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + enter Expression + enter Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Xml + exit Xml + exit Expression + exit Expression + exit Expression + enter Expression + enter Expression + enter Expression + exit Expression + enter Expression + exit Expression + exit Expression + exit Expression + exit Body + exit Member + exit TypeDeclaration +exit Global +"); + } + + [Test] + public void Imports() + { + RunTest(@"Imports System +Imports System.Linq +Imports System.Collections.Generic", + @"enter Global + enter Importable + exit Importable + enter Importable + exit Importable + enter Importable + exit Importable +exit Global +"); + } + + void RunTest(string code, string expectedOutput) + { + ExpressionFinder p = new ExpressionFinder(); + VBLexer lexer = new VBLexer(new StringReader(code)); + Token t; + + do { + t = lexer.NextToken(); + p.InformToken(t); + } while (t.Kind != Tokens.EOF); + + Console.WriteLine(p.Output); + + Assert.IsEmpty(p.Errors); + + Assert.AreEqual(expectedOutput, p.Output); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs new file mode 100644 index 0000000000..553ba27a69 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs @@ -0,0 +1,87 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class LexerPositionTests + { + VBLexer GenerateLexer(string s) + { + return new VBLexer(new StringReader(s)); + } + + [Test] + public void TestNewLine() + { + VBLexer l = GenerateLexer("public\nstatic"); + Token t = l.NextToken(); + Assert.AreEqual(Tokens.Public, t.Kind); + Assert.AreEqual(new AstLocation(1, 1), t.Location); + Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + t = l.NextToken(); + Assert.AreEqual(Tokens.EOL, t.Kind); + Assert.AreEqual(new AstLocation(7, 1), t.Location); + Assert.AreEqual(new AstLocation(1, 2), t.EndLocation); + t = l.NextToken(); + Assert.AreEqual(Tokens.Static, t.Kind); + Assert.AreEqual(new AstLocation(1, 2), t.Location); + Assert.AreEqual(new AstLocation(7, 2), t.EndLocation); + } + + [Test] + public void TestCarriageReturnNewLine() + { + VBLexer l = GenerateLexer("public\r\nstatic"); + Token t = l.NextToken(); + Assert.AreEqual(Tokens.Public, t.Kind); + Assert.AreEqual(new AstLocation(1, 1), t.Location); + Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + t = l.NextToken(); + Assert.AreEqual(Tokens.EOL, t.Kind); + Assert.AreEqual(new AstLocation(7, 1), t.Location); + Assert.AreEqual(new AstLocation(1, 2), t.EndLocation); + t = l.NextToken(); + Assert.AreEqual(Tokens.Static, t.Kind); + Assert.AreEqual(new AstLocation(1, 2), t.Location); + Assert.AreEqual(new AstLocation(7, 2), t.EndLocation); + } + + [Test] + public void TestPositionOfEOF1() + { + VBLexer l = GenerateLexer("public"); + l.NextToken(); // public + Token t = l.NextToken(); + Assert.AreEqual(Tokens.EOL, t.Kind); + Assert.AreEqual(new AstLocation(7, 1), t.Location); + Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + + t = l.NextToken(); + Assert.AreEqual(Tokens.EOF, t.Kind); + Assert.AreEqual(new AstLocation(7, 1), t.Location); + Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + } + + [Test] + public void TestPositionOfEOF2() + { + VBLexer l = GenerateLexer("public _\n "); + l.NextToken(); // public + Token t = l.NextToken(); + Assert.AreEqual(Tokens.EOL, t.Kind); + Assert.AreEqual(new AstLocation(2, 2), t.Location); + Assert.AreEqual(new AstLocation(2, 2), t.EndLocation); + + t = l.NextToken(); + Assert.AreEqual(Tokens.EOF, t.Kind); + Assert.AreEqual(new AstLocation(2, 2), t.Location); + Assert.AreEqual(new AstLocation(2, 2), t.EndLocation); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerTests.cs new file mode 100644 index 0000000000..9b2ec83867 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerTests.cs @@ -0,0 +1,1538 @@ +// this file was autogenerated by a tool. +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.PrettyPrinter; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public sealed class LexerTests + { + VBLexer GenerateLexer(StringReader sr) + { + return new VBLexer(sr); + } + + [Test] + public void TestAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("=")); + Assert.AreEqual(Tokens.Assign, lexer.NextToken().Kind); + } + + [Test] + public void TestColon() + { + VBLexer lexer = GenerateLexer(new StringReader(":")); + Assert.AreEqual(Tokens.Colon, lexer.NextToken().Kind); + } + + [Test] + public void TestComma() + { + VBLexer lexer = GenerateLexer(new StringReader(",")); + Assert.AreEqual(Tokens.Comma, lexer.NextToken().Kind); + } + + [Test] + public void TestConcatString() + { + VBLexer lexer = GenerateLexer(new StringReader("&")); + Assert.AreEqual(Tokens.ConcatString, lexer.NextToken().Kind); + } + + [Test] + public void TestDiv() + { + VBLexer lexer = GenerateLexer(new StringReader("/")); + Assert.AreEqual(Tokens.Div, lexer.NextToken().Kind); + } + + [Test] + public void TestDivInteger() + { + VBLexer lexer = GenerateLexer(new StringReader("\\")); + Assert.AreEqual(Tokens.DivInteger, lexer.NextToken().Kind); + } + + [Test] + public void TestDot() + { + VBLexer lexer = GenerateLexer(new StringReader(".")); + Assert.AreEqual(Tokens.Dot, lexer.NextToken().Kind); + } + + [Test] + public void TestTripleDot() + { + VBLexer lexer = GenerateLexer(new StringReader("...")); + Assert.AreEqual(Tokens.TripleDot, lexer.NextToken().Kind); + } + + [Test] + public void TestDotAt() + { + VBLexer lexer = GenerateLexer(new StringReader(".@")); + Assert.AreEqual(Tokens.DotAt, lexer.NextToken().Kind); + } + + [Test] + public void TestExclamationMark() + { + VBLexer lexer = GenerateLexer(new StringReader("!")); + Assert.AreEqual(Tokens.ExclamationMark, lexer.NextToken().Kind); + } + + [Test] + public void TestMinus() + { + VBLexer lexer = GenerateLexer(new StringReader("-")); + Assert.AreEqual(Tokens.Minus, lexer.NextToken().Kind); + } + + [Test] + public void TestPlus() + { + VBLexer lexer = GenerateLexer(new StringReader("+")); + Assert.AreEqual(Tokens.Plus, lexer.NextToken().Kind); + } + + [Test] + public void TestPower() + { + VBLexer lexer = GenerateLexer(new StringReader("^")); + Assert.AreEqual(Tokens.Power, lexer.NextToken().Kind); + } + + [Test] + public void TestQuestionMark() + { + VBLexer lexer = GenerateLexer(new StringReader("?")); + Assert.AreEqual(Tokens.QuestionMark, lexer.NextToken().Kind); + } + + [Test] + public void TestTimes() + { + VBLexer lexer = GenerateLexer(new StringReader("*")); + Assert.AreEqual(Tokens.Times, lexer.NextToken().Kind); + } + + [Test] + public void TestOpenCurlyBrace() + { + VBLexer lexer = GenerateLexer(new StringReader("{")); + Assert.AreEqual(Tokens.OpenCurlyBrace, lexer.NextToken().Kind); + } + + [Test] + public void TestCloseCurlyBrace() + { + VBLexer lexer = GenerateLexer(new StringReader("}")); + Assert.AreEqual(Tokens.CloseCurlyBrace, lexer.NextToken().Kind); + } + + [Test] + public void TestOpenParenthesis() + { + VBLexer lexer = GenerateLexer(new StringReader("(")); + Assert.AreEqual(Tokens.OpenParenthesis, lexer.NextToken().Kind); + } + + [Test] + public void TestCloseParenthesis() + { + VBLexer lexer = GenerateLexer(new StringReader(")")); + Assert.AreEqual(Tokens.CloseParenthesis, lexer.NextToken().Kind); + } + + [Test] + public void TestGreaterThan() + { + VBLexer lexer = GenerateLexer(new StringReader(">")); + Assert.AreEqual(Tokens.GreaterThan, lexer.NextToken().Kind); + } + + [Test] + public void TestLessThan() + { + VBLexer lexer = GenerateLexer(new StringReader("<")); + Assert.AreEqual(Tokens.LessThan, lexer.NextToken().Kind); + } + + [Test] + public void TestNotEqual() + { + VBLexer lexer = GenerateLexer(new StringReader("<>")); + Assert.AreEqual(Tokens.NotEqual, lexer.NextToken().Kind); + } + + [Test] + public void TestGreaterEqual() + { + VBLexer lexer = GenerateLexer(new StringReader(">=")); + Assert.AreEqual(Tokens.GreaterEqual, lexer.NextToken().Kind); + } + + [Test] + public void TestLessEqual() + { + VBLexer lexer = GenerateLexer(new StringReader("<=")); + Assert.AreEqual(Tokens.LessEqual, lexer.NextToken().Kind); + } + + [Test] + public void TestShiftLeft() + { + VBLexer lexer = GenerateLexer(new StringReader("<<")); + Assert.AreEqual(Tokens.ShiftLeft, lexer.NextToken().Kind); + } + + [Test] + public void TestShiftRight() + { + VBLexer lexer = GenerateLexer(new StringReader(">>")); + Assert.AreEqual(Tokens.ShiftRight, lexer.NextToken().Kind); + } + + [Test] + public void TestPlusAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("+=")); + Assert.AreEqual(Tokens.PlusAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestPowerAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("^=")); + Assert.AreEqual(Tokens.PowerAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestMinusAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("-=")); + Assert.AreEqual(Tokens.MinusAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestTimesAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("*=")); + Assert.AreEqual(Tokens.TimesAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestDivAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("/=")); + Assert.AreEqual(Tokens.DivAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestDivIntegerAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("\\=")); + Assert.AreEqual(Tokens.DivIntegerAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestShiftLeftAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("<<=")); + Assert.AreEqual(Tokens.ShiftLeftAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestShiftRightAssign() + { + VBLexer lexer = GenerateLexer(new StringReader(">>=")); + Assert.AreEqual(Tokens.ShiftRightAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestConcatStringAssign() + { + VBLexer lexer = GenerateLexer(new StringReader("&=")); + Assert.AreEqual(Tokens.ConcatStringAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestColonAssign() + { + VBLexer lexer = GenerateLexer(new StringReader(":=")); + Assert.AreEqual(Tokens.ColonAssign, lexer.NextToken().Kind); + } + + [Test] + public void TestAddHandler() + { + VBLexer lexer = GenerateLexer(new StringReader("AddHandler")); + Assert.AreEqual(Tokens.AddHandler, lexer.NextToken().Kind); + } + + [Test] + public void TestAddressOf() + { + VBLexer lexer = GenerateLexer(new StringReader("AddressOf")); + Assert.AreEqual(Tokens.AddressOf, lexer.NextToken().Kind); + } + + [Test] + public void TestAggregate() + { + VBLexer lexer = GenerateLexer(new StringReader("Aggregate")); + Assert.AreEqual(Tokens.Aggregate, lexer.NextToken().Kind); + } + + [Test] + public void TestAlias() + { + VBLexer lexer = GenerateLexer(new StringReader("Alias")); + Assert.AreEqual(Tokens.Alias, lexer.NextToken().Kind); + } + + [Test] + public void TestAnd() + { + VBLexer lexer = GenerateLexer(new StringReader("And")); + Assert.AreEqual(Tokens.And, lexer.NextToken().Kind); + } + + [Test] + public void TestAndAlso() + { + VBLexer lexer = GenerateLexer(new StringReader("AndAlso")); + Assert.AreEqual(Tokens.AndAlso, lexer.NextToken().Kind); + } + + [Test] + public void TestAnsi() + { + VBLexer lexer = GenerateLexer(new StringReader("Ansi")); + Assert.AreEqual(Tokens.Ansi, lexer.NextToken().Kind); + } + + [Test] + public void TestAs() + { + VBLexer lexer = GenerateLexer(new StringReader("As")); + Assert.AreEqual(Tokens.As, lexer.NextToken().Kind); + } + + [Test] + public void TestAscending() + { + VBLexer lexer = GenerateLexer(new StringReader("Ascending")); + Assert.AreEqual(Tokens.Ascending, lexer.NextToken().Kind); + } + + [Test] + public void TestAssembly() + { + VBLexer lexer = GenerateLexer(new StringReader("Assembly")); + Assert.AreEqual(Tokens.Assembly, lexer.NextToken().Kind); + } + + [Test] + public void TestAuto() + { + VBLexer lexer = GenerateLexer(new StringReader("Auto")); + Assert.AreEqual(Tokens.Auto, lexer.NextToken().Kind); + } + + [Test] + public void TestBinary() + { + VBLexer lexer = GenerateLexer(new StringReader("Binary")); + Assert.AreEqual(Tokens.Binary, lexer.NextToken().Kind); + } + + [Test] + public void TestBoolean() + { + VBLexer lexer = GenerateLexer(new StringReader("Boolean")); + Assert.AreEqual(Tokens.Boolean, lexer.NextToken().Kind); + } + + [Test] + public void TestByRef() + { + VBLexer lexer = GenerateLexer(new StringReader("ByRef")); + Assert.AreEqual(Tokens.ByRef, lexer.NextToken().Kind); + } + + [Test] + public void TestBy() + { + VBLexer lexer = GenerateLexer(new StringReader("By")); + Assert.AreEqual(Tokens.By, lexer.NextToken().Kind); + } + + [Test] + public void TestByte() + { + VBLexer lexer = GenerateLexer(new StringReader("Byte")); + Assert.AreEqual(Tokens.Byte, lexer.NextToken().Kind); + } + + [Test] + public void TestByVal() + { + VBLexer lexer = GenerateLexer(new StringReader("ByVal")); + Assert.AreEqual(Tokens.ByVal, lexer.NextToken().Kind); + } + + [Test] + public void TestCall() + { + VBLexer lexer = GenerateLexer(new StringReader("Call")); + Assert.AreEqual(Tokens.Call, lexer.NextToken().Kind); + } + + [Test] + public void TestCase() + { + VBLexer lexer = GenerateLexer(new StringReader("Case")); + Assert.AreEqual(Tokens.Case, lexer.NextToken().Kind); + } + + [Test] + public void TestCatch() + { + VBLexer lexer = GenerateLexer(new StringReader("Catch")); + Assert.AreEqual(Tokens.Catch, lexer.NextToken().Kind); + } + + [Test] + public void TestCBool() + { + VBLexer lexer = GenerateLexer(new StringReader("CBool")); + Assert.AreEqual(Tokens.CBool, lexer.NextToken().Kind); + } + + [Test] + public void TestCByte() + { + VBLexer lexer = GenerateLexer(new StringReader("CByte")); + Assert.AreEqual(Tokens.CByte, lexer.NextToken().Kind); + } + + [Test] + public void TestCChar() + { + VBLexer lexer = GenerateLexer(new StringReader("CChar")); + Assert.AreEqual(Tokens.CChar, lexer.NextToken().Kind); + } + + [Test] + public void TestCDate() + { + VBLexer lexer = GenerateLexer(new StringReader("CDate")); + Assert.AreEqual(Tokens.CDate, lexer.NextToken().Kind); + } + + [Test] + public void TestCDbl() + { + VBLexer lexer = GenerateLexer(new StringReader("CDbl")); + Assert.AreEqual(Tokens.CDbl, lexer.NextToken().Kind); + } + + [Test] + public void TestCDec() + { + VBLexer lexer = GenerateLexer(new StringReader("CDec")); + Assert.AreEqual(Tokens.CDec, lexer.NextToken().Kind); + } + + [Test] + public void TestChar() + { + VBLexer lexer = GenerateLexer(new StringReader("Char")); + Assert.AreEqual(Tokens.Char, lexer.NextToken().Kind); + } + + [Test] + public void TestCInt() + { + VBLexer lexer = GenerateLexer(new StringReader("CInt")); + Assert.AreEqual(Tokens.CInt, lexer.NextToken().Kind); + } + + [Test] + public void TestClass() + { + VBLexer lexer = GenerateLexer(new StringReader("Class")); + Assert.AreEqual(Tokens.Class, lexer.NextToken().Kind); + } + + [Test] + public void TestCLng() + { + VBLexer lexer = GenerateLexer(new StringReader("CLng")); + Assert.AreEqual(Tokens.CLng, lexer.NextToken().Kind); + } + + [Test] + public void TestCObj() + { + VBLexer lexer = GenerateLexer(new StringReader("CObj")); + Assert.AreEqual(Tokens.CObj, lexer.NextToken().Kind); + } + + [Test] + public void TestCompare() + { + VBLexer lexer = GenerateLexer(new StringReader("Compare")); + Assert.AreEqual(Tokens.Compare, lexer.NextToken().Kind); + } + + [Test] + public void TestConst() + { + VBLexer lexer = GenerateLexer(new StringReader("Const")); + Assert.AreEqual(Tokens.Const, lexer.NextToken().Kind); + } + + [Test] + public void TestContinue() + { + VBLexer lexer = GenerateLexer(new StringReader("Continue")); + Assert.AreEqual(Tokens.Continue, lexer.NextToken().Kind); + } + + [Test] + public void TestCSByte() + { + VBLexer lexer = GenerateLexer(new StringReader("CSByte")); + Assert.AreEqual(Tokens.CSByte, lexer.NextToken().Kind); + } + + [Test] + public void TestCShort() + { + VBLexer lexer = GenerateLexer(new StringReader("CShort")); + Assert.AreEqual(Tokens.CShort, lexer.NextToken().Kind); + } + + [Test] + public void TestCSng() + { + VBLexer lexer = GenerateLexer(new StringReader("CSng")); + Assert.AreEqual(Tokens.CSng, lexer.NextToken().Kind); + } + + [Test] + public void TestCStr() + { + VBLexer lexer = GenerateLexer(new StringReader("CStr")); + Assert.AreEqual(Tokens.CStr, lexer.NextToken().Kind); + } + + [Test] + public void TestCType() + { + VBLexer lexer = GenerateLexer(new StringReader("CType")); + Assert.AreEqual(Tokens.CType, lexer.NextToken().Kind); + } + + [Test] + public void TestCUInt() + { + VBLexer lexer = GenerateLexer(new StringReader("CUInt")); + Assert.AreEqual(Tokens.CUInt, lexer.NextToken().Kind); + } + + [Test] + public void TestCULng() + { + VBLexer lexer = GenerateLexer(new StringReader("CULng")); + Assert.AreEqual(Tokens.CULng, lexer.NextToken().Kind); + } + + [Test] + public void TestCUShort() + { + VBLexer lexer = GenerateLexer(new StringReader("CUShort")); + Assert.AreEqual(Tokens.CUShort, lexer.NextToken().Kind); + } + + [Test] + public void TestCustom() + { + VBLexer lexer = GenerateLexer(new StringReader("Custom")); + Assert.AreEqual(Tokens.Custom, lexer.NextToken().Kind); + } + + [Test] + public void TestDate() + { + VBLexer lexer = GenerateLexer(new StringReader("Date")); + Assert.AreEqual(Tokens.Date, lexer.NextToken().Kind); + } + + [Test] + public void TestDecimal() + { + VBLexer lexer = GenerateLexer(new StringReader("Decimal")); + Assert.AreEqual(Tokens.Decimal, lexer.NextToken().Kind); + } + + [Test] + public void TestDeclare() + { + VBLexer lexer = GenerateLexer(new StringReader("Declare")); + Assert.AreEqual(Tokens.Declare, lexer.NextToken().Kind); + } + + [Test] + public void TestDefault() + { + VBLexer lexer = GenerateLexer(new StringReader("Default")); + Assert.AreEqual(Tokens.Default, lexer.NextToken().Kind); + } + + [Test] + public void TestDelegate() + { + VBLexer lexer = GenerateLexer(new StringReader("Delegate")); + Assert.AreEqual(Tokens.Delegate, lexer.NextToken().Kind); + } + + [Test] + public void TestDescending() + { + VBLexer lexer = GenerateLexer(new StringReader("Descending")); + Assert.AreEqual(Tokens.Descending, lexer.NextToken().Kind); + } + + [Test] + public void TestDim() + { + VBLexer lexer = GenerateLexer(new StringReader("Dim")); + Assert.AreEqual(Tokens.Dim, lexer.NextToken().Kind); + } + + [Test] + public void TestDirectCast() + { + VBLexer lexer = GenerateLexer(new StringReader("DirectCast")); + Assert.AreEqual(Tokens.DirectCast, lexer.NextToken().Kind); + } + + [Test] + public void TestDistinct() + { + VBLexer lexer = GenerateLexer(new StringReader("Distinct")); + Assert.AreEqual(Tokens.Distinct, lexer.NextToken().Kind); + } + + [Test] + public void TestDo() + { + VBLexer lexer = GenerateLexer(new StringReader("Do")); + Assert.AreEqual(Tokens.Do, lexer.NextToken().Kind); + } + + [Test] + public void TestDouble() + { + VBLexer lexer = GenerateLexer(new StringReader("Double")); + Assert.AreEqual(Tokens.Double, lexer.NextToken().Kind); + } + + [Test] + public void TestEach() + { + VBLexer lexer = GenerateLexer(new StringReader("Each")); + Assert.AreEqual(Tokens.Each, lexer.NextToken().Kind); + } + + [Test] + public void TestElse() + { + VBLexer lexer = GenerateLexer(new StringReader("Else")); + Assert.AreEqual(Tokens.Else, lexer.NextToken().Kind); + } + + [Test] + public void TestElseIf() + { + VBLexer lexer = GenerateLexer(new StringReader("ElseIf")); + Assert.AreEqual(Tokens.ElseIf, lexer.NextToken().Kind); + } + + [Test] + public void TestEnd() + { + VBLexer lexer = GenerateLexer(new StringReader("End")); + Assert.AreEqual(Tokens.End, lexer.NextToken().Kind); + } + + [Test] + public void TestEndIf() + { + VBLexer lexer = GenerateLexer(new StringReader("EndIf")); + Assert.AreEqual(Tokens.EndIf, lexer.NextToken().Kind); + } + + [Test] + public void TestEnum() + { + VBLexer lexer = GenerateLexer(new StringReader("Enum")); + Assert.AreEqual(Tokens.Enum, lexer.NextToken().Kind); + } + + [Test] + public void TestEquals() + { + VBLexer lexer = GenerateLexer(new StringReader("Equals")); + Assert.AreEqual(Tokens.Equals, lexer.NextToken().Kind); + } + + [Test] + public void TestErase() + { + VBLexer lexer = GenerateLexer(new StringReader("Erase")); + Assert.AreEqual(Tokens.Erase, lexer.NextToken().Kind); + } + + [Test] + public void TestError() + { + VBLexer lexer = GenerateLexer(new StringReader("Error")); + Assert.AreEqual(Tokens.Error, lexer.NextToken().Kind); + } + + [Test] + public void TestEvent() + { + VBLexer lexer = GenerateLexer(new StringReader("Event")); + Assert.AreEqual(Tokens.Event, lexer.NextToken().Kind); + } + + [Test] + public void TestExit() + { + VBLexer lexer = GenerateLexer(new StringReader("Exit")); + Assert.AreEqual(Tokens.Exit, lexer.NextToken().Kind); + } + + [Test] + public void TestExplicit() + { + VBLexer lexer = GenerateLexer(new StringReader("Explicit")); + Assert.AreEqual(Tokens.Explicit, lexer.NextToken().Kind); + } + + [Test] + public void TestFalse() + { + VBLexer lexer = GenerateLexer(new StringReader("False")); + Assert.AreEqual(Tokens.False, lexer.NextToken().Kind); + } + + [Test] + public void TestFinally() + { + VBLexer lexer = GenerateLexer(new StringReader("Finally")); + Assert.AreEqual(Tokens.Finally, lexer.NextToken().Kind); + } + + [Test] + public void TestFor() + { + VBLexer lexer = GenerateLexer(new StringReader("For")); + Assert.AreEqual(Tokens.For, lexer.NextToken().Kind); + } + + [Test] + public void TestFriend() + { + VBLexer lexer = GenerateLexer(new StringReader("Friend")); + Assert.AreEqual(Tokens.Friend, lexer.NextToken().Kind); + } + + [Test] + public void TestFrom() + { + VBLexer lexer = GenerateLexer(new StringReader("From")); + Assert.AreEqual(Tokens.From, lexer.NextToken().Kind); + } + + [Test] + public void TestFunction() + { + VBLexer lexer = GenerateLexer(new StringReader("Function")); + Assert.AreEqual(Tokens.Function, lexer.NextToken().Kind); + } + + [Test] + public void TestGet() + { + VBLexer lexer = GenerateLexer(new StringReader("Get")); + Assert.AreEqual(Tokens.Get, lexer.NextToken().Kind); + } + + [Test] + public void TestGetType() + { + VBLexer lexer = GenerateLexer(new StringReader("GetType")); + Assert.AreEqual(Tokens.GetType, lexer.NextToken().Kind); + } + + [Test] + public void TestGlobal() + { + VBLexer lexer = GenerateLexer(new StringReader("Global")); + Assert.AreEqual(Tokens.Global, lexer.NextToken().Kind); + } + + [Test] + public void TestGoSub() + { + VBLexer lexer = GenerateLexer(new StringReader("GoSub")); + Assert.AreEqual(Tokens.GoSub, lexer.NextToken().Kind); + } + + [Test] + public void TestGoTo() + { + VBLexer lexer = GenerateLexer(new StringReader("GoTo")); + Assert.AreEqual(Tokens.GoTo, lexer.NextToken().Kind); + } + + [Test] + public void TestGroup() + { + VBLexer lexer = GenerateLexer(new StringReader("Group")); + Assert.AreEqual(Tokens.Group, lexer.NextToken().Kind); + } + + [Test] + public void TestHandles() + { + VBLexer lexer = GenerateLexer(new StringReader("Handles")); + Assert.AreEqual(Tokens.Handles, lexer.NextToken().Kind); + } + + [Test] + public void TestIf() + { + VBLexer lexer = GenerateLexer(new StringReader("If")); + Assert.AreEqual(Tokens.If, lexer.NextToken().Kind); + } + + [Test] + public void TestImplements() + { + VBLexer lexer = GenerateLexer(new StringReader("Implements")); + Assert.AreEqual(Tokens.Implements, lexer.NextToken().Kind); + } + + [Test] + public void TestImports() + { + VBLexer lexer = GenerateLexer(new StringReader("Imports")); + Assert.AreEqual(Tokens.Imports, lexer.NextToken().Kind); + } + + [Test] + public void TestIn() + { + VBLexer lexer = GenerateLexer(new StringReader("In")); + Assert.AreEqual(Tokens.In, lexer.NextToken().Kind); + } + + [Test] + public void TestInfer() + { + VBLexer lexer = GenerateLexer(new StringReader("Infer")); + Assert.AreEqual(Tokens.Infer, lexer.NextToken().Kind); + } + + [Test] + public void TestInherits() + { + VBLexer lexer = GenerateLexer(new StringReader("Inherits")); + Assert.AreEqual(Tokens.Inherits, lexer.NextToken().Kind); + } + + [Test] + public void TestInteger() + { + VBLexer lexer = GenerateLexer(new StringReader("Integer")); + Assert.AreEqual(Tokens.Integer, lexer.NextToken().Kind); + } + + [Test] + public void TestInterface() + { + VBLexer lexer = GenerateLexer(new StringReader("Interface")); + Assert.AreEqual(Tokens.Interface, lexer.NextToken().Kind); + } + + [Test] + public void TestInto() + { + VBLexer lexer = GenerateLexer(new StringReader("Into")); + Assert.AreEqual(Tokens.Into, lexer.NextToken().Kind); + } + + [Test] + public void TestIs() + { + VBLexer lexer = GenerateLexer(new StringReader("Is")); + Assert.AreEqual(Tokens.Is, lexer.NextToken().Kind); + } + + [Test] + public void TestIsNot() + { + VBLexer lexer = GenerateLexer(new StringReader("IsNot")); + Assert.AreEqual(Tokens.IsNot, lexer.NextToken().Kind); + } + + [Test] + public void TestJoin() + { + VBLexer lexer = GenerateLexer(new StringReader("Join")); + Assert.AreEqual(Tokens.Join, lexer.NextToken().Kind); + } + + [Test] + public void TestKey() + { + VBLexer lexer = GenerateLexer(new StringReader("Key")); + Assert.AreEqual(Tokens.Key, lexer.NextToken().Kind); + } + + [Test] + public void TestLet() + { + VBLexer lexer = GenerateLexer(new StringReader("Let")); + Assert.AreEqual(Tokens.Let, lexer.NextToken().Kind); + } + + [Test] + public void TestLib() + { + VBLexer lexer = GenerateLexer(new StringReader("Lib")); + Assert.AreEqual(Tokens.Lib, lexer.NextToken().Kind); + } + + [Test] + public void TestLike() + { + VBLexer lexer = GenerateLexer(new StringReader("Like")); + Assert.AreEqual(Tokens.Like, lexer.NextToken().Kind); + } + + [Test] + public void TestLong() + { + VBLexer lexer = GenerateLexer(new StringReader("Long")); + Assert.AreEqual(Tokens.Long, lexer.NextToken().Kind); + } + + [Test] + public void TestLoop() + { + VBLexer lexer = GenerateLexer(new StringReader("Loop")); + Assert.AreEqual(Tokens.Loop, lexer.NextToken().Kind); + } + + [Test] + public void TestMe() + { + VBLexer lexer = GenerateLexer(new StringReader("Me")); + Assert.AreEqual(Tokens.Me, lexer.NextToken().Kind); + } + + [Test] + public void TestMod() + { + VBLexer lexer = GenerateLexer(new StringReader("Mod")); + Assert.AreEqual(Tokens.Mod, lexer.NextToken().Kind); + } + + [Test] + public void TestModule() + { + VBLexer lexer = GenerateLexer(new StringReader("Module")); + Assert.AreEqual(Tokens.Module, lexer.NextToken().Kind); + } + + [Test] + public void TestMustInherit() + { + VBLexer lexer = GenerateLexer(new StringReader("MustInherit")); + Assert.AreEqual(Tokens.MustInherit, lexer.NextToken().Kind); + } + + [Test] + public void TestMustOverride() + { + VBLexer lexer = GenerateLexer(new StringReader("MustOverride")); + Assert.AreEqual(Tokens.MustOverride, lexer.NextToken().Kind); + } + + [Test] + public void TestMyBase() + { + VBLexer lexer = GenerateLexer(new StringReader("MyBase")); + Assert.AreEqual(Tokens.MyBase, lexer.NextToken().Kind); + } + + [Test] + public void TestMyClass() + { + VBLexer lexer = GenerateLexer(new StringReader("MyClass")); + Assert.AreEqual(Tokens.MyClass, lexer.NextToken().Kind); + } + + [Test] + public void TestNamespace() + { + VBLexer lexer = GenerateLexer(new StringReader("Namespace")); + Assert.AreEqual(Tokens.Namespace, lexer.NextToken().Kind); + } + + [Test] + public void TestNarrowing() + { + VBLexer lexer = GenerateLexer(new StringReader("Narrowing")); + Assert.AreEqual(Tokens.Narrowing, lexer.NextToken().Kind); + } + + [Test] + public void TestNew() + { + VBLexer lexer = GenerateLexer(new StringReader("New")); + Assert.AreEqual(Tokens.New, lexer.NextToken().Kind); + } + + [Test] + public void TestNext() + { + VBLexer lexer = GenerateLexer(new StringReader("Next")); + Assert.AreEqual(Tokens.Next, lexer.NextToken().Kind); + } + + [Test] + public void TestNot() + { + VBLexer lexer = GenerateLexer(new StringReader("Not")); + Assert.AreEqual(Tokens.Not, lexer.NextToken().Kind); + } + + [Test] + public void TestNothing() + { + VBLexer lexer = GenerateLexer(new StringReader("Nothing")); + Assert.AreEqual(Tokens.Nothing, lexer.NextToken().Kind); + } + + [Test] + public void TestNotInheritable() + { + VBLexer lexer = GenerateLexer(new StringReader("NotInheritable")); + Assert.AreEqual(Tokens.NotInheritable, lexer.NextToken().Kind); + } + + [Test] + public void TestNotOverridable() + { + VBLexer lexer = GenerateLexer(new StringReader("NotOverridable")); + Assert.AreEqual(Tokens.NotOverridable, lexer.NextToken().Kind); + } + + [Test] + public void TestObject() + { + VBLexer lexer = GenerateLexer(new StringReader("Object")); + Assert.AreEqual(Tokens.Object, lexer.NextToken().Kind); + } + + [Test] + public void TestOf() + { + VBLexer lexer = GenerateLexer(new StringReader("Of")); + Assert.AreEqual(Tokens.Of, lexer.NextToken().Kind); + } + + [Test] + public void TestOff() + { + VBLexer lexer = GenerateLexer(new StringReader("Off")); + Assert.AreEqual(Tokens.Off, lexer.NextToken().Kind); + } + + [Test] + public void TestOn() + { + VBLexer lexer = GenerateLexer(new StringReader("On")); + Assert.AreEqual(Tokens.On, lexer.NextToken().Kind); + } + + [Test] + public void TestOperator() + { + VBLexer lexer = GenerateLexer(new StringReader("Operator")); + Assert.AreEqual(Tokens.Operator, lexer.NextToken().Kind); + } + + [Test] + public void TestOption() + { + VBLexer lexer = GenerateLexer(new StringReader("Option")); + Assert.AreEqual(Tokens.Option, lexer.NextToken().Kind); + } + + [Test] + public void TestOptional() + { + VBLexer lexer = GenerateLexer(new StringReader("Optional")); + Assert.AreEqual(Tokens.Optional, lexer.NextToken().Kind); + } + + [Test] + public void TestOr() + { + VBLexer lexer = GenerateLexer(new StringReader("Or")); + Assert.AreEqual(Tokens.Or, lexer.NextToken().Kind); + } + + [Test] + public void TestOrder() + { + VBLexer lexer = GenerateLexer(new StringReader("Order")); + Assert.AreEqual(Tokens.Order, lexer.NextToken().Kind); + } + + [Test] + public void TestOrElse() + { + VBLexer lexer = GenerateLexer(new StringReader("OrElse")); + Assert.AreEqual(Tokens.OrElse, lexer.NextToken().Kind); + } + + [Test] + public void TestOut() + { + VBLexer lexer = GenerateLexer(new StringReader("Out")); + Assert.AreEqual(Tokens.Out, lexer.NextToken().Kind); + } + + [Test] + public void TestOverloads() + { + VBLexer lexer = GenerateLexer(new StringReader("Overloads")); + Assert.AreEqual(Tokens.Overloads, lexer.NextToken().Kind); + } + + [Test] + public void TestOverridable() + { + VBLexer lexer = GenerateLexer(new StringReader("Overridable")); + Assert.AreEqual(Tokens.Overridable, lexer.NextToken().Kind); + } + + [Test] + public void TestOverrides() + { + VBLexer lexer = GenerateLexer(new StringReader("Overrides")); + Assert.AreEqual(Tokens.Overrides, lexer.NextToken().Kind); + } + + [Test] + public void TestParamArray() + { + VBLexer lexer = GenerateLexer(new StringReader("ParamArray")); + Assert.AreEqual(Tokens.ParamArray, lexer.NextToken().Kind); + } + + [Test] + public void TestPartial() + { + VBLexer lexer = GenerateLexer(new StringReader("Partial")); + Assert.AreEqual(Tokens.Partial, lexer.NextToken().Kind); + } + + [Test] + public void TestPreserve() + { + VBLexer lexer = GenerateLexer(new StringReader("Preserve")); + Assert.AreEqual(Tokens.Preserve, lexer.NextToken().Kind); + } + + [Test] + public void TestPrivate() + { + VBLexer lexer = GenerateLexer(new StringReader("Private")); + Assert.AreEqual(Tokens.Private, lexer.NextToken().Kind); + } + + [Test] + public void TestProperty() + { + VBLexer lexer = GenerateLexer(new StringReader("Property")); + Assert.AreEqual(Tokens.Property, lexer.NextToken().Kind); + } + + [Test] + public void TestProtected() + { + VBLexer lexer = GenerateLexer(new StringReader("Protected")); + Assert.AreEqual(Tokens.Protected, lexer.NextToken().Kind); + } + + [Test] + public void TestPublic() + { + VBLexer lexer = GenerateLexer(new StringReader("Public")); + Assert.AreEqual(Tokens.Public, lexer.NextToken().Kind); + } + + [Test] + public void TestRaiseEvent() + { + VBLexer lexer = GenerateLexer(new StringReader("RaiseEvent")); + Assert.AreEqual(Tokens.RaiseEvent, lexer.NextToken().Kind); + } + + [Test] + public void TestReadOnly() + { + VBLexer lexer = GenerateLexer(new StringReader("ReadOnly")); + Assert.AreEqual(Tokens.ReadOnly, lexer.NextToken().Kind); + } + + [Test] + public void TestReDim() + { + VBLexer lexer = GenerateLexer(new StringReader("ReDim")); + Assert.AreEqual(Tokens.ReDim, lexer.NextToken().Kind); + } + + [Test] + public void TestRemoveHandler() + { + VBLexer lexer = GenerateLexer(new StringReader("RemoveHandler")); + Assert.AreEqual(Tokens.RemoveHandler, lexer.NextToken().Kind); + } + + [Test] + public void TestResume() + { + VBLexer lexer = GenerateLexer(new StringReader("Resume")); + Assert.AreEqual(Tokens.Resume, lexer.NextToken().Kind); + } + + [Test] + public void TestReturn() + { + VBLexer lexer = GenerateLexer(new StringReader("Return")); + Assert.AreEqual(Tokens.Return, lexer.NextToken().Kind); + } + + [Test] + public void TestSByte() + { + VBLexer lexer = GenerateLexer(new StringReader("SByte")); + Assert.AreEqual(Tokens.SByte, lexer.NextToken().Kind); + } + + [Test] + public void TestSelect() + { + VBLexer lexer = GenerateLexer(new StringReader("Select")); + Assert.AreEqual(Tokens.Select, lexer.NextToken().Kind); + } + + [Test] + public void TestSet() + { + VBLexer lexer = GenerateLexer(new StringReader("Set")); + Assert.AreEqual(Tokens.Set, lexer.NextToken().Kind); + } + + [Test] + public void TestShadows() + { + VBLexer lexer = GenerateLexer(new StringReader("Shadows")); + Assert.AreEqual(Tokens.Shadows, lexer.NextToken().Kind); + } + + [Test] + public void TestShared() + { + VBLexer lexer = GenerateLexer(new StringReader("Shared")); + Assert.AreEqual(Tokens.Shared, lexer.NextToken().Kind); + } + + [Test] + public void TestShort() + { + VBLexer lexer = GenerateLexer(new StringReader("Short")); + Assert.AreEqual(Tokens.Short, lexer.NextToken().Kind); + } + + [Test] + public void TestSingle() + { + VBLexer lexer = GenerateLexer(new StringReader("Single")); + Assert.AreEqual(Tokens.Single, lexer.NextToken().Kind); + } + + [Test] + public void TestSkip() + { + VBLexer lexer = GenerateLexer(new StringReader("Skip")); + Assert.AreEqual(Tokens.Skip, lexer.NextToken().Kind); + } + + [Test] + public void TestStatic() + { + VBLexer lexer = GenerateLexer(new StringReader("Static")); + Assert.AreEqual(Tokens.Static, lexer.NextToken().Kind); + } + + [Test] + public void TestStep() + { + VBLexer lexer = GenerateLexer(new StringReader("Step")); + Assert.AreEqual(Tokens.Step, lexer.NextToken().Kind); + } + + [Test] + public void TestStop() + { + VBLexer lexer = GenerateLexer(new StringReader("Stop")); + Assert.AreEqual(Tokens.Stop, lexer.NextToken().Kind); + } + + [Test] + public void TestStrict() + { + VBLexer lexer = GenerateLexer(new StringReader("Strict")); + Assert.AreEqual(Tokens.Strict, lexer.NextToken().Kind); + } + + [Test] + public void TestString() + { + VBLexer lexer = GenerateLexer(new StringReader("String")); + Assert.AreEqual(Tokens.String, lexer.NextToken().Kind); + } + + [Test] + public void TestStructure() + { + VBLexer lexer = GenerateLexer(new StringReader("Structure")); + Assert.AreEqual(Tokens.Structure, lexer.NextToken().Kind); + } + + [Test] + public void TestSub() + { + VBLexer lexer = GenerateLexer(new StringReader("Sub")); + Assert.AreEqual(Tokens.Sub, lexer.NextToken().Kind); + } + + [Test] + public void TestSyncLock() + { + VBLexer lexer = GenerateLexer(new StringReader("SyncLock")); + Assert.AreEqual(Tokens.SyncLock, lexer.NextToken().Kind); + } + + [Test] + public void TestTake() + { + VBLexer lexer = GenerateLexer(new StringReader("Take")); + Assert.AreEqual(Tokens.Take, lexer.NextToken().Kind); + } + + [Test] + public void TestText() + { + VBLexer lexer = GenerateLexer(new StringReader("Text")); + Assert.AreEqual(Tokens.Text, lexer.NextToken().Kind); + } + + [Test] + public void TestThen() + { + VBLexer lexer = GenerateLexer(new StringReader("Then")); + Assert.AreEqual(Tokens.Then, lexer.NextToken().Kind); + } + + [Test] + public void TestThrow() + { + VBLexer lexer = GenerateLexer(new StringReader("Throw")); + Assert.AreEqual(Tokens.Throw, lexer.NextToken().Kind); + } + + [Test] + public void TestTo() + { + VBLexer lexer = GenerateLexer(new StringReader("To")); + Assert.AreEqual(Tokens.To, lexer.NextToken().Kind); + } + + [Test] + public void TestTrue() + { + VBLexer lexer = GenerateLexer(new StringReader("True")); + Assert.AreEqual(Tokens.True, lexer.NextToken().Kind); + } + + [Test] + public void TestTry() + { + VBLexer lexer = GenerateLexer(new StringReader("Try")); + Assert.AreEqual(Tokens.Try, lexer.NextToken().Kind); + } + + [Test] + public void TestTryCast() + { + VBLexer lexer = GenerateLexer(new StringReader("TryCast")); + Assert.AreEqual(Tokens.TryCast, lexer.NextToken().Kind); + } + + [Test] + public void TestTypeOf() + { + VBLexer lexer = GenerateLexer(new StringReader("TypeOf")); + Assert.AreEqual(Tokens.TypeOf, lexer.NextToken().Kind); + } + + [Test] + public void TestUInteger() + { + VBLexer lexer = GenerateLexer(new StringReader("UInteger")); + Assert.AreEqual(Tokens.UInteger, lexer.NextToken().Kind); + } + + [Test] + public void TestULong() + { + VBLexer lexer = GenerateLexer(new StringReader("ULong")); + Assert.AreEqual(Tokens.ULong, lexer.NextToken().Kind); + } + + [Test] + public void TestUnicode() + { + VBLexer lexer = GenerateLexer(new StringReader("Unicode")); + Assert.AreEqual(Tokens.Unicode, lexer.NextToken().Kind); + } + + [Test] + public void TestUntil() + { + VBLexer lexer = GenerateLexer(new StringReader("Until")); + Assert.AreEqual(Tokens.Until, lexer.NextToken().Kind); + } + + [Test] + public void TestUShort() + { + VBLexer lexer = GenerateLexer(new StringReader("UShort")); + Assert.AreEqual(Tokens.UShort, lexer.NextToken().Kind); + } + + [Test] + public void TestUsing() + { + VBLexer lexer = GenerateLexer(new StringReader("Using")); + Assert.AreEqual(Tokens.Using, lexer.NextToken().Kind); + } + + [Test] + public void TestVariant() + { + VBLexer lexer = GenerateLexer(new StringReader("Variant")); + Assert.AreEqual(Tokens.Variant, lexer.NextToken().Kind); + } + + [Test] + public void TestWend() + { + VBLexer lexer = GenerateLexer(new StringReader("Wend")); + Assert.AreEqual(Tokens.Wend, lexer.NextToken().Kind); + } + + [Test] + public void TestWhen() + { + VBLexer lexer = GenerateLexer(new StringReader("When")); + Assert.AreEqual(Tokens.When, lexer.NextToken().Kind); + } + + [Test] + public void TestWhere() + { + VBLexer lexer = GenerateLexer(new StringReader("Where")); + Assert.AreEqual(Tokens.Where, lexer.NextToken().Kind); + } + + [Test] + public void TestWhile() + { + VBLexer lexer = GenerateLexer(new StringReader("While")); + Assert.AreEqual(Tokens.While, lexer.NextToken().Kind); + } + + [Test] + public void TestWidening() + { + VBLexer lexer = GenerateLexer(new StringReader("Widening")); + Assert.AreEqual(Tokens.Widening, lexer.NextToken().Kind); + } + + [Test] + public void TestWith() + { + VBLexer lexer = GenerateLexer(new StringReader("With")); + Assert.AreEqual(Tokens.With, lexer.NextToken().Kind); + } + + [Test] + public void TestWithEvents() + { + VBLexer lexer = GenerateLexer(new StringReader("WithEvents")); + Assert.AreEqual(Tokens.WithEvents, lexer.NextToken().Kind); + } + + [Test] + public void TestWriteOnly() + { + VBLexer lexer = GenerateLexer(new StringReader("WriteOnly")); + Assert.AreEqual(Tokens.WriteOnly, lexer.NextToken().Kind); + } + + [Test] + public void TestXor() + { + VBLexer lexer = GenerateLexer(new StringReader("Xor")); + Assert.AreEqual(Tokens.Xor, lexer.NextToken().Kind); + } + + [Test] + public void TestGetXmlNamespace() + { + VBLexer lexer = GenerateLexer(new StringReader("GetXmlNamespace")); + Assert.AreEqual(Tokens.GetXmlNamespace, lexer.NextToken().Kind); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LiteralsTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LiteralsTests.cs new file mode 100644 index 0000000000..7572b916c8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/LiteralsTests.cs @@ -0,0 +1,194 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public sealed class LiteralsTests + { + VBLexer GenerateLexer(StringReader sr) + { + return new VBLexer(sr); + } + + Token GetSingleToken(string text) + { + VBLexer lexer = GenerateLexer(new StringReader(text)); + Token t = lexer.NextToken(); + Assert.AreEqual(Tokens.EOL, lexer.NextToken().Kind, "Tokens.EOL"); + Assert.AreEqual(Tokens.EOF, lexer.NextToken().Kind, "Tokens.EOF"); + Assert.AreEqual("", lexer.Errors.ErrorOutput); + return t; + } + + void CheckToken(string text, int tokenType, object val) + { + Token t = GetSingleToken(text); + Assert.AreEqual(tokenType, t.Kind, "Tokens.Literal"); + Assert.IsNotNull(t.LiteralValue, "literalValue is null"); + Assert.AreEqual(val.GetType(), t.LiteralValue.GetType(), "literalValue.GetType()"); + Assert.AreEqual(val, t.LiteralValue, "literalValue"); + } + + [Test] + public void TestSingleDigit() + { + CheckToken("5", Tokens.LiteralInteger, 5); + } + + [Test] + public void TestZero() + { + CheckToken("0", Tokens.LiteralInteger, 0); + } + + [Test] + public void TestInteger() + { + CheckToken("15", Tokens.LiteralInteger, 15); + CheckToken("8581", Tokens.LiteralInteger, 8581); + } + + [Test] + public void InvalidTypeCharacter() + { + // just check that we don't get exceptions: + GenerateLexer(new StringReader(".5s")).NextToken(); + GenerateLexer(new StringReader(".5ul")).NextToken(); + } + + [Test] + public void TestHexadecimalInteger() + { + CheckToken("&H10", Tokens.LiteralInteger, 0x10); + CheckToken("&H10&", Tokens.LiteralInteger, (long)0x10); + CheckToken("&h3ff%", Tokens.LiteralInteger, 0x3ff); + CheckToken("&h8000s", Tokens.LiteralInteger, short.MinValue); + CheckToken("&h8000us", Tokens.LiteralInteger, (ushort)0x8000); + CheckToken("&HffffFFFF", Tokens.LiteralInteger, -1); + CheckToken("&HffffFFFF%", Tokens.LiteralInteger, -1); + CheckToken("&HffffFFFFui", Tokens.LiteralInteger, uint.MaxValue); + CheckToken("&HffffFFFF&", Tokens.LiteralInteger, (long)uint.MaxValue); + } + + [Test] + public void TestLongHexadecimalInteger() + { + CheckToken("&H4244636f446c6d58", Tokens.LiteralInteger, 0x4244636f446c6d58); + CheckToken("&hf244636f446c6d58", Tokens.LiteralInteger, -989556688574190248); + CheckToken("&hf244636f446c6d58&", Tokens.LiteralInteger, -989556688574190248); + CheckToken("&hf244636f446c6d58ul", Tokens.LiteralInteger, 0xf244636f446c6d58); + } + + [Test] + public void InvalidHexadecimalInteger() + { + // just check that we don't get exceptions: + GenerateLexer(new StringReader("&H")).NextToken(); + // >ulong.MaxValue + GenerateLexer(new StringReader("&hff244636f446c6d58")).NextToken(); + // needs an ulong, but "i" postfix specified integer + GenerateLexer(new StringReader("&hf244636f446c6d58i")).NextToken(); + GenerateLexer(new StringReader("&hf244636f446c6d58ui")).NextToken(); + } + + [Test] + public void TestIncompleteHexadecimal() + { + VBLexer lexer = GenerateLexer(new StringReader("&H\r\nabc")); + Token t = lexer.NextToken(); + Assert.AreEqual(Tokens.LiteralInteger, t.Kind); + Assert.AreEqual(0, (int)t.LiteralValue); + Assert.AreEqual(Tokens.EOL, lexer.NextToken().Kind, "Tokens.EOL (1)"); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind, "Tokens.Identifier"); + Assert.AreEqual(Tokens.EOL, lexer.NextToken().Kind, "Tokens.EOL (2)"); + Assert.AreEqual(Tokens.EOF, lexer.NextToken().Kind, "Tokens.EOF"); + Assert.AreNotEqual("", lexer.Errors.ErrorOutput); + } + + [Test] + public void TestStringLiterals() + { + CheckToken("\"\"", Tokens.LiteralString, ""); + CheckToken("\"Hello, World!\"", Tokens.LiteralString, "Hello, World!"); + CheckToken("\"\"\"\"", Tokens.LiteralString, "\""); + } + + [Test] + public void TestCharacterLiterals() + { + CheckToken("\" \"c", Tokens.LiteralCharacter, ' '); + CheckToken("\"!\"c", Tokens.LiteralCharacter, '!'); + CheckToken("\"\"\"\"c", Tokens.LiteralCharacter, '"'); + } + + [Test] + public void TestDateLiterals() + { + CheckToken("# 8/23/1970 #", Tokens.LiteralDate, new DateTime(1970, 8, 23, 0, 0, 0)); + CheckToken("#8/23/1970#", Tokens.LiteralDate, new DateTime(1970, 8, 23, 0, 0, 0)); + CheckToken("# 8/23/1970 3:45:39AM #", Tokens.LiteralDate, new DateTime(1970, 8, 23, 3, 45, 39)); + CheckToken("# 3:45:39AM #", Tokens.LiteralDate, new DateTime(1, 1, 1, 3, 45, 39)); + CheckToken("# 3:45:39 PM #", Tokens.LiteralDate, new DateTime(1, 1, 1, 15, 45, 39)); + CheckToken("# 3:45:39 #", Tokens.LiteralDate, new DateTime(1, 1, 1, 3, 45, 39)); + CheckToken("# 13:45:39 #", Tokens.LiteralDate, new DateTime(1, 1, 1, 13, 45, 39)); + CheckToken("# 1AM #", Tokens.LiteralDate, new DateTime(1, 1, 1, 1, 0, 0)); + } + + [Test] + public void TestDouble() + { + CheckToken("1.0", Tokens.LiteralDouble, 1.0); + CheckToken("1.1", Tokens.LiteralDouble, 1.1); + CheckToken("2e-5", Tokens.LiteralDouble, 2e-5); + CheckToken("2.0e-5", Tokens.LiteralDouble, 2e-5); + CheckToken("2e5", Tokens.LiteralDouble, 2e5); + CheckToken("2.2e5", Tokens.LiteralDouble, 2.2e5); + CheckToken("2e+5", Tokens.LiteralDouble, 2e5); + CheckToken("2.2e+5", Tokens.LiteralDouble, 2.2e5); + + CheckToken("1r", Tokens.LiteralDouble, 1.0); + CheckToken("1.0r", Tokens.LiteralDouble, 1.0); + CheckToken("1.1r", Tokens.LiteralDouble, 1.1); + CheckToken("2e-5r", Tokens.LiteralDouble, 2e-5); + CheckToken("2.0e-5r", Tokens.LiteralDouble, 2e-5); + CheckToken("2e5r", Tokens.LiteralDouble, 2e5); + CheckToken("2.2e5r", Tokens.LiteralDouble, 2.2e5); + CheckToken("2e+5r", Tokens.LiteralDouble, 2e5); + CheckToken("2.2e+5r", Tokens.LiteralDouble, 2.2e5); + } + + [Test] + public void TestSingle() + { + CheckToken("1f", Tokens.LiteralSingle, 1.0f); + CheckToken("1.0f", Tokens.LiteralSingle, 1.0f); + CheckToken("1.1f", Tokens.LiteralSingle, 1.1f); + CheckToken("2e-5f", Tokens.LiteralSingle, 2e-5f); + CheckToken("2.0e-5f", Tokens.LiteralSingle, 2e-5f); + CheckToken("2e5f", Tokens.LiteralSingle, 2e5f); + CheckToken("2.2e5f", Tokens.LiteralSingle, 2.2e5f); + CheckToken("2e+5f", Tokens.LiteralSingle, 2e5f); + CheckToken("2.2e+5f", Tokens.LiteralSingle, 2.2e5f); + } + + [Test] + public void TestDecimal() + { + CheckToken("1d", Tokens.LiteralDecimal, 1m); + CheckToken("1.0d", Tokens.LiteralDecimal, 1.0m); + CheckToken("1.1d", Tokens.LiteralDecimal, 1.1m); + CheckToken("2e-5d", Tokens.LiteralDecimal, 2e-5m); + CheckToken("2.0e-5d", Tokens.LiteralDecimal, 2.0e-5m); + CheckToken("2e5d", Tokens.LiteralDecimal, 2e5m); + CheckToken("2.2e5d", Tokens.LiteralDecimal, 2.2e5m); + CheckToken("2e+5d", Tokens.LiteralDecimal, 2e5m); + CheckToken("2.2e+5d", Tokens.LiteralDecimal, 2.2e5m); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/TokenTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/TokenTests.cs new file mode 100644 index 0000000000..5b21fe89af --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/TokenTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class TokenTests + { + [Test] + public void TokenToStringDoesNotThrowException() + { + Assert.DoesNotThrow( + () => { + string text = new Token(71, 1, 1).ToString(); + } + ); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/XmlModeLexerTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/XmlModeLexerTests.cs new file mode 100644 index 0000000000..e55c4f9b53 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Lexer/XmlModeLexerTests.cs @@ -0,0 +1,993 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Lexer +{ + [TestFixture] + public class XmlModeLexerTests + { + #region Xml Tests + [Test] + public void TagWithContent() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = Hello World"))); + + CheckHead(lexer); + + Assert.AreEqual(Tokens.Dim, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Assign, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + CheckFoot(lexer); + } + + [Test] + public void HtmlText() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x =

Title

" + + "

test test
test

"))); + + CheckHead(lexer); + + Assert.AreEqual(Tokens.Dim, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Assign, lexer.NextToken().Kind); + + //
+ Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + //

+ Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + // Title + Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind); + + //

+ Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + //

+ Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + // test test + Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind); + + //
+ Assert.AreEqual(Tokens.XmlOpenTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTagEmptyElement, lexer.NextToken().Kind); + + // test + Assert.AreEqual(Tokens.XmlContent, lexer.NextToken().Kind); + + //

+ Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + //
+ Assert.AreEqual(Tokens.XmlOpenEndTag, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.Identifier, lexer.NextToken().Kind); + Assert.AreEqual(Tokens.XmlCloseTag, lexer.NextToken().Kind); + + CheckFoot(lexer); + } + + [Test] + public void XmlLiteralsExample1() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim xml = \n" + + " \n" + + " Shrimp Cocktail\n" + + " Escargot\n" + + " \n" + + " \n" + + " Filet Mignon\n" + + " Garlic Potatoes\n" + + " Broccoli\n" + + " \n" + + " \n" + + " Chocolate Cheesecake\n" + + " \n" + + " "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + // + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // Shrimp Cocktail + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // Escargot + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // Filet Mignon + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // Garlic Potatoes + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // Broccoli + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // Chocolate Cheesecake + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + // whitespaces + Tokens.XmlContent, + // + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag + ); + + CheckFoot(lexer); + } + + [Test] + public void SimpleXmlWithComments() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim x = + + + + + + + "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.XmlProcessingInstruction, Tokens.XmlContent, Tokens.XmlComment, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.XmlContent, Tokens.XmlComment, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, + Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlComment, Tokens.XmlComment, Tokens.XmlProcessingInstruction); + + CheckFoot(lexer); + } + + [Test] + public void SimpleEmptyTag() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement); + + CheckFoot(lexer); + } + + [Test] + public void SimpleTag() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim x = "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlOpenEndTag, + Tokens.Identifier, Tokens.XmlCloseTag); + + CheckFoot(lexer); + } + + [Test] + public void XmlImport() + { + string code = @"Imports System +Imports System.Linq + +Imports +Imports + +Class TestClass + Sub TestSub() + Dim xml = + + 1. Cell + + + End Sub +End Class"; + + VBLexer lexer = GenerateLexer(new StringReader(code)); + + CheckTokens(lexer, Tokens.Imports, Tokens.Identifier, Tokens.EOL, + Tokens.Imports, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.EOL, + Tokens.Imports, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.EOL, + Tokens.Imports, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.EOL, + Tokens.Class, Tokens.Identifier, Tokens.EOL, Tokens.Sub, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.CloseParenthesis, Tokens.EOL, + Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.EOL, Tokens.End, Tokens.Sub, Tokens.EOL, Tokens.End, Tokens.Class + ); + } + + [Test] + public void CDataSection() + { + string xml = @"Dim xml = + "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(xml))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, // 2 + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 6 + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 10 + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 14 + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 18 + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, // 22 + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, // 28 + Tokens.XmlContent, Tokens.XmlCData, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, // 34 + Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, + Tokens.XmlContent, Tokens.XmlCData, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag + ); + + + CheckFoot(lexer); + } + + [Test] + public void InlineVB() + { + string code = @"Dim xml = + + + <%= From m In menu _ + Where m.Course = ""appetizer"" _ + Select <%= m.Food %> _ + %> + + + <%= From m In menu _ + Where m.Course = ""main"" _ + Select <%= m.Food %> _ + %> + + + <%= From m In menu _ + Where m.Course = ""dessert"" _ + Select <%= m.Food %> _ + %> + + "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(code))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlProcessingInstruction, Tokens.XmlContent, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlStartInlineVB, + Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Where, Tokens.Identifier, Tokens.Dot, + Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.Select, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.XmlEndInlineVB, + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlEndInlineVB, Tokens.XmlContent, Tokens.XmlOpenEndTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlStartInlineVB, + Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Where, Tokens.Identifier, Tokens.Dot, + Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.Select, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.XmlEndInlineVB, + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlEndInlineVB, Tokens.XmlContent, Tokens.XmlOpenEndTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlStartInlineVB, + Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Where, Tokens.Identifier, Tokens.Dot, + Tokens.Identifier, Tokens.Assign, Tokens.LiteralString, Tokens.Select, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.XmlEndInlineVB, + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlEndInlineVB, Tokens.XmlContent, Tokens.XmlOpenEndTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag + ); + + CheckFoot(lexer); + } + + [Test] + public void InlineVB2() + { + string code = @"Dim contact As XElement = <<%=elementName %>> + <%= MyName %> + "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(code))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.As, Tokens.Identifier, Tokens.Assign, Tokens.XmlOpenTag, + Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.XmlEndInlineVB, Tokens.XmlCloseTag, Tokens.XmlContent, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlStartInlineVB, Tokens.Identifier, Tokens.XmlEndInlineVB, + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, Tokens.XmlCloseTag); + + CheckFoot(lexer); + } + + [Test] + public void XmlAccessOperators() + { + string code = @"Dim childAxis = xml.
. +Dim course3 = xml...(2) +Dim childAxis = xml... +For Each item In childAxis + Console.WriteLine(item.@name) +Next"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(code))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.Dot, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.Dot, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, + Tokens.EOL, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.TripleDot, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.OpenParenthesis, Tokens.LiteralInteger, Tokens.CloseParenthesis, + Tokens.EOL, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.Identifier, Tokens.TripleDot, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTag, Tokens.EOL, Tokens.For, Tokens.Each, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.EOL, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.DotAt, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.EOL, + Tokens.Next); + + CheckFoot(lexer); + } + + [Test] + public void GetXmlNamespace() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim name = GetXmlNamespace(x)"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.GetXmlNamespace, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.CloseParenthesis); + + CheckFoot(lexer); + } + + [Test] + public void GetXmlNamespace2() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim name = GetXmlNamespace(db-name)"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.GetXmlNamespace, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.CloseParenthesis); + + + CheckFoot(lexer); + } + + [Test] + public void XmlInSelect() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim data = From x In list Select x"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.From, Tokens.Identifier, Tokens.In, Tokens.Identifier, Tokens.Select, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, Tokens.XmlOpenEndTag, + Tokens.Identifier, Tokens.XmlCloseTag); + + CheckFoot(lexer); + } + + [Test] + public void IfExpressionTest() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Dim name = If(a <> 2, 4, 8)"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.If, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.NotEqual, Tokens.LiteralInteger, + Tokens.Comma, Tokens.LiteralInteger, Tokens.Comma, Tokens.LiteralInteger, Tokens.CloseParenthesis); + + CheckFoot(lexer); + } + + [Test] + public void IfStatementTest() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("If a <> 2 Then Return"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.If, Tokens.Identifier, Tokens.NotEqual, Tokens.LiteralInteger, + Tokens.Then, Tokens.Return); + + + CheckFoot(lexer); + } + + [Test] + public void Bug1() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim xml = "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.XmlComment); + + CheckFoot(lexer); + } + + [Test] + public void Bug2() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim xml = "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, + Tokens.XmlProcessingInstruction, Tokens.XmlOpenTag, Tokens.Identifier, + Tokens.XmlCloseTagEmptyElement, Tokens.XmlComment); + + CheckFoot(lexer); + } + + [Test] + public void Bug3() + { + VBLexer lexer = GenerateLexerForSnippet(new StringReader("New String() {}"), SnippetType.Expression); + + CheckTokens(lexer, Tokens.New, Tokens.String, Tokens.OpenParenthesis, + Tokens.CloseParenthesis, Tokens.OpenCurlyBrace, Tokens.CloseCurlyBrace); + } + + [Test] + public void Bug4() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim x = From kvp As KeyValuePair(Of String, DataGridViewCellStyle) In styleCache.CellStyleCache _ + Select includeStyle(kvp.Key, kvp.Value)"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Dim, Tokens.Identifier, Tokens.Assign, Tokens.From, Tokens.Identifier, Tokens.As, Tokens.Identifier, + Tokens.OpenParenthesis, Tokens.Of, Tokens.String, Tokens.Comma, Tokens.Identifier, Tokens.CloseParenthesis, + Tokens.In, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, + Tokens.Select, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.Identifier, Tokens.Dot, Tokens.Key, Tokens.Comma, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.CloseParenthesis); + + CheckFoot(lexer); + } + + [Test] + public void LessThanCheck() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(@"Dim xml = , True)"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, Tokens.True, + Tokens.CloseParenthesis); + + CheckFoot(lexer); + } + + [Test] + public void AddHandlerStatement() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("AddHandler , True"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.AddHandler, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, Tokens.True); + + CheckFoot(lexer); + } + + [Test] + public void AddHandlerStatement2() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("AddHandler , "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.AddHandler, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTagEmptyElement); + + CheckFoot(lexer); + } + + [Test] + public void RemoveHandlerStatement() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("RemoveHandler , 5"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.RemoveHandler, Tokens.XmlOpenTag, + Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlContent, + Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag + ); + + CheckFoot(lexer); + } + + [Test] + public void ErrorHandlingStatement() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("On Error Resume Next\n" + + "On Error GoTo -1\n" + + "On Error GoTo 0\n" + + "On Error GoTo Test\n" + + "Error 5\n" + + "Error \n" + + "Resume Next\n" + + "Resume Label\n" + + "Resume 4"))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.On, Tokens.Error, Tokens.Resume, Tokens.Next, Tokens.EOL, + Tokens.On, Tokens.Error, Tokens.GoTo, Tokens.Minus, Tokens.LiteralInteger, Tokens.EOL, + Tokens.On, Tokens.Error, Tokens.GoTo, Tokens.LiteralInteger, Tokens.EOL, + Tokens.On, Tokens.Error, Tokens.GoTo, Tokens.Identifier, Tokens.EOL, + Tokens.Error, Tokens.LiteralInteger, Tokens.EOL, + Tokens.Error, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Resume, Tokens.Next, Tokens.EOL, + Tokens.Resume, Tokens.Identifier, Tokens.EOL, + Tokens.Resume, Tokens.LiteralInteger + ); + + CheckFoot(lexer); + } + + [Test] + public void ForLoopStatement() + { + string statement = @"For = To Step +Next , + +For Each In +Next "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.For, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, + Tokens.Assign, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, + Tokens.To, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, + Tokens.Step, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Next, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.For, Tokens.Each, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, + Tokens.In, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Next, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement + ); + + CheckFoot(lexer); + } + + [Test] + public void WhileLoopStatement() + { + string statement = @"While +End While"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.While, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.End, Tokens.While + ); + + CheckFoot(lexer); + } + + [Test] + public void WhileLoopStatement2() + { + string statement = @"Do While +Loop"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Do, Tokens.While, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Loop + ); + + CheckFoot(lexer); + } + + [Test] + public void WhileLoopStatement3() + { + string statement = @"Do +Loop While "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Do, Tokens.EOL, + Tokens.Loop, Tokens.While, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement + ); + + CheckFoot(lexer); + } + + [Test] + public void UntilLoopStatement() + { + string statement = @"Do Until +Loop"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Do, Tokens.Until, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Loop + ); + + CheckFoot(lexer); + } + + [Test] + public void UntilLoopStatement2() + { + string statement = @"Do +Loop Until "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Do, Tokens.EOL, + Tokens.Loop, Tokens.Until, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement + ); + + CheckFoot(lexer); + } + + [Test] + public void IfStatementLarge() + { + string statement = @"If Then +Else If Then +ElseIf Then +Else +End If"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.If, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Then, Tokens.EOL, + Tokens.Else, Tokens.If, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Then, Tokens.EOL, + Tokens.ElseIf, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.XmlOpenEndTag, Tokens.Identifier, Tokens.XmlCloseTag, Tokens.Then, Tokens.EOL, + Tokens.Else, Tokens.EOL, + Tokens.End, Tokens.If + ); + + CheckFoot(lexer); + } + + [Test] + public void SelectStatement() + { + string statement = @"Select Case + Case , + Case Else +End Select"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Select, Tokens.Case, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Case, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Case, Tokens.Else, Tokens.EOL, + Tokens.End, Tokens.Select + ); + + CheckFoot(lexer); + } + + [Test] + public void TryStatement() + { + string statement = @"Try + Catch x + Catch y As Exception + Catch When + Finally +End Try"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Try, Tokens.EOL, + Tokens.Catch, Tokens.Identifier, Tokens.EOL, + Tokens.Catch, Tokens.Identifier, Tokens.As, Tokens.Identifier, Tokens.EOL, + Tokens.Catch, Tokens.When, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Finally, Tokens.EOL, + Tokens.End, Tokens.Try + ); + + CheckFoot(lexer); + } + + [Test] + public void ThrowStatement() + { + VBLexer lexer = GenerateLexer(new StringReader(TestStatement("Throw "))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Throw, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement); + + CheckFoot(lexer); + } + + [Test] + public void BranchStatements() + { + string statement = @"GoTo 5 +GoTo LabelName +Exit Do +Exit For +Exit While +Exit Select +Exit Sub +Exit Function +Exit Property +Exit Try +Continue Do +Continue For +Continue While +Stop +End +Return +Return 5 +Return "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.GoTo, Tokens.LiteralInteger, Tokens.EOL, + Tokens.GoTo, Tokens.Identifier, Tokens.EOL, + Tokens.Exit, Tokens.Do, Tokens.EOL, + Tokens.Exit, Tokens.For, Tokens.EOL, + Tokens.Exit, Tokens.While, Tokens.EOL, + Tokens.Exit, Tokens.Select, Tokens.EOL, + Tokens.Exit, Tokens.Sub, Tokens.EOL, + Tokens.Exit, Tokens.Function, Tokens.EOL, + Tokens.Exit, Tokens.Property, Tokens.EOL, + Tokens.Exit, Tokens.Try, Tokens.EOL, + Tokens.Continue, Tokens.Do, Tokens.EOL, + Tokens.Continue, Tokens.For, Tokens.EOL, + Tokens.Continue, Tokens.While, Tokens.EOL, + Tokens.Stop, Tokens.EOL, + Tokens.End, Tokens.EOL, + Tokens.Return, Tokens.EOL, + Tokens.Return, Tokens.LiteralInteger, Tokens.EOL, + Tokens.Return, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement + ); + + CheckFoot(lexer); + } + + [Test] + public void ArrayHandlingStatements() + { + string statement = @"Erase +Erase , +ReDim Preserve "; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Erase, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.Erase, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.Comma, + Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.ReDim, Tokens.Preserve, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement + ); + + CheckFoot(lexer); + } + + [Test] + public void UsingStatement() + { + string statement = @"Using +End Using"; + + VBLexer lexer = GenerateLexer(new StringReader(TestStatement(statement))); + + CheckHead(lexer); + + CheckTokens(lexer, Tokens.Using, Tokens.XmlOpenTag, Tokens.Identifier, Tokens.XmlCloseTagEmptyElement, Tokens.EOL, + Tokens.End, Tokens.Using + ); + + CheckFoot(lexer); + } + + [Test] + public void NewExpressionWithObjectInitializer() + { + string code = @"New Common.ComboBoxItem With {.Item = _ + Localizer.GetString(""Month"" & initParameters.SelectedDate.FirstDayOfPreviousMonth.Month) & "" "" & + initParameters.SelectedDate.FirstDayOfPreviousMonth.Year, .Value = New Date(2010, initParameters.SelectedDate.FirstDayOfPreviousMonth.Month, 1)}"; + + VBLexer lexer = GenerateLexerForSnippet(new StringReader(code), SnippetType.Expression); + + CheckTokens(lexer, Tokens.New, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, + Tokens.With, Tokens.OpenCurlyBrace, Tokens.Dot, Tokens.Identifier, Tokens.Assign, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.OpenParenthesis, Tokens.LiteralString, + Tokens.ConcatString, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Dot, + Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.CloseParenthesis, Tokens.ConcatString, + Tokens.LiteralString, Tokens.ConcatString, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, + Tokens.Dot, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Comma, Tokens.Dot, + Tokens.Identifier, Tokens.Assign, Tokens.New, Tokens.Date, Tokens.OpenParenthesis, Tokens.LiteralInteger, + Tokens.Comma, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Dot, Tokens.Identifier, Tokens.Dot, + Tokens.Identifier, Tokens.Comma, Tokens.LiteralInteger, Tokens.CloseParenthesis, Tokens.CloseCurlyBrace); + } + #endregion + + #region Helpers + VBLexer GenerateLexer(StringReader sr) + { + return new VBLexer(sr); + } + + VBLexer GenerateLexerForSnippet(StringReader sr, SnippetType type) + { + var lexer = new VBLexer(sr); + lexer.SetInitialContext(type); + return lexer; + } + + string TestStatement(string stmt) + { + return "Class Test\n" + + "Sub A\n" + + stmt + "\n" + + "End Sub\n" + + "End Class"; + } + + void CheckFoot(VBLexer lexer) + { + CheckTokens(lexer, Tokens.EOL, Tokens.End, Tokens.Sub, Tokens.EOL, Tokens.End, Tokens.Class); + } + + void CheckHead(VBLexer lexer) + { + CheckTokens(lexer, Tokens.Class, Tokens.Identifier, Tokens.EOL, + Tokens.Sub, Tokens.Identifier, Tokens.EOL); + } + + void CheckTokens(VBLexer lexer, params int[] tokens) + { + for (int i = 0; i < tokens.Length; i++) { + int token = tokens[i]; + Token t = lexer.NextToken(); + int next = t.Kind; + Assert.IsEmpty(lexer.Errors.ErrorOutput); + Assert.AreEqual(token, next, "{2} of {3}: expected: \"{0}\", was: \"{1}\"; at {4}", Tokens.GetTokenString(token), Tokens.GetTokenString(next), i + 1, tokens.Length, t.Location); + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMParenthesizedExpressionTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMParenthesizedExpressionTest.cs new file mode 100644 index 0000000000..6d4bb2da99 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMParenthesizedExpressionTest.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.CodeDom; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Visitors; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests +{ + [TestFixture] + public class CodeDOMParenthesizedExpressionTest + { + [Test] + public void TestParenthesizedExpression() + { + object output = new ParenthesizedExpression(new PrimitiveExpression(5, "5")).AcceptVisitor(new CodeDomVisitor(), null); + Assert.IsTrue(output is CodePrimitiveExpression); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMPrimitiveExpressionTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMPrimitiveExpressionTest.cs new file mode 100644 index 0000000000..2d1c89d1b3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMPrimitiveExpressionTest.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.CodeDom; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Visitors; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests +{ + [TestFixture] + public class CodeDOMPrimitiveExpressionsTests + { + [Test] + public void TestPrimitiveExpression() + { + object output = new PrimitiveExpression(5, "5").AcceptVisitor(new CodeDomVisitor(), null); + Assert.IsTrue(output is CodePrimitiveExpression); + Assert.AreEqual(((CodePrimitiveExpression)output).Value, 5); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMTypeReferenceTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMTypeReferenceTest.cs new file mode 100644 index 0000000000..fffd395c1e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/CodeDOMTypeReferenceTest.cs @@ -0,0 +1,30 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.CodeDom; +using System.Collections.Generic; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Visitors; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests +{ + [TestFixture] + public class CodeDOMTypeReferenceTest + { + [TestAttribute] + public void InnerClassTypeReferencTest() + { + InnerClassTypeReference ictr = new InnerClassTypeReference( + new TypeReference("OuterClass", new List { new TypeReference("String") }), + "InnerClass", + new List { new TypeReference("Int32"), new TypeReference("Int64") }); + Assert.AreEqual("OuterClass+InnerClass", ictr.ToString()); + CodeTypeOfExpression result = (CodeTypeOfExpression)new TypeOfExpression(ictr).AcceptVisitor(new CodeDomVisitor(), null); + Assert.AreEqual("OuterClass`1+InnerClass`2", result.Type.BaseType); + Assert.AreEqual(3, result.Type.TypeArguments.Count); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/InvocationExpressionTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/InvocationExpressionTest.cs new file mode 100644 index 0000000000..443dcfe3ce --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/CodeDOM/InvocationExpressionTest.cs @@ -0,0 +1,59 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.CodeDom; +using System.Collections.Generic; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Visitors; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Output.CodeDom.Tests +{ + [TestFixture] + public class InvocationExpressionsTests + { + [Test] + public void IdentifierOnlyInvocation() + { + // InitializeComponents(); + SimpleNameExpression identifier = new SimpleNameExpression("InitializeComponents"); + InvocationExpression invocation = new InvocationExpression(identifier, new List()); + object output = invocation.AcceptVisitor(new CodeDomVisitor(), null); + Assert.IsTrue(output is CodeMethodInvokeExpression); + CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output; + Assert.AreEqual("InitializeComponents", mie.Method.MethodName); + Assert.IsTrue(mie.Method.TargetObject is CodeThisReferenceExpression); + } + + [Test] + public void MethodOnThisReferenceInvocation() + { + // InitializeComponents(); + MemberReferenceExpression field = new MemberReferenceExpression(new ThisReferenceExpression(), "InitializeComponents"); + InvocationExpression invocation = new InvocationExpression(field, new List()); + object output = invocation.AcceptVisitor(new CodeDomVisitor(), null); + Assert.IsTrue(output is CodeMethodInvokeExpression); + CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output; + Assert.AreEqual("InitializeComponents", mie.Method.MethodName); + Assert.IsTrue(mie.Method.TargetObject is CodeThisReferenceExpression); + } + + [Test] + public void InvocationOfStaticMethod() + { + // System.Drawing.Color.FromArgb(); + MemberReferenceExpression field = new MemberReferenceExpression(new SimpleNameExpression("System"), "Drawing"); + field = new MemberReferenceExpression(field, "Color"); + field = new MemberReferenceExpression(field, "FromArgb"); + InvocationExpression invocation = new InvocationExpression(field, new List()); + object output = invocation.AcceptVisitor(new CodeDomVisitor(), null); + Assert.IsTrue(output is CodeMethodInvokeExpression); + CodeMethodInvokeExpression mie = (CodeMethodInvokeExpression)output; + Assert.AreEqual("FromArgb", mie.Method.MethodName); + Assert.IsTrue(mie.Method.TargetObject is CodeTypeReferenceExpression); + Assert.AreEqual("System.Drawing.Color", (mie.Method.TargetObject as CodeTypeReferenceExpression).Type.BaseType); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/SpecialOutputVisitorTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/SpecialOutputVisitorTest.cs new file mode 100644 index 0000000000..5c0328ec29 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/SpecialOutputVisitorTest.cs @@ -0,0 +1,79 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.IO; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.PrettyPrinter; + +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.PrettyPrinter +{ + [TestFixture] + public class SpecialOutputVisitorTest + { + void TestProgram(string program) + { + VBParser parser = ParserFactory.CreateParser(new StringReader(program)); + parser.Parse(); + Assert.AreEqual("", parser.Errors.ErrorOutput); + VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); + outputVisitor.Options.IndentationChar = ' '; + outputVisitor.Options.TabSize = 2; + outputVisitor.Options.IndentSize = 2; + using (SpecialNodesInserter.Install(parser.Lexer.SpecialTracker.RetrieveSpecials(), + outputVisitor)) { + outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); + } + Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); + Assert.AreEqual(program.Replace("\r", ""), outputVisitor.Text.TrimEnd().Replace("\r", "")); + parser.Dispose(); + } + + [Test] + public void Enum() + { + TestProgram("Enum Test\n" + + " ' a\n" + + " m1\n" + + " ' b\n" + + " m2\n" + + " ' c\n" + + "End Enum\n" + + "' d"); + } + + [Test] + public void CommentsInsideMethod() + { + TestProgram(@"Public Class Class1 + Private Function test(l As Integer, lvw As Integer) As Boolean + ' Begin + Dim i As Integer = 1 + Return False + ' End of method + End Function +End Class"); + } + + [Test] + public void BlankLines() + { + TestProgram("Imports System\n" + + "\n" + + "Imports System.IO"); + TestProgram("Imports System\n" + + "\n" + + "\n" + + "Imports System.IO"); + TestProgram("\n" + + "' Some comment\n" + + "\n" + + "Imports System.IO"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/VBNet/VBNetOutputTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/VBNet/VBNetOutputTest.cs new file mode 100644 index 0000000000..dc81606383 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Output/VBNet/VBNetOutputTest.cs @@ -0,0 +1,670 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.PrettyPrinter; +using ICSharpCode.NRefactory.VB.Visitors; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.PrettyPrinter +{ + [TestFixture] + public class VBNetOutputTest + { + void TestProgram(string program) + { + VBParser parser = ParserFactory.CreateParser(new StringReader(program)); + parser.Parse(); + Assert.AreEqual("", parser.Errors.ErrorOutput); + VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); + outputVisitor.Options.OutputByValModifier = true; + outputVisitor.VisitCompilationUnit(parser.CompilationUnit, null); + Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); + Assert.AreEqual(StripWhitespace(program), StripWhitespace(outputVisitor.Text)); + } + + string StripWhitespace(string text) + { + text = text.Trim().Replace("\t", "").Replace("\r", "").Replace("\n", " ").Replace(" ", " "); + while (text.Contains(" ")) { + text = text.Replace(" ", " "); + } + return text; + } + + void TestTypeMember(string program) + { + TestProgram("Class A\n" + program + "\nEnd Class"); + } + + void TestStatement(string statement) + { + TestTypeMember("Sub Method()\n" + statement + "\nEnd Sub"); + } + + void TestExpression(string expression) + { + VBParser parser = ParserFactory.CreateParser(new StringReader(expression)); + Expression e = parser.ParseExpression(); + Assert.AreEqual("", parser.Errors.ErrorOutput); + VBNetOutputVisitor outputVisitor = new VBNetOutputVisitor(); + e.AcceptVisitor(outputVisitor, null); + Assert.AreEqual("", outputVisitor.Errors.ErrorOutput); + Assert.AreEqual(StripWhitespace(expression), StripWhitespace(outputVisitor.Text)); + } + + [Test] + public void Field() + { + TestTypeMember("Private a As Integer"); + } + + [Test] + public void Method() + { + TestTypeMember("Sub Method()\nEnd Sub"); + } + + [Test] + public void EnumWithBaseType() + { + TestProgram("Public Enum Foo As UShort\nEnd Enum"); + } + + [Test] + public void PartialModifier() + { + TestProgram("Public Partial Class Foo\nEnd Class"); + } + + [Test] + public void MustInheritClass() + { + TestProgram("Public MustInherit Class Foo\nEnd Class"); + } + + [Test] + public void GenericClassDefinition() + { + TestProgram("Public Class Foo(Of T As {IDisposable, ICloneable})\nEnd Class"); + } + + [Test] + public void GenericClassDefinitionWithBaseType() + { + TestProgram("Public Class Foo(Of T As IDisposable)\nInherits BaseType\nEnd Class"); + } + + [Test] + public void GenericMethodDefinition() + { + TestTypeMember("Public Sub Foo(Of T As {IDisposable, ICloneable})(ByVal arg As T)\nEnd Sub"); + } + + [Test] + public void ArrayRank() + { + TestStatement("Dim a As Object(,,)"); + } + + [Test] + public void ArrayInitialization() + { + TestStatement("Dim a As Object() = New Object(10) {}"); + TestTypeMember("Private MultiDim As Integer(,) = {{1, 2}, {1, 3}}"); + TestExpression("New Integer(, ) {{1, 1}, {1, 1}}"); + TestTypeMember("Private _titles As String() = New String() {}"); + } + + [Test] + public void MethodCallWithOptionalArguments() + { + TestExpression("M(, )"); + } + + [Test] + public void IfStatement() + { + TestStatement("If a Then\n" + + "\tm1()\n" + + "ElseIf b Then\n" + + "\tm2()\n" + + "Else\n" + + "\tm3()\n" + + "End If"); + } + + [Test] + public void ForNextLoop() + { + TestStatement("For i = 0 To 10\n" + + "Next"); + TestStatement("For i As Long = 10 To 0 Step -1\n" + + "Next"); + } + + [Test] + public void DoLoop() + { + TestStatement("Do\n" + + "Loop"); + TestStatement("Do\n" + + "Loop While Not (i = 10)"); + } + + [Test] + public void SelectCase() + { + TestStatement(@"Select Case i + Case 0 + Case 1 To 4 + Case Else +End Select"); + } + + [Test] + public void UsingStatement() + { + TestStatement(@"Using nf As New Font(), nf2 As New List(Of Font)(), nf3 = Nothing + Bla(nf) +End Using"); + } + + [Test] + public void UntypedVariable() + { + TestStatement("Dim x = 0"); + } + + [Test] + public void UntypedField() + { + TestTypeMember("Dim x = 0"); + } + + [Test] + public void Assignment() + { + TestExpression("a = b"); + } + + [Test] + public void SpecialIdentifiers() + { + // Assembly, Ansi and Until are contextual keywords + // Custom is valid inside methods, but not valid for field names + TestExpression("Assembly = Ansi * [For] + Until - [Custom]"); + } + + [Test] + public void DictionaryAccess() + { + TestExpression("c!key"); + } + + [Test] + public void GenericMethodInvocation() + { + TestExpression("GenericMethod(Of T)(arg)"); + } + + [Test] + public void SpecialIdentifierName() + { + TestExpression("[Class]"); + } + + [Test] + public void GenericDelegate() + { + TestProgram("Public Delegate Function Predicate(Of T)(ByVal item As T) As String"); + } + + [Test] + public void Enum() + { + TestProgram("Enum MyTest\nRed\n Green\n Blue\nYellow\n End Enum"); + } + + [Test] + public void EnumWithInitializers() + { + TestProgram("Enum MyTest\nRed = 1\n Green = 2\n Blue = 4\n Yellow = 8\n End Enum"); + } + + [Test] + public void SyncLock() + { + TestStatement("SyncLock a\nWork()\nEnd SyncLock"); + } + + [Test] + public void Using() + { + TestStatement("Using a As New A()\na.Work()\nEnd Using"); + } + + [Test] + public void Cast() + { + TestExpression("CType(a, T)"); + } + + [Test] + public void DirectCast() + { + TestExpression("DirectCast(a, T)"); + } + + [Test] + public void TryCast() + { + TestExpression("TryCast(a, T)"); + } + + [Test] + public void PrimitiveCast() + { + TestExpression("CStr(a)"); + } + + [Test] + public void TypeOfIs() + { + TestExpression("TypeOf a Is String"); + } + + [Test] + public void PropertyWithAccessorAccessModifiers() + { + TestTypeMember("Public Property ExpectsValue() As Boolean\n" + + "\tPublic Get\n" + + "\tEnd Get\n" + + "\tProtected Set\n" + + "\tEnd Set\n" + + "End Property"); + } + + [Test] + public void AutoProperty() + { + TestTypeMember("Public Property Value()"); + TestTypeMember("Public Property Value() As Integer"); + TestTypeMember("Public Property Value() As Integer = 5"); + TestTypeMember("Public Property Value() As New List()"); + } + + [Test] + public void AbstractProperty() + { + TestTypeMember("Public MustOverride Property ExpectsValue() As Boolean"); + TestTypeMember("Public MustOverride ReadOnly Property ExpectsValue() As Boolean"); + TestTypeMember("Public MustOverride WriteOnly Property ExpectsValue() As Boolean"); + } + + [Test] + public void AbstractMethod() + { + TestTypeMember("Public MustOverride Sub Run()"); + TestTypeMember("Public MustOverride Function Run() As Boolean"); + } + + [Test] + public void InterfaceImplementingMethod() + { + TestTypeMember("Public Sub Run() Implements SomeInterface.Run\nEnd Sub"); + TestTypeMember("Public Function Run() As Boolean Implements SomeInterface.Bla\nEnd Function"); + } + + [Test] + public void NamedAttributeArgument() + { + TestProgram(" _\n" + + "Class Test\n" + + "End Class"); + } + + [Test] + public void ReturnTypeAttribute() + { + TestTypeMember("Function A() As String\n" + + "End Function"); + } + + [Test] + public void AssemblyAttribute() + { + TestProgram(""); + } + + [Test] + public void ModuleAttribute() + { + TestProgram(""); + } + + [Test] + public void Interface() + { + TestProgram("Interface ITest\n" + + "Property GetterAndSetter() As Boolean\n" + + "ReadOnly Property GetterOnly() As Boolean\n" + + "WriteOnly Property SetterOnly() As Boolean\n" + + "Sub InterfaceMethod()\n" + + "Function InterfaceMethod2() As String\n" + + "End Interface"); + } + + [Test] + public void OnErrorStatement() + { + TestStatement("On Error Resume Next"); + } + + [Test] + public void OverloadedConversionOperators() + { + TestTypeMember("Public Shared Narrowing Operator CType(ByVal xmlNode As XmlNode) As TheBug\nEnd Operator"); + TestTypeMember("Public Shared Widening Operator CType(ByVal bugNode As TheBug) As XmlNode\nEnd Operator"); + } + + [Test] + public void OverloadedTrueFalseOperators() + { + TestTypeMember("Public Shared Operator IsTrue(ByVal a As TheBug) As Boolean\nEnd Operator"); + TestTypeMember("Public Shared Operator IsFalse(ByVal a As TheBug) As Boolean\nEnd Operator"); + } + + [Test] + public void OverloadedOperators() + { + TestTypeMember("Public Shared Operator +(ByVal bugNode As TheBug, ByVal bugNode2 As TheBug) As TheBug\nEnd Operator"); + TestTypeMember("Public Shared Operator >>(ByVal bugNode As TheBug, ByVal b As Integer) As TheBug\nEnd Operator"); + } + + [Test] + public void AttributeOnParameter() + { + TestTypeMember("Sub Main(ByRef one As Integer, ByRef two As Integer, ByRef three As Integer)\nEnd Sub"); + } + + [Test] + public void FieldWithoutType() + { + TestTypeMember("Dim X"); + } + + [Test] + public void UsingStatementForExistingVariable() + { + TestStatement("Using obj\nEnd Using"); + } + + [Test] + public void ContinueFor() + { + TestStatement("Continue For"); + } + + [Test] + public void ForNextStatementWithFieldLoopVariable() + { + TestStatement("For Me.Field = 0 To 10\n" + + "Next Me.Field"); + } + + [Test] + public void WithStatement() + { + TestStatement("With Ejes\n" + + "\t.AddLine(New Point(Me.ClientSize.Width / 2, 0), (New Point(Me.ClientSize.Width / 2, Me.ClientSize.Height)))\n" + + "End With"); + } + + [Test] + public void NewConstraint() + { + TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), New})\nEnd Class"); + } + + [Test] + public void StructConstraint() + { + TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), Structure})\nEnd Class"); + } + + [Test] + public void ClassConstraint() + { + TestProgram("Public Class Rational(Of T, O As {IRationalMath(Of T), Class})\nEnd Class"); + } + + [Test] + public void Integer() + { + TestExpression("16"); + } + + [Test] + public void Double() + { + TestExpression("1.0"); + } + + [Test] + public void HexadecimalInteger() + { + TestExpression("&H10"); + } + + [Test] + public void HexadecimalMinusOne() + { + TestExpression("&Hffffffff"); + } + + [Test] + public void TypeCharacters() + { + TestExpression("347S"); + TestExpression("347L"); + TestExpression("347D"); + TestExpression("347F"); + TestExpression("347US"); + TestExpression("347UI"); + TestExpression("347UL"); + TestExpression("\".\"C"); + } + + [Test] + public void AddressOf() + { + TestExpression("AddressOf Abc"); + } + + [Test] + public void ChainedConstructorCall() + { + TestExpression("MyBase.New()"); + TestExpression("Me.New()"); + TestExpression("MyClass.New()"); + } + + [Test] + public void NewMethodCall() + { + TestExpression("something.[New]()"); + } + + [Test] + public void ObjectInitializer() + { + TestExpression("New StringWriter() With { _\n" + + " .NewLine = Environment.NewLine, _\n" + + " .Encoding = Encoding.UTF8 _\n" + + "}"); + } + + [Test] + public void EventDefinition() + { + TestTypeMember("Public Event MyEvent(ByVal sender As Object)"); + } + + [Test] + public void Options() + { + TestProgram("Option Strict On\n" + + "Option Explicit On\n" + + "Option Infer On\n" + + "Option Compare Text"); + } + + [Test] + public void UntypedForeach() + { + TestStatement("For Each x In myGuidArray\nNext"); + } + + [Test] + public void MethodDefinitionWithOptionalParameter() + { + TestTypeMember("Sub M(Optional ByVal msg As String = Nothing, Optional ByRef output As String = Nothing)\nEnd Sub"); + } + + [Test] + public void Module() + { + TestProgram("Module Test\n" + + " Sub M()\n" + + " End Sub\n" + + "End Module"); + } + + [Test] + public void WithEvents() + { + TestTypeMember("Dim WithEvents a As Button"); + } + + [Test] + public void FriendWithEventsField() + { + TestTypeMember("Friend WithEvents Button1 As System.Windows.Forms.Button"); + } + + [Test] + public void SimpleFunctionLambda() + { + TestExpression("Function(x) x * x"); + } + + [Test] + public void SimpleFunctionLambdaWithType() + { + TestExpression("Function(x As Integer) x * x"); + } + + [Test] + public void SimpleSubLambdaWithType() + { + TestExpression("Sub(x As Integer) Console.WriteLine(x)"); + } + + [Test] + public void BlockSubLambdaWithType() + { + TestExpression("Sub(x As Integer)\n" + + " Console.WriteLine(x)\n" + + "End Sub"); + } + + [Test] + public void BlockFunctionLambdaWithType() + { + TestExpression("Function(x As Integer) As Integer\n" + + " If x < 2 Then\n" + + " Return x\n" + + " End If\n" + + " Return x * x\n" + + "End Function"); + } + + [Test] + public void XmlSimple() + { + TestExpression("\n" + + "\n" + + "\n" + + " \n" + + " />\n" + + ""); + } + + [Test] + public void XmlNested() + { + TestExpression(@" + + Shrimp Cocktail + Escargot + + + Filet Mignon + Garlic Potatoes + Broccoli + + + Chocolate Cheesecake + + "); + } + + [Test] + public void XmlDocument() + { + TestExpression(@" + + + Shrimp Cocktail + Escargot + + "); + } + + [Test] + public void XmlNestedWithExpressions() + { + TestExpression(@" + + + <%= From m In menu _ + Where m.Course = ""appetizer"" _ + Select <%= m.Food %> %> + + + <%= From m In menu _ + Where m.Course = ""main"" _ + Select <%= m.Food %> %> + + + <%= From m In menu _ + Where m.Course = ""dessert"" _ + Select <%= m.Food %> %> + + "); + } + + [Test] + public void XmlAccessExpressions() + { + TestExpression("xml.."); + TestExpression("xml..."); + TestExpression("xml...(2)"); + TestExpression("item.@name"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/AddressOfExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/AddressOfExpressionTests.cs new file mode 100644 index 0000000000..40df05fefe --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/AddressOfExpressionTests.cs @@ -0,0 +1,45 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class AddressOfExpressionTests + { + [Test] + public void SimpleAddressOfExpressionTest() + { + AddressOfExpression ae = ParseUtil.ParseExpression("AddressOf t"); + Assert.IsNotNull(ae); + Assert.IsInstanceOf(typeof(IdentifierExpression), ae.Expression); + Assert.AreEqual("t", ((IdentifierExpression)ae.Expression).Identifier, "t"); + } + + [Test] + public void GenericAddressOfExpressionTest() + { + AddressOfExpression ae = ParseUtil.ParseExpression("AddressOf t(Of X)"); + Assert.IsNotNull(ae); + Assert.IsInstanceOf(typeof(IdentifierExpression), ae.Expression); + Assert.AreEqual("t", ((IdentifierExpression)ae.Expression).Identifier, "t"); + Assert.AreEqual(1, ((IdentifierExpression)ae.Expression).TypeArguments.Count); + Assert.AreEqual("X", ((IdentifierExpression)ae.Expression).TypeArguments[0].Type); + } + + [Test] + public void MemberReferenceAddressOfExpressionTest() + { + AddressOfExpression ae = ParseUtil.ParseExpression("AddressOf Me.t(Of X)"); + Assert.IsNotNull(ae); + Assert.IsInstanceOf(typeof(MemberReferenceExpression), ae.Expression); + Assert.AreEqual("t", ((MemberReferenceExpression)ae.Expression).MemberName, "t"); + Assert.IsInstanceOf(typeof(ThisReferenceExpression), ((MemberReferenceExpression)ae.Expression).TargetObject); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ArrayCreateExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ArrayCreateExpressionTests.cs new file mode 100644 index 0000000000..673c6f8ab3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ArrayCreateExpressionTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ArrayCreateExpressionTests + { + [Test] + public void ArrayCreateExpressionTest1() + { + ArrayCreateExpression ace = ParseUtil.ParseExpression("new Integer() {1, 2, 3, 4}"); + + Assert.AreEqual("System.Int32", ace.CreateType.Type); + Assert.AreEqual(0, ace.Arguments.Count); + Assert.AreEqual(new int[] {0}, ace.CreateType.RankSpecifier); + } + + [Test] + public void ArrayCreateExpressionTest2() + { + ArrayCreateExpression ace = ParseUtil.ParseExpression("New Integer(0 To 5){0, 1, 2, 3, 4, 5}"); + + Assert.AreEqual("System.Int32", ace.CreateType.Type); + Assert.AreEqual(1, ace.Arguments.Count); + Assert.AreEqual(5, (ace.Arguments[0] as PrimitiveExpression).Value); + Assert.AreEqual(new int[] {0}, ace.CreateType.RankSpecifier); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/AssignmentExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/AssignmentExpressionTests.cs new file mode 100644 index 0000000000..f01c4e2729 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/AssignmentExpressionTests.cs @@ -0,0 +1,73 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class AssignmentExpressionTests + { + void TestAssignmentExpression(string program, AssignmentOperatorType op) + { + ExpressionStatement se = ParseUtil.ParseStatement(program); + AssignmentExpression ae = se.Expression as AssignmentExpression; + Assert.AreEqual(op, ae.Op); + + Assert.IsTrue(ae.Left is IdentifierExpression); + Assert.IsTrue(ae.Right is IdentifierExpression); + } + + [Test] + public void AssignTest() + { + TestAssignmentExpression("a = b", AssignmentOperatorType.Assign); + } + + [Test] + public void AddTest() + { + TestAssignmentExpression("a += b", AssignmentOperatorType.Add); + } + + [Test] + public void SubtractTest() + { + TestAssignmentExpression("a -= b", AssignmentOperatorType.Subtract); + } + + [Test] + public void MultiplyTest() + { + TestAssignmentExpression("a *= b", AssignmentOperatorType.Multiply); + } + + [Test] + public void DivideTest() + { + TestAssignmentExpression("a /= b", AssignmentOperatorType.Divide); + } + + [Test] + public void ExclusiveOrTest() + { + TestAssignmentExpression("a ^= b", AssignmentOperatorType.Power); + } + + [Test] + public void StringConcatTest() + { + TestAssignmentExpression("a &= b", AssignmentOperatorType.ConcatString); + } + + [Test] + public void ModulusTest() + { + TestAssignmentExpression("a \\= b", AssignmentOperatorType.DivideInteger); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/BaseReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/BaseReferenceExpressionTests.cs new file mode 100644 index 0000000000..0747f40f6c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/BaseReferenceExpressionTests.cs @@ -0,0 +1,24 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class BaseReferenceExpressionTests + { + #region VB.NET + [Test] + public void VBNetBaseReferenceExpressionTest1() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("MyBase.myField"); + Assert.IsTrue(fre.TargetObject is BaseReferenceExpression); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/BinaryOperatorExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/BinaryOperatorExpressionTests.cs new file mode 100644 index 0000000000..256144aaeb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/BinaryOperatorExpressionTests.cs @@ -0,0 +1,268 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.PrettyPrinter; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class BinaryOperatorExpressionTests + { + void OperatorPrecedenceTest(string strongOperator, BinaryOperatorType strongOperatorType, + string weakOperator, BinaryOperatorType weakOperatorType) + { + string program = "a " + weakOperator + " b " + strongOperator + " c"; + BinaryOperatorExpression boe; + boe = ParseUtil.ParseExpression(program); + Assert.AreEqual(weakOperatorType, boe.Op); + Assert.IsTrue(boe.Left is SimpleNameExpression); + boe = (BinaryOperatorExpression)boe.Right; + Assert.AreEqual(strongOperatorType, boe.Op); + Assert.IsTrue(boe.Left is SimpleNameExpression); + Assert.IsTrue(boe.Right is SimpleNameExpression); + + program = "a " + strongOperator + " b " + weakOperator + " c"; + boe = ParseUtil.ParseExpression(program); + Assert.AreEqual(weakOperatorType, boe.Op); + Assert.IsTrue(boe.Right is SimpleNameExpression); + boe = (BinaryOperatorExpression)boe.Left; + Assert.AreEqual(strongOperatorType, boe.Op); + Assert.IsTrue(boe.Left is SimpleNameExpression); + Assert.IsTrue(boe.Right is SimpleNameExpression); + } + + void SameOperatorPrecedenceTest(string firstOperator, BinaryOperatorType firstOperatorType, + string secondOperator, BinaryOperatorType secondOperatorType) + { + string program = "a " + secondOperator + " b " + firstOperator + " c"; + BinaryOperatorExpression boe; + boe = ParseUtil.ParseExpression(program); + Assert.AreEqual(firstOperatorType, boe.Op); + Assert.IsTrue(boe.Right is SimpleNameExpression); + boe = (BinaryOperatorExpression)boe.Left; + Assert.AreEqual(secondOperatorType, boe.Op); + Assert.IsTrue(boe.Left is SimpleNameExpression); + Assert.IsTrue(boe.Right is SimpleNameExpression); + + program = "a " + firstOperator + " b " + secondOperator + " c"; + boe = ParseUtil.ParseExpression(program); + Assert.AreEqual(secondOperatorType, boe.Op); + Assert.IsTrue(boe.Right is SimpleNameExpression); + boe = (BinaryOperatorExpression)boe.Left; + Assert.AreEqual(firstOperatorType, boe.Op); + Assert.IsTrue(boe.Left is SimpleNameExpression); + Assert.IsTrue(boe.Right is SimpleNameExpression); + } + + #region VB.NET + void VBNetTestBinaryOperatorExpressionTest(string program, BinaryOperatorType op) + { + BinaryOperatorExpression boe = ParseUtil.ParseExpression(program); + Assert.AreEqual(op, boe.Op); + + Assert.IsTrue(boe.Left is SimpleNameExpression); + Assert.IsTrue(boe.Right is SimpleNameExpression); + } + + [Test] + public void VBOperatorPrecedenceTest() + { + OperatorPrecedenceTest("^", BinaryOperatorType.Power, "*", BinaryOperatorType.Multiply); + SameOperatorPrecedenceTest("*", BinaryOperatorType.Multiply, "/", BinaryOperatorType.Divide); + OperatorPrecedenceTest("/", BinaryOperatorType.Divide, "\\", BinaryOperatorType.DivideInteger); + OperatorPrecedenceTest("\\", BinaryOperatorType.DivideInteger, "Mod", BinaryOperatorType.Modulus); + OperatorPrecedenceTest("Mod", BinaryOperatorType.Modulus, "+", BinaryOperatorType.Add); + SameOperatorPrecedenceTest("+", BinaryOperatorType.Add, "-", BinaryOperatorType.Subtract); + OperatorPrecedenceTest("-", BinaryOperatorType.Subtract, "&", BinaryOperatorType.Concat); + OperatorPrecedenceTest("&", BinaryOperatorType.Concat, "<<", BinaryOperatorType.ShiftLeft); + SameOperatorPrecedenceTest("<<", BinaryOperatorType.ShiftLeft, ">>", BinaryOperatorType.ShiftRight); + OperatorPrecedenceTest("<<", BinaryOperatorType.ShiftLeft, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest("<>", BinaryOperatorType.InEquality, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest("<", BinaryOperatorType.LessThan, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest("<=", BinaryOperatorType.LessThanOrEqual, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest(">", BinaryOperatorType.GreaterThan, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest(">=", BinaryOperatorType.GreaterThanOrEqual, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest("Like", BinaryOperatorType.Like, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest("Is", BinaryOperatorType.ReferenceEquality, "=", BinaryOperatorType.Equality); + SameOperatorPrecedenceTest("IsNot", BinaryOperatorType.ReferenceInequality, "=", BinaryOperatorType.Equality); + OperatorPrecedenceTest("=", BinaryOperatorType.Equality, "And", BinaryOperatorType.BitwiseAnd); + SameOperatorPrecedenceTest("And", BinaryOperatorType.BitwiseAnd, "AndAlso", BinaryOperatorType.LogicalAnd); + OperatorPrecedenceTest("And", BinaryOperatorType.BitwiseAnd, "Or", BinaryOperatorType.BitwiseOr); + SameOperatorPrecedenceTest("Or", BinaryOperatorType.BitwiseOr, "OrElse", BinaryOperatorType.LogicalOr); + SameOperatorPrecedenceTest("Or", BinaryOperatorType.BitwiseOr, "Xor", BinaryOperatorType.ExclusiveOr); + } + + [Test] + public void VBNetPowerTest() + { + VBNetTestBinaryOperatorExpressionTest("a ^ b", BinaryOperatorType.Power); + } + + [Test] + public void VBNetConcatTest() + { + VBNetTestBinaryOperatorExpressionTest("a & b", BinaryOperatorType.Concat); + } + + [Test] + public void VBNetLogicalAndTest() + { + VBNetTestBinaryOperatorExpressionTest("a AndAlso b", BinaryOperatorType.LogicalAnd); + } + [Test] + public void VBNetLogicalAndNotLazyTest() + { + VBNetTestBinaryOperatorExpressionTest("a And b", BinaryOperatorType.BitwiseAnd); + } + + [Test] + public void VBNetLogicalOrTest() + { + VBNetTestBinaryOperatorExpressionTest("a OrElse b", BinaryOperatorType.LogicalOr); + } + [Test] + public void VBNetLogicalOrNotLazyTest() + { + VBNetTestBinaryOperatorExpressionTest("a Or b", BinaryOperatorType.BitwiseOr); + } + + [Test] + public void VBNetExclusiveOrTest() + { + VBNetTestBinaryOperatorExpressionTest("a Xor b", BinaryOperatorType.ExclusiveOr); + } + + + [Test] + public void VBNetGreaterThanTest() + { + VBNetTestBinaryOperatorExpressionTest("a > b", BinaryOperatorType.GreaterThan); + } + + [Test] + public void VBNetGreaterThanOrEqualTest() + { + VBNetTestBinaryOperatorExpressionTest("a >= b", BinaryOperatorType.GreaterThanOrEqual); + } + + [Test] + public void VBNetEqualityTest() + { + VBNetTestBinaryOperatorExpressionTest("a = b", BinaryOperatorType.Equality); + } + + [Test] + public void VBNetInEqualityTest() + { + VBNetTestBinaryOperatorExpressionTest("a <> b", BinaryOperatorType.InEquality); + } + + [Test] + public void VBNetLessThanTest() + { + VBNetTestBinaryOperatorExpressionTest("a < b", BinaryOperatorType.LessThan); + } + + [Test] + public void VBNetLessThanOrEqualTest() + { + VBNetTestBinaryOperatorExpressionTest("a <= b", BinaryOperatorType.LessThanOrEqual); + } + + [Test] + public void VBNetAddTest() + { + VBNetTestBinaryOperatorExpressionTest("a + b", BinaryOperatorType.Add); + } + + [Test] + public void VBNetSubtractTest() + { + VBNetTestBinaryOperatorExpressionTest("a - b", BinaryOperatorType.Subtract); + } + + [Test] + public void VBNetMultiplyTest() + { + VBNetTestBinaryOperatorExpressionTest("a * b", BinaryOperatorType.Multiply); + } + + [Test] + public void VBNetDivideTest() + { + VBNetTestBinaryOperatorExpressionTest("a / b", BinaryOperatorType.Divide); + } + + [Test] + public void VBNetDivideIntegerTest() + { + VBNetTestBinaryOperatorExpressionTest("a \\ b", BinaryOperatorType.DivideInteger); + } + + [Test] + public void VBNetModulusTest() + { + VBNetTestBinaryOperatorExpressionTest("a Mod b", BinaryOperatorType.Modulus); + } + + [Test] + public void VBNetShiftLeftTest() + { + VBNetTestBinaryOperatorExpressionTest("a << b", BinaryOperatorType.ShiftLeft); + } + + [Test] + public void VBNetShiftRightTest() + { + VBNetTestBinaryOperatorExpressionTest("a >> b", BinaryOperatorType.ShiftRight); + } + + [Test] + public void VBNetISTest() + { + VBNetTestBinaryOperatorExpressionTest("a is b", BinaryOperatorType.ReferenceEquality); + } + + [Test] + public void VBNetISNotTest() + { + VBNetTestBinaryOperatorExpressionTest("a IsNot b", BinaryOperatorType.ReferenceInequality); + } + + [Test] + public void VBNetLikeTest() + { + VBNetTestBinaryOperatorExpressionTest("a Like b", BinaryOperatorType.Like); + } + + [Test] + public void VBNetNullCoalescingTest() + { + VBNetTestBinaryOperatorExpressionTest("If(a, b)", BinaryOperatorType.NullCoalescing); + } + + [Test] + public void VBNetDictionaryAccess() + { + BinaryOperatorExpression boe = ParseUtil.ParseExpression("a!b"); + Assert.AreEqual(BinaryOperatorType.DictionaryAccess, boe.Op); + Assert.IsTrue(boe.Left is SimpleNameExpression); + Assert.IsTrue(boe.Right is PrimitiveExpression); + } + + [Test] + public void VBNetWithDictionaryAccess() + { + BinaryOperatorExpression boe = ParseUtil.ParseExpression("!b"); + Assert.AreEqual(BinaryOperatorType.DictionaryAccess, boe.Op); + Assert.IsTrue(boe.Left.IsNull); + Assert.IsTrue(boe.Right is PrimitiveExpression); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/CastExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/CastExpressionTests.cs new file mode 100644 index 0000000000..d93aa709d6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/CastExpressionTests.cs @@ -0,0 +1,181 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class CastExpressionTests + { + #region VB.NET + void TestSpecializedCast(string castExpression, Type castType) + { + CastExpression ce = ParseUtil.ParseExpression(castExpression); + Assert.AreEqual(castType.FullName, ce.CastTo.Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.PrimitiveConversion, ce.CastType); + } + + + [Test] + public void VBNetSimpleCastExpression() + { + CastExpression ce = ParseUtil.ParseExpression("CType(o, MyObject)"); + Assert.AreEqual("MyObject", ce.CastTo.Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.Conversion, ce.CastType); + } + + [Test] + public void VBNetGenericCastExpression() + { + CastExpression ce = ParseUtil.ParseExpression("CType(o, List(of T))"); + Assert.AreEqual("List", ce.CastTo.Type); + Assert.AreEqual("T", ce.CastTo.GenericTypes[0].Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.Conversion, ce.CastType); + } + + [Test] + public void VBNetSimpleDirectCastExpression() + { + CastExpression ce = ParseUtil.ParseExpression("DirectCast(o, MyObject)"); + Assert.AreEqual("MyObject", ce.CastTo.Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.Cast, ce.CastType); + } + + [Test] + public void VBNetGenericDirectCastExpression() + { + CastExpression ce = ParseUtil.ParseExpression("DirectCast(o, List(of T))"); + Assert.AreEqual("List", ce.CastTo.Type); + Assert.AreEqual("T", ce.CastTo.GenericTypes[0].Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.Cast, ce.CastType); + } + + [Test] + public void VBNetSimpleTryCastExpression() + { + CastExpression ce = ParseUtil.ParseExpression("TryCast(o, MyObject)"); + Assert.AreEqual("MyObject", ce.CastTo.Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.TryCast, ce.CastType); + } + + [Test] + public void VBNetGenericTryCastExpression() + { + CastExpression ce = ParseUtil.ParseExpression("TryCast(o, List(of T))"); + Assert.AreEqual("List", ce.CastTo.Type); + Assert.AreEqual("T", ce.CastTo.GenericTypes[0].Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + Assert.AreEqual(CastType.TryCast, ce.CastType); + } + + [Test] + public void VBNetSpecializedBoolCastExpression() + { + TestSpecializedCast("CBool(o)", typeof(System.Boolean)); + } + + [Test] + public void VBNetSpecializedCharCastExpression() + { + TestSpecializedCast("CChar(o)", typeof(System.Char)); + } + + + [Test] + public void VBNetSpecializedStringCastExpression() + { + TestSpecializedCast("CStr(o)", typeof(System.String)); + } + + [Test] + public void VBNetSpecializedDateTimeCastExpression() + { + TestSpecializedCast("CDate(o)", typeof(System.DateTime)); + } + + [Test] + public void VBNetSpecializedDecimalCastExpression() + { + TestSpecializedCast("CDec(o)", typeof(System.Decimal)); + } + + [Test] + public void VBNetSpecializedSingleCastExpression() + { + TestSpecializedCast("CSng(o)", typeof(System.Single)); + } + + [Test] + public void VBNetSpecializedDoubleCastExpression() + { + TestSpecializedCast("CDbl(o)", typeof(System.Double)); + } + + [Test] + public void VBNetSpecializedByteCastExpression() + { + TestSpecializedCast("CByte(o)", typeof(System.Byte)); + } + + [Test] + public void VBNetSpecializedInt16CastExpression() + { + TestSpecializedCast("CShort(o)", typeof(System.Int16)); + } + + [Test] + public void VBNetSpecializedInt32CastExpression() + { + TestSpecializedCast("CInt(o)", typeof(System.Int32)); + } + + [Test] + public void VBNetSpecializedInt64CastExpression() + { + TestSpecializedCast("CLng(o)", typeof(System.Int64)); + } + + [Test] + public void VBNetSpecializedSByteCastExpression() + { + TestSpecializedCast("CSByte(o)", typeof(System.SByte)); + } + + [Test] + public void VBNetSpecializedUInt16CastExpression() + { + TestSpecializedCast("CUShort(o)", typeof(System.UInt16)); + } + + [Test] + public void VBNetSpecializedUInt32CastExpression() + { + TestSpecializedCast("CUInt(o)", typeof(System.UInt32)); + } + + [Test] + public void VBNetSpecializedUInt64CastExpression() + { + TestSpecializedCast("CULng(o)", typeof(System.UInt64)); + } + + + [Test] + public void VBNetSpecializedObjectCastExpression() + { + TestSpecializedCast("CObj(o)", typeof(System.Object)); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ClassReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ClassReferenceExpressionTests.cs new file mode 100644 index 0000000000..b9b8929561 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ClassReferenceExpressionTests.cs @@ -0,0 +1,24 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ClassReferenceExpressionTests + { + #region VB.NET + [Test] + public void VBNetClassReferenceExpressionTest1() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("MyClass.myField"); + Assert.IsTrue(fre.TargetObject is ClassReferenceExpression); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ConditionalExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ConditionalExpressionTests.cs new file mode 100644 index 0000000000..715d716f7d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ConditionalExpressionTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ConditionalExpressionTests + { + #region VB.NET + + [Test] + public void VBNetConditionalExpressionTest() + { + ConditionalExpression ce = ParseUtil.ParseExpression("If(x IsNot Nothing, x.Test, \"nothing\")"); + + Assert.IsTrue(ce.Condition is BinaryOperatorExpression); + Assert.IsTrue(ce.TrueExpression is MemberReferenceExpression); + Assert.IsTrue(ce.FalseExpression is PrimitiveExpression); + } + + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/GlobalReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/GlobalReferenceExpressionTests.cs new file mode 100644 index 0000000000..54445299fe --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/GlobalReferenceExpressionTests.cs @@ -0,0 +1,32 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class GlobalReferenceExpressionTests + { + [Test] + public void VBNetGlobalReferenceExpressionTest() + { + TypeReferenceExpression tre = ParseUtil.ParseExpression("Global.System"); + Assert.IsTrue(tre.TypeReference.IsGlobal); + Assert.AreEqual("System", tre.TypeReference.Type); + } + + [Test] + public void VBNetGlobalTypeDeclaration() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As Global.System.String"); + TypeReference typeRef = lvd.GetTypeForVariable(0); + Assert.IsTrue(typeRef.IsGlobal); + Assert.AreEqual("System.String", typeRef.Type); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/IdentifierExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/IdentifierExpressionTests.cs new file mode 100644 index 0000000000..9c929a2e52 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/IdentifierExpressionTests.cs @@ -0,0 +1,40 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class IdentifierExpressionTests + { + #region VB.NET + [Test] + public void VBNetIdentifierExpressionTest1() + { + IdentifierExpression ie = ParseUtil.ParseExpression("MyIdentifier"); + Assert.AreEqual("MyIdentifier", ie.Identifier); + } + + [Test] + public void VBNetIdentifierExpressionTest2() + { + IdentifierExpression ie = ParseUtil.ParseExpression("[Public]"); + Assert.AreEqual("Public", ie.Identifier); + } + + [Test] + public void VBNetContextKeywordsTest() + { + Assert.AreEqual("Assembly", ParseUtil.ParseExpression("Assembly").Identifier); + Assert.AreEqual("Custom", ParseUtil.ParseExpression("Custom").Identifier); + Assert.AreEqual("Off", ParseUtil.ParseExpression("Off").Identifier); + Assert.AreEqual("Explicit", ParseUtil.ParseExpression("Explicit").Identifier); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/InvocationExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/InvocationExpressionTests.cs new file mode 100644 index 0000000000..dcc4e731c9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/InvocationExpressionTests.cs @@ -0,0 +1,116 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class InvocationExpressionTests + { + void CheckSimpleInvoke(InvocationExpression ie) + { + Assert.AreEqual(0, ie.Arguments.Count); + Assert.IsTrue(ie.TargetObject is SimpleNameExpression); + Assert.AreEqual("myMethod", ((SimpleNameExpression)ie.TargetObject).Identifier); + } + + void CheckGenericInvoke(InvocationExpression expr) + { + Assert.AreEqual(1, expr.Arguments.Count); + Assert.IsTrue(expr.TargetObject is SimpleNameExpression); + SimpleNameExpression ident = (SimpleNameExpression)expr.TargetObject; + Assert.AreEqual("myMethod", ident.Identifier); + Assert.AreEqual(1, ident.TypeArguments.Count); + Assert.AreEqual("System.Char", ident.TypeArguments[0].Type); + } + + void CheckGenericInvoke2(InvocationExpression expr) + { + Assert.AreEqual(0, expr.Arguments.Count); + Assert.IsTrue(expr.TargetObject is SimpleNameExpression); + SimpleNameExpression ident = (SimpleNameExpression)expr.TargetObject; + Assert.AreEqual("myMethod", ident.Identifier); + Assert.AreEqual(2, ident.TypeArguments.Count); + Assert.AreEqual("T", ident.TypeArguments[0].Type); + Assert.IsFalse(ident.TypeArguments[0].IsKeyword); + Assert.AreEqual("System.Boolean", ident.TypeArguments[1].Type); + Assert.IsTrue(ident.TypeArguments[1].IsKeyword); + } + + #region VB.NET + [Test] + public void VBNetSimpleInvocationExpressionTest() + { + CheckSimpleInvoke(ParseUtil.ParseExpression("myMethod()")); + } + + [Test] + public void VBNetGenericInvocationExpressionTest() + { + CheckGenericInvoke(ParseUtil.ParseExpression("myMethod(Of Char)(\"a\"c)")); + } + + [Test] + public void VBNetGenericInvocation2ExpressionTest() + { + CheckGenericInvoke2(ParseUtil.ParseExpression("myMethod(Of T, Boolean)()")); + } + + [Test] + public void PrimitiveExpression1Test() + { + InvocationExpression ie = ParseUtil.ParseExpression("546.ToString()"); + Assert.AreEqual(0, ie.Arguments.Count); + } + + [Test] + public void VBInvocationOnGenericType() + { + InvocationExpression expr = ParseUtil.ParseExpression("A(Of T).Foo()"); + MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; + Assert.AreEqual("Foo", mre.MemberName); + SimpleNameExpression tre = (SimpleNameExpression)mre.TargetObject; + Assert.AreEqual("A", tre.Identifier); + Assert.AreEqual("T", tre.TypeArguments[0].Type); + } + + [Test] + public void VBInvocationOnInnerClassInGenericType() + { + InvocationExpression expr = ParseUtil.ParseExpression("A(Of T).B.Foo()"); + MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; + Assert.AreEqual("Foo", mre.MemberName); + MemberReferenceExpression mre2 = (MemberReferenceExpression)mre.TargetObject; + Assert.AreEqual("B", mre2.MemberName); + SimpleNameExpression tre = (SimpleNameExpression)mre2.TargetObject; + Assert.AreEqual("A", tre.Identifier); + Assert.AreEqual("T", tre.TypeArguments[0].Type); + } + + [Test] + public void VBInvocationOnGenericInnerClassInGenericType() + { + InvocationExpression expr = ParseUtil.ParseExpression("A(Of T).B.C(Of U).Foo()"); + MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; + Assert.AreEqual("Foo", mre.MemberName); + + MemberReferenceExpression mre2 = (MemberReferenceExpression)mre.TargetObject; + Assert.AreEqual("C", mre2.MemberName); + Assert.AreEqual("U", mre2.TypeArguments[0].Type); + + MemberReferenceExpression mre3 = (MemberReferenceExpression)mre2.TargetObject; + Assert.AreEqual("B", mre3.MemberName); + + SimpleNameExpression tre = (SimpleNameExpression)mre3.TargetObject; + Assert.AreEqual("A", tre.Identifier); + Assert.AreEqual("T", tre.TypeArguments[0].Type); + } + + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/LambdaExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/LambdaExpressionTests.cs new file mode 100644 index 0000000000..b88297f046 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/LambdaExpressionTests.cs @@ -0,0 +1,137 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class LambdaExpressionTests + { + static LambdaExpression Parse(string program) + { + return ParseUtil.ParseExpression(program); + } + + [Test] + public void LambdaWithParameters() + { + LambdaExpression e = Parse("Function(x As Boolean) x Or True"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.AreEqual("x", e.Parameters[0].ParameterName); + Assert.AreEqual("System.Boolean", e.Parameters[0].TypeReference.Type); + Assert.IsTrue(e.ExpressionBody is BinaryOperatorExpression); + Assert.IsTrue(e.ReturnType.IsNull); + } + + [Test] + public void LambdaWithoutParameters() + { + LambdaExpression e = Parse("Function() x Or True"); + Assert.AreEqual(0, e.Parameters.Count); + Assert.IsTrue(e.ExpressionBody is BinaryOperatorExpression); + Assert.IsTrue(e.ReturnType.IsNull, "ReturnType"); + } + + [Test] + public void NestedLambda() + { + LambdaExpression e = Parse("Function(x As Boolean) Function(y As Boolean) x And y"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.IsTrue(e.ExpressionBody is LambdaExpression); + Assert.IsTrue(e.ReturnType.IsNull, "ReturnType"); + } + + [Test] + public void SubLambda() + { + LambdaExpression e = Parse("Sub(x As Integer) Console.WriteLine(x)"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.IsTrue(e.StatementBody is ExpressionStatement); + Assert.IsNotNull(e.ReturnType); + Assert.AreEqual("System.Void", e.ReturnType.Type); + Assert.IsTrue(e.ReturnType.IsKeyword); + } + + [Test] + public void SubWithStatementLambda() + { + LambdaExpression e = Parse("Sub(x As Integer) Call Console.WriteLine(x)"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.IsTrue(e.StatementBody is ExpressionStatement); + Assert.IsNotNull(e.ReturnType); + Assert.AreEqual("System.Void", e.ReturnType.Type); + Assert.IsTrue(e.ReturnType.IsKeyword); + } + + [Test] + public void MultilineSubLambda() + { + LambdaExpression e = Parse("Sub(x As Integer)\n" + + " For i As Integer = 0 To x\n" + + " Console.WriteLine(i)\n" + + " Next\n" + + "End Sub"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.IsTrue(e.StatementBody is BlockStatement); + Assert.IsNotNull(e.ReturnType); + Assert.AreEqual("System.Void", e.ReturnType.Type); + Assert.IsTrue(e.ReturnType.IsKeyword); + + BlockStatement b = e.StatementBody as BlockStatement; + + Assert.AreEqual(1, b.Children.Count); + Assert.IsTrue(b.Children[0] is ForNextStatement); + } + + [Test] + public void MultilineFunctionLambda() + { + LambdaExpression e = Parse("Function(x As Integer)\n" + + " Dim prod As Integer = 1\n" + + " For i As Integer = 1 To x\n" + + " prod = prod * i\n" + + " Next\n" + + " Return prod\n" + + "End Function"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.IsTrue(e.StatementBody is BlockStatement); + Assert.IsTrue(e.ReturnType.IsNull); + + BlockStatement b = e.StatementBody as BlockStatement; + + Assert.AreEqual(3, b.Children.Count); + Assert.IsTrue(b.Children[0] is LocalVariableDeclaration); + Assert.IsTrue(b.Children[1] is ForNextStatement); + Assert.IsTrue(b.Children[2] is ReturnStatement); + } + + [Test] + public void MultilineFunctionWithReturnTypeLambda() + { + LambdaExpression e = Parse("Function(x As Integer) As Integer\n" + + " Dim prod As Integer = 1\n" + + " For i As Integer = 1 To x\n" + + " prod = prod * i\n" + + " Next\n" + + " Return prod\n" + + "End Function"); + Assert.AreEqual(1, e.Parameters.Count); + Assert.IsTrue(e.StatementBody is BlockStatement); + Assert.IsNotNull(e.ReturnType); + Assert.AreEqual("System.Int32", e.ReturnType.Type); + Assert.IsTrue(e.ReturnType.IsKeyword); + + BlockStatement b = e.StatementBody as BlockStatement; + + Assert.AreEqual(3, b.Children.Count); + Assert.IsTrue(b.Children[0] is LocalVariableDeclaration); + Assert.IsTrue(b.Children[1] is ForNextStatement); + Assert.IsTrue(b.Children[2] is ReturnStatement); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/MemberReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/MemberReferenceExpressionTests.cs new file mode 100644 index 0000000000..94efda65b8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/MemberReferenceExpressionTests.cs @@ -0,0 +1,82 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class MemberReferenceExpressionTests + { + #region VB.NET + [Test] + public void VBNetSimpleFieldReferenceExpressionTest() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("myTargetObject.myField"); + Assert.AreEqual("myField", fre.MemberName); + Assert.IsTrue(fre.TargetObject is SimpleNameExpression); + Assert.AreEqual("myTargetObject", ((SimpleNameExpression)fre.TargetObject).Identifier); + } + + [Test] + public void VBNetFieldReferenceExpressionWithoutTargetTest() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression(".myField"); + Assert.AreEqual("myField", fre.MemberName); + Assert.IsTrue(fre.TargetObject.IsNull); + } + + [Test] + public void VBNetGenericFieldReferenceExpressionTest() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("SomeClass(of string).myField"); + Assert.AreEqual("myField", fre.MemberName); + Assert.IsInstanceOf(typeof(SimpleNameExpression), fre.TargetObject); + TypeReference tr = ((SimpleNameExpression)fre.TargetObject).TypeArguments[0]; + Assert.AreEqual("System.String", tr.Type); + } + + [Test] + public void VBNetFullNamespaceGenericFieldReferenceExpressionTest() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("System.Subnamespace.SomeClass(of string).myField"); + Assert.AreEqual("myField", fre.MemberName); + Assert.IsInstanceOf(typeof(MemberReferenceExpression), fre.TargetObject); + + MemberReferenceExpression inner = (MemberReferenceExpression)fre.TargetObject; + Assert.AreEqual("SomeClass", inner.MemberName); + Assert.AreEqual(1, inner.TypeArguments.Count); + Assert.AreEqual("System.String", inner.TypeArguments[0].Type); + } + + [Test] + public void VBNetGlobalFullNamespaceGenericFieldReferenceExpressionTest() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("Global.System.Subnamespace.SomeClass(of string).myField"); + Assert.AreEqual("myField", fre.MemberName); + Assert.IsInstanceOf(typeof(MemberReferenceExpression), fre.TargetObject); + MemberReferenceExpression inner = (MemberReferenceExpression)fre.TargetObject; + + Assert.AreEqual("SomeClass", inner.MemberName); + Assert.AreEqual(1, inner.TypeArguments.Count); + Assert.AreEqual("System.String", inner.TypeArguments[0].Type); + } + + [Test] + public void VBNetNestedGenericFieldReferenceExpressionTest() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("MyType(of string).InnerClass(of integer).myField"); + Assert.AreEqual("myField", fre.MemberName); + Assert.IsInstanceOf(typeof(MemberReferenceExpression), fre.TargetObject); + + MemberReferenceExpression inner = (MemberReferenceExpression)fre.TargetObject; + Assert.AreEqual("InnerClass", inner.MemberName); + } + + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ObjectCreateExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ObjectCreateExpressionTests.cs new file mode 100644 index 0000000000..2b6a8f886c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ObjectCreateExpressionTests.cs @@ -0,0 +1,114 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ObjectCreateExpressionTests + { + void CheckSimpleObjectCreateExpression(ObjectCreateExpression oce) + { + Assert.AreEqual("MyObject", oce.CreateType.Type); + Assert.AreEqual(3, oce.Parameters.Count); + Assert.IsTrue(oce.ObjectInitializer.IsNull); + + for (int i = 0; i < oce.Parameters.Count; ++i) { + Assert.IsTrue(oce.Parameters[i] is PrimitiveExpression); + } + } + + Expression CheckPropertyInitializationExpression(Expression e, string name) + { + Assert.IsInstanceOf(typeof(MemberInitializerExpression), e); + Assert.AreEqual(name, ((MemberInitializerExpression)e).Name); + return ((MemberInitializerExpression)e).Expression; + } + + [Test] + public void VBNetAnonymousType() + { + ObjectCreateExpression oce = ParseUtil.ParseExpression( + "New With {.Id = 1, .Name= \"Bill Gates\" }"); + + Assert.IsTrue(oce.CreateType.IsNull); + Assert.AreEqual(0, oce.Parameters.Count); + Assert.AreEqual(2, oce.ObjectInitializer.CreateExpressions.Count); + + Assert.IsInstanceOf(typeof(PrimitiveExpression), CheckPropertyInitializationExpression(oce.ObjectInitializer.CreateExpressions[0], "Id")); + Assert.IsInstanceOf(typeof(MemberInitializerExpression), oce.ObjectInitializer.CreateExpressions[1]); + } + + [Test] + public void VBNetAnonymousTypeWithoutProperty() + { + ObjectCreateExpression oce = ParseUtil.ParseExpression("New With { c }"); + + Assert.IsTrue(oce.CreateType.IsNull); + Assert.AreEqual(0, oce.Parameters.Count); + Assert.AreEqual(1, oce.ObjectInitializer.CreateExpressions.Count); + + Assert.IsInstanceOf(typeof(SimpleNameExpression), oce.ObjectInitializer.CreateExpressions[0]); + Assert.AreEqual("c", (oce.ObjectInitializer.CreateExpressions[0] as SimpleNameExpression).Identifier); + } + + [Test] + public void VBNetSimpleObjectCreateExpressionTest() + { + CheckSimpleObjectCreateExpression(ParseUtil.ParseExpression("New MyObject(1, 2, 3)")); + } + + [Test] + public void VBNetInvalidTypeArgumentListObjectCreateExpressionTest() + { + // this test was written because this bug caused the AbstractDomVisitor to crash + + InvocationExpression expr = ParseUtil.ParseExpression("WriteLine(New SomeGenericType(Of Integer, )())", true); + Assert.IsTrue(expr.TargetObject is SimpleNameExpression); + Assert.AreEqual("WriteLine", ((SimpleNameExpression)expr.TargetObject).Identifier); + Assert.AreEqual(1, expr.Arguments.Count); // here a second null parameter was added incorrectly + + Assert.IsTrue(expr.Arguments[0] is ObjectCreateExpression); + TypeReference typeRef = ((ObjectCreateExpression)expr.Arguments[0]).CreateType; + Assert.AreEqual("SomeGenericType", typeRef.Type); + Assert.AreEqual(1, typeRef.GenericTypes.Count); + Assert.AreEqual("System.Int32", typeRef.GenericTypes[0].Type); + } + + [Test] + public void VBNetMemberInitializationTest() + { + ObjectCreateExpression oce = ParseUtil.ParseExpression("new Contact() With { .FirstName = \"Bill\", .LastName = \"Gates\" }"); + Assert.AreEqual(2, oce.ObjectInitializer.CreateExpressions.Count); + + Assert.AreEqual("FirstName", ((MemberInitializerExpression)oce.ObjectInitializer.CreateExpressions[0]).Name); + Assert.AreEqual("LastName", ((MemberInitializerExpression)oce.ObjectInitializer.CreateExpressions[1]).Name); + + Assert.IsInstanceOf(typeof(PrimitiveExpression), ((MemberInitializerExpression)oce.ObjectInitializer.CreateExpressions[0]).Expression); + Assert.IsInstanceOf(typeof(PrimitiveExpression), ((MemberInitializerExpression)oce.ObjectInitializer.CreateExpressions[1]).Expression); + } + + [Test] + public void VBNetNullableObjectCreateExpressionTest() + { + ObjectCreateExpression oce = ParseUtil.ParseExpression("New Integer?"); + Assert.AreEqual("System.Nullable", oce.CreateType.Type); + Assert.AreEqual(1, oce.CreateType.GenericTypes.Count); + Assert.AreEqual("System.Int32", oce.CreateType.GenericTypes[0].Type); + } + + [Test] + public void VBNetNullableObjectArrayCreateExpressionTest() + { + ObjectCreateExpression oce = ParseUtil.ParseExpression("New Integer?()"); + Assert.AreEqual("System.Nullable", oce.CreateType.Type); + Assert.AreEqual(1, oce.CreateType.GenericTypes.Count); + Assert.AreEqual("System.Int32", oce.CreateType.GenericTypes[0].Type); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ParenthesizedExpressionTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ParenthesizedExpressionTest.cs new file mode 100644 index 0000000000..b3ed4f87a0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ParenthesizedExpressionTest.cs @@ -0,0 +1,26 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ParenthesizedExpressionTests + { + #region VB.NET + [Test] + public void VBNetPrimitiveParenthesizedExpression() + { + ParenthesizedExpression p = ParseUtil.ParseExpression("((1))"); + Assert.IsTrue(p.Expression is ParenthesizedExpression); + p = p.Expression as ParenthesizedExpression;; + Assert.IsTrue(p.Expression is PrimitiveExpression); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/PrimitiveExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/PrimitiveExpressionTests.cs new file mode 100644 index 0000000000..af197957fc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/PrimitiveExpressionTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class PrimitiveExpressionTests + { + #region VB.NET + [Test] + public void PrimitiveExpression1Test() + { + InvocationExpression ie = ParseUtil.ParseExpression("546.ToString()"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/QueryExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/QueryExpressionTests.cs new file mode 100644 index 0000000000..8d46f278eb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/QueryExpressionTests.cs @@ -0,0 +1,635 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class QueryExpressionTests + { + void RunTest(string expression, int expectedCount, Action constraint, params Type[] expectedTypes) + { + var expr = ParseUtil.ParseExpression(expression); + + Assert.AreEqual(expectedCount, expr.Clauses.Count); + + for (int i = 0; i < expectedTypes.Length; i++) { + Assert.IsTrue(expectedTypes[i] == expr.Clauses[i].GetType()); + } + + constraint(expr); + } + + [Test] + public void SimpleQueryTest() + { + RunTest("From o In db.Orders Select o.OrderID", 2, + expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var selectClause = expr.Clauses[1] as QueryExpressionSelectVBClause; + + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("o", var1.Identifier); + Assert.IsTrue(var1.Expression is MemberReferenceExpression); + var inExpr = var1.Expression as MemberReferenceExpression; + Assert.IsTrue(inExpr.MemberName == "Orders" && inExpr.TargetObject is IdentifierExpression && (inExpr.TargetObject as IdentifierExpression).Identifier == "db"); + + Assert.AreEqual(1, selectClause.Variables.Count); + Assert.IsTrue(selectClause.Variables[0].Expression is MemberReferenceExpression); + var member = selectClause.Variables[0].Expression as MemberReferenceExpression; + + Assert.IsTrue(member.MemberName == "OrderID" && member.TargetObject is IdentifierExpression && (member.TargetObject as IdentifierExpression).Identifier == "o"); + }, + typeof(QueryExpressionFromClause), typeof(QueryExpressionSelectVBClause) + ); + } + + [Test] + public void SkipTakeQueryTest() + { + RunTest("From o In db.Orders Select o.OrderID Skip 10 Take 5", 4, + expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var selectClause = expr.Clauses[1] as QueryExpressionSelectVBClause; + var skipClause = expr.Clauses[2] as QueryExpressionPartitionVBClause; + var takeClause = expr.Clauses[3] as QueryExpressionPartitionVBClause; + + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("o", var1.Identifier); + Assert.IsTrue(var1.Expression is MemberReferenceExpression); + var inExpr = var1.Expression as MemberReferenceExpression; + Assert.IsTrue(inExpr.MemberName == "Orders" && inExpr.TargetObject is IdentifierExpression && (inExpr.TargetObject as IdentifierExpression).Identifier == "db"); + + Assert.AreEqual(1, selectClause.Variables.Count); + Assert.IsTrue(selectClause.Variables[0].Expression is MemberReferenceExpression); + var member = selectClause.Variables[0].Expression as MemberReferenceExpression; + + Assert.IsTrue(member.MemberName == "OrderID" && member.TargetObject is IdentifierExpression && (member.TargetObject as IdentifierExpression).Identifier == "o"); + + Assert.AreEqual(QueryExpressionPartitionType.Skip, skipClause.PartitionType); + Assert.IsTrue(skipClause.Expression is PrimitiveExpression && + (skipClause.Expression as PrimitiveExpression).StringValue == "10"); + + Assert.AreEqual(QueryExpressionPartitionType.Take, takeClause.PartitionType); + Assert.IsTrue(takeClause.Expression is PrimitiveExpression && + (takeClause.Expression as PrimitiveExpression).StringValue == "5"); + }, + typeof(QueryExpressionFromClause), typeof(QueryExpressionSelectVBClause), + typeof(QueryExpressionPartitionVBClause), typeof(QueryExpressionPartitionVBClause) + ); + } + + [Test] + public void SkipWhileTakeWhileQueryTest() + { + RunTest("From o In db.Orders Select o.OrderID Skip While o.OrderId > 2 Take While o.OrderId < 5", 4, + expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var selectClause = expr.Clauses[1] as QueryExpressionSelectVBClause; + var skipClause = expr.Clauses[2] as QueryExpressionPartitionVBClause; + var takeClause = expr.Clauses[3] as QueryExpressionPartitionVBClause; + + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("o", var1.Identifier); + Assert.IsTrue(var1.Expression is MemberReferenceExpression); + var inExpr = var1.Expression as MemberReferenceExpression; + Assert.IsTrue(inExpr.MemberName == "Orders" && inExpr.TargetObject is IdentifierExpression && (inExpr.TargetObject as IdentifierExpression).Identifier == "db"); + + Assert.AreEqual(1, selectClause.Variables.Count); + Assert.IsTrue(selectClause.Variables[0].Expression is MemberReferenceExpression); + var member = selectClause.Variables[0].Expression as MemberReferenceExpression; + + Assert.IsTrue(member.MemberName == "OrderID" && member.TargetObject is IdentifierExpression && (member.TargetObject as IdentifierExpression).Identifier == "o"); + + Assert.AreEqual(QueryExpressionPartitionType.SkipWhile, skipClause.PartitionType); + Assert.IsTrue(skipClause.Expression is BinaryOperatorExpression); + + Assert.AreEqual(QueryExpressionPartitionType.TakeWhile, takeClause.PartitionType); + Assert.IsTrue(takeClause.Expression is BinaryOperatorExpression); + }, + typeof(QueryExpressionFromClause), typeof(QueryExpressionSelectVBClause), + typeof(QueryExpressionPartitionVBClause), typeof(QueryExpressionPartitionVBClause) + ); + } + + [Test] + public void MultipleValuesSelectTest() + { + RunTest(@"From i In list Select i, x2 = i^2", + 2, expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var selectClause = expr.Clauses[1] as QueryExpressionSelectVBClause; + + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("i", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression); + Assert.IsTrue((var1.Expression as IdentifierExpression).Identifier == "list"); + + Assert.AreEqual(2, selectClause.Variables.Count); + + var selectExpr1 = selectClause.Variables[0]; + var selectExpr2 = selectClause.Variables[1]; + + Assert.IsEmpty(selectExpr1.Identifier); + Assert.IsTrue(selectExpr1.Expression is IdentifierExpression && + (selectExpr1.Expression as IdentifierExpression).Identifier == "i"); + + Assert.AreEqual("x2", selectExpr2.Identifier); + Assert.IsTrue(selectExpr2.Type.IsNull); + Assert.IsTrue(selectExpr2.Expression is BinaryOperatorExpression); + + var binOp = selectExpr2.Expression as BinaryOperatorExpression; + + Assert.AreEqual(BinaryOperatorType.Power, binOp.Op); + Assert.IsTrue(binOp.Left is IdentifierExpression && (binOp.Left as IdentifierExpression).Identifier == "i"); + Assert.IsTrue(binOp.Right is PrimitiveExpression && (binOp.Right as PrimitiveExpression).StringValue == "2"); + }, + typeof(QueryExpressionFromClause), typeof(QueryExpressionSelectVBClause) + ); + } + + [Test] + public void GroupTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var groupClause = expr.Clauses[1] as QueryExpressionGroupVBClause; + var selectClause = expr.Clauses[2] as QueryExpressionSelectVBClause; + + Assert.AreEqual(1, fromClause.Sources.Count); + + var fromVar1 = fromClause.Sources.First(); + + Assert.AreEqual("p", fromVar1.Identifier); + Assert.IsTrue(fromVar1.Expression is IdentifierExpression); + Assert.IsTrue((fromVar1.Expression as IdentifierExpression).Identifier == "products"); + + Assert.AreEqual(1, groupClause.GroupVariables.Count); + Assert.AreEqual(1, groupClause.ByVariables.Count); + Assert.AreEqual(1, groupClause.IntoVariables.Count); + + var gv = groupClause.GroupVariables.First(); + var bv = groupClause.ByVariables.First(); + var iv = groupClause.IntoVariables.First(); + + Assert.IsTrue(gv.Expression is IdentifierExpression && (gv.Expression as IdentifierExpression).Identifier == "p"); + Assert.IsTrue(bv.Expression is MemberReferenceExpression && + (bv.Expression as MemberReferenceExpression).MemberName == "Category"); + Assert.IsTrue((bv.Expression as MemberReferenceExpression).TargetObject is IdentifierExpression && + ((bv.Expression as MemberReferenceExpression).TargetObject as IdentifierExpression).Identifier == "p"); + Assert.IsTrue(iv.Expression is IdentifierExpression && + (iv.Expression as IdentifierExpression).Identifier == "Group"); + + Assert.AreEqual(2, selectClause.Variables.Count); + + var var1 = selectClause.Variables.First(); + var var2 = selectClause.Variables.Skip(1).First(); + + Assert.IsTrue(var1.Expression is IdentifierExpression && + (var1.Expression as IdentifierExpression).Identifier == "Category"); + Assert.IsTrue(var2.Expression is InvocationExpression && + (var2.Expression as InvocationExpression).TargetObject is MemberReferenceExpression && + ((var2.Expression as InvocationExpression).TargetObject as MemberReferenceExpression).MemberName == "Average" && + ((var2.Expression as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject is IdentifierExpression && + (((var2.Expression as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject as IdentifierExpression).Identifier == "Group"); + }; + + RunTest(@"From p In products _ + Group p By p.Category Into Group _ + Select Category, AveragePrice = Group.Average(Function(p) p.UnitPrice)", 3, constraint, + typeof(QueryExpressionFromClause), typeof(QueryExpressionGroupVBClause), typeof(QueryExpressionSelectVBClause)); + } + + [Test] + public void LetTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var groupClause = expr.Clauses[1] as QueryExpressionGroupVBClause; + var letClause = expr.Clauses[2] as QueryExpressionLetClause; + var selectClause = expr.Clauses[3] as QueryExpressionSelectVBClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var fromVar1 = fromClause.Sources.First(); + + Assert.AreEqual("p", fromVar1.Identifier); + Assert.IsTrue(fromVar1.Expression is IdentifierExpression); + Assert.IsTrue((fromVar1.Expression as IdentifierExpression).Identifier == "products"); + + // Group By Into + Assert.AreEqual(1, groupClause.GroupVariables.Count); + Assert.AreEqual(1, groupClause.ByVariables.Count); + Assert.AreEqual(1, groupClause.IntoVariables.Count); + + var gv = groupClause.GroupVariables.First(); + var bv = groupClause.ByVariables.First(); + var iv = groupClause.IntoVariables.First(); + + Assert.IsTrue(gv.Expression is IdentifierExpression && (gv.Expression as IdentifierExpression).Identifier == "p"); + CheckMemberReferenceExpression(bv.Expression, "Category", "p"); + Assert.IsTrue(iv.Expression is IdentifierExpression && + (iv.Expression as IdentifierExpression).Identifier == "Group"); + + // Let + Assert.AreEqual(1, letClause.Variables.Count); + + var letVariable = letClause.Variables.First(); + + Assert.AreEqual("minPrice", letVariable.Identifier); + Assert.IsTrue(letVariable.Expression is InvocationExpression); + CheckMemberReferenceExpression((letVariable.Expression as InvocationExpression).TargetObject, "Min", "Group"); + + // Select + Assert.AreEqual(2, selectClause.Variables.Count); + + var var1 = selectClause.Variables.First(); + var var2 = selectClause.Variables.Skip(1).First(); + + Assert.IsTrue(var1.Expression is IdentifierExpression && + (var1.Expression as IdentifierExpression).Identifier == "Category"); + Assert.IsTrue(var2.Expression is InvocationExpression); + CheckMemberReferenceExpression((var2.Expression as InvocationExpression).TargetObject, "Where", "Group"); + }; + + RunTest(@"From p In products _ + Group p By p.Category Into Group _ + Let minPrice = Group.Min(Function(p) p.UnitPrice) _ + Select Category, CheapestProducts = Group.Where(Function(p) p.UnitPrice = minPrice)", 4, constraint, + typeof(QueryExpressionFromClause), typeof(QueryExpressionGroupVBClause), typeof(QueryExpressionLetClause), typeof(QueryExpressionSelectVBClause)); + } + + [Test] + public void CrossJoinTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var joinClause = expr.Clauses[1] as QueryExpressionJoinVBClause; + var selectClause = expr.Clauses[2] as QueryExpressionSelectVBClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var fromVar1 = fromClause.Sources.First(); + + Assert.AreEqual("c", fromVar1.Identifier); + Assert.IsTrue(fromVar1.Expression is IdentifierExpression); + Assert.IsTrue((fromVar1.Expression as IdentifierExpression).Identifier == "categories"); + + // Join In On Equals + var inClause = joinClause.JoinVariable as CollectionRangeVariable; + + Assert.AreEqual("p", inClause.Identifier); + Assert.IsTrue(inClause.Expression is IdentifierExpression && + (inClause.Expression as IdentifierExpression).Identifier == "products"); + + Assert.IsTrue(joinClause.SubJoin.IsNull); + + Assert.AreEqual(1, joinClause.Conditions.Count); + + var condition1 = joinClause.Conditions.First(); + + Assert.IsTrue(condition1.LeftSide is IdentifierExpression && (condition1.LeftSide as IdentifierExpression).Identifier == "c"); + + CheckMemberReferenceExpression(condition1.RightSide, "Category", "p"); + + // Select + Assert.AreEqual(2, selectClause.Variables.Count); + + var var1 = selectClause.Variables.First(); + var var2 = selectClause.Variables.Skip(1).First(); + + Assert.AreEqual("Category", var1.Identifier); + Assert.IsEmpty(var2.Identifier); + + Assert.IsTrue(var1.Expression is IdentifierExpression && + (var1.Expression as IdentifierExpression).Identifier == "c"); + CheckMemberReferenceExpression(var2.Expression, "ProductName", "p"); + }; + + RunTest(@"From c In categories _ + Join p In products On c Equals p.Category _ + Select Category = c, p.ProductName", 3, constraint, + typeof(QueryExpressionFromClause), typeof(QueryExpressionJoinVBClause), typeof(QueryExpressionSelectVBClause)); + } + + [Test] + public void OrderByTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var orderClause = expr.Clauses[1] as QueryExpressionOrderClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("i", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression); + Assert.IsTrue((var1.Expression as IdentifierExpression).Identifier == "list"); + + // Order By + Assert.AreEqual(1, orderClause.Orderings.Count); + + var ordering1 = orderClause.Orderings.First(); + + Assert.IsTrue(ordering1.Criteria is IdentifierExpression && + (ordering1.Criteria as IdentifierExpression).Identifier == "i"); + Assert.AreEqual(QueryExpressionOrderingDirection.None, ordering1.Direction); + }; + + RunTest(@"From i In list Order By i", 2, constraint, typeof(QueryExpressionFromClause), typeof(QueryExpressionOrderClause)); + } + + [Test] + public void OrderByTest2() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var orderClause = expr.Clauses[1] as QueryExpressionOrderClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("i", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression); + Assert.IsTrue((var1.Expression as IdentifierExpression).Identifier == "list"); + + // Order By + Assert.AreEqual(1, orderClause.Orderings.Count); + + var ordering1 = orderClause.Orderings.First(); + + Assert.IsTrue(ordering1.Criteria is IdentifierExpression && + (ordering1.Criteria as IdentifierExpression).Identifier == "i"); + Assert.AreEqual(QueryExpressionOrderingDirection.Ascending, ordering1.Direction); + }; + + RunTest(@"From i In list Order By i Ascending", 2, constraint, typeof(QueryExpressionFromClause), typeof(QueryExpressionOrderClause)); + } + + [Test] + public void OrderByTest3() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var orderClause = expr.Clauses[1] as QueryExpressionOrderClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("i", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression); + Assert.IsTrue((var1.Expression as IdentifierExpression).Identifier == "list"); + + // Order By + Assert.AreEqual(1, orderClause.Orderings.Count); + + var ordering1 = orderClause.Orderings.First(); + + Assert.IsTrue(ordering1.Criteria is IdentifierExpression && + (ordering1.Criteria as IdentifierExpression).Identifier == "i"); + Assert.AreEqual(QueryExpressionOrderingDirection.Descending, ordering1.Direction); + }; + + RunTest(@"From i In list Order By i Descending", 2, constraint, typeof(QueryExpressionFromClause), typeof(QueryExpressionOrderClause)); + } + + [Test] + public void OrderByThenByTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var orderClause = expr.Clauses[1] as QueryExpressionOrderClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("d", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression); + Assert.IsTrue((var1.Expression as IdentifierExpression).Identifier == "digits"); + + // Order By + Assert.AreEqual(2, orderClause.Orderings.Count); + + var ordering1 = orderClause.Orderings.First(); + var ordering2 = orderClause.Orderings.Skip(1).First(); + + CheckMemberReferenceExpression(ordering1.Criteria, "Length", "d"); + + Assert.IsTrue(ordering2.Criteria is IdentifierExpression && + (ordering2.Criteria as IdentifierExpression).Identifier == "d"); + + Assert.AreEqual(QueryExpressionOrderingDirection.None, ordering1.Direction); + Assert.AreEqual(QueryExpressionOrderingDirection.None, ordering2.Direction); + + }; + + RunTest(@"From d In digits _ + Order By d.Length, d", 2, constraint, + typeof(QueryExpressionFromClause), typeof(QueryExpressionOrderClause)); + } + + [Test] + public void DistinctTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + + // From + Assert.AreEqual(1, fromClause.Sources.Count); + + var var1 = fromClause.Sources.First(); + + Assert.AreEqual("d", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression); + Assert.IsTrue((var1.Expression as IdentifierExpression).Identifier == "digits"); + }; + + RunTest(@"From d In digits Distinct", 2, constraint, + typeof(QueryExpressionFromClause), typeof(QueryExpressionDistinctClause)); + } + + [Test] + public void AggregateTest() + { + Action constraint = expr => { + var clause = expr.Clauses[0] as QueryExpressionAggregateClause; + + Assert.AreEqual("p", clause.Source.Identifier); + CheckMemberReferenceExpression(clause.Source.Expression, "GetProcesses", "Process"); + + Assert.AreEqual(1, clause.IntoVariables.Count); + + var into1 = clause.IntoVariables.First(); + + Assert.AreEqual("virtualMemory", into1.Identifier); + + Assert.IsTrue(into1.Expression is InvocationExpression && + (into1.Expression as InvocationExpression).TargetObject is IdentifierExpression && + ((into1.Expression as InvocationExpression).TargetObject as IdentifierExpression).Identifier == "Sum"); + Assert.AreEqual(1, (into1.Expression as InvocationExpression).Arguments.Count); + CheckMemberReferenceExpression((into1.Expression as InvocationExpression).Arguments.First(), "VirtualMemorySize64", "p"); + }; + + RunTest(@"Aggregate p In Process.GetProcesses _ + Into virtualMemory = Sum(p.VirtualMemorySize64)", 1, constraint, typeof(QueryExpressionAggregateClause)); + } + + [Test] + public void GroupJoinTest() + { + Action constraint = expr => { + var fromClause1 = expr.Clauses[0] as QueryExpressionFromClause; + var groupJoinClause = expr.Clauses[1] as QueryExpressionGroupJoinVBClause; + var fromClause2 = expr.Clauses[2] as QueryExpressionFromClause; + var selectClause = expr.Clauses[3] as QueryExpressionSelectVBClause; + + // From 1 + Assert.AreEqual(1, fromClause1.Sources.Count); + + var var1 = fromClause1.Sources.First(); + + Assert.AreEqual("s", var1.Identifier); + Assert.IsTrue(var1.Expression is IdentifierExpression && + (var1.Expression as IdentifierExpression).Identifier == "fileList"); + + // From 2 + Assert.AreEqual(1, fromClause2.Sources.Count); + + var var2 = fromClause2.Sources.First(); + + Assert.AreEqual("p", var2.Identifier); + Assert.IsTrue(var2.Expression is IdentifierExpression && + (var2.Expression as IdentifierExpression).Identifier == "Group"); + + // Select + Assert.AreEqual(1, selectClause.Variables.Count); + + var var3 = selectClause.Variables.First(); + + Assert.IsEmpty(var3.Identifier); + Assert.IsTrue(var3.Expression is IdentifierExpression && + (var3.Expression as IdentifierExpression).Identifier == "s"); + + // Group Join + var joinClause = groupJoinClause.JoinClause; + + // Join In On Equals + var inClause = joinClause.JoinVariable as CollectionRangeVariable; + + Assert.AreEqual("p", inClause.Identifier); + Assert.IsTrue(inClause.Expression is IdentifierExpression && + (inClause.Expression as IdentifierExpression).Identifier == "IMAGES"); + + Assert.IsTrue(joinClause.SubJoin.IsNull); + + Assert.AreEqual(1, joinClause.Conditions.Count); + + var condition1 = joinClause.Conditions.First(); + + Assert.IsTrue(condition1.LeftSide is InvocationExpression); + Assert.IsTrue((condition1.LeftSide as InvocationExpression).TargetObject is MemberReferenceExpression); + Assert.IsTrue(((condition1.LeftSide as InvocationExpression).TargetObject as MemberReferenceExpression).MemberName == "ToUpper"); + Assert.IsTrue(((condition1.LeftSide as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject is MemberReferenceExpression); + Assert.IsTrue((((condition1.LeftSide as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject as MemberReferenceExpression).MemberName == "Extension"); + Assert.IsTrue((((condition1.LeftSide as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject as MemberReferenceExpression).TargetObject is IdentifierExpression); + Assert.IsTrue(((((condition1.LeftSide as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject as MemberReferenceExpression).TargetObject as IdentifierExpression).Identifier == "s"); + + Assert.IsTrue(condition1.RightSide is InvocationExpression); + Assert.IsTrue((condition1.RightSide as InvocationExpression).TargetObject is MemberReferenceExpression); + Assert.IsTrue(((condition1.RightSide as InvocationExpression).TargetObject as MemberReferenceExpression).MemberName == "ToUpper"); + Assert.IsTrue(((condition1.RightSide as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject is IdentifierExpression); + Assert.IsTrue((((condition1.RightSide as InvocationExpression).TargetObject as MemberReferenceExpression).TargetObject as IdentifierExpression).Identifier == "p"); + }; + + RunTest(@"From s In fileList _ +Group Join p In IMAGES On s.Extension.ToUpper() Equals p.ToUpper() Into Group _ +From p In Group _ +Select s", 4, constraint, + typeof(QueryExpressionFromClause), typeof(QueryExpressionGroupJoinVBClause), typeof(QueryExpressionFromClause), typeof(QueryExpressionSelectVBClause)); + } + + [Test] + public void SelectManyTest() + { + Action constraint = expr => { + var fromClause = expr.Clauses[0] as QueryExpressionFromClause; + var whereClause = expr.Clauses[1] as QueryExpressionWhereClause; + var selectClause = expr.Clauses[2] as QueryExpressionSelectVBClause; + + // From + Assert.AreEqual(2, fromClause.Sources.Count); + + var fromVar1 = fromClause.Sources.First(); + var fromVar2 = fromClause.Sources.Skip(1).First(); + + Assert.AreEqual("c", fromVar1.Identifier); + Assert.IsTrue(fromVar1.Expression is IdentifierExpression); + Assert.IsTrue((fromVar1.Expression as IdentifierExpression).Identifier == "customers"); + + Assert.AreEqual("o", fromVar2.Identifier); + CheckMemberReferenceExpression(fromVar2.Expression, "Orders", "c"); + + // Where + Assert.IsTrue(whereClause.Condition is BinaryOperatorExpression); + Assert.IsTrue((whereClause.Condition as BinaryOperatorExpression).Op == BinaryOperatorType.LessThan); + CheckMemberReferenceExpression((whereClause.Condition as BinaryOperatorExpression).Left, "Total", "o"); + Assert.IsTrue((whereClause.Condition as BinaryOperatorExpression).Right is PrimitiveExpression); + Assert.IsTrue((double)((whereClause.Condition as BinaryOperatorExpression).Right as PrimitiveExpression).Value == 500.0); + + // Select + foreach (var v in selectClause.Variables) { + Assert.IsEmpty(v.Identifier); + } + + var var1 = selectClause.Variables.First(); + var var2 = selectClause.Variables.Skip(1).First(); + var var3 = selectClause.Variables.Skip(2).First(); + + CheckMemberReferenceExpression(var1.Expression, "CustomerID", "c"); + CheckMemberReferenceExpression(var2.Expression, "OrderID", "o"); + CheckMemberReferenceExpression(var3.Expression, "Total", "o"); + }; + + RunTest(@"From c In customers, o In c.Orders _ + Where o.Total < 500.0 _ + Select c.CustomerID, o.OrderID, o.Total", 3, constraint, typeof(QueryExpressionFromClause), typeof(QueryExpressionWhereClause), typeof(QueryExpressionSelectVBClause)); + } + + void CheckMemberReferenceExpression(Expression expr, string memberName, string targetObjectIdentifier) + { + Assert.IsTrue(expr is MemberReferenceExpression); + Assert.IsTrue((expr as MemberReferenceExpression).MemberName == memberName && + (expr as MemberReferenceExpression).TargetObject is IdentifierExpression && + ((expr as MemberReferenceExpression).TargetObject as IdentifierExpression).Identifier == targetObjectIdentifier); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ThisReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ThisReferenceExpressionTests.cs new file mode 100644 index 0000000000..4762bbeb08 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/ThisReferenceExpressionTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ThisReferenceExpressionTests + { + #region VB.NET + [Test] + public void VBNetThisReferenceExpressionTest1() + { + ThisReferenceExpression ie = ParseUtil.ParseExpression("Me"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeOfExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeOfExpressionTests.cs new file mode 100644 index 0000000000..a86a722a87 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeOfExpressionTests.cs @@ -0,0 +1,87 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class TypeOfExpressionTests + { + #region VB.NET + [Test] + public void VBSimpleTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(MyNamespace.N1.MyType)"); + Assert.AreEqual("MyNamespace.N1.MyType", toe.TypeReference.Type); + } + + + [Test] + public void VBGlobalTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(Global.System.Console)"); + Assert.AreEqual("System.Console", toe.TypeReference.Type); + } + + [Test] + public void VBPrimitiveTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(integer)"); + Assert.AreEqual("System.Int32", toe.TypeReference.Type); + } + + [Test] + public void VBVoidTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(void)"); + Assert.AreEqual("void", toe.TypeReference.Type); + } + + [Test] + public void VBArrayTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(MyType())"); + Assert.AreEqual("MyType", toe.TypeReference.Type); + Assert.AreEqual(new int[] {0}, toe.TypeReference.RankSpecifier); + } + + [Test] + public void VBGenericTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(MyNamespace.N1.MyType(Of string))"); + Assert.AreEqual("MyNamespace.N1.MyType", toe.TypeReference.Type); + Assert.AreEqual("System.String", toe.TypeReference.GenericTypes[0].Type); + } + + [Test] + public void VBUnboundTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(MyType(Of ,))"); + Assert.AreEqual("MyType", toe.TypeReference.Type); + Assert.IsTrue(toe.TypeReference.GenericTypes[0].IsNull); + Assert.IsTrue(toe.TypeReference.GenericTypes[1].IsNull); + } + + [Test] + public void VBNestedGenericTypeOfExpressionTest() + { + TypeOfExpression toe = ParseUtil.ParseExpression("GetType(MyType(Of string).InnerClass(of integer).InnerInnerClass)"); + InnerClassTypeReference ic = (InnerClassTypeReference)toe.TypeReference; + Assert.AreEqual("InnerInnerClass", ic.Type); + Assert.AreEqual(0, ic.GenericTypes.Count); + ic = (InnerClassTypeReference)ic.BaseType; + Assert.AreEqual("InnerClass", ic.Type); + Assert.AreEqual(1, ic.GenericTypes.Count); + Assert.AreEqual("System.Int32", ic.GenericTypes[0].Type); + Assert.AreEqual("MyType", ic.BaseType.Type); + Assert.AreEqual(1, ic.BaseType.GenericTypes.Count); + Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].Type); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeOfIsExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeOfIsExpressionTests.cs new file mode 100644 index 0000000000..46f7e959e9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeOfIsExpressionTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class TypeOfIsExpressionTests + { + #region VB.NET + [Test] + public void VBNetSimpleTypeOfIsExpression() + { + TypeOfIsExpression ce = ParseUtil.ParseExpression("TypeOf o Is MyObject"); + Assert.AreEqual("MyObject", ce.TypeReference.Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + } + + [Test] + public void VBNetGenericTypeOfIsExpression() + { + TypeOfIsExpression ce = ParseUtil.ParseExpression("TypeOf o Is List(of T)"); + Assert.AreEqual("List", ce.TypeReference.Type); + Assert.AreEqual("T", ce.TypeReference.GenericTypes[0].Type); + Assert.IsTrue(ce.Expression is SimpleNameExpression); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeReferenceExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeReferenceExpressionTests.cs new file mode 100644 index 0000000000..c002b4b540 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/TypeReferenceExpressionTests.cs @@ -0,0 +1,47 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class TypeReferenceExpressionTests + { + #region VB.NET + [Test] + public void VBIntReferenceExpression() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("inTeGer.MaxValue"); + Assert.AreEqual("MaxValue", fre.MemberName); + Assert.AreEqual("System.Int32", ((TypeReferenceExpression)fre.TargetObject).TypeReference.Type); + } + + [Test] + public void VBStandaloneIntReferenceExpression() + { + TypeReferenceExpression tre = ParseUtil.ParseExpression("inTeGer"); + Assert.AreEqual("System.Int32", tre.TypeReference.Type); + } + + [Test] + public void VBObjectReferenceExpression() + { + MemberReferenceExpression fre = ParseUtil.ParseExpression("Object.ReferenceEquals"); + Assert.AreEqual("ReferenceEquals", fre.MemberName); + Assert.AreEqual("System.Object", ((TypeReferenceExpression)fre.TargetObject).TypeReference.Type); + } + + [Test] + public void VBStandaloneObjectReferenceExpression() + { + TypeReferenceExpression tre = ParseUtil.ParseExpression("obJect"); + Assert.AreEqual("System.Object", tre.TypeReference.Type); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/UnaryOperatorExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/UnaryOperatorExpressionTests.cs new file mode 100644 index 0000000000..b5100b2cdf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/UnaryOperatorExpressionTests.cs @@ -0,0 +1,61 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class UnaryOperatorExpressionTests + { + #region VB.NET + void VBNetTestUnaryOperatorExpressionTest(string program, UnaryOperatorType op) + { + UnaryOperatorExpression uoe = ParseUtil.ParseExpression(program); + Assert.AreEqual(op, uoe.Op); + + Assert.IsTrue(uoe.Expression is SimpleNameExpression); + } + + [Test] + public void VBNetNotTest() + { + VBNetTestUnaryOperatorExpressionTest("Not a", UnaryOperatorType.Not); + } + + [Test] + public void VBNetInEqualsNotTest() + { + BinaryOperatorExpression e = ParseUtil.ParseExpression("b <> Not a"); + Assert.AreEqual(BinaryOperatorType.InEquality, e.Op); + UnaryOperatorExpression ue = (UnaryOperatorExpression)e.Right; + Assert.AreEqual(UnaryOperatorType.Not, ue.Op); + } + + [Test] + public void VBNetNotEqualTest() + { + UnaryOperatorExpression e = ParseUtil.ParseExpression("Not a = b"); + Assert.AreEqual(UnaryOperatorType.Not, e.Op); + BinaryOperatorExpression boe = (BinaryOperatorExpression)e.Expression; + Assert.AreEqual(BinaryOperatorType.Equality, boe.Op); + } + + [Test] + public void VBNetPlusTest() + { + VBNetTestUnaryOperatorExpressionTest("+a", UnaryOperatorType.Plus); + } + + [Test] + public void VBNetMinusTest() + { + VBNetTestUnaryOperatorExpressionTest("-a", UnaryOperatorType.Minus); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/XmlExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/XmlExpressionTests.cs new file mode 100644 index 0000000000..e36b43b0d7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/XmlExpressionTests.cs @@ -0,0 +1,255 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class XmlExpressionTests + { + #region VB.NET + [Test] + public void VBNetSimpleCommentTest() + { + XmlContentExpression content = ParseUtil.ParseExpression(""); + Assert.AreEqual(XmlContentType.Comment, content.Type); + Assert.AreEqual(" test ", content.Content); + Assert.AreEqual(new Location(1,1), content.StartLocation); + Assert.AreEqual(new Location(14,1), content.EndLocation); + } + + [Test] + public void VBNetSimplePreprocessingInstructionTest() + { + XmlContentExpression content = ParseUtil.ParseExpression(""); + Assert.AreEqual(XmlContentType.ProcessingInstruction, content.Type); + Assert.AreEqual("xml version='1.0'", content.Content); + Assert.AreEqual(new Location(1,1), content.StartLocation); + Assert.AreEqual(new Location(22,1), content.EndLocation); + } + + [Test] + public void VBNetSimpleCDataTest() + { + XmlContentExpression content = ParseUtil.ParseExpression(" ]]>"); + Assert.AreEqual(XmlContentType.CData, content.Type); + Assert.AreEqual(" ", content.Content); + Assert.AreEqual(new Location(1,1), content.StartLocation); + Assert.AreEqual(new Location(29,1), content.EndLocation); + } + + [Test] + public void VBNetSimpleEmptyElementTest() + { + XmlElementExpression element = ParseUtil.ParseExpression(""); + Assert.IsFalse(element.NameIsExpression); + Assert.AreEqual("Test", element.XmlName); + Assert.IsEmpty(element.Attributes); + Assert.IsEmpty(element.Children); + Assert.AreEqual(new Location(1,1), element.StartLocation); + Assert.AreEqual(new Location(9,1), element.EndLocation); + } + + [Test] + public void VBNetSimpleEmptyElementWithAttributeTest() + { + XmlElementExpression element = ParseUtil.ParseExpression(""); + Assert.IsFalse(element.NameIsExpression); + Assert.AreEqual("Test", element.XmlName); + Assert.IsNotEmpty(element.Attributes); + Assert.AreEqual(1, element.Attributes.Count); + Assert.IsTrue(element.Attributes[0] is XmlAttributeExpression); + XmlAttributeExpression attribute = element.Attributes[0] as XmlAttributeExpression; + Assert.AreEqual("id", attribute.Name); + Assert.IsTrue(attribute.IsLiteralValue); + Assert.IsTrue(attribute.ExpressionValue.IsNull); + Assert.AreEqual("0", attribute.LiteralValue); + Assert.AreEqual(new Location(7,1), attribute.StartLocation); + Assert.AreEqual(new Location(13,1), attribute.EndLocation); + Assert.IsEmpty(element.Children); + Assert.AreEqual(new Location(1,1), element.StartLocation); + Assert.AreEqual(new Location(16,1), element.EndLocation); + } + + [Test] + public void VBNetSimpleEmptyElementWithAttributesTest() + { + XmlElementExpression element = ParseUtil.ParseExpression(" <%= contentData %> />"); Assert.IsFalse(element.NameIsExpression); + Assert.AreEqual("Test", element.XmlName); + Assert.IsNotEmpty(element.Attributes); + Assert.AreEqual(3, element.Attributes.Count); + + Assert.IsTrue(element.Attributes[0] is XmlAttributeExpression); + XmlAttributeExpression attribute = element.Attributes[0] as XmlAttributeExpression; + Assert.AreEqual("id", attribute.Name); + Assert.IsTrue(attribute.IsLiteralValue); + Assert.IsTrue(attribute.ExpressionValue.IsNull); + Assert.AreEqual("0", attribute.LiteralValue); + Assert.AreEqual(new Location(7,1), attribute.StartLocation); + Assert.AreEqual(new Location(13,1), attribute.EndLocation); + + Assert.IsTrue(element.Attributes[1] is XmlAttributeExpression); + XmlAttributeExpression attribute2 = element.Attributes[1] as XmlAttributeExpression; + Assert.AreEqual("name", attribute2.Name); + Assert.IsFalse(attribute2.IsLiteralValue); + Assert.IsFalse(attribute2.ExpressionValue.IsNull); + + Assert.IsTrue(attribute2.ExpressionValue is IdentifierExpression); + IdentifierExpression identifier = attribute2.ExpressionValue as IdentifierExpression; + Assert.AreEqual("name", identifier.Identifier); + Assert.AreEqual(new Location(23,1), identifier.StartLocation); + Assert.AreEqual(new Location(27,1), identifier.EndLocation); + + Assert.AreEqual(new Location(14,1), attribute2.StartLocation); + Assert.AreEqual(new Location(30,1), attribute2.EndLocation); + + Assert.IsTrue(element.Attributes[2] is XmlEmbeddedExpression); + XmlEmbeddedExpression attribute3 = element.Attributes[2] as XmlEmbeddedExpression; + + Assert.IsTrue(attribute3.InlineVBExpression is IdentifierExpression); + IdentifierExpression identifier2 = attribute3.InlineVBExpression as IdentifierExpression; + + Assert.AreEqual("contentData", identifier2.Identifier); + Assert.AreEqual(new Location(35,1), identifier2.StartLocation); + Assert.AreEqual(new Location(46,1), identifier2.EndLocation); + + Assert.AreEqual(new Location(31,1), attribute3.StartLocation); + Assert.AreEqual(new Location(49,1), attribute3.EndLocation); + + Assert.IsEmpty(element.Children); + Assert.AreEqual(new Location(1,1), element.StartLocation); + Assert.AreEqual(new Location(52,1), element.EndLocation); + } + + [Test] + public void VBNetElementWithAttributeTest() + { + XmlElementExpression element = ParseUtil.ParseExpression("\n" + + " \n" + + " \n" + + ""); + Assert.IsFalse(element.NameIsExpression); + Assert.AreEqual("Test", element.XmlName); + + Assert.IsNotEmpty(element.Attributes); + Assert.AreEqual(1, element.Attributes.Count); + Assert.IsTrue(element.Attributes[0] is XmlAttributeExpression); + XmlAttributeExpression attribute = element.Attributes[0] as XmlAttributeExpression; + Assert.AreEqual("id", attribute.Name); + Assert.IsTrue(attribute.IsLiteralValue); + Assert.IsTrue(attribute.ExpressionValue.IsNull); + Assert.AreEqual("0", attribute.LiteralValue); + Assert.AreEqual(new Location(7,1), attribute.StartLocation); + Assert.AreEqual(new Location(13,1), attribute.EndLocation); + + Assert.IsNotEmpty(element.Children); + Assert.AreEqual(5, element.Children.Count); + + CheckContent(element.Children[0], "\n\t", XmlContentType.Text, new Location(14,1), new Location(2,2)); + CheckContent(element.Children[2], "\n\t", XmlContentType.Text, new Location(10,2), new Location(2,3)); + CheckContent(element.Children[4], "\n", XmlContentType.Text, new Location(10,3), new Location(1,4)); + + CheckElement(element.Children[1], "Item", new Location(2,2), new Location(10,2)); + CheckElement(element.Children[3], "Item", new Location(2,3), new Location(10,3)); + + Assert.AreEqual(new Location(1,1), element.StartLocation); + Assert.AreEqual(new Location(8,4), element.EndLocation); + } + + [Test] + public void VBNetElementWithMixedContentTest() + { + XmlElementExpression element = ParseUtil.ParseExpression("\n" + + " \n" + + " \n" + + " \n" + + " section]]>\n" + + ""); + Assert.IsFalse(element.NameIsExpression); + Assert.AreEqual("Test", element.XmlName); + + Assert.IsNotEmpty(element.Attributes); + Assert.AreEqual(1, element.Attributes.Count); + Assert.IsTrue(element.Attributes[0] is XmlAttributeExpression); + XmlAttributeExpression attribute = element.Attributes[0] as XmlAttributeExpression; + Assert.AreEqual("id", attribute.Name); + Assert.IsTrue(attribute.IsLiteralValue); + Assert.IsTrue(attribute.ExpressionValue.IsNull); + Assert.AreEqual("0", attribute.LiteralValue); + Assert.AreEqual(new Location(7,1), attribute.StartLocation); + Assert.AreEqual(new Location(13,1), attribute.EndLocation); + + Assert.IsNotEmpty(element.Children); + Assert.AreEqual(9, element.Children.Count); + + CheckContent(element.Children[0], "\n\t", XmlContentType.Text, new Location(14,1), new Location(2,2)); + CheckContent(element.Children[2], "\n\t", XmlContentType.Text, new Location(15,2), new Location(2,3)); + CheckContent(element.Children[4], "\n\t", XmlContentType.Text, new Location(10,3), new Location(2,4)); + CheckContent(element.Children[6], "\n\t", XmlContentType.Text, new Location(10,4), new Location(2,5)); + CheckContent(element.Children[7], " section", XmlContentType.CData, new Location(2,5), new Location(29,5)); + CheckContent(element.Children[8], "\n", XmlContentType.Text, new Location(29,5), new Location(1,6)); + + CheckContent(element.Children[1], " test ", XmlContentType.Comment, new Location(2,2), new Location(15,2)); + CheckElement(element.Children[3], "Item", new Location(2,3), new Location(10,3)); + CheckElement(element.Children[5], "Item", new Location(2,4), new Location(10,4)); + + Assert.AreEqual(new Location(1,1), element.StartLocation); + Assert.AreEqual(new Location(8,6), element.EndLocation); + } + + [Test] + public void VBNetElementWithMixedContentTest2() + { + XmlElementExpression element = ParseUtil.ParseExpression(" aaaa "); + Assert.IsFalse(element.NameIsExpression); + Assert.AreEqual("Test", element.XmlName); + + Assert.IsNotEmpty(element.Children); + Assert.AreEqual(1, element.Children.Count); + + CheckContent(element.Children[0], " aaaa ", XmlContentType.Text, new Location(7,1), new Location(14,1)); + } + + [Test] + public void VBNetProcessingInstructionAndCommentAtEndTest() + { + XmlDocumentExpression document = ParseUtil.ParseExpression("\n" + + "\n" + + ""); + Assert.IsNotEmpty(document.Expressions); + Assert.AreEqual(3, document.Expressions.Count); + + CheckElement(document.Expressions[0], "Test", new Location(1,1), new Location(9,1)); + CheckContent(document.Expressions[1], " test ", XmlContentType.Comment, new Location(1,2), new Location(14,2)); + CheckContent(document.Expressions[2], "target some text", XmlContentType.ProcessingInstruction, new Location(1,3), new Location(21,3)); + } + #endregion + + void CheckElement(AstNode node, string name, AstLocation start, AstLocation end) + { + Assert.IsTrue(node is XmlElementExpression); + XmlElementExpression expr = node as XmlElementExpression; + Assert.IsEmpty(expr.Attributes); + Assert.IsEmpty(expr.Children); + Assert.IsFalse(expr.NameIsExpression); + Assert.AreEqual(name, expr.XmlName); + Assert.AreEqual(start, expr.StartLocation); + Assert.AreEqual(end, expr.EndLocation); + } + + void CheckContent(AstNode node, string content, XmlContentType type, AstLocation start, AstLocation end) + { + Assert.IsTrue(node is XmlContentExpression); + XmlContentExpression expr = node as XmlContentExpression; + Assert.AreEqual(type, expr.Type); + Assert.AreEqual(content, expr.Content); + Assert.AreEqual(start, expr.StartLocation); + Assert.AreEqual(end, expr.EndLocation); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/XmlMemberAccessExpressionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/XmlMemberAccessExpressionTests.cs new file mode 100644 index 0000000000..23f39194b3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Expressions/XmlMemberAccessExpressionTests.cs @@ -0,0 +1,101 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class XmlMemberAccessExpressionTests + { + #region VB.NET + [Test] + public void VBNetSimpleElementReferenceTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression("xml."); + Assert.AreEqual("ns:MyElement", xmae.Identifier); + Assert.IsTrue(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Element, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject is IdentifierExpression); + Assert.AreEqual("xml", ((IdentifierExpression)xmae.TargetObject).Identifier); + } + + [Test] + public void VBNetSimpleAttributeReferenceTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression("xml.@attribute"); + Assert.AreEqual("attribute", xmae.Identifier); + Assert.IsFalse(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Attribute, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject is IdentifierExpression); + Assert.AreEqual("xml", ((IdentifierExpression)xmae.TargetObject).Identifier); + } + + [Test] + public void VBNetXmlNameAttributeReferenceTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression("xml.@"); + Assert.AreEqual("ns:attribute", xmae.Identifier); + Assert.IsTrue(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Attribute, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject is IdentifierExpression); + Assert.AreEqual("xml", ((IdentifierExpression)xmae.TargetObject).Identifier); + } + + [Test] + public void VBNetSimpleDescendentsReferenceTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression("xml..."); + Assert.AreEqual("ns:Element", xmae.Identifier); + Assert.IsTrue(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Descendents, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject is IdentifierExpression); + Assert.AreEqual("xml", ((IdentifierExpression)xmae.TargetObject).Identifier); + } + + [Test] + public void VBNetSimpleElementReferenceWithDotTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression("."); + Assert.AreEqual("ns:MyElement", xmae.Identifier); + Assert.IsTrue(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Element, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject.IsNull); + } + + [Test] + public void VBNetSimpleAttributeReferenceWithDotTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression(".@attribute"); + Assert.AreEqual("attribute", xmae.Identifier); + Assert.IsFalse(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Attribute, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject.IsNull); + } + + [Test] + public void VBNetXmlNameAttributeReferenceWithDotTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression(".@"); + Assert.AreEqual("ns:attribute", xmae.Identifier); + Assert.IsTrue(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Attribute, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject.IsNull); + } + + [Test] + public void VBNetSimpleDescendentsReferenceWithDotTest() + { + XmlMemberAccessExpression xmae = ParseUtil.ParseExpression("..."); + Assert.AreEqual("ns:Element", xmae.Identifier); + Assert.IsTrue(xmae.IsXmlIdentifier); + Assert.AreEqual(XmlAxisType.Descendents, xmae.AxisType); + Assert.IsTrue(xmae.TargetObject.IsNull); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/AttributeSectionTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/AttributeSectionTests.cs new file mode 100644 index 0000000000..997e2dc111 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/AttributeSectionTests.cs @@ -0,0 +1,74 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class AttributeSectionTests + { +// [Test] +// public void AttributeOnStructure() +// { +// string program = @" +// _ +//Public Structure MyUnion +// +// Public i As Integer +// < FieldOffset( 0 )> Public d As Double +// +//End Structure 'MyUnion +//"; +// TypeDeclaration decl = ParseUtil.ParseGlobal(program); +// Assert.AreEqual("StructLayout", decl.Attributes[0].Attributes[0].Type); +// } +// +// [Test] +// public void AttributeOnModule() +// { +// string program = @" +// _ +//Public Module MyExtra +// +// Public i As Integer +// Public d As Double +// +//End Module +//"; +// TypeDeclaration decl = ParseUtil.ParseGlobal(program); +// Assert.AreEqual("HideModule", decl.Attributes[0].Attributes[0].Type); +// } +// +// [Test] +// public void GlobalAttribute() +// { +// string program = @" _ +//Public Class Form1 +// +//End Class"; +// TypeDeclaration decl = ParseUtil.ParseGlobal(program); +// Assert.AreEqual("Microsoft.VisualBasic.CompilerServices.DesignerGenerated", decl.Attributes[0].Attributes[0].Type); +// } +// +// [Test] +// public void AssemblyAttribute() +// { +// string program = @""; +// AttributeSection decl = ParseUtil.ParseGlobal(program); +// Assert.AreEqual(new Location(1, 1), decl.StartLocation); +// Assert.AreEqual("assembly", decl.AttributeTarget); +// } +// +// [Test] +// public void ModuleAttributeTargetEscaped() +// { +// // check that this doesn't crash the parser: +// ParseUtil.ParseGlobal("<[Module]: SuppressMessageAttribute>", true); +// } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs new file mode 100644 index 0000000000..56c7d8ee9f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/ImportsStatementTests.cs @@ -0,0 +1,168 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ImportsStatementTests + { + [Test] + public void InvalidImportsStatement() + { + string program = "Imports\n"; + ParseUtil.ParseGlobal(program, true); + } + + [Test] + public void InvalidImportsStatement2() + { + string program = "Imports ,\n"; + ParseUtil.ParseGlobal(program, true); + } + + [Test] + public void SimpleImportsStatement() + { + string program = "Imports System\n"; + + var clause1 = new MemberImportsClause { + Member = new SimpleType("System") + }; + + var node = new ImportsStatement(); + node.AddChild(clause1, ImportsStatement.ImportsClauseRole); + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void QualifiedTypeImportsStatement() + { + string program = "Imports My.Name.Space\n"; + + var clause2 = new MemberImportsClause { + Member = new QualifiedType(new QualifiedType(new SimpleType("My"), new Identifier ("Name", AstLocation.Empty)), new Identifier ("Space", AstLocation.Empty)) + }; + + var node = new ImportsStatement(); + node.AddChild(clause2, ImportsStatement.ImportsClauseRole); + + ParseUtil.AssertGlobal(program, node); + } +// +// [Test] +// public void VBNetUsingAliasDeclarationTest() +// { +// string program = "Imports TESTME=System\n" + +// "Imports myAlias=My.Name.Space\n" + +// "Imports StringCollection = System.Collections.Generic.List(Of string)\n"; +// VBParser parser = ParserFactory.CreateParser(new StringReader(program)); +// parser.Parse(); +// +// Assert.AreEqual("", parser.Errors.ErrorOutput); +// CheckAliases(parser.CompilationUnit); +// } +// +// [Test] +// public void VBNetComplexUsingAliasDeclarationTest() +// { +// string program = "Imports NS1, AL=NS2, NS3, AL2=NS4, NS5\n"; +// VBParser parser = ParserFactory.CreateParser(new StringReader(program)); +// parser.Parse(); +// +// Assert.AreEqual("", parser.Errors.ErrorOutput); +// // TODO : Extend test ... +// } +// +// [Test] +// public void VBNetXmlNamespaceUsingTest() +// { +// string program = "Imports "; +// VBParser parser = ParserFactory.CreateParser(new StringReader(program)); +// parser.Parse(); +// +// Assert.AreEqual("", parser.Errors.ErrorOutput); +// CompilationUnit unit = parser.CompilationUnit; +// +// Assert.AreEqual(1, unit.Children.Count); +// Assert.IsTrue(unit.Children[0] is ImportsStatement); +// ImportsStatement ud = (ImportsStatement)unit.Children[0]; +// Assert.AreEqual(1, ud.ImportsClauses.Count); +// Assert.IsFalse(ud.ImportsClauses[0].IsAlias); +// Assert.IsTrue(ud.ImportsClauses[0].IsXml); +// +// Assert.AreEqual("xmlns", ud.ImportsClauses[0].XmlPrefix); +// Assert.AreEqual("http://icsharpcode.net/sharpdevelop/avalonedit", ud.ImportsClauses[0].Name); +// } +// +// [Test] +// public void VBNetXmlNamespaceWithPrefixUsingTest() +// { +// string program = "Imports "; +// VBParser parser = ParserFactory.CreateParser(new StringReader(program)); +// parser.Parse(); +// +// Assert.AreEqual("", parser.Errors.ErrorOutput); +// CompilationUnit unit = parser.CompilationUnit; +// +// Assert.AreEqual(1, unit.Children.Count); +// Assert.IsTrue(unit.Children[0] is ImportsStatement); +// ImportsStatement ud = (ImportsStatement)unit.Children[0]; +// Assert.AreEqual(1, ud.ImportsClauses.Count); +// Assert.IsFalse(ud.ImportsClauses[0].IsAlias); +// Assert.IsTrue(ud.ImportsClauses[0].IsXml); +// +// Assert.AreEqual("xmlns:avalonedit", ud.ImportsClauses[0].XmlPrefix); +// Assert.AreEqual("http://icsharpcode.net/sharpdevelop/avalonedit", ud.ImportsClauses[0].Name); +// } +// +// [Test] +// public void VBNetXmlNamespaceSingleQuotedUsingTest() +// { +// string program = "Imports "; +// VBParser parser = ParserFactory.CreateParser(new StringReader(program)); +// parser.Parse(); +// +// Assert.AreEqual("", parser.Errors.ErrorOutput); +// CompilationUnit unit = parser.CompilationUnit; +// +// Assert.AreEqual(1, unit.Children.Count); +// Assert.IsTrue(unit.Children[0] is ImportsStatement); +// ImportsStatement ud = (ImportsStatement)unit.Children[0]; +// Assert.AreEqual(1, ud.ImportsClauses.Count); +// Assert.IsFalse(ud.ImportsClauses[0].IsAlias); +// Assert.IsTrue(ud.ImportsClauses[0].IsXml); +// +// Assert.AreEqual("xmlns", ud.ImportsClauses[0].XmlPrefix); +// Assert.AreEqual("http://icsharpcode.net/sharpdevelop/avalonedit", ud.ImportsClauses[0].Name); +// } +// +// [Test] +// public void VBNetXmlNamespaceSingleQuotedWithPrefixUsingTest() +// { +// string program = "Imports "; +// VBParser parser = ParserFactory.CreateParser(new StringReader(program)); +// parser.Parse(); +// +// Assert.AreEqual("", parser.Errors.ErrorOutput); +// CompilationUnit unit = parser.CompilationUnit; +// +// Assert.AreEqual(1, unit.Children.Count); +// Assert.IsTrue(unit.Children[0] is ImportsStatement); +// ImportsStatement ud = (ImportsStatement)unit.Children[0]; +// Assert.AreEqual(1, ud.ImportsClauses.Count); +// Assert.IsFalse(ud.ImportsClauses[0].IsAlias); +// Assert.IsTrue(ud.ImportsClauses[0].IsXml); +// +// Assert.AreEqual("xmlns:avalonedit", ud.ImportsClauses[0].XmlPrefix); +// Assert.AreEqual("http://icsharpcode.net/sharpdevelop/avalonedit", ud.ImportsClauses[0].Name); +// } +// #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/NamespaceDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/NamespaceDeclarationTests.cs new file mode 100644 index 0000000000..33f994443d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/NamespaceDeclarationTests.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class NamespaceDeclarationTests + { +// #region VB.NET +// [Test] +// public void VBNetSimpleNamespaceTest() +// { +// string program = "Namespace TestNamespace" + Environment.NewLine + +// "End Namespace" +Environment.NewLine; +// NamespaceDeclaration ns = ParseUtil.ParseGlobal(program); +// Assert.AreEqual("TestNamespace", ns.Name); +// } +// +// [Test] +// public void VBNetJuggedNamespaceTest() +// { +// string program = "Namespace N1 'TestNamespace\n" + +// " Namespace N2 ' Declares a namespace named N2 within N1.\n" + +// " End Namespace\n" + +// "End Namespace\n"; +// +// NamespaceDeclaration ns = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("N1", ns.Name); +// +// Assert.IsTrue(ns.Children[0] is NamespaceDeclaration); +// +// ns = (NamespaceDeclaration)ns.Children[0]; +// +// Assert.AreEqual("N2", ns.Name); +// } +// #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/OptionStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/OptionStatementTests.cs new file mode 100644 index 0000000000..a3b28897a6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/OptionStatementTests.cs @@ -0,0 +1,113 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class OptionStatementTests + { + [Test] + public void InvalidOptionSyntax() + { + string program = "Option\n"; + ParseUtil.ParseGlobal(program, true); + } + + [Test] + public void StrictOption() + { + string program = "Option Strict On\n"; + + var node = new OptionStatement { + OptionType = OptionType.Strict, + OptionValue = OptionValue.On + }; + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void ExplicitOption() + { + string program = "Option Explicit Off\n"; + + var node = new OptionStatement { + OptionType = OptionType.Explicit, + OptionValue = OptionValue.Off + }; + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void CompareBinaryOption() + { + string program = "Option Compare Binary\n"; + + var node = new OptionStatement { + OptionType = OptionType.Compare, + OptionValue = OptionValue.Binary + }; + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void CompareTextOption() + { + string program = "Option Compare Text\n"; + + var node = new OptionStatement { + OptionType = OptionType.Compare, + OptionValue = OptionValue.Text + }; + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void InferOnOption() + { + string program = "Option Infer On\n"; + + var node = new OptionStatement { + OptionType = OptionType.Infer, + OptionValue = OptionValue.On + }; + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void InferOffOption() + { + string program = "Option Infer Off\n"; + + var node = new OptionStatement { + OptionType = OptionType.Infer, + OptionValue = OptionValue.Off + }; + + ParseUtil.AssertGlobal(program, node); + } + + [Test] + public void InferOption() + { + string program = "Option Infer\n"; + + var node = new OptionStatement { + OptionType = OptionType.Infer, + OptionValue = OptionValue.On + }; + + ParseUtil.AssertGlobal(program, node); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/TypeDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/TypeDeclarationTests.cs new file mode 100644 index 0000000000..cc71f4c093 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/GlobalScope/TypeDeclarationTests.cs @@ -0,0 +1,203 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class TypeDeclarationTests + { +// #region VB.NET +// [Test] +// public void VBNetSimpleClassTypeDeclarationTest() +// { +// string program = "Class TestClass\n" + +// "End Class\n"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestClass", td.Name); +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual(1, td.StartLocation.Line, "start line"); +// Assert.AreEqual(1, td.BodyStartLocation.Line, "bodystart line"); +// Assert.AreEqual(16, td.BodyStartLocation.Column, "bodystart col"); +// Assert.AreEqual(2, td.EndLocation.Line, "end line"); +// Assert.AreEqual(10, td.EndLocation.Column, "end col"); +// } +// +// [Test] +// public void VBNetMissingBaseClassTest() +// { +// // SD2-1499: test that this invalid code doesn't crash +// TypeDeclaration td = ParseUtil.ParseGlobal("public class test inherits", true); +// Assert.AreEqual(0, td.BaseTypes.Count); +// } +// +// [Test] +// public void VBNetEnumWithBaseClassDeclarationTest() +// { +// string program = "Enum TestEnum As Byte\n" + +// "End Enum\n"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestEnum", td.Name); +// Assert.AreEqual(ClassType.Enum, td.Type); +// Assert.AreEqual("System.Byte", td.BaseTypes[0].Type); +// Assert.AreEqual(0, td.Children.Count); +// } +// +// [Test] +// public void VBNetEnumOnSingleLine() +// { +// string program = "Enum TestEnum : A : B = 1 : C : End Enum"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestEnum", td.Name); +// Assert.AreEqual(ClassType.Enum, td.Type); +// Assert.AreEqual(3, td.Children.Count); +// } +// +// [Test] +// public void VBNetEnumOnSingleLine2() +// { +// string program = "Enum TestEnum : A : : B = 1 :: C : End Enum"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestEnum", td.Name); +// Assert.AreEqual(ClassType.Enum, td.Type); +// Assert.AreEqual(3, td.Children.Count); +// } +// +// +// [Test] +// public void VBNetEnumWithSystemBaseClassDeclarationTest() +// { +// string program = "Enum TestEnum As System.UInt16\n" + +// "End Enum\n"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestEnum", td.Name); +// Assert.AreEqual(ClassType.Enum, td.Type); +// Assert.AreEqual("System.UInt16", td.BaseTypes[0].Type); +// Assert.AreEqual(0, td.Children.Count); +// } +// +// [Test] +// public void VBNetSimpleClassTypeDeclarationWithoutLastNewLineTest() +// { +// string program = "Class TestClass\n" + +// "End Class"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestClass", td.Name); +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual(1, td.StartLocation.Line, "start line"); +// Assert.AreEqual(2, td.EndLocation.Line, "end line"); +// } +// +// [Test] +// public void VBNetSimpleClassTypeDeclarationWithColon() +// { +// string program = "Class TestClass\n" + +// " : \n" + +// "End Class"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestClass", td.Name); +// Assert.AreEqual(ClassType.Class, td.Type); +// } +// +// [Test] +// public void VBNetSimplePartialClassTypeDeclarationTest() +// { +// string program = "Partial Class TestClass\n" + +// "End Class\n"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestClass", td.Name); +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual(Modifiers.Partial, td.Modifier); +// } +// +// [Test] +// public void VBNetPartialPublicClass() +// { +// string program = "Partial Public Class TestClass\nEnd Class\n"; +// TypeDeclaration td = ParseUtil.ParseGlobal(program); +// +// Assert.AreEqual("TestClass", td.Name); +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual(Modifiers.Partial | Modifiers.Public, td.Modifier); +// } +// +// [Test] +// public void VBNetGenericClassTypeDeclarationTest() +// { +// string declr = @" +//Public Class Test(Of T) +// +//End Class +//"; +// TypeDeclaration td = ParseUtil.ParseGlobal(declr); +// +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual("Test", td.Name); +// Assert.AreEqual(Modifiers.Public, td.Modifier); +// Assert.AreEqual(0, td.BaseTypes.Count); +// Assert.AreEqual(1, td.Templates.Count); +// Assert.AreEqual("T", td.Templates[0].Name); +// } +// +// [Test] +// public void VBNetGenericClassWithConstraint() +// { +// string declr = @" +//Public Class Test(Of T As IMyInterface) +// +//End Class +//"; +// TypeDeclaration td = ParseUtil.ParseGlobal(declr); +// +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual("Test", td.Name); +// +// Assert.AreEqual(1, td.Templates.Count); +// Assert.AreEqual("T", td.Templates[0].Name); +// Assert.AreEqual("IMyInterface", td.Templates[0].Bases[0].Type); +// } +// +// [Test] +// public void VBNetComplexGenericClassTypeDeclarationTest() +// { +// string declr = @" +//Public Class Generic(Of T As MyNamespace.IMyInterface, S As {G(Of T()), IAnotherInterface}) +// Implements System.IComparable +// +//End Class +//"; +// TypeDeclaration td = ParseUtil.ParseGlobal(declr); +// +// Assert.AreEqual(ClassType.Class, td.Type); +// Assert.AreEqual("Generic", td.Name); +// Assert.AreEqual(Modifiers.Public, td.Modifier); +// Assert.AreEqual(1, td.BaseTypes.Count); +// Assert.AreEqual("System.IComparable", td.BaseTypes[0].Type); +// +// Assert.AreEqual(2, td.Templates.Count); +// Assert.AreEqual("T", td.Templates[0].Name); +// Assert.AreEqual("MyNamespace.IMyInterface", td.Templates[0].Bases[0].Type); +// +// Assert.AreEqual("S", td.Templates[1].Name); +// Assert.AreEqual(2, td.Templates[1].Bases.Count); +// Assert.AreEqual("G", td.Templates[1].Bases[0].Type); +// Assert.AreEqual(1, td.Templates[1].Bases[0].GenericTypes.Count); +// Assert.IsTrue(td.Templates[1].Bases[0].GenericTypes[0].IsArrayType); +// Assert.AreEqual("T", td.Templates[1].Bases[0].GenericTypes[0].Type); +// Assert.AreEqual(new int[] {0}, td.Templates[1].Bases[0].GenericTypes[0].RankSpecifier); +// Assert.AreEqual("IAnotherInterface", td.Templates[1].Bases[1].Type); +// } +// #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/ParseUtil.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/ParseUtil.cs new file mode 100644 index 0000000000..5704c031e9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/ParseUtil.cs @@ -0,0 +1,108 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using System.Linq; + +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + public class ParseUtil + { + public static T ParseGlobal(string code, bool expectErrors = false) where T : AstNode + { + VBParser parser = new VBParser(); + CompilationUnit cu = parser.Parse(new StringReader(code)); + + Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); + + AstNode node = cu.Children.Single(); + Type type = typeof(T); + Assert.IsTrue(type.IsAssignableFrom(node.GetType()), String.Format("Parsed node was {0} instead of {1} ({2})", node.GetType(), type, node)); + return (T)node; + } + + public static void AssertGlobal(string code, AstNode expectedNode) + { + var node = ParseGlobal(code); + if (!expectedNode.IsMatch(node)) { + Assert.Fail("Expected '{0}' but was '{1}'", ToVB(expectedNode), ToVB(node)); + } + } + +// public static T ParseStatement(string stmt, bool expectErrors = false) where T : AstNode +// { +// VBParser parser = new VBParser(); +// var statements = parser.ParseStatements(new StringReader(stmt)); +// +// Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); +// +// AstNode statement = statements.Single(); +// Type type = typeof(T); +// Assert.IsTrue(type.IsAssignableFrom(statement.GetType()), String.Format("Parsed statement was {0} instead of {1} ({2})", statement.GetType(), type, statement)); +// return (T)statement; +// } +// +// public static void AssertStatement(string code, VB.Ast.Statement expectedStmt) +// { +// var stmt = ParseStatement(code); +// if (!expectedStmt.IsMatch(stmt)) { +// Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedStmt), ToCSharp(stmt)); +// } +// } +// +// public static T ParseExpression(string expr, bool expectErrors = false) where T : AstNode +// { +// VBParser parser = new VBParser(); +// AstNode parsedExpression = parser.ParseExpression(new StringReader(expr)); +// +// Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); +// if (expectErrors && parsedExpression == null) +// return default (T); +// Type type = typeof(T); +// Assert.IsTrue(type.IsAssignableFrom(parsedExpression.GetType()), String.Format("Parsed expression was {0} instead of {1} ({2})", parsedExpression.GetType(), type, parsedExpression)); +// return (T)parsedExpression; +// } +// +// public static void AssertExpression(string code, VB.Ast.Expression expectedExpr) +// { +// var expr = ParseExpression(code); +// if (!expectedExpr.IsMatch(expr)) { +// Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedExpr), ToCSharp(expr)); +// } +// } +// +// public static T ParseTypeMember(string expr, bool expectErrors = false) where T : AttributedNode +// { +// VBParser parser = new VBParser(); +// var members = parser.ParseTypeMembers(new StringReader(expr)); +// +// Assert.AreEqual(expectErrors, parser.HasErrors, "HasErrors"); +// +// AttributedNode m = members.Single(); +// Type type = typeof(T); +// Assert.IsTrue(type.IsAssignableFrom(m.GetType()), String.Format("Parsed member was {0} instead of {1} ({2})", m.GetType(), type, m)); +// return (T)m; +// } +// +// public static void AssertTypeMember(string code, VB.Ast.AttributedNode expectedMember) +// { +// var member = ParseTypeMember(code); +// if (!expectedMember.IsMatch(member)) { +// Assert.Fail("Expected '{0}' but was '{1}'", ToVB(expectedMember), ToVB(member)); +// } +// } + + static string ToVB(AstNode node) + { + StringWriter w = new StringWriter(); + node.AcceptVisitor(new OutputVisitor(w, new VBFormattingOptions()), null); + return w.ToString(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/SnippetParserTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/SnippetParserTests.cs new file mode 100644 index 0000000000..bf64c982bf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/SnippetParserTests.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using ICSharpCode.NRefactory.VB.Ast; +using System; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests +{ + [TestFixture] + public class SnippetParserTests + { +// [Test] +// public void InvalidExpressionSyntax() +// { +// // SD2-1584: ensure we don't crash on this invalid VB code +// SnippetParser parser = new SnippetParser(); +// INode node = parser.Parse("i == 5"); +// Assert.IsTrue(parser.Errors.Count > 0); +// } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/AddHandlerStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/AddHandlerStatementTests.cs new file mode 100644 index 0000000000..714476ef68 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/AddHandlerStatementTests.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class AddHandlerStatementTests + { + [Test] + public void AddHandlerTest() + { + AddHandlerStatement addHandlerStatement = ParseUtil.ParseStatement("AddHandler Obj.Ev_Event, AddressOf EventHandler"); + // TODO : extend tests + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/BlockStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/BlockStatementTests.cs new file mode 100644 index 0000000000..85d2dd39bb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/BlockStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class BlockStatementTests + { + // TODO create BlockStatementTests + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ContinueStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ContinueStatementTests.cs new file mode 100644 index 0000000000..630054149d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ContinueStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ContinueStatementTests + { + // TODO : add ContinueStatementTests + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/DoLoopStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/DoLoopStatementTests.cs new file mode 100644 index 0000000000..512e7f1117 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/DoLoopStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class DoLoopStatementTests + { + // TODO write some DoLoopStatement tests + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/EndStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/EndStatementTests.cs new file mode 100644 index 0000000000..9041a2763c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/EndStatementTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class EndStatementTests + { + #region VB.NET + [Test] + public void VBNetEndStatementTest() + { + EndStatement endStatement = ParseUtil.ParseStatement("End"); + } + + [Test] + public void VBNetEndStatementInIfThenTest2() + { + IfElseStatement endStatement = ParseUtil.ParseStatement("IF a THEN End"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/EraseStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/EraseStatementTests.cs new file mode 100644 index 0000000000..742c0fdc2f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/EraseStatementTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class EraseStatementTests + { + #region VB.NET + [Test] + public void VBNetEraseStatementTest() + { + EraseStatement eraseStatement = ParseUtil.ParseStatement("Erase a, b, c"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ErrorStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ErrorStatementTests.cs new file mode 100644 index 0000000000..e5ae7289f2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ErrorStatementTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ErrorStatementTests + { + #region VB.NET + [Test] + public void VBNetErrorStatementTest() + { + ErrorStatement errorStatement = ParseUtil.ParseStatement("Error a"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ExpressionStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ExpressionStatementTests.cs new file mode 100644 index 0000000000..9262294027 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ExpressionStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ExpressionStatementTests + { + // TODO : Create ExpressionStatementTests + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ForNextStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ForNextStatementTests.cs new file mode 100644 index 0000000000..68433fd303 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ForNextStatementTests.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ForNextStatementTests + { + #region VB.NET + [Test] + public void VBNetForNextStatementTest() + { + ForNextStatement forNextStatement = ParseUtil.ParseStatement("For i=0 To 10 Step 2 : Next i"); + } + + [Test] + public void VBNetForNextStatementWithComplexExpressionTest() + { + ForNextStatement forNextStatement = ParseUtil.ParseStatement("For SomeMethod().Property = 0 To 10 : Next SomeMethod().Property"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ForeachStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ForeachStatementTests.cs new file mode 100644 index 0000000000..f6e874a967 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ForeachStatementTests.cs @@ -0,0 +1,25 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ForeachStatementTests + { + #region VB.NET + [Test] + public void VBNetForeachStatementTest() + { + ForeachStatement foreachStmt = ParseUtil.ParseStatement("For Each i As Integer In myColl : Next"); + // TODO : Extend test. + } + #endregion + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/GotoStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/GotoStatementTests.cs new file mode 100644 index 0000000000..f4c2c51333 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/GotoStatementTests.cs @@ -0,0 +1,24 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class GotoStatementTests + { + #region VB.NET + [Test] + public void VBNetGotoStatementTest() + { + GotoStatement gotoStmt = ParseUtil.ParseStatement("GoTo myLabel"); + Assert.AreEqual("myLabel", gotoStmt.Label); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/IfElseStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/IfElseStatementTests.cs new file mode 100644 index 0000000000..dee85e7fdb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/IfElseStatementTests.cs @@ -0,0 +1,142 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class IfElseStatementTests + { + #region VB.NET + [Test] + public void VBNetSimpleIfStatementTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN END"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.IsTrue(ifElseStatement.TrueStatement.Count == 1, "true count != 1:" + ifElseStatement.TrueStatement.Count); + Assert.IsTrue(ifElseStatement.FalseStatement.Count == 0, "false count != 0:" + ifElseStatement.FalseStatement.Count); + + Assert.IsTrue(ifElseStatement.TrueStatement[0] is EndStatement, "Statement was: " + ifElseStatement.TrueStatement[0]); + } + [Test] + public void VBNetSimpleIfStatementTest2() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN\n END\n END IF"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.IsTrue(ifElseStatement.TrueStatement.Count == 1, "true count != 1:" + ifElseStatement.TrueStatement.Count); + Assert.IsTrue(ifElseStatement.FalseStatement.Count == 0, "false count != 0:" + ifElseStatement.FalseStatement.Count); + + Assert.IsTrue(ifElseStatement.TrueStatement[0] is BlockStatement, "Statement was: " + ifElseStatement.TrueStatement[0]); + } + + // test for SD2-1201 + [Test] + public void VBNetIfStatementLocationTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN\n" + + "DoIt()\n" + + "ElseIf False Then\n" + + "DoIt()\n" + + "End If"); + Assert.AreEqual(3, (ifElseStatement.StartLocation).Line); + Assert.AreEqual(7, (ifElseStatement.EndLocation).Line); + Assert.AreEqual(5, (ifElseStatement.ElseIfSections[0].StartLocation).Line); + Assert.AreEqual(6, (ifElseStatement.ElseIfSections[0].EndLocation).Line); + Assert.IsNotNull(ifElseStatement.ElseIfSections[0].Parent); + + } + + [Test] + public void VBNetElseIfStatementTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN\n" + + "END\n" + + "ElseIf False Then\n" + + "Stop\n" + + "End If"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.IsTrue(ifElseStatement.TrueStatement.Count == 1, "true count != 1:" + ifElseStatement.TrueStatement.Count); + Assert.IsTrue(ifElseStatement.FalseStatement.Count == 0, "false count != 0:" + ifElseStatement.FalseStatement.Count); + Assert.IsFalse((bool)(ifElseStatement.ElseIfSections[0].Condition as PrimitiveExpression).Value); + + Assert.IsTrue(ifElseStatement.TrueStatement[0] is BlockStatement, "Statement was: " + ifElseStatement.TrueStatement[0]); + Assert.IsTrue(ifElseStatement.ElseIfSections[0].EmbeddedStatement.Children[0] is StopStatement, "Statement was: " + ifElseStatement.ElseIfSections[0].EmbeddedStatement.Children[0]); + } + [Test] + public void VBNetElse_IfStatementTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN\n" + + "END\n" + + "Else If False Then\n" + + "Stop\n" + + "End If"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.IsTrue(ifElseStatement.TrueStatement.Count == 1, "true count != 1:" + ifElseStatement.TrueStatement.Count); + Assert.IsTrue(ifElseStatement.FalseStatement.Count == 0, "false count != 0:" + ifElseStatement.FalseStatement.Count); + Assert.IsFalse((bool)(ifElseStatement.ElseIfSections[0].Condition as PrimitiveExpression).Value); + + Assert.IsTrue(ifElseStatement.TrueStatement[0] is BlockStatement, "Statement was: " + ifElseStatement.TrueStatement[0]); + Assert.IsTrue(ifElseStatement.ElseIfSections[0].EmbeddedStatement.Children[0] is StopStatement, "Statement was: " + ifElseStatement.ElseIfSections[0].EmbeddedStatement.Children[0]); + } + [Test] + public void VBNetMultiStatementIfStatementTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN Stop : b"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.AreEqual(2, ifElseStatement.TrueStatement.Count, "true count"); + Assert.AreEqual(0, ifElseStatement.FalseStatement.Count, "false count"); + + Assert.IsTrue(ifElseStatement.TrueStatement[0] is StopStatement); + Assert.IsTrue(ifElseStatement.TrueStatement[1] is ExpressionStatement); + } + [Test] + public void VBNetMultiStatementIfStatementWithEndStatementTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN Stop : End : b"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.AreEqual(3, ifElseStatement.TrueStatement.Count, "true count"); + Assert.AreEqual(0, ifElseStatement.FalseStatement.Count, "false count"); + + Assert.IsTrue(ifElseStatement.TrueStatement[0] is StopStatement); + Assert.IsTrue(ifElseStatement.TrueStatement[1] is EndStatement); + Assert.IsTrue(ifElseStatement.TrueStatement[2] is ExpressionStatement); + } + + [Test] + public void VBNetIfWithEmptyElseTest() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN a Else"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.AreEqual(1, ifElseStatement.TrueStatement.Count, "true count"); + Assert.AreEqual(0, ifElseStatement.FalseStatement.Count, "false count"); + } + + [Test] + public void VBNetIfWithMultipleColons() + { + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN a : : b"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.AreEqual(2, ifElseStatement.TrueStatement.Count, "true count"); + Assert.AreEqual(0, ifElseStatement.FalseStatement.Count, "false count"); + } + + [Test] + public void VBNetIfWithSingleLineElse() + { + // This isn't legal according to the VB spec, but the MS VB compiler seems to allow it. + IfElseStatement ifElseStatement = ParseUtil.ParseStatement("If True THEN\n" + + " x()\n" + + "Else y()\n" + + "End If"); + Assert.IsFalse(ifElseStatement.Condition.IsNull); + Assert.AreEqual(1, ifElseStatement.TrueStatement.Count, "true count"); + Assert.AreEqual(1, ifElseStatement.FalseStatement.Count, "false count"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LabelStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LabelStatementTests.cs new file mode 100644 index 0000000000..8bdd6f7faf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LabelStatementTests.cs @@ -0,0 +1,26 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class LabelStatementTests + { + #region VB.NET + [Test] + public void VBNetLabelStatementTest() + { + MethodDeclaration method = ParseUtil.ParseTypeMember("Sub Test \n myLabel: Console.WriteLine() \n End Sub"); + Assert.AreEqual(2, method.Body.Children.Count); + LabelStatement labelStmt = (LabelStatement)method.Body.Children[0]; + Assert.AreEqual("myLabel", labelStmt.Label); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LocalVariableDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LocalVariableDeclarationTests.cs new file mode 100644 index 0000000000..d0b9ced62f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LocalVariableDeclarationTests.cs @@ -0,0 +1,204 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class LocalVariableDeclarationTests + { + #region VB.NET + [Test] + public void VBNetLocalVariableDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As Integer = 5"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("a", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.Int32", type.Type); + Assert.AreEqual(5, ((PrimitiveExpression)lvd.Variables[0].Initializer).Value); + } + + [Test] + public void VBNetLocalVariableNamedOverrideDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim override As Integer = 5"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("override", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.Int32", type.Type); + Assert.AreEqual(5, ((PrimitiveExpression)lvd.Variables[0].Initializer).Value); + } + + [Test] + public void VBNetLocalArrayDeclarationWithInitializationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a(10) As Integer"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("a", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.Int32", type.Type); + Assert.AreEqual(new int[] { 0 } , type.RankSpecifier); + ArrayCreateExpression ace = (ArrayCreateExpression)lvd.Variables[0].Initializer; + Assert.AreEqual(new int[] { 0 } , ace.CreateType.RankSpecifier); + Assert.AreEqual(1, ace.Arguments.Count); + Assert.AreEqual(10, ((PrimitiveExpression)ace.Arguments[0]).Value); + } + + [Test] + public void VBNetLocalArrayDeclarationWithInitializationAndLowerBoundTest() + { + // VB.NET allows only "0" as lower bound + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a(0 To 10) As Integer"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("a", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.Int32", type.Type); + Assert.AreEqual(new int[] { 0 } , type.RankSpecifier); + ArrayCreateExpression ace = (ArrayCreateExpression)lvd.Variables[0].Initializer; + Assert.AreEqual(new int[] { 0 } , ace.CreateType.RankSpecifier); + Assert.AreEqual(1, ace.Arguments.Count); + Assert.AreEqual(10, ((PrimitiveExpression)ace.Arguments[0]).Value); + } + + [Test] + public void VBNetLocalArrayDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a() As Integer"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("a", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.Int32", type.Type); + Assert.AreEqual(new int[] { 0 } , type.RankSpecifier); + } + + [Test] + public void VBNetLocalJaggedArrayDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a(10)() As Integer"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("a", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.Int32", type.Type); + Assert.AreEqual(new int[] { 0, 0 } , type.RankSpecifier); + ArrayCreateExpression ace = (ArrayCreateExpression)lvd.Variables[0].Initializer; + Assert.AreEqual(new int[] {0, 0}, ace.CreateType.RankSpecifier); + Assert.AreEqual(1, ace.Arguments.Count); + Assert.AreEqual(10, ((PrimitiveExpression)ace.Arguments[0]).Value); + } + + [Test] + public void VBNetComplexGenericLocalVariableDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim where As Generic(Of Printable, G(Of Printable()))"); + Assert.AreEqual(1, lvd.Variables.Count); + Assert.AreEqual("where", lvd.Variables[0].Name); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("Generic", type.Type); + Assert.AreEqual(2, type.GenericTypes.Count); + Assert.AreEqual("Printable", type.GenericTypes[0].Type); + Assert.AreEqual(0, type.GenericTypes[0].GenericTypes.Count); + Assert.AreEqual("G", type.GenericTypes[1].Type); + Assert.AreEqual(1, type.GenericTypes[1].GenericTypes.Count); + Assert.AreEqual("Printable", type.GenericTypes[1].GenericTypes[0].Type); + } + + [Test] + public void VBNetGenericWithArrayLocalVariableDeclarationTest1() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As G(Of Integer)()"); + Assert.AreEqual(1, lvd.Variables.Count); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("G", type.Type); + Assert.AreEqual(1, type.GenericTypes.Count); + Assert.AreEqual("System.Int32", type.GenericTypes[0].Type); + Assert.AreEqual(0, type.GenericTypes[0].GenericTypes.Count); + Assert.IsFalse(type.GenericTypes[0].IsArrayType); + Assert.AreEqual(new int[] { 0 }, type.RankSpecifier); + } + + [Test] + public void VBNetGenericWithArrayLocalVariableDeclarationTest2() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As G(Of Integer())"); + Assert.AreEqual(1, lvd.Variables.Count); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("G", type.Type); + Assert.AreEqual(1, type.GenericTypes.Count); + Assert.AreEqual("System.Int32", type.GenericTypes[0].Type); + Assert.AreEqual(0, type.GenericTypes[0].GenericTypes.Count); + Assert.IsFalse(type.IsArrayType); + Assert.AreEqual(1, type.GenericTypes[0].RankSpecifier.Length); + Assert.AreEqual(0, type.GenericTypes[0].RankSpecifier[0]); + } + + [Test] + public void VBNetGenericLocalVariableDeclarationTest2() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As G(Of G(Of Integer))"); + Assert.AreEqual(1, lvd.Variables.Count); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("G", type.Type); + Assert.AreEqual(1, type.GenericTypes.Count); + Assert.AreEqual("G", type.GenericTypes[0].Type); + Assert.AreEqual(1, type.GenericTypes[0].GenericTypes.Count); + Assert.AreEqual("System.Int32", type.GenericTypes[0].GenericTypes[0].Type); + } + + [Test] + public void VBNetGenericLocalVariableDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As G(Of Integer)"); + Assert.AreEqual(1, lvd.Variables.Count); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("G", type.Type); + Assert.AreEqual(1, type.GenericTypes.Count); + Assert.AreEqual("System.Int32", type.GenericTypes[0].Type); + } + + [Test] + public void VBNetGenericLocalVariableInitializationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a As New G(Of Integer)"); + Assert.AreEqual(1, lvd.Variables.Count); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("G", type.Type); + Assert.AreEqual(1, type.GenericTypes.Count); + Assert.AreEqual("System.Int32", type.GenericTypes[0].Type); + // TODO: Check initializer + } + + [Test] + public void VBNetNestedGenericLocalVariableDeclarationTest() + { + LocalVariableDeclaration lvd = ParseUtil.ParseStatement("Dim a as MyType(of string).InnerClass(of integer).InnerInnerClass"); + Assert.AreEqual(1, lvd.Variables.Count); + InnerClassTypeReference ic = (InnerClassTypeReference)lvd.GetTypeForVariable(0); + Assert.AreEqual("InnerInnerClass", ic.Type); + Assert.AreEqual(0, ic.GenericTypes.Count); + ic = (InnerClassTypeReference)ic.BaseType; + Assert.AreEqual("InnerClass", ic.Type); + Assert.AreEqual(1, ic.GenericTypes.Count); + Assert.AreEqual("System.Int32", ic.GenericTypes[0].Type); + Assert.AreEqual("MyType", ic.BaseType.Type); + Assert.AreEqual(1, ic.BaseType.GenericTypes.Count); + Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].Type); + } + + [Test] + public void VBNetDimInSingleLineIf() + { + IfElseStatement ifes = ParseUtil.ParseStatement("If a Then Dim b As String"); + LocalVariableDeclaration lvd = (LocalVariableDeclaration)ifes.TrueStatement[0]; + Assert.AreEqual(1, lvd.Variables.Count); + TypeReference type = lvd.GetTypeForVariable(0); + Assert.AreEqual("System.String", type.Type); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LockStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LockStatementTests.cs new file mode 100644 index 0000000000..ec3501c759 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/LockStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class LockStatementTests + { + // TODO : write some tests on SyncLock + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/OnErrorStatementTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/OnErrorStatementTest.cs new file mode 100644 index 0000000000..db4c5ab96f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/OnErrorStatementTest.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class OnErrorStatementTest + { + #region VB.NET + [Test] + public void VBNetOnErrorStatementTest() + { + OnErrorStatement onErrorStatement = ParseUtil.ParseStatement("On Error Goto err"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/RaiseEventStatementTest.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/RaiseEventStatementTest.cs new file mode 100644 index 0000000000..96bbd89e68 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/RaiseEventStatementTest.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class RaiseEventStatementTest + { + #region VB.NET + [Test] + public void VBNetRaiseEventStatementTest() + { + RaiseEventStatement raiseEventStatement = ParseUtil.ParseStatement("RaiseEvent MyEvent(a, 5, (6))"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ReDimStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ReDimStatementTests.cs new file mode 100644 index 0000000000..4a4ea8db14 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ReDimStatementTests.cs @@ -0,0 +1,77 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ReDimStatementTests + { + [Test] + public void VBNetReDimStatementTest() + { + ReDimStatement reDimStatement = ParseUtil.ParseStatement("ReDim Preserve MyArray(15)"); + Assert.AreEqual(1, reDimStatement.ReDimClauses.Count); + Assert.AreSame(reDimStatement, reDimStatement.ReDimClauses[0].Parent); + } + + [Test] + public void VBNetReDimStatementTest2() + { + ReDimStatement reDimStatement = ParseUtil.ParseStatement("ReDim calCheckData(channelNum, lambdaNum).ShiftFromLastFullCalPixels(CalCheckPeak.HighWavelength)"); + } + + [Test] + public void VBNetBigReDimStatementTest() + { + string program = @" +Class X + Sub x + ReDim sU(m - 1, n - 1) + ReDim sW(n - 1) + ReDim sV(n - 1, n - 1) + ReDim rv1(n - 1) + ReDim sMt(iNrCols - 1, 0) + ReDim Preserve sMt(iNrCols - 1, iRowNr) + ReDim sM(iRowNr - 1, iNrCols - 1) + If (IsNothing(ColLengths)) Then ReDim ColLengths(0) + If (ColLengths.Length = (SubItem + 1)) Then ReDim Preserve ColLengths(SubItem + 1) + ReDim sTransform(2, iTransformType - 1) + ReDim Preserve _Items(_Count) + ReDim Preserve _Items(nCapacity) + ReDim Preserve _Items(0 To _Count) + ReDim Preserve _Items(0 To nCapacity) + ReDim sU(m - 1, n - 1) + ReDim sW(n - 1) + ReDim sV(n - 1, n - 1) + ReDim rv1(n - 1) + ReDim sMt(iNrCols - 1, 0) + ReDim Preserve sMt(iNrCols - 1, iRowNr) + ReDim sM(iRowNr - 1, iNrCols - 1) + If (IsNothing(ColLengths)) Then ReDim ColLengths(0) + If (ColLengths.Length = (SubItem + 1)) Then ReDim Preserve ColLengths(SubItem + 1) + ReDim sTransform(2, iTransformType - 1) + ReDim Preserve Samples(Samples.GetUpperBound(0) + 1) + ReDim Samples(0) + ReDim BaseCssContent(BaseCssContentRows - 1) + ReDim mabtRxBuf(Bytes2Read - 1) + ReDim Preserve primarykey(primarykey.Length) + ReDim Preserve IntArray(10, 10, 15) + ReDim X(10, 10) + ReDim Preserve IntArray(0 To 10, 10, 0 To 20) + ReDim Preserve IntArray(10, 10, 15) + ReDim X(0 To 10, 0 To 10) + ReDim GetMe().IntArray(0 To 10, 10, 0 To 20) + ReDim GetMe(ExplicitParameter := 3).IntArray(0 To 10, 10, 0 To 20) + ReDim SomeType(Of Integer).IntArray(0 To 10, 10, 0 To 20) + End Sub +End Class"; + TypeDeclaration typeDeclaration = ParseUtil.ParseGlobal(program); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/RemoveHandlerStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/RemoveHandlerStatement.cs new file mode 100644 index 0000000000..fb01666aec --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/RemoveHandlerStatement.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class RemoveHandlerStatementTests + { + #region VB.NET + [Test] + public void VBNetRemoveHandlerTest() + { + RemoveHandlerStatement removeHandlerStatement = ParseUtil.ParseStatement("RemoveHandler MyHandler, AddressOf MyMethod"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ResumeStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ResumeStatement.cs new file mode 100644 index 0000000000..85ab30a311 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ResumeStatement.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ResumeStatementTests + { + [Test] + public void ResumeStatementTest() + { + ResumeStatement resumeStatement = ParseUtil.ParseStatement("Resume"); + } + + // TODO : write some more + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ReturnStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ReturnStatementTests.cs new file mode 100644 index 0000000000..f6403d5eba --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ReturnStatementTests.cs @@ -0,0 +1,32 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ReturnStatementTests + { + #region VB.NET + [Test] + public void VBNetEmptyReturnStatementTest() + { + ReturnStatement returnStatement = ParseUtil.ParseStatement("Return"); + Assert.IsTrue(returnStatement.Expression.IsNull); + } + + [Test] + public void VBNetReturnStatementTest() + { + ReturnStatement returnStatement = ParseUtil.ParseStatement("Return 5"); + Assert.IsFalse(returnStatement.Expression.IsNull); + Assert.IsTrue(returnStatement.Expression is PrimitiveExpression); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/StopStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/StopStatementTests.cs new file mode 100644 index 0000000000..0a0d27595d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/StopStatementTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class StopStatementTests + { + #region VB.NET + [Test] + public void VBNetStopStatementTest() + { + StopStatement stopStatement = ParseUtil.ParseStatement("Stop"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/SwitchStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/SwitchStatementTests.cs new file mode 100644 index 0000000000..39f4a47a82 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/SwitchStatementTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class SwitchStatementTests + { + #region VB.NET + [Test] + public void VBSwitchStatementTest() + { + SwitchStatement switchStmt = ParseUtil.ParseStatement("Select Case a\n Case 4, 5\n Case 6\n Case Else\n End Select"); + Assert.AreEqual("a", ((SimpleNameExpression)switchStmt.SwitchExpression).Identifier); + // TODO: Extend test + } + + [Test] + public void InvalidVBSwitchStatementTest() + { + SwitchStatement switchStmt = ParseUtil.ParseStatement("Select Case a\n Case \n End Select", true); + Assert.AreEqual("a", ((SimpleNameExpression)switchStmt.SwitchExpression).Identifier); + SwitchSection sec = switchStmt.SwitchSections[0]; + Assert.AreEqual(0, sec.SwitchLabels.Count); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ThrowStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ThrowStatementTests.cs new file mode 100644 index 0000000000..c9df1d6922 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/ThrowStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ThrowStatementTests + { + // TODO : ThrowStatementTests + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/TryCatchStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/TryCatchStatementTests.cs new file mode 100644 index 0000000000..8d4b492893 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/TryCatchStatementTests.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class TryCatchStatementTests + { + // TODO : TryCatchStatementTests + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/UsingStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/UsingStatementTests.cs new file mode 100644 index 0000000000..059eb21a06 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/UsingStatementTests.cs @@ -0,0 +1,47 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class UsingStatementTests + { + [Test] + public void UsingStatement() + { + string usingText = @" +Using nf As New System.Drawing.Font(""Arial"", 12.0F, FontStyle.Bold) + c.Font = nf + c.Text = ""This is 12-point Arial bold"" +End Using"; + UsingStatement usingStmt = ParseUtil.ParseStatement(usingText); + // TODO : Extend test. + } + [Test] + public void UsingStatement2() + { + string usingText = @" +Using nf As Font = New Font() + Bla(nf) +End Using"; + UsingStatement usingStmt = ParseUtil.ParseStatement(usingText); + // TODO : Extend test. + } + [Test] + public void UsingStatement3() + { + string usingText = @" +Using nf As New Font(), nf2 As New List(Of Font)(), nf3 = Nothing + Bla(nf) +End Using"; + UsingStatement usingStmt = ParseUtil.ParseStatement(usingText); + // TODO : Extend test. + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/WithStatementTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/WithStatementTests.cs new file mode 100644 index 0000000000..7f0ce5c446 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/Statements/WithStatementTests.cs @@ -0,0 +1,23 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class WithStatementTests + { + #region VB.NET + [Test] + public void VBNetWithStatementTest() + { + WithStatement withStatement = ParseUtil.ParseStatement("With MyObj : End With"); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/ConstructorDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/ConstructorDeclarationTests.cs new file mode 100644 index 0000000000..8c6d27a666 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/ConstructorDeclarationTests.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class ConstructorDeclarationTests + { + #region VB.NET + [Test] + public void VBNetConstructorDeclarationTest1() + { + string program = @"Sub New() + End Sub"; + ConstructorDeclaration cd = ParseUtil.ParseTypeMember(program); + Assert.IsTrue(cd.ConstructorInitializer.IsNull); + } + + [Test] + public void VBNetConstructorDeclarationTest2() + { + ConstructorDeclaration cd = ParseUtil.ParseTypeMember("Sub New(x As Integer, Optional y As String) \nEnd Sub"); + Assert.AreEqual(2, cd.Parameters.Count); + Assert.AreEqual("System.Int32", cd.Parameters[0].TypeReference.Type); + Assert.AreEqual("System.String", cd.Parameters[1].TypeReference.Type); + Assert.AreEqual(ParameterModifiers.Optional, cd.Parameters[1].ParamModifier & ParameterModifiers.Optional); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/CustomEventTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/CustomEventTests.cs new file mode 100644 index 0000000000..5634c982b0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/CustomEventTests.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using NUnit.Framework; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class CustomEventTests + { + #region VB.NET + [Test] + public void VBNetCustomEventsStatementTest() + { + string code = @" Public Custom Event TestEvent As EventHandler + AddHandler(ByVal value As EventHandler) + Handlers = CType([Delegate].Combine(Handlers, value), _ + EventHandler) + End AddHandler + + RemoveHandler(ByVal value as EventHandler) + Handlers = CType([Delegate].Remove(Handlers, value), _ + EventHandler) + End RemoveHandler + + RaiseEvent(ByVal sender As Object, ByVal e As EventArgs) + Dim TempHandlers As EventHandler = Handlers + + If TempHandlers IsNot Nothing Then + TempHandlers(sender, e) + End If + End RaiseEvent + End Event"; + EventDeclaration customEventDecl = ParseUtil.ParseTypeMember(code); + Assert.IsNotNull(customEventDecl); + Assert.AreEqual("TestEvent", customEventDecl.Name); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/DeclareDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/DeclareDeclarationTests.cs new file mode 100644 index 0000000000..3b1ae48c08 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/DeclareDeclarationTests.cs @@ -0,0 +1,28 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class DeclareDeclarationTests + { + #region VB.NET + [Test] + public void VBNetDeclareDeclarationTest() + { + string program = "Declare Ansi Function GetUserName Lib \"advapi32.dll\" Alias \"GetUserNameA\" (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer\n"; + DeclareDeclaration dd = ParseUtil.ParseTypeMember(program); + Assert.AreEqual("System.Int32", dd.TypeReference.Type); + Assert.AreEqual("GetUserName", dd.Name); + Assert.AreEqual("advapi32.dll", dd.Library); + Assert.AreEqual("GetUserNameA", dd.Alias); + Assert.AreEqual(CharsetModifier.Ansi, dd.Charset); + } + #endregion + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/EventDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/EventDeclarationTests.cs new file mode 100644 index 0000000000..f88e8e27fa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/EventDeclarationTests.cs @@ -0,0 +1,25 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class EventDeclarationTests + { + #region VB.NET + [Test] + public void VBNetSimpleEventDeclarationTest() + { + EventDeclaration ed = ParseUtil.ParseTypeMember("event MyEvent(x as Integer)"); + Assert.AreEqual(1, ed.Parameters.Count); + Assert.AreEqual("MyEvent", ed.Name); + Assert.IsFalse(ed.HasAddRegion); + Assert.IsFalse(ed.HasRemoveRegion); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/FieldDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/FieldDeclarationTests.cs new file mode 100644 index 0000000000..2aa54fdb2d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/FieldDeclarationTests.cs @@ -0,0 +1,74 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class FieldDeclarationTests + { + #region VB.NET + [Test] + public void VBNetSimpleFieldDeclarationTest() + { + FieldDeclaration fd = ParseUtil.ParseTypeMember("myField As Integer(,,,)"); + Assert.AreEqual(1, fd.Fields.Count); + + Assert.AreEqual("System.Int32", ((VariableDeclaration)fd.Fields[0]).TypeReference.Type); + Assert.AreEqual("System.Int32", ((VariableDeclaration)fd.Fields[0]).TypeReference.Type); + Assert.AreEqual("myField", ((VariableDeclaration)fd.Fields[0]).Name); + Assert.AreEqual(new int[] { 3 } , ((VariableDeclaration)fd.Fields[0]).TypeReference.RankSpecifier); + } + + [Test] + public void VBNetMultiFieldDeclarationTest() + { + FieldDeclaration fd = ParseUtil.ParseTypeMember("a, b As String"); + Assert.AreEqual(2, fd.Fields.Count); + + Assert.AreEqual("System.String", ((VariableDeclaration)fd.Fields[0]).TypeReference.Type); + Assert.IsFalse(((VariableDeclaration)fd.Fields[0]).TypeReference.IsArrayType); + Assert.AreEqual("System.String", ((VariableDeclaration)fd.Fields[1]).TypeReference.Type); + Assert.IsFalse(((VariableDeclaration)fd.Fields[1]).TypeReference.IsArrayType); + } + + [Test] + public void VBNetMultiFieldsOnSingleLineTest() + { + string program = "Class TestClass : Dim a : Dim b : End Class"; + TypeDeclaration td = ParseUtil.ParseGlobal(program); + + Assert.AreEqual(2, td.Children.Count); + Assert.IsTrue(td.Children[0] is FieldDeclaration); + Assert.IsTrue(td.Children[1] is FieldDeclaration); + } + + [Test] + public void VBNetMultiFieldDeclarationTest2() + { + FieldDeclaration fd = ParseUtil.ParseTypeMember("Dim a, b() As String"); + Assert.AreEqual(2, fd.Fields.Count); + + Assert.AreEqual("System.String", ((VariableDeclaration)fd.Fields[0]).TypeReference.Type); + Assert.AreEqual("System.String", ((VariableDeclaration)fd.Fields[1]).TypeReference.Type); + Assert.IsFalse(((VariableDeclaration)fd.Fields[0]).TypeReference.IsArrayType); + Assert.IsTrue(((VariableDeclaration)fd.Fields[1]).TypeReference.IsArrayType); + } + + [Test] + public void VBNetMultiFieldDeclarationTest3() + { + FieldDeclaration fd = ParseUtil.ParseTypeMember("Dim a(), b As String"); + Assert.AreEqual(2, fd.Fields.Count); + + Assert.AreEqual("System.String", ((VariableDeclaration)fd.Fields[0]).TypeReference.Type); + Assert.AreEqual("System.String", ((VariableDeclaration)fd.Fields[1]).TypeReference.Type); + Assert.IsTrue(((VariableDeclaration)fd.Fields[0]).TypeReference.IsArrayType); + Assert.IsFalse(((VariableDeclaration)fd.Fields[1]).TypeReference.IsArrayType); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/MethodDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/MethodDeclarationTests.cs new file mode 100644 index 0000000000..5be86af631 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/MethodDeclarationTests.cs @@ -0,0 +1,199 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class MethodDeclarationTests + { + #region VB.NET + + [Test] + public void VBNetDefiningPartialMethodDeclarationTest() + { + MethodDeclaration md = ParseUtil.ParseTypeMember(@"Partial Sub MyMethod() + End Sub"); + Assert.AreEqual(0, md.Parameters.Count); + Assert.AreEqual("MyMethod", md.Name); + Assert.IsFalse(md.IsExtensionMethod); + Assert.AreEqual(Modifiers.Partial, md.Modifier); + } + + [Test] + public void VBNetMethodWithModifiersRegionTest() + { + const string program = @"public shared sub MyMethod() + OtherMethod() + end sub"; + + MethodDeclaration md = ParseUtil.ParseTypeMember(program); + Assert.AreEqual(Modifiers.Public | Modifiers.Static, md.Modifier); + Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y"); + Assert.AreEqual(2, md.EndLocation.Line, "EndLocation.Y"); + Assert.AreEqual(2, md.StartLocation.Column, "StartLocation.X"); + } + + [Test] + public void VBNetFunctionMethodDeclarationTest() + { + const string program = @"public function MyFunction() as Integer + return 1 + end function"; + + MethodDeclaration md = ParseUtil.ParseTypeMember(program); + Assert.AreEqual(Modifiers.Public, md.Modifier); + Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y"); + Assert.AreEqual(2, md.StartLocation.Column, "StartLocation.X"); + Assert.AreEqual(2, md.EndLocation.Line, "EndLocation.Y"); + } + + [Test] + public void VBNetSubroutineMethodDeclarationTest() + { + const string program = @"public Sub MyMethod() + OtherMethod() + end Sub"; + + MethodDeclaration md = ParseUtil.ParseTypeMember(program); + Assert.AreEqual(Modifiers.Public, md.Modifier); + Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y"); + Assert.AreEqual(2, md.StartLocation.Column, "StartLocation.X"); + Assert.AreEqual(2, md.EndLocation.Line, "EndLocation.Y"); + } + + [Test] + public void VBNetGenericFunctionMethodDeclarationTest() + { + MethodDeclaration md = ParseUtil.ParseTypeMember("function MyMethod(Of T)(a As T) As Double\nEnd Function"); + Assert.AreEqual("System.Double", md.TypeReference.Type); + Assert.AreEqual(1, md.Parameters.Count); + Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); + Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); + + Assert.AreEqual(1, md.Templates.Count); + Assert.AreEqual("T", md.Templates[0].Name); + } + + [Test] + public void VBNetGenericMethodDeclarationTest() + { + MethodDeclaration md = ParseUtil.ParseTypeMember("Function MyMethod(Of T)(a As T) As T\nEnd Function "); + Assert.AreEqual("T", md.TypeReference.Type); + Assert.AreEqual(1, md.Parameters.Count); + Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); + Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); + + Assert.AreEqual(1, md.Templates.Count); + Assert.AreEqual("T", md.Templates[0].Name); + } + + [Test] + public void VBNetGenericMethodDeclarationWithConstraintTest() + { + string program = "Function MyMethod(Of T As { ISomeInterface })(a As T) As T\n End Function"; + MethodDeclaration md = ParseUtil.ParseTypeMember(program); + Assert.AreEqual("T", md.TypeReference.Type); + Assert.AreEqual(1, md.Parameters.Count); + Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); + Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); + + Assert.AreEqual(1, md.Templates.Count); + Assert.AreEqual("T", md.Templates[0].Name); + Assert.AreEqual(1, md.Templates[0].Bases.Count); + Assert.AreEqual("ISomeInterface", md.Templates[0].Bases[0].Type); + } + + [Test] + public void VBNetExtensionMethodDeclaration() + { + MethodDeclaration md = ParseUtil.ParseTypeMember( + @" _ + Sub Print(s As String) + Console.WriteLine(s) + End Sub"); + + Assert.AreEqual("Print", md.Name); + + // IsExtensionMethod is only valid for c#. + // Assert.IsTrue(md.IsExtensionMethod); + + Assert.AreEqual("s", md.Parameters[0].ParameterName); + Assert.AreEqual("System.String", md.Parameters[0].TypeReference.Type); + } + + [Test] + public void VBNetGenericMethodInInterface() + { + const string program = @"Interface MyInterface + Function MyMethod(Of T As {ISomeInterface})(a As T) As T + End Interface"; + TypeDeclaration td = ParseUtil.ParseGlobal(program); + MethodDeclaration md = (MethodDeclaration)td.Children[0]; + Assert.AreEqual("T", md.TypeReference.Type); + Assert.AreEqual(1, md.Parameters.Count); + Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); + Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); + + Assert.AreEqual(1, md.Templates.Count); + Assert.AreEqual("T", md.Templates[0].Name); + Assert.AreEqual(1, md.Templates[0].Bases.Count); + Assert.AreEqual("ISomeInterface", md.Templates[0].Bases[0].Type); + } + + [Test] + public void VBNetGenericVoidMethodInInterface() + { + const string program = @"interface MyInterface + Sub MyMethod(Of T As {ISomeInterface})(a as T) +End Interface +"; + TypeDeclaration td = ParseUtil.ParseGlobal(program); + MethodDeclaration md = (MethodDeclaration)td.Children[0]; + Assert.AreEqual("System.Void", md.TypeReference.Type); + Assert.AreEqual(1, md.Parameters.Count); + Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); + Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); + + Assert.AreEqual(1, md.Templates.Count); + Assert.AreEqual("T", md.Templates[0].Name); + Assert.AreEqual(1, md.Templates[0].Bases.Count); + Assert.AreEqual("ISomeInterface", md.Templates[0].Bases[0].Type); + } + + [Test] + public void VBNetMethodWithHandlesClause() + { + MethodDeclaration md = ParseUtil.ParseTypeMember( + @"Public Sub MyMethod(sender As Object, e As EventArgs) Handles x.y + End Sub"); + Assert.AreEqual(new string[] { "x.y" }, md.HandlesClause.ToArray()); + + md = ParseUtil.ParseTypeMember( + @"Public Sub MyMethod() Handles Me.FormClosing + End Sub"); + Assert.AreEqual(new string[] { "Me.FormClosing" }, md.HandlesClause.ToArray()); + + md = ParseUtil.ParseTypeMember( + @"Public Sub MyMethod() Handles MyBase.Event, Button1.Click + End Sub"); + Assert.AreEqual(new string[] { "MyBase.Event", "Button1.Click" }, md.HandlesClause.ToArray()); + } + + [Test] + public void VBNetMethodWithTypeCharactersTest() + { + const string program = @"Public Function Func!(ByVal Param&) + Func! = CSingle(Param&) + End Function"; + + MethodDeclaration md = ParseUtil.ParseTypeMember(program); + Assert.AreEqual(Modifiers.Public, md.Modifier); + } + + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/OperatorDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/OperatorDeclarationTests.cs new file mode 100644 index 0000000000..049f7f4644 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/OperatorDeclarationTests.cs @@ -0,0 +1,30 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class OperatorDeclarationTests + { + #region VB.NET + + [Test] + public void VBNetImplictOperatorDeclarationTest() + { + string programm = @"Public Shared Operator + (ByVal v As Complex) As Complex + Return v + End Operator"; + + OperatorDeclaration od = ParseUtil.ParseTypeMember(programm); + Assert.IsFalse(od.IsConversionOperator); + Assert.AreEqual(1, od.Parameters.Count); + Assert.AreEqual(ConversionType.None, od.ConversionType); + Assert.AreEqual("Complex", od.TypeReference.Type); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/PropertyDeclarationTests.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/PropertyDeclarationTests.cs new file mode 100644 index 0000000000..c31f7bb9de --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB.Tests/Parser/TypeLevel/PropertyDeclarationTests.cs @@ -0,0 +1,107 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.IO; +using ICSharpCode.NRefactory.VB.Ast; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.VB.Tests.Ast +{ + [TestFixture] + public class PropertyDeclarationTests + { + #region VB.NET + [Test] + public void VBNetSimpleGetSetPropertyDeclarationTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("Property MyProperty As Integer \n Get \n End Get \n Set \n End Set\nEnd Property"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + } + + [Test] + public void VBNetSimpleGetPropertyDeclarationTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("ReadOnly Property MyProperty \nGet\nEnd Get\nEnd Property"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsFalse(pd.HasSetRegion); + Assert.IsTrue((pd.Modifier & Modifiers.ReadOnly) == Modifiers.ReadOnly); + } + + [Test] + public void VBNetSimpleSetPropertyDeclarationTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("WriteOnly Property MyProperty \n Set\nEnd Set\nEnd Property "); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + Assert.IsTrue((pd.Modifier & Modifiers.WriteOnly) == Modifiers.WriteOnly); + } + + [Test] + public void VBNetAutoPropertyTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("Property MyProperty"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + Assert.AreEqual(pd.Initializer, Expression.Null); + } + + [Test] + public void VBNetReadOnlyAutoPropertyTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("ReadOnly Property MyProperty"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsFalse(pd.HasSetRegion); + Assert.AreEqual(pd.Initializer, Expression.Null); + } + + [Test] + public void VBNetWriteOnlyAutoPropertyTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("WriteOnly Property MyProperty"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsFalse(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + Assert.AreEqual(pd.Initializer, Expression.Null); + } + + [Test] + public void VBNetSimpleInitializerAutoPropertyTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("Property MyProperty = 5"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + Assert.AreEqual(pd.Initializer.ToString(), new PrimitiveExpression(5).ToString()); + } + + [Test] + public void VBNetSimpleInitializerAutoPropertyWithTypeTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("Property MyProperty As Integer = 5"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.AreEqual("System.Int32", pd.TypeReference.Type); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + Assert.AreEqual(pd.Initializer.ToString(), new PrimitiveExpression(5).ToString()); + } + + [Test] + public void VBNetSimpleObjectInitializerAutoPropertyTest() + { + PropertyDeclaration pd = ParseUtil.ParseTypeMember("Property MyProperty As New List"); + Assert.AreEqual("MyProperty", pd.Name); + Assert.AreEqual("List", pd.TypeReference.Type); + Assert.IsTrue(pd.HasGetRegion); + Assert.IsTrue(pd.HasSetRegion); + Assert.AreEqual(pd.Initializer.ToString(), new ObjectCreateExpression(new TypeReference("List"), null).ToString()); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/.gitignore b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/.gitignore new file mode 100644 index 0000000000..9ce745d95d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstLocation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstLocation.cs new file mode 100644 index 0000000000..4a3a1bc688 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstLocation.cs @@ -0,0 +1,137 @@ +// +// DomLocation.cs +// +// Author: +// Mike Krüger +// +// Copyright (C) 2008 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.VB +{ + [Serializable] + public struct AstLocation : IComparable, IEquatable + { + public static readonly AstLocation Empty = new AstLocation(0, 0); + + readonly int line, column; + + public AstLocation (int line, int column) + { + this.line = line; + this.column = column; + } + + public bool IsEmpty { + get { + return line <= 0; + } + } + + public int Line { + get { return line; } + } + + public int Column { + get { return column; } + } + + public override bool Equals (object obj) + { + if (!(obj is AstLocation)) + return false; + return (AstLocation)obj == this; + } + + public override int GetHashCode () + { + unchecked { + return line + column * 5000; + } + } + + public bool Equals (AstLocation other) + { + return other == this; + } + + public int CompareTo (AstLocation other) + { + if (this == other) + return 0; + if (this < other) + return -1; + return 1; + } + + public override string ToString () + { + return String.Format ("(Line {0}, Column {1})", Line, Column); + } + + public static AstLocation FromInvariantString (string invariantString) + { + if (string.Equals(invariantString, "EMPTY", StringComparison.OrdinalIgnoreCase)) + return AstLocation.Empty; + string[] splits = invariantString.Split (',', '/'); + if (splits.Length == 2) + return new AstLocation (Int32.Parse (splits[0]), Int32.Parse (splits[1])); + return AstLocation.Empty; + } + + public string ToInvariantString () + { + if (IsEmpty) + return "Empty"; + return String.Format ("{0}/{1}", line, column); + } + + public static bool operator==(AstLocation left, AstLocation right) + { + return left.line == right.line && left.column == right.column; + } + + public static bool operator!=(AstLocation left, AstLocation right) + { + return left.line != right.line || left.column != right.column; + } + + public static bool operator<(AstLocation left, AstLocation right) + { + return left.line < right.line || left.line == right.line && left.column < right.column; + } + public static bool operator>(AstLocation left, AstLocation right) + { + return left.line > right.line || left.line == right.line && left.column > right.column; + } + public static bool operator<=(AstLocation left, AstLocation right) + { + return !(left > right); + } + public static bool operator>=(AstLocation left, AstLocation right) + { + return !(left < right); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstNode.cs new file mode 100644 index 0000000000..7a79baf682 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstNode.cs @@ -0,0 +1,586 @@ +// +// AstNode.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB +{ + public abstract class AstNode : AbstractAnnotatable, PatternMatching.INode + { + #region Null + public static readonly AstNode Null = new NullAstNode (); + + sealed class NullAstNode : AstNode + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator AstNode(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : AstNode, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + AstNode parent; + AstNode prevSibling; + AstNode nextSibling; + AstNode firstChild; + AstNode lastChild; + Role role = RootRole; + + public virtual bool IsNull { + get { + return false; + } + } + + public virtual AstLocation StartLocation { + get { + var child = firstChild; + if (child == null) + return AstLocation.Empty; + return child.StartLocation; + } + } + + public virtual AstLocation EndLocation { + get { + var child = lastChild; + if (child == null) + return AstLocation.Empty; + return child.EndLocation; + } + } + + public AstNode Parent { + get { return parent; } + } + + public Role Role { + get { return role; } + } + + public AstNode NextSibling { + get { return nextSibling; } + } + + public AstNode PrevSibling { + get { return prevSibling; } + } + + public AstNode FirstChild { + get { return firstChild; } + } + + public AstNode LastChild { + get { return lastChild; } + } + + public IEnumerable Children { + get { + AstNode next; + for (AstNode cur = firstChild; cur != null; cur = next) { + Debug.Assert(cur.parent == this); + // Remember next before yielding cur. + // This allows removing/replacing nodes while iterating through the list. + next = cur.nextSibling; + yield return cur; + } + } + } + + /// + /// Gets the ancestors of this node (excluding this node itself) + /// + public IEnumerable Ancestors { + get { + for (AstNode cur = parent; cur != null; cur = cur.parent) { + yield return cur; + } + } + } + + /// + /// Gets all descendants of this node (excluding this node itself). + /// + public IEnumerable Descendants { + get { + return Utils.TreeTraversal.PreOrder(this.Children, n => n.Children); + } + } + + /// + /// Gets all descendants of this node (including this node itself). + /// + public IEnumerable DescendantsAndSelf { + get { + return Utils.TreeTraversal.PreOrder(this, n => n.Children); + } + } + + /// + /// Gets the first child with the specified role. + /// Returns the role's null object if the child is not found. + /// + public T GetChildByRole(Role role) where T : AstNode + { + if (role == null) + throw new ArgumentNullException("role"); + for (var cur = firstChild; cur != null; cur = cur.nextSibling) { + if (cur.role == role) + return (T)cur; + } + return role.NullObject; + } + + public AstNodeCollection GetChildrenByRole(Role role) where T : AstNode + { + return new AstNodeCollection(this, role); + } + + protected void SetChildByRole(Role role, T newChild) where T : AstNode + { + AstNode oldChild = GetChildByRole(role); + if (oldChild.IsNull) + AddChild(newChild, role); + else + oldChild.ReplaceWith(newChild); + } + + public void AddChild(T child, Role role) where T : AstNode + { + if (role == null) + throw new ArgumentNullException("role"); + if (child == null || child.IsNull) + return; + if (this.IsNull) + throw new InvalidOperationException("Cannot add children to null nodes"); + if (child.parent != null) + throw new ArgumentException ("Node is already used in another tree.", "child"); + AddChildUnsafe(child, role); + } + + internal void AddChildUntyped(AstNode child, Role role) + { + if (role == null) + throw new ArgumentNullException("role"); + if (child == null || child.IsNull) + return; + if (this.IsNull) + throw new InvalidOperationException("Cannot add children to null nodes"); + if (child.parent != null) + throw new ArgumentException ("Node is already used in another tree.", "child"); + AddChildUnsafe(child, role); + } + + /// + /// Adds a child without performing any safety checks. + /// + void AddChildUnsafe(AstNode child, Role role) + { + child.parent = this; + child.role = role; + if (firstChild == null) { + lastChild = firstChild = child; + } else { + lastChild.nextSibling = child; + child.prevSibling = lastChild; + lastChild = child; + } + } + + public void InsertChildBefore(AstNode nextSibling, T child, Role role) where T : AstNode + { + if (role == null) + throw new ArgumentNullException("role"); + if (nextSibling == null || nextSibling.IsNull) { + AddChild(child, role); + return; + } + + if (child == null || child.IsNull) + return; + if (child.parent != null) + throw new ArgumentException ("Node is already used in another tree.", "child"); + if (nextSibling.parent != this) + throw new ArgumentException ("NextSibling is not a child of this node.", "nextSibling"); + // No need to test for "Cannot add children to null nodes", + // as there isn't any valid nextSibling in null nodes. + InsertChildBeforeUnsafe(nextSibling, child, role); + } + + + void InsertChildBeforeUnsafe(AstNode nextSibling, AstNode child, Role role) + { + child.parent = this; + child.role = role; + child.nextSibling = nextSibling; + child.prevSibling = nextSibling.prevSibling; + + if (nextSibling.prevSibling != null) { + Debug.Assert(nextSibling.prevSibling.nextSibling == nextSibling); + nextSibling.prevSibling.nextSibling = child; + } else { + Debug.Assert(firstChild == nextSibling); + firstChild = child; + } + nextSibling.prevSibling = child; + } + + public void InsertChildAfter(AstNode prevSibling, T child, Role role) where T : AstNode + { + InsertChildBefore((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role); + } + + /// + /// Removes this node from its parent. + /// + public void Remove() + { + if (parent != null) { + if (prevSibling != null) { + Debug.Assert(prevSibling.nextSibling == this); + prevSibling.nextSibling = nextSibling; + } else { + Debug.Assert(parent.firstChild == this); + parent.firstChild = nextSibling; + } + if (nextSibling != null) { + Debug.Assert(nextSibling.prevSibling == this); + nextSibling.prevSibling = prevSibling; + } else { + Debug.Assert(parent.lastChild == this); + parent.lastChild = prevSibling; + } + parent = null; + role = Roles.Root; + prevSibling = null; + nextSibling = null; + } + } + + /// + /// Replaces this node with the new node. + /// + public void ReplaceWith(AstNode newNode) + { + if (newNode == null || newNode.IsNull) { + Remove(); + return; + } + if (newNode == this) + return; // nothing to do... + if (parent == null) { + throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); + } + // Because this method doesn't statically check the new node's type with the role, + // we perform a runtime test: + if (!role.IsValid(newNode)) { + throw new ArgumentException (string.Format("The new node '{0}' is not valid in the role {1}", newNode.GetType().Name, role.ToString()), "newNode"); + } + if (newNode.parent != null) { + // newNode is used within this tree? + if (newNode.Ancestors.Contains(this)) { + // e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);" + // enable automatic removal + newNode.Remove(); + } else { + throw new ArgumentException ("Node is already used in another tree.", "newNode"); + } + } + + newNode.parent = parent; + newNode.role = role; + newNode.prevSibling = prevSibling; + newNode.nextSibling = nextSibling; + if (parent != null) { + if (prevSibling != null) { + Debug.Assert(prevSibling.nextSibling == this); + prevSibling.nextSibling = newNode; + } else { + Debug.Assert(parent.firstChild == this); + parent.firstChild = newNode; + } + if (nextSibling != null) { + Debug.Assert(nextSibling.prevSibling == this); + nextSibling.prevSibling = newNode; + } else { + Debug.Assert(parent.lastChild == this); + parent.lastChild = newNode; + } + parent = null; + prevSibling = null; + nextSibling = null; + role = Roles.Root; + } + } + + public AstNode ReplaceWith(Func replaceFunction) + { + if (replaceFunction == null) + throw new ArgumentNullException("replaceFunction"); + if (parent == null) { + throw new InvalidOperationException(this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); + } + AstNode oldParent = parent; + AstNode oldSuccessor = nextSibling; + Role oldRole = role; + Remove(); + AstNode replacement = replaceFunction(this); + if (oldSuccessor != null && oldSuccessor.parent != oldParent) + throw new InvalidOperationException("replace function changed nextSibling of node being replaced?"); + if (!(replacement == null || replacement.IsNull)) { + if (replacement.parent != null) + throw new InvalidOperationException("replace function must return the root of a tree"); + if (!oldRole.IsValid(replacement)) { + throw new InvalidOperationException (string.Format("The new node '{0}' is not valid in the role {1}", replacement.GetType().Name, oldRole.ToString())); + } + + if (oldSuccessor != null) + oldParent.InsertChildBeforeUnsafe(oldSuccessor, replacement, oldRole); + else + oldParent.AddChildUnsafe(replacement, oldRole); + } + return replacement; + } + + /// + /// Clones the whole subtree starting at this AST node. + /// + /// Annotations are copied over to the new nodes; and any annotations implementating ICloneable will be cloned. + public AstNode Clone() + { + AstNode copy = (AstNode)MemberwiseClone(); + // First, reset the shallow pointer copies + copy.parent = null; + copy.role = Roles.Root; + copy.firstChild = null; + copy.lastChild = null; + copy.prevSibling = null; + copy.nextSibling = null; + + // Then perform a deep copy: + for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) { + copy.AddChildUnsafe(cur.Clone(), cur.role); + } + + // Finally, clone the annotation, if necessary + ICloneable annotations = copy.annotations as ICloneable; // read from copy (for thread-safety) + if (annotations != null) + copy.annotations = annotations.Clone(); + + return copy; + } + + public override void AddAnnotation (object annotation) + { + if (this.IsNull) + throw new InvalidOperationException("Cannot add annotations to the null node"); + base.AddAnnotation (annotation); + } + + public abstract S AcceptVisitor (IAstVisitor visitor, T data); + + #region Pattern Matching + protected static bool MatchString(string name1, string name2) + { + return string.IsNullOrEmpty(name1) || string.Equals(name1, name2, StringComparison.OrdinalIgnoreCase); + } + + protected static bool MatchStringXml(string name1, string name2) + { + return string.IsNullOrEmpty(name1) || string.Equals(name1, name2, StringComparison.Ordinal); + } + + protected internal abstract bool DoMatch(AstNode other, PatternMatching.Match match); + + bool PatternMatching.INode.DoMatch(PatternMatching.INode other, PatternMatching.Match match) + { + AstNode o = other as AstNode; + // try matching if other is null, or if other is an AstNode + return (other == null || o != null) && DoMatch(o, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + AstNode o = pos as AstNode; + return (pos == null || o != null) && DoMatch (o, match); + } + + PatternMatching.INode PatternMatching.INode.NextSibling { + get { return nextSibling; } + } + + PatternMatching.INode PatternMatching.INode.FirstChild { + get { return firstChild; } + } + #endregion + + public AstNode GetNextNode () + { + if (NextSibling != null) + return NextSibling; + if (Parent != null) + return Parent.GetNextNode (); + return null; + } + + public AstNode GetPrevNode () + { + if (PrevSibling != null) + return PrevSibling; + if (Parent != null) + return Parent.GetPrevNode (); + return null; + } + + // filters all non VB nodes (comments, white spaces or pre processor directives) + public AstNode GetVBNodeBefore (AstNode node) + { + var n = node.PrevSibling; + while (n != null) { + if (n.Role != Roles.Comment) + return n; + n = n.GetPrevNode (); + } + return null; + } + + // the Root role must be available when creating the null nodes, so we can't put it in the Roles class + static readonly Role RootRole = new Role("Root"); + + public static class Roles + { + /// + /// Root of an abstract syntax tree. + /// + public static readonly Role Root = RootRole; + + // some pre defined constants for common roles + public static readonly Role Identifier = new Role("Identifier", Ast.Identifier.Null); + public static readonly Role XmlIdentifier = new Role("XmlIdentifier", Ast.XmlIdentifier.Null); + public static readonly Role XmlLiteralString = new Role("XmlLiteralString", Ast.XmlLiteralString.Null); + +// public static readonly Role Body = new Role("Body", CSharp.BlockStatement.Null); + public static readonly Role Parameter = new Role("Parameter"); + public static readonly Role Argument = new Role("Argument", Ast.Expression.Null); + public static readonly Role Type = new Role("Type", AstType.Null); + public static readonly Role Expression = new Role("Expression", Ast.Expression.Null); +// public static readonly Role TargetExpression = new Role("Target", CSharp.Expression.Null); +// public readonly static Role Condition = new Role("Condition", CSharp.Expression.Null); +// + public static readonly Role TypeParameter = new Role("TypeParameter"); + public static readonly Role TypeArgument = new Role("TypeArgument", AstType.Null); +// public static readonly Role Variable = new Role("Variable"); +// public static readonly Role EmbeddedStatement = new Role("EmbeddedStatement", CSharp.Statement.Null); +// + public static readonly Role Keyword = new Role("Keyword", VBTokenNode.Null); +// public static readonly Role InKeyword = new Role("InKeyword", VBTokenNode.Null); + + // some pre defined constants for most used punctuation + public static readonly Role LPar = new Role("LPar", VBTokenNode.Null); + public static readonly Role RPar = new Role("RPar", VBTokenNode.Null); + public static readonly Role LBracket = new Role("LBracket", VBTokenNode.Null); + public static readonly Role RBracket = new Role("RBracket", VBTokenNode.Null); + public static readonly Role LBrace = new Role("LBrace", VBTokenNode.Null); + public static readonly Role RBrace = new Role("RBrace", VBTokenNode.Null); + public static readonly Role LChevron = new Role("LChevron", VBTokenNode.Null); + public static readonly Role RChevron = new Role("RChevron", VBTokenNode.Null); + public static readonly Role Comma = new Role("Comma", VBTokenNode.Null); + public static readonly Role Dot = new Role("Dot", VBTokenNode.Null); + public static readonly Role Semicolon = new Role("Semicolon", VBTokenNode.Null); + public static readonly Role Assign = new Role("Assign", VBTokenNode.Null); + public static readonly Role Colon = new Role("Colon", VBTokenNode.Null); + public static readonly Role StatementTerminator = new Role("StatementTerminator", VBTokenNode.Null); + + // XML + /// + /// Text: < + /// + public static readonly Role XmlOpenTag = new Role("XmlOpenTag", VBTokenNode.Null); + /// + /// Text: > + /// + public static readonly Role XmlCloseTag = new Role("XmlOpenTag", VBTokenNode.Null); + + public static readonly Role Comment = new Role("Comment"); + + } + } + + public class Comment + { + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs new file mode 100644 index 0000000000..236f27a0ba --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs @@ -0,0 +1,209 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.VB +{ + /// + /// Represents the children of an AstNode that have a specific role. + /// + public class AstNodeCollection : ICollection where T : AstNode + { + readonly AstNode node; + readonly Role role; + + public AstNodeCollection(AstNode node, Role role) + { + if (node == null) + throw new ArgumentNullException("node"); + if (role == null) + throw new ArgumentNullException("role"); + this.node = node; + this.role = role; + } + + public int Count { + get { + int count = 0; + for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) { + if (cur.Role == role) + count++; + } + return count; + } + } + + public void Add(T element) + { + node.AddChild(element, role); + } + + public void AddRange(IEnumerable nodes) + { + // Evaluate 'nodes' first, since it might change when we add the new children + // Example: collection.AddRange(collection); + if (nodes != null) { + foreach (T node in nodes.ToList()) + Add(node); + } + } + + public void AddRange(T[] nodes) + { + // Fast overload for arrays - we don't need to create a copy + if (nodes != null) { + foreach (T node in nodes) + Add(node); + } + } + + public void ReplaceWith(IEnumerable nodes) + { + // Evaluate 'nodes' first, since it might change when we call Clear() + // Example: collection.ReplaceWith(collection); + if (nodes != null) + nodes = nodes.ToList(); + Clear(); + foreach (T node in nodes) + Add(node); + } + + public void MoveTo(ICollection targetCollection) + { + foreach (T node in this) { + node.Remove(); + targetCollection.Add(node); + } + } + + public bool Contains(T element) + { + return element != null && element.Parent == node && element.Role == role; + } + + public bool Remove(T element) + { + if (Contains(element)) { + element.Remove(); + return true; + } else { + return false; + } + } + + public void CopyTo(T[] array, int arrayIndex) + { + foreach (T item in this) + array[arrayIndex++] = item; + } + + public void Clear() + { + foreach (T item in this) + item.Remove(); + } + + bool ICollection.IsReadOnly { + get { return false; } + } + + public IEnumerator GetEnumerator() + { + AstNode next; + for (AstNode cur = node.FirstChild; cur != null; cur = next) { + Debug.Assert(cur.Parent == node); + // Remember next before yielding cur. + // This allows removing/replacing nodes while iterating through the list. + next = cur.NextSibling; + if (cur.Role == role) + yield return (T)cur; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #region Equals and GetHashCode implementation + public override bool Equals(object obj) + { + if (obj is AstNodeCollection) { + return ((AstNodeCollection)obj) == this; + } else { + return false; + } + } + + public override int GetHashCode() + { + return node.GetHashCode() ^ role.GetHashCode(); + } + + public static bool operator ==(AstNodeCollection left, AstNodeCollection right) + { + return left.role == right.role && left.node == right.node; + } + + public static bool operator !=(AstNodeCollection left, AstNodeCollection right) + { + return !(left.role == right.role && left.node == right.node); + } + #endregion + + internal bool DoMatch(AstNodeCollection other, Match match) + { + // TODO : does not compile (ask Daniel)! +// Stack patternStack = new Stack(); +// Stack stack = new Stack(); +// patternStack.Push(this.node.FirstChild); +// stack.Push(new Pattern.PossibleMatch(other.node.FirstChild, match.CheckPoint())); +// while (stack.Count > 0) { +// AstNode cur1 = patternStack.Pop(); +// AstNode cur2 = stack.Peek().NextOther; +// match.RestoreCheckPoint(stack.Pop().Checkpoint); +// bool success = true; +// while (cur1 != null && success) { +// while (cur1 != null && cur1.Role != role) +// cur1 = cur1.NextSibling; +// while (cur2 != null && cur2.Role != role) +// cur2 = cur2.NextSibling; +// if (cur1 == null) +// break; +// +// Debug.Assert(stack.Count == patternStack.Count); +// success = cur1.DoMatchCollection(role, cur2, match, stack); +// Debug.Assert(stack.Count >= patternStack.Count); +// while (stack.Count > patternStack.Count) +// patternStack.Push(cur1.NextSibling); +// +// cur1 = cur1.NextSibling; +// if (cur2 != null) +// cur2 = cur2.NextSibling; +// } +// while (cur2 != null && cur2.Role != role) +// cur2 = cur2.NextSibling; +// if (success && cur2 == null) +// return true; +// } + return false; + } + + public void InsertAfter(T existingItem, T newItem) + { + node.InsertChildAfter(existingItem, newItem, role); + } + + public void InsertBefore(T existingItem, T newItem) + { + node.InsertChildBefore(existingItem, newItem, role); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Enums.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Enums.cs new file mode 100644 index 0000000000..d0fc139296 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Enums.cs @@ -0,0 +1,349 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + [Flags] + public enum Modifiers + { + None = 0x0000, + + // Accessibility + Private = 0x0001, + Friend = 0x0002, + Protected = 0x0004, + Public = 0x0008, + + // Scope + MustInherit = 0x0010, // Types + MustOverride = 0x0020, // Members + Overridable = 0x0040, + NotInheritable = 0x0080, // Types + NotOverridable = 0x0100, // Members + Const = 0x0200, + Shared = 0x0400, + Static = 0x0800, + Override = 0x1000, + ReadOnly = 0x2000, + Shadows = 0x4000, + Partial = 0x8000, + + // Special + Overloads = 0x10000, // VB specific + WithEvents = 0x20000, // VB specific + Default = 0x40000, // VB specific + + Dim = 0x80000, // VB.NET SPECIFIC, for fields/local variables only + + /// Only for VB properties. + WriteOnly = 0x100000, // VB specific + + ByVal = 0x200000, + ByRef = 0x400000, + ParamArray = 0x800000, + Optional = 0x1000000, + + /// + /// Special value used to match any modifiers during pattern matching. + /// + Any = unchecked((int)0x80000000) + } + + public enum ParentType + { + ClassOrStruct, + InterfaceOrEnum, + Namespace, + Unknown + } + + public enum FieldDirection + { + None, + In, + Out, + Ref + } + + public enum VarianceModifier + { + Invariant, + Covariant, + Contravariant + }; + + public enum AssignmentOperatorType + { + None, + Assign, + + Add, + Subtract, + Multiply, + Divide, + Modulus, + + Power, // (VB only) + DivideInteger, // (VB only) + ConcatString, // (VB only) + + ShiftLeft, + ShiftRight, + + BitwiseAnd, + BitwiseOr, + ExclusiveOr, + } + + public enum BinaryOperatorType + { + None, + + /// '&' in C#, 'And' in VB. + BitwiseAnd, + /// '|' in C#, 'Or' in VB. + BitwiseOr, + /// '&&' in C#, 'AndAlso' in VB. + LogicalAnd, + /// '||' in C#, 'OrElse' in VB. + LogicalOr, + /// '^' in C#, 'Xor' in VB. + ExclusiveOr, + + /// > + GreaterThan, + /// >= + GreaterThanOrEqual, + /// '==' in C#, '=' in VB. + Equality, + /// '!=' in C#, '<>' in VB. + InEquality, + /// < + LessThan, + /// <= + LessThanOrEqual, + + /// + + Add, + /// - + Subtract, + /// * + Multiply, + /// / + Divide, + /// '%' in C#, 'Mod' in VB. + Modulus, + /// VB-only: \ + DivideInteger, + /// VB-only: ^ + Power, + /// VB-only: & + Concat, + + /// C#: << + ShiftLeft, + /// C#: >> + ShiftRight, + /// VB-only: Is + ReferenceEquality, + /// VB-only: IsNot + ReferenceInequality, + + /// VB-only: Like + Like, + /// + /// C#: ?? + /// VB: IF(x, y) + /// + NullCoalescing, + + /// VB-only: ! + DictionaryAccess + } + + public enum CastType + { + /// + /// direct cast (C#, VB "DirectCast") + /// + Cast, + /// + /// try cast (C# "as", VB "TryCast") + /// + TryCast, + /// + /// converting cast (VB "CType") + /// + Conversion, + /// + /// primitive converting cast (VB "CString" etc.) + /// + PrimitiveConversion + } + + public enum UnaryOperatorType + { + None, + Not, + BitNot, + + Minus, + Plus, + + Increment, + Decrement, + + PostIncrement, + PostDecrement, + + /// Dereferencing pointer + Dereference, + /// Get address of + AddressOf + } + + public enum ContinueType + { + None, + Do, + For, + While + } + + public enum ConditionType + { + None, + Until, + While, + DoWhile + } + + public enum ConditionPosition + { + None, + Start, + End + } + + public enum ExitType + { + None, + Sub, + Function, + Property, + Do, + For, + While, + Select, + Try + } + + public enum ConstructorInitializerType + { + None, + Base, + This + } + + public enum ConversionType + { + None, + Implicit, + Explicit + } + + public enum OverloadableOperatorType + { + None, + + Add, + Subtract, + Multiply, + Divide, + Modulus, + Concat, + + UnaryPlus, + UnaryMinus, + + Not, + BitNot, + + BitwiseAnd, + BitwiseOr, + ExclusiveOr, + + ShiftLeft, + ShiftRight, + + GreaterThan, + GreaterThanOrEqual, + Equality, + InEquality, + LessThan, + LessThanOrEqual, + + Increment, + Decrement, + + IsTrue, + IsFalse, + + // VB specific + Like, + Power, + CType, + DivideInteger + } + + /// + /// Charset types, used in external methods + /// declarations (VB only). + /// + public enum CharsetModifier + { + None, + Auto, + Unicode, + Ansi + } + + /// + /// Specifies the ordering direction of a QueryExpressionOrdering node. + /// + public enum QueryExpressionOrderingDirection + { + None, + Ascending, + Descending + } + + /// + /// Specifies the partition type for a VB.NET + /// query expression. + /// + public enum QueryExpressionPartitionType + { + Take, + TakeWhile, + Skip, + SkipWhile + } + + public enum XmlAxisType + { + Element, // . + Attribute, // .@ + Descendents // ... + } + + public enum XmlContentType + { + Comment, + Text, + CData, + ProcessingInstruction + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs new file mode 100644 index 0000000000..d15756e3ee --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs @@ -0,0 +1,33 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public abstract class Expression : AstNode + { + #region Null + public new static readonly Expression Null = new NullExpression (); + + sealed class NullExpression : Expression + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs new file mode 100644 index 0000000000..c01adaf8ad --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs @@ -0,0 +1,75 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using ICSharpCode.NRefactory.VB.PrettyPrinter; +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Represents a literal value. + /// + public class PrimitiveExpression : Expression + { + public static readonly object AnyValue = new object(); + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + } + + int length; + public override AstLocation EndLocation { + get { + return new AstLocation(StartLocation.Line, StartLocation.Column + length); + } + } + + public object Value { get; private set; } + + string stringValue; + + public string StringValue { + get { return stringValue; } // TODO ?? VBNetOutputVisitor.ToVBNetString(this); } + } + + public PrimitiveExpression(object value) + { + this.Value = value; + } + + public PrimitiveExpression(object value, string stringValue) + { + this.Value = value; + this.stringValue = stringValue; + } + + public PrimitiveExpression(object value, AstLocation startLocation, int length) + { + this.Value = value; + this.startLocation = startLocation; + this.length = length; + } + + public PrimitiveExpression(object value, string stringValue, AstLocation startLocation, int length) + { + this.Value = value; + this.stringValue = stringValue; + this.startLocation = startLocation; + this.length = length; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPrimitiveExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PrimitiveExpression o = other as PrimitiveExpression; + return o != null && (this.Value == AnyValue || object.Equals(this.Value, o.Value)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs new file mode 100644 index 0000000000..257b8e744a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs @@ -0,0 +1,27 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of IdentifierExpression. + /// + public class SimpleNameExpression : Expression + { + public Identifier Identifier { get; set; } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var node = other as SimpleNameExpression; + return node != null + && Identifier.DoMatch(node.Identifier, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSimpleNameExpression(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs new file mode 100644 index 0000000000..7d3a6ca0b9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs @@ -0,0 +1,72 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of XmlIdentifier. + /// + public class XmlIdentifier : AstNode + { + public static readonly new XmlIdentifier Null = new NullXmlIdentifier(); + + class NullXmlIdentifier : XmlIdentifier + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default(S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + public string Name { get; set; } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { return startLocation; } + } + + AstLocation endLocation; + public override AstLocation EndLocation { + get { return endLocation; } + } + + private XmlIdentifier() + { + this.Name = string.Empty; + } + + public XmlIdentifier(string name, AstLocation startLocation, AstLocation endLocation) + { + this.Name = name; + this.startLocation = startLocation; + this.endLocation = endLocation; + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var ident = other as XmlIdentifier; + return ident != null + && MatchStringXml(Name, ident.Name) + && ident.startLocation == startLocation + && ident.endLocation == endLocation; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitXmlIdentifier(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs new file mode 100644 index 0000000000..3195bcd69a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs @@ -0,0 +1,69 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class XmlLiteralString : AstNode + { + public static readonly new XmlLiteralString Null = new XmlLiteralString(); + + class NullXmlLiteralString : XmlLiteralString + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default(S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + public string Value { get; set; } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { return startLocation; } + } + + AstLocation endLocation; + public override AstLocation EndLocation { + get { return endLocation; } + } + + private XmlLiteralString() + { + this.Value = string.Empty; + } + + public XmlLiteralString(string value, AstLocation startLocation, AstLocation endLocation) + { + this.Value = value; + this.startLocation = startLocation; + this.endLocation = endLocation; + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var ident = other as XmlLiteralString; + return ident != null + && MatchStringXml(Value, ident.Value) + && ident.startLocation == startLocation + && ident.endLocation == endLocation; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitXmlLiteralString(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs new file mode 100644 index 0000000000..22261575ef --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs @@ -0,0 +1,93 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class Attribute : AstNode + { + #region PatternPlaceholder + public static implicit operator Attribute(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : Attribute, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public static readonly Role AttributeRole = new Role("Attribute"); + public static readonly Role TargetRole = new Role("Target", VBTokenNode.Null); + + public VBTokenNode Target { + get { return GetChildByRole(TargetRole); } + set { SetChildByRole(TargetRole, value); } + } + + public VBTokenNode ColonToken { + get { return GetChildByRole(Roles.StatementTerminator); } + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public VBTokenNode LParToken { + get { return GetChildByRole(Roles.LPar); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole(Roles.Argument); } + } + + public VBTokenNode RParToken { + get { return GetChildByRole(Roles.RPar); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAttribute(this, data); + } + +// public override string ToString() +// { +// return string.Format("[Attribute Type={0} Arguments={1}]", Type, GetCollectionString(Arguments)); +// } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var node = other as Attribute; + return node != null && node.Target.DoMatch(this.Target, match) && node.Type.DoMatch(this.Type, match) && node.Arguments.DoMatch(this.Arguments, match); + } + } + + public enum AttributeTarget + { + Assembly, + Module + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs new file mode 100644 index 0000000000..2e06d39172 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class AttributeBlock : AstNode + { + public readonly static Role AttributeBlockRole = new Role("AttributeBlock"); + public readonly static Role ReturnTypeAttributeBlockRole = new Role("ReturnTypeAttributeBlock"); + + public VBTokenNode LChevron { + get { return GetChildByRole(Roles.LChevron); } + } + + public AstNodeCollection Attributes { + get { return GetChildrenByRole(Attribute.AttributeRole); } + } + + public VBTokenNode RChevron { + get { return GetChildByRole(Roles.RChevron); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var node = other as AttributeBlock; + return node != null && Attributes.DoMatch(node.Attributes, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAttributeBlock(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs new file mode 100644 index 0000000000..37e364ee6b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs @@ -0,0 +1,67 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public abstract class AttributedNode : AstNode + { + public AstNodeCollection Attributes { + get { return GetChildrenByRole(AttributeBlock.AttributeBlockRole); } + } + + public static readonly Role ModifierRole = new Role("Modifier"); + + public Modifiers Modifiers { + get { return GetModifiers(this); } + set { SetModifiers(this, value); } + } + + public IEnumerable ModifierTokens { + get { return GetChildrenByRole (ModifierRole); } + } + + internal static Modifiers GetModifiers(AstNode node) + { + Modifiers m = 0; + foreach (VBModifierToken t in node.GetChildrenByRole (ModifierRole)) { + m |= t.Modifier; + } + return m; + } + + internal static void SetModifiers(AstNode node, Modifiers newValue) + { + Modifiers oldValue = GetModifiers(node); + AstNode insertionPos = node.GetChildrenByRole(Attribute.AttributeRole).LastOrDefault(); + foreach (Modifiers m in VBModifierToken.AllModifiers) { + if ((m & newValue) != 0) { + if ((m & oldValue) == 0) { + // Modifier was added + var newToken = new VBModifierToken(AstLocation.Empty, m); + node.InsertChildAfter(insertionPos, newToken, ModifierRole); + insertionPos = newToken; + } else { + // Modifier already exists + insertionPos = node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m); + } + } else { + if ((m & oldValue) != 0) { + // Modifier was removed + node.GetChildrenByRole (ModifierRole).First(t => t.Modifier == m).Remove(); + } + } + } + } + + protected bool MatchAttributesAndModifiers(AttributedNode o, PatternMatching.Match match) + { + return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch(o.Attributes, match); + } + } + + +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs new file mode 100644 index 0000000000..6dbe784277 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs @@ -0,0 +1,81 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class CompilationUnit : AstNode + { + public static readonly Role MemberRole = new Role("Member", AstNode.Null); + + public CompilationUnit () + { + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CompilationUnit o = other as CompilationUnit; + return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match); + } + + public AstNode GetNodeAt (int line, int column) + { + return GetNodeAt (new AstLocation (line, column)); + } + + public AstNode GetNodeAt (AstLocation location) + { + AstNode node = this; + while (node.FirstChild != null) { + var child = node.FirstChild; + while (child != null) { + if (child.StartLocation <= location && location < child.EndLocation) { + node = child; + break; + } + child = child.NextSibling; + } + // found no better child node - therefore the parent is the right one. + if (child == null) + break; + } + return node; + } + + public IEnumerable GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn) + { + return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn)); + } + + public IEnumerable GetNodesBetween (AstLocation start, AstLocation end) + { + AstNode node = this; + while (node != null) { + AstNode next; + if (start <= node.StartLocation && node.EndLocation <= end) { + // Remember next before yielding node. + // This allows iteration to continue when the caller removes/replaces the node. + next = node.NextSibling; + yield return node; + } else { + if (node.EndLocation < start) { + next = node.NextSibling; + } else { + next = node.FirstChild; + } + } + + if (next != null && next.StartLocation > end) + yield break; + node = next; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCompilationUnit (this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs new file mode 100644 index 0000000000..87b4162b4f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs @@ -0,0 +1,40 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ParameterDeclaration : AttributedNode + { + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public Expression OptionalValue { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var param = other as ParameterDeclaration; + return param != null && + MatchAttributesAndModifiers(param, match) && + Name.DoMatch(param.Name, match) && + OptionalValue.DoMatch(param.OptionalValue, match) && + ReturnType.DoMatch(param.ReturnType, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitParameterDeclaration(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs new file mode 100644 index 0000000000..90be4263a7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// [In|Out] Name [As Contraints] + /// + /// Represents a type parameter. + /// + public class TypeParameterDeclaration : AstNode + { + public static readonly Role TypeConstraintRole = TypeDeclaration.InheritsTypeRole; + public static readonly Role VarianceRole = new Role("Variance"); + + public VarianceModifier Variance { get; set; } + + public string Name { + get { return GetChildByRole (Roles.Identifier).Name; } + set { SetChildByRole(Roles.Identifier, new Identifier (value, AstLocation.Empty)); } + } + + public AstNodeCollection Constraints { + get { return GetChildrenByRole(TypeConstraintRole); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeParameterDeclaration(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeParameterDeclaration o = other as TypeParameterDeclaration; + return o != null && this.Variance == o.Variance + && MatchString(this.Name, o.Name) + && this.Constraints.DoMatch(o.Constraints, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Generated.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Generated.cs new file mode 100644 index 0000000000..bd973a0d79 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Generated.cs @@ -0,0 +1,4866 @@ +//// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +//// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +//using System; +//using System.Collections.Generic; +// +//namespace ICSharpCode.NRefactory.VB.Ast { +// public class AddHandlerStatement : Statement { +// +// Expression eventExpression; +// +// Expression handlerExpression; +// +// public Expression EventExpression { +// get { +// return eventExpression; +// } +// set { +// eventExpression = value ?? Expression.Null; +// if (!eventExpression.IsNull) eventExpression.Parent = this; +// } +// } +// +// public Expression HandlerExpression { +// get { +// return handlerExpression; +// } +// set { +// handlerExpression = value ?? Expression.Null; +// if (!handlerExpression.IsNull) handlerExpression.Parent = this; +// } +// } +// +// public AddHandlerStatement(Expression eventExpression, Expression handlerExpression) { +// EventExpression = eventExpression; +// HandlerExpression = handlerExpression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitAddHandlerStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[AddHandlerStatement EventExpression={0} HandlerExpression={1}]", EventExpression, HandlerExpression); +// } +// } +// +// public class AddressOfExpression : Expression { +// +// Expression expression; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public AddressOfExpression(Expression expression) { +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitAddressOfExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[AddressOfExpression Expression={0}]", Expression); +// } +// } +// +// public class ArrayCreateExpression : Expression { +// +// TypeReference createType; +// +// List arguments; +// +// CollectionInitializerExpression arrayInitializer; +// +// public TypeReference CreateType { +// get { +// return createType; +// } +// set { +// createType = value ?? TypeReference.Null; +// if (!createType.IsNull) createType.Parent = this; +// } +// } +// +// public List Arguments { +// get { +// return arguments; +// } +// set { +// arguments = value ?? new List(); +// } +// } +// +// public CollectionInitializerExpression ArrayInitializer { +// get { +// return arrayInitializer; +// } +// set { +// arrayInitializer = value ?? CollectionInitializerExpression.Null; +// if (!arrayInitializer.IsNull) arrayInitializer.Parent = this; +// } +// } +// +// public ArrayCreateExpression(TypeReference createType) { +// CreateType = createType; +// arguments = new List(); +// arrayInitializer = CollectionInitializerExpression.Null; +// } +// +// public ArrayCreateExpression(TypeReference createType, List arguments) { +// CreateType = createType; +// Arguments = arguments; +// arrayInitializer = CollectionInitializerExpression.Null; +// } +// +// public ArrayCreateExpression(TypeReference createType, CollectionInitializerExpression arrayInitializer) { +// CreateType = createType; +// ArrayInitializer = arrayInitializer; +// arguments = new List(); +// } +// +// public bool IsImplicitlyTyped { +// get { +// return createType.IsNull || string.IsNullOrEmpty(createType.Type); +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitArrayCreateExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ArrayCreateExpression CreateType={0} Arguments={1} ArrayInitializer={2}]", CreateType, GetCollectionString(Arguments), ArrayInitializer); +// } +// } +// +// public class AssignmentExpression : Expression { +// +// Expression left; +// +// AssignmentOperatorType op; +// +// Expression right; +// +// public Expression Left { +// get { +// return left; +// } +// set { +// left = value ?? Expression.Null; +// if (!left.IsNull) left.Parent = this; +// } +// } +// +// public AssignmentOperatorType Op { +// get { +// return op; +// } +// set { +// op = value; +// } +// } +// +// public Expression Right { +// get { +// return right; +// } +// set { +// right = value ?? Expression.Null; +// if (!right.IsNull) right.Parent = this; +// } +// } +// +// public AssignmentExpression(Expression left, AssignmentOperatorType op, Expression right) { +// Left = left; +// Op = op; +// Right = right; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitAssignmentExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[AssignmentExpression Left={0} Op={1} Right={2}]", Left, Op, Right); +// } +// } +// +// public abstract class AttributedNode : AbstractNode { +// +// List attributes; +// +// Modifiers modifier; +// +// public List Attributes { +// get { +// return attributes; +// } +// set { +// attributes = value ?? new List(); +// } +// } +// +// public Modifiers Modifier { +// get { +// return modifier; +// } +// set { +// modifier = value; +// } +// } +// +// protected AttributedNode() { +// attributes = new List(); +// } +// +// protected AttributedNode(List attributes) { +// Attributes = attributes; +// } +// +// protected AttributedNode(Modifiers modifier, List attributes) { +// Modifier = modifier; +// Attributes = attributes; +// } +// } +// +// public class AttributeSection : AbstractNode { +// +// string attributeTarget; +// +// List attributes; +// +// public string AttributeTarget { +// get { +// return attributeTarget; +// } +// set { +// attributeTarget = value ?? ""; +// } +// } +// +// public List Attributes { +// get { +// return attributes; +// } +// set { +// attributes = value ?? new List(); +// } +// } +// +// public AttributeSection() { +// attributeTarget = ""; +// attributes = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitAttributeSection(this, data); +// } +// +// public override string ToString() { +// return string.Format("[AttributeSection AttributeTarget={0} Attributes={1}]", AttributeTarget, GetCollectionString(Attributes)); +// } +// } +// +// public class BaseReferenceExpression : Expression { +// +// public BaseReferenceExpression() { +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitBaseReferenceExpression(this, data); +// } +// +// public override string ToString() { +// return "[BaseReferenceExpression]"; +// } +// } +// +// public class BinaryOperatorExpression : Expression { +// +// Expression left; +// +// BinaryOperatorType op; +// +// Expression right; +// +// public Expression Left { +// get { +// return left; +// } +// set { +// left = value ?? Expression.Null; +// if (!left.IsNull) left.Parent = this; +// } +// } +// +// public BinaryOperatorType Op { +// get { +// return op; +// } +// set { +// op = value; +// } +// } +// +// public Expression Right { +// get { +// return right; +// } +// set { +// right = value ?? Expression.Null; +// if (!right.IsNull) right.Parent = this; +// } +// } +// +// public BinaryOperatorExpression() { +// left = Expression.Null; +// right = Expression.Null; +// } +// +// public BinaryOperatorExpression(Expression left, BinaryOperatorType op, Expression right) { +// Left = left; +// Op = op; +// Right = right; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitBinaryOperatorExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[BinaryOperatorExpression Left={0} Op={1} Right={2}]", Left, Op, Right); +// } +// } +// +// public class CaseLabel : AbstractNode { +// +// Expression label; +// +// BinaryOperatorType binaryOperatorType; +// +// Expression toExpression; +// +// public Expression Label { +// get { +// return label; +// } +// set { +// label = value ?? Expression.Null; +// if (!label.IsNull) label.Parent = this; +// } +// } +// +// public BinaryOperatorType BinaryOperatorType { +// get { +// return binaryOperatorType; +// } +// set { +// binaryOperatorType = value; +// } +// } +// +// public Expression ToExpression { +// get { +// return toExpression; +// } +// set { +// toExpression = value ?? Expression.Null; +// if (!toExpression.IsNull) toExpression.Parent = this; +// } +// } +// +// public CaseLabel() { +// label = Expression.Null; +// toExpression = Expression.Null; +// } +// +// public CaseLabel(Expression label) { +// Label = label; +// toExpression = Expression.Null; +// } +// +// public CaseLabel(Expression label, Expression toExpression) { +// Label = label; +// ToExpression = toExpression; +// } +// +// public CaseLabel(BinaryOperatorType binaryOperatorType, Expression label) { +// BinaryOperatorType = binaryOperatorType; +// Label = label; +// toExpression = Expression.Null; +// } +// +// public bool IsDefault { +// get { +// return label.IsNull; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitCaseLabel(this, data); +// } +// +// public override string ToString() { +// return string.Format("[CaseLabel Label={0} BinaryOperatorType={1} ToExpression={2}]", Label, BinaryOperatorType, ToExpression); +// } +// } +// +// public class CastExpression : Expression { +// +// TypeReference castTo; +// +// Expression expression; +// +// CastType castType; +// +// public TypeReference CastTo { +// get { +// return castTo; +// } +// set { +// castTo = value ?? TypeReference.Null; +// if (!castTo.IsNull) castTo.Parent = this; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public CastType CastType { +// get { +// return castType; +// } +// set { +// castType = value; +// } +// } +// +// public CastExpression(TypeReference castTo) { +// CastTo = castTo; +// expression = Expression.Null; +// } +// +// public CastExpression(TypeReference castTo, Expression expression, CastType castType) { +// CastTo = castTo; +// Expression = expression; +// CastType = castType; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitCastExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[CastExpression CastTo={0} Expression={1} CastType={2}]", CastTo, Expression, CastType); +// } +// } +// +// public class CatchClause : AbstractNode { +// +// TypeReference typeReference; +// +// string variableName; +// +// Statement statementBlock; +// +// Expression condition; +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public string VariableName { +// get { +// return variableName; +// } +// set { +// variableName = value ?? ""; +// } +// } +// +// public Statement StatementBlock { +// get { +// return statementBlock; +// } +// set { +// statementBlock = value ?? Statement.Null; +// if (!statementBlock.IsNull) statementBlock.Parent = this; +// } +// } +// +// public Expression Condition { +// get { +// return condition; +// } +// set { +// condition = value ?? Expression.Null; +// if (!condition.IsNull) condition.Parent = this; +// } +// } +// +// public CatchClause(TypeReference typeReference, string variableName, Statement statementBlock) { +// TypeReference = typeReference; +// VariableName = variableName; +// StatementBlock = statementBlock; +// condition = Expression.Null; +// } +// +// public CatchClause(TypeReference typeReference, string variableName, Statement statementBlock, Expression condition) { +// TypeReference = typeReference; +// VariableName = variableName; +// StatementBlock = statementBlock; +// Condition = condition; +// } +// +// public CatchClause(Statement statementBlock) { +// StatementBlock = statementBlock; +// typeReference = TypeReference.Null; +// variableName = ""; +// condition = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitCatchClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[CatchClause TypeReference={0} VariableName={1} StatementBlock={2} Condition={3}]" + +// "", TypeReference, VariableName, StatementBlock, Condition); +// } +// } +// +// public class ClassReferenceExpression : Expression { +// +// public ClassReferenceExpression() { +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitClassReferenceExpression(this, data); +// } +// +// public override string ToString() { +// return "[ClassReferenceExpression]"; +// } +// } +// +// public class CollectionInitializerExpression : Expression { +// +// List createExpressions; +// +// public List CreateExpressions { +// get { +// return createExpressions; +// } +// set { +// createExpressions = value ?? new List(); +// } +// } +// +// public CollectionInitializerExpression() { +// createExpressions = new List(); +// } +// +// public CollectionInitializerExpression(List createExpressions) { +// CreateExpressions = createExpressions; +// } +// +// public new static CollectionInitializerExpression Null { +// get { +// return NullCollectionInitializerExpression.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitCollectionInitializerExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[CollectionInitializerExpression CreateExpressions={0}]", GetCollectionString(CreateExpressions)); +// } +// } +// +// internal sealed class NullCollectionInitializerExpression : CollectionInitializerExpression { +// +// internal static NullCollectionInitializerExpression Instance = new NullCollectionInitializerExpression(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullCollectionInitializerExpression]"; +// } +// } +// +// public class CollectionRangeVariable : AbstractNode, INullable { +// +// string identifier; +// +// Expression expression; +// +// TypeReference type; +// +// public string Identifier { +// get { +// return identifier; +// } +// set { +// identifier = value ?? ""; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public TypeReference Type { +// get { +// return type; +// } +// set { +// type = value ?? TypeReference.Null; +// if (!type.IsNull) type.Parent = this; +// } +// } +// +// public CollectionRangeVariable() { +// identifier = ""; +// expression = Expression.Null; +// type = TypeReference.Null; +// } +// +// public virtual bool IsNull { +// get { +// return false; +// } +// } +// +// public static CollectionRangeVariable Null { +// get { +// return NullCollectionRangeVariable.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitCollectionRangeVariable(this, data); +// } +// +// public override string ToString() { +// return string.Format("[CollectionRangeVariable Identifier={0} Expression={1} Type={2}]", Identifier, Expression, Type); +// } +// } +// +// internal sealed class NullCollectionRangeVariable : CollectionRangeVariable { +// +// internal static NullCollectionRangeVariable Instance = new NullCollectionRangeVariable(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullCollectionRangeVariable]"; +// } +// } +// +// public class ConditionalExpression : Expression { +// +// Expression condition; +// +// Expression trueExpression; +// +// Expression falseExpression; +// +// public Expression Condition { +// get { +// return condition; +// } +// set { +// condition = value ?? Expression.Null; +// if (!condition.IsNull) condition.Parent = this; +// } +// } +// +// public Expression TrueExpression { +// get { +// return trueExpression; +// } +// set { +// trueExpression = value ?? Expression.Null; +// if (!trueExpression.IsNull) trueExpression.Parent = this; +// } +// } +// +// public Expression FalseExpression { +// get { +// return falseExpression; +// } +// set { +// falseExpression = value ?? Expression.Null; +// if (!falseExpression.IsNull) falseExpression.Parent = this; +// } +// } +// +// public ConditionalExpression() { +// condition = Expression.Null; +// trueExpression = Expression.Null; +// falseExpression = Expression.Null; +// } +// +// public ConditionalExpression(Expression condition, Expression trueExpression, Expression falseExpression) { +// Condition = condition; +// TrueExpression = trueExpression; +// FalseExpression = falseExpression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitConditionalExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ConditionalExpression Condition={0} TrueExpression={1} FalseExpression={2}]", Condition, TrueExpression, FalseExpression); +// } +// } +// +// public class ConstructorDeclaration : ParametrizedNode { +// +// ConstructorInitializer constructorInitializer; +// +// BlockStatement body; +// +// public ConstructorInitializer ConstructorInitializer { +// get { +// return constructorInitializer; +// } +// set { +// constructorInitializer = value ?? ConstructorInitializer.Null; +// if (!constructorInitializer.IsNull) constructorInitializer.Parent = this; +// } +// } +// +// public BlockStatement Body { +// get { +// return body; +// } +// set { +// body = value ?? BlockStatement.Null; +// if (!body.IsNull) body.Parent = this; +// } +// } +// +// public ConstructorDeclaration(string name, Modifiers modifier, List parameters, List attributes) { +// Name = name; +// Modifier = modifier; +// Parameters = parameters; +// Attributes = attributes; +// constructorInitializer = ConstructorInitializer.Null; +// body = BlockStatement.Null; +// } +// +// public ConstructorDeclaration(string name, Modifiers modifier, List parameters, ConstructorInitializer constructorInitializer, List attributes) { +// Name = name; +// Modifier = modifier; +// Parameters = parameters; +// ConstructorInitializer = constructorInitializer; +// Attributes = attributes; +// body = BlockStatement.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitConstructorDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ConstructorDeclaration ConstructorInitializer={0} Body={1} Name={2} Parameters={" + +// "3} Attributes={4} Modifier={5}]", ConstructorInitializer, Body, Name, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class ConstructorInitializer : AbstractNode, INullable { +// +// ConstructorInitializerType constructorInitializerType; +// +// List arguments; +// +// public ConstructorInitializerType ConstructorInitializerType { +// get { +// return constructorInitializerType; +// } +// set { +// constructorInitializerType = value; +// } +// } +// +// public List Arguments { +// get { +// return arguments; +// } +// set { +// arguments = value ?? new List(); +// } +// } +// +// public ConstructorInitializer() { +// arguments = new List(); +// } +// +// public virtual bool IsNull { +// get { +// return false; +// } +// } +// +// public static ConstructorInitializer Null { +// get { +// return NullConstructorInitializer.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitConstructorInitializer(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ConstructorInitializer ConstructorInitializerType={0} Arguments={1}]", ConstructorInitializerType, GetCollectionString(Arguments)); +// } +// } +// +// internal sealed class NullConstructorInitializer : ConstructorInitializer { +// +// internal static NullConstructorInitializer Instance = new NullConstructorInitializer(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullConstructorInitializer]"; +// } +// } +// +// public class ContinueStatement : Statement { +// +// ContinueType continueType; +// +// public ContinueType ContinueType { +// get { +// return continueType; +// } +// set { +// continueType = value; +// } +// } +// +// public ContinueStatement() { +// } +// +// public ContinueStatement(ContinueType continueType) { +// ContinueType = continueType; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitContinueStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ContinueStatement ContinueType={0}]", ContinueType); +// } +// } +// +// public class DeclareDeclaration : ParametrizedNode { +// +// string alias; +// +// string library; +// +// CharsetModifier charset; +// +// TypeReference typeReference; +// +// public string Alias { +// get { +// return alias; +// } +// set { +// alias = value ?? ""; +// } +// } +// +// public string Library { +// get { +// return library; +// } +// set { +// library = value ?? ""; +// } +// } +// +// public CharsetModifier Charset { +// get { +// return charset; +// } +// set { +// charset = value; +// } +// } +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public DeclareDeclaration(string name, Modifiers modifier, TypeReference typeReference, List parameters, List attributes, string library, string alias, CharsetModifier charset) { +// Name = name; +// Modifier = modifier; +// TypeReference = typeReference; +// Parameters = parameters; +// Attributes = attributes; +// Library = library; +// Alias = alias; +// Charset = charset; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitDeclareDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[DeclareDeclaration Alias={0} Library={1} Charset={2} TypeReference={3} Name={4} " + +// "Parameters={5} Attributes={6} Modifier={7}]", Alias, Library, Charset, TypeReference, Name, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class DefaultValueExpression : Expression { +// +// TypeReference typeReference; +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public DefaultValueExpression(TypeReference typeReference) { +// TypeReference = typeReference; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitDefaultValueExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[DefaultValueExpression TypeReference={0}]", TypeReference); +// } +// } +// +// public class DelegateDeclaration : AttributedNode { +// +// string name; +// +// TypeReference returnType; +// +// List parameters; +// +// List templates; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = string.IsNullOrEmpty(value) ? "?" : value; +// } +// } +// +// public TypeReference ReturnType { +// get { +// return returnType; +// } +// set { +// returnType = value ?? TypeReference.Null; +// if (!returnType.IsNull) returnType.Parent = this; +// } +// } +// +// public List Parameters { +// get { +// return parameters; +// } +// set { +// parameters = value ?? new List(); +// } +// } +// +// public List Templates { +// get { +// return templates; +// } +// set { +// templates = value ?? new List(); +// } +// } +// +// public DelegateDeclaration(Modifiers modifier, List attributes) { +// Modifier = modifier; +// Attributes = attributes; +// name = "?"; +// returnType = TypeReference.Null; +// parameters = new List(); +// templates = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitDelegateDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[DelegateDeclaration Name={0} ReturnType={1} Parameters={2} Templates={3} Attribu" + +// "tes={4} Modifier={5}]", Name, ReturnType, GetCollectionString(Parameters), GetCollectionString(Templates), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class DirectionExpression : Expression { +// +// FieldDirection fieldDirection; +// +// Expression expression; +// +// public FieldDirection FieldDirection { +// get { +// return fieldDirection; +// } +// set { +// fieldDirection = value; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public DirectionExpression(FieldDirection fieldDirection, Expression expression) { +// FieldDirection = fieldDirection; +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitDirectionExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[DirectionExpression FieldDirection={0} Expression={1}]", FieldDirection, Expression); +// } +// } +// +// public class DoLoopStatement : StatementWithEmbeddedStatement { +// +// Expression condition; +// +// ConditionType conditionType; +// +// ConditionPosition conditionPosition; +// +// public Expression Condition { +// get { +// return condition; +// } +// set { +// condition = value ?? Expression.Null; +// if (!condition.IsNull) condition.Parent = this; +// } +// } +// +// public ConditionType ConditionType { +// get { +// return conditionType; +// } +// set { +// conditionType = value; +// } +// } +// +// public ConditionPosition ConditionPosition { +// get { +// return conditionPosition; +// } +// set { +// conditionPosition = value; +// } +// } +// +// public DoLoopStatement(Expression condition, Statement embeddedStatement, ConditionType conditionType, ConditionPosition conditionPosition) { +// Condition = condition; +// EmbeddedStatement = embeddedStatement; +// ConditionType = conditionType; +// ConditionPosition = conditionPosition; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitDoLoopStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[DoLoopStatement Condition={0} ConditionType={1} ConditionPosition={2} EmbeddedSt" + +// "atement={3}]", Condition, ConditionType, ConditionPosition, EmbeddedStatement); +// } +// } +// +// public class ElseIfSection : StatementWithEmbeddedStatement { +// +// Expression condition; +// +// public Expression Condition { +// get { +// return condition; +// } +// set { +// condition = value ?? Expression.Null; +// if (!condition.IsNull) condition.Parent = this; +// } +// } +// +// public ElseIfSection(Expression condition, Statement embeddedStatement) { +// Condition = condition; +// EmbeddedStatement = embeddedStatement; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitElseIfSection(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ElseIfSection Condition={0} EmbeddedStatement={1}]", Condition, EmbeddedStatement); +// } +// } +// +// public class EndStatement : Statement { +// +// public EndStatement() { +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitEndStatement(this, data); +// } +// +// public override string ToString() { +// return "[EndStatement]"; +// } +// } +// +// public class EraseStatement : Statement { +// +// List expressions; +// +// public List Expressions { +// get { +// return expressions; +// } +// set { +// expressions = value ?? new List(); +// } +// } +// +// public EraseStatement() { +// expressions = new List(); +// } +// +// public EraseStatement(List expressions) { +// Expressions = expressions; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitEraseStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[EraseStatement Expressions={0}]", GetCollectionString(Expressions)); +// } +// } +// +// public class ErrorStatement : Statement { +// +// Expression expression; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public ErrorStatement(Expression expression) { +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitErrorStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ErrorStatement Expression={0}]", Expression); +// } +// } +// +// public class EventAddRegion : EventAddRemoveRegion { +// +// public EventAddRegion(List attributes) : +// base(attributes) { +// } +// +// public static EventAddRegion Null { +// get { +// return NullEventAddRegion.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitEventAddRegion(this, data); +// } +// +// public override string ToString() { +// return string.Format("[EventAddRegion Block={0} Parameters={1} Attributes={2} Modifier={3}]", Block, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// internal sealed class NullEventAddRegion : EventAddRegion { +// +// private NullEventAddRegion() : +// base(null) { +// } +// +// internal static NullEventAddRegion Instance = new NullEventAddRegion(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullEventAddRegion]"; +// } +// } +// +// public abstract class EventAddRemoveRegion : AttributedNode, INullable { +// +// BlockStatement block; +// +// List parameters; +// +// public BlockStatement Block { +// get { +// return block; +// } +// set { +// block = value ?? BlockStatement.Null; +// if (!block.IsNull) block.Parent = this; +// } +// } +// +// public List Parameters { +// get { +// return parameters; +// } +// set { +// parameters = value ?? new List(); +// } +// } +// +// protected EventAddRemoveRegion(List attributes) { +// Attributes = attributes; +// block = BlockStatement.Null; +// parameters = new List(); +// } +// +// public virtual bool IsNull { +// get { +// return false; +// } +// } +// } +// +// public class EventDeclaration : MemberNode { +// +// EventAddRegion addRegion; +// +// EventRemoveRegion removeRegion; +// +// EventRaiseRegion raiseRegion; +// +// Location bodyStart; +// +// Location bodyEnd; +// +// Expression initializer; +// +// public EventAddRegion AddRegion { +// get { +// return addRegion; +// } +// set { +// addRegion = value ?? EventAddRegion.Null; +// if (!addRegion.IsNull) addRegion.Parent = this; +// } +// } +// +// public EventRemoveRegion RemoveRegion { +// get { +// return removeRegion; +// } +// set { +// removeRegion = value ?? EventRemoveRegion.Null; +// if (!removeRegion.IsNull) removeRegion.Parent = this; +// } +// } +// +// public EventRaiseRegion RaiseRegion { +// get { +// return raiseRegion; +// } +// set { +// raiseRegion = value ?? EventRaiseRegion.Null; +// if (!raiseRegion.IsNull) raiseRegion.Parent = this; +// } +// } +// +// public Location BodyStart { +// get { +// return bodyStart; +// } +// set { +// bodyStart = value; +// } +// } +// +// public Location BodyEnd { +// get { +// return bodyEnd; +// } +// set { +// bodyEnd = value; +// } +// } +// +// public Expression Initializer { +// get { +// return initializer; +// } +// set { +// initializer = value ?? Expression.Null; +// if (!initializer.IsNull) initializer.Parent = this; +// } +// } +// +// public EventDeclaration() { +// addRegion = EventAddRegion.Null; +// removeRegion = EventRemoveRegion.Null; +// raiseRegion = EventRaiseRegion.Null; +// bodyStart = Location.Empty; +// bodyEnd = Location.Empty; +// initializer = Expression.Null; +// } +// +// public bool HasAddRegion { +// get { +// return !addRegion.IsNull; +// } +// } +// +// public bool HasRemoveRegion { +// get { +// return !removeRegion.IsNull; +// } +// } +// +// public bool HasRaiseRegion { +// get { +// return !raiseRegion.IsNull; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitEventDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[EventDeclaration AddRegion={0} RemoveRegion={1} RaiseRegion={2} BodyStart={3} Bo" + +// "dyEnd={4} Initializer={5} InterfaceImplementations={6} TypeReference={7} Name={8" + +// "} Parameters={9} Attributes={10} Modifier={11}]", AddRegion, RemoveRegion, RaiseRegion, BodyStart, BodyEnd, Initializer, GetCollectionString(InterfaceImplementations), TypeReference, Name, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class EventRaiseRegion : EventAddRemoveRegion { +// +// public EventRaiseRegion(List attributes) : +// base(attributes) { +// } +// +// public static EventRaiseRegion Null { +// get { +// return NullEventRaiseRegion.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitEventRaiseRegion(this, data); +// } +// +// public override string ToString() { +// return string.Format("[EventRaiseRegion Block={0} Parameters={1} Attributes={2} Modifier={3}]", Block, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// internal sealed class NullEventRaiseRegion : EventRaiseRegion { +// +// private NullEventRaiseRegion() : +// base(null) { +// } +// +// internal static NullEventRaiseRegion Instance = new NullEventRaiseRegion(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullEventRaiseRegion]"; +// } +// } +// +// public class EventRemoveRegion : EventAddRemoveRegion { +// +// public EventRemoveRegion(List attributes) : +// base(attributes) { +// } +// +// public static EventRemoveRegion Null { +// get { +// return NullEventRemoveRegion.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitEventRemoveRegion(this, data); +// } +// +// public override string ToString() { +// return string.Format("[EventRemoveRegion Block={0} Parameters={1} Attributes={2} Modifier={3}]", Block, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// internal sealed class NullEventRemoveRegion : EventRemoveRegion { +// +// private NullEventRemoveRegion() : +// base(null) { +// } +// +// internal static NullEventRemoveRegion Instance = new NullEventRemoveRegion(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullEventRemoveRegion]"; +// } +// } +// +// public class ExitStatement : Statement { +// +// ExitType exitType; +// +// public ExitType ExitType { +// get { +// return exitType; +// } +// set { +// exitType = value; +// } +// } +// +// public ExitStatement(ExitType exitType) { +// ExitType = exitType; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitExitStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ExitStatement ExitType={0}]", ExitType); +// } +// } +// +// public class ExpressionRangeVariable : AbstractNode, INullable { +// +// string identifier; +// +// Expression expression; +// +// TypeReference type; +// +// public string Identifier { +// get { +// return identifier; +// } +// set { +// identifier = value ?? ""; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public TypeReference Type { +// get { +// return type; +// } +// set { +// type = value ?? TypeReference.Null; +// if (!type.IsNull) type.Parent = this; +// } +// } +// +// public ExpressionRangeVariable() { +// identifier = ""; +// expression = Expression.Null; +// type = TypeReference.Null; +// } +// +// public virtual bool IsNull { +// get { +// return false; +// } +// } +// +// public static ExpressionRangeVariable Null { +// get { +// return NullExpressionRangeVariable.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitExpressionRangeVariable(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ExpressionRangeVariable Identifier={0} Expression={1} Type={2}]", Identifier, Expression, Type); +// } +// } +// +// internal sealed class NullExpressionRangeVariable : ExpressionRangeVariable { +// +// internal static NullExpressionRangeVariable Instance = new NullExpressionRangeVariable(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullExpressionRangeVariable]"; +// } +// } +// +// public class ExpressionStatement : Statement { +// +// Expression expression; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public ExpressionStatement(Expression expression) { +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitExpressionStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ExpressionStatement Expression={0}]", Expression); +// } +// } +// +// public class ExternAliasDirective : AbstractNode { +// +// string name; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public ExternAliasDirective() { +// name = ""; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitExternAliasDirective(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ExternAliasDirective Name={0}]", Name); +// } +// } +// +// public class FieldDeclaration : AttributedNode { +// +// TypeReference typeReference; +// +// List fields; +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public List Fields { +// get { +// return fields; +// } +// set { +// fields = value ?? new List(); +// } +// } +// +// public FieldDeclaration(List attributes) { +// Attributes = attributes; +// typeReference = TypeReference.Null; +// fields = new List(); +// } +// +// public FieldDeclaration(List attributes, TypeReference typeReference, Modifiers modifier) { +// Attributes = attributes; +// TypeReference = typeReference; +// Modifier = modifier; +// fields = new List(); +// } +// +// +// public TypeReference GetTypeForField(int fieldIndex) +// { +// if (!typeReference.IsNull) { +// return typeReference; +// } +// return ((VariableDeclaration)Fields[fieldIndex]).TypeReference; +// } +// +// +// public VariableDeclaration GetVariableDeclaration(string variableName) +// { +// foreach (VariableDeclaration variableDeclaration in Fields) { +// if (variableDeclaration.Name == variableName) { +// return variableDeclaration; +// } +// } +// return null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitFieldDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[FieldDeclaration TypeReference={0} Fields={1} Attributes={2} Modifier={3}]", TypeReference, GetCollectionString(Fields), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class ForeachStatement : StatementWithEmbeddedStatement { +// +// TypeReference typeReference; +// +// string variableName; +// +// Expression expression; +// +// Expression nextExpression; +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public string VariableName { +// get { +// return variableName; +// } +// set { +// variableName = value ?? ""; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public Expression NextExpression { +// get { +// return nextExpression; +// } +// set { +// nextExpression = value ?? Expression.Null; +// if (!nextExpression.IsNull) nextExpression.Parent = this; +// } +// } +// +// public ForeachStatement(TypeReference typeReference, string variableName, Expression expression, Statement embeddedStatement) { +// TypeReference = typeReference; +// VariableName = variableName; +// Expression = expression; +// EmbeddedStatement = embeddedStatement; +// nextExpression = Expression.Null; +// } +// +// public ForeachStatement(TypeReference typeReference, string variableName, Expression expression, Statement embeddedStatement, Expression nextExpression) { +// TypeReference = typeReference; +// VariableName = variableName; +// Expression = expression; +// EmbeddedStatement = embeddedStatement; +// NextExpression = nextExpression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitForeachStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ForeachStatement TypeReference={0} VariableName={1} Expression={2} NextExpressio" + +// "n={3} EmbeddedStatement={4}]", TypeReference, VariableName, Expression, NextExpression, EmbeddedStatement); +// } +// } +// +// public class ForNextStatement : StatementWithEmbeddedStatement { +// +// Expression start; +// +// Expression end; +// +// Expression step; +// +// List nextExpressions; +// +// TypeReference typeReference; +// +// string variableName; +// +// Expression loopVariableExpression; +// +// public Expression Start { +// get { +// return start; +// } +// set { +// start = value ?? Expression.Null; +// if (!start.IsNull) start.Parent = this; +// } +// } +// +// public Expression End { +// get { +// return end; +// } +// set { +// end = value ?? Expression.Null; +// if (!end.IsNull) end.Parent = this; +// } +// } +// +// public Expression Step { +// get { +// return step; +// } +// set { +// step = value ?? Expression.Null; +// if (!step.IsNull) step.Parent = this; +// } +// } +// +// public List NextExpressions { +// get { +// return nextExpressions; +// } +// set { +// nextExpressions = value ?? new List(); +// } +// } +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public string VariableName { +// get { +// return variableName; +// } +// set { +// variableName = value ?? ""; +// } +// } +// +// public Expression LoopVariableExpression { +// get { +// return loopVariableExpression; +// } +// set { +// loopVariableExpression = value ?? Expression.Null; +// if (!loopVariableExpression.IsNull) loopVariableExpression.Parent = this; +// } +// } +// +// public ForNextStatement() { +// start = Expression.Null; +// end = Expression.Null; +// step = Expression.Null; +// nextExpressions = new List(); +// typeReference = TypeReference.Null; +// variableName = ""; +// loopVariableExpression = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitForNextStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ForNextStatement Start={0} End={1} Step={2} NextExpressions={3} TypeReference={4" + +// "} VariableName={5} LoopVariableExpression={6} EmbeddedStatement={7}]", Start, End, Step, GetCollectionString(NextExpressions), TypeReference, VariableName, LoopVariableExpression, EmbeddedStatement); +// } +// } +// +// public class GotoStatement : Statement { +// +// string label; +// +// public string Label { +// get { +// return label; +// } +// set { +// label = value ?? ""; +// } +// } +// +// public GotoStatement(string label) { +// Label = label; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitGotoStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[GotoStatement Label={0}]", Label); +// } +// } +// +// public class IfElseStatement : Statement { +// +// Expression condition; +// +// List trueStatement; +// +// List falseStatement; +// +// List elseIfSections; +// +// public Expression Condition { +// get { +// return condition; +// } +// set { +// condition = value ?? Expression.Null; +// if (!condition.IsNull) condition.Parent = this; +// } +// } +// +// public List TrueStatement { +// get { +// return trueStatement; +// } +// set { +// trueStatement = value ?? new List(); +// } +// } +// +// public List FalseStatement { +// get { +// return falseStatement; +// } +// set { +// falseStatement = value ?? new List(); +// } +// } +// +// public List ElseIfSections { +// get { +// return elseIfSections; +// } +// set { +// elseIfSections = value ?? new List(); +// } +// } +// +// public IfElseStatement(Expression condition) { +// Condition = condition; +// trueStatement = new List(); +// falseStatement = new List(); +// elseIfSections = new List(); +// } +// +// +// public IfElseStatement(Expression condition, Statement trueStatement) +// : this(condition) { +// this.trueStatement.Add(Statement.CheckNull(trueStatement)); +// if (trueStatement != null) trueStatement.Parent = this; +// } +// +// public bool HasElseStatements { +// get { +// return falseStatement.Count > 0; +// } +// } +// +// public bool HasElseIfSections { +// get { +// return elseIfSections.Count > 0; +// } +// } +// +// +// public IfElseStatement(Expression condition, Statement trueStatement, Statement falseStatement) +// : this(condition) { +// this.trueStatement.Add(Statement.CheckNull(trueStatement)); +// this.falseStatement.Add(Statement.CheckNull(falseStatement)); +// if (trueStatement != null) trueStatement.Parent = this; +// if (falseStatement != null) falseStatement.Parent = this; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitIfElseStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[IfElseStatement Condition={0} TrueStatement={1} FalseStatement={2} ElseIfSection" + +// "s={3}]", Condition, GetCollectionString(TrueStatement), GetCollectionString(FalseStatement), GetCollectionString(ElseIfSections)); +// } +// } +// +// public class InterfaceImplementation : AbstractNode { +// +// TypeReference interfaceType; +// +// string memberName; +// +// public TypeReference InterfaceType { +// get { +// return interfaceType; +// } +// set { +// interfaceType = value ?? TypeReference.Null; +// if (!interfaceType.IsNull) interfaceType.Parent = this; +// } +// } +// +// public string MemberName { +// get { +// return memberName; +// } +// set { +// memberName = string.IsNullOrEmpty(value) ? "?" : value; +// } +// } +// +// public InterfaceImplementation(TypeReference interfaceType, string memberName) { +// InterfaceType = interfaceType; +// MemberName = memberName; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitInterfaceImplementation(this, data); +// } +// +// public override string ToString() { +// return string.Format("[InterfaceImplementation InterfaceType={0} MemberName={1}]", InterfaceType, MemberName); +// } +// } +// +// public class InvocationExpression : Expression { +// +// Expression targetObject; +// +// List arguments; +// +// public Expression TargetObject { +// get { +// return targetObject; +// } +// set { +// targetObject = value ?? Expression.Null; +// if (!targetObject.IsNull) targetObject.Parent = this; +// } +// } +// +// public List Arguments { +// get { +// return arguments; +// } +// set { +// arguments = value ?? new List(); +// } +// } +// +// public InvocationExpression(Expression targetObject) { +// TargetObject = targetObject; +// arguments = new List(); +// } +// +// public InvocationExpression(Expression targetObject, List arguments) { +// TargetObject = targetObject; +// Arguments = arguments; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitInvocationExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[InvocationExpression TargetObject={0} Arguments={1}]", TargetObject, GetCollectionString(Arguments)); +// } +// } +// +// public class LabelStatement : Statement { +// +// string label; +// +// public string Label { +// get { +// return label; +// } +// set { +// label = value ?? ""; +// } +// } +// +// public LabelStatement(string label) { +// Label = label; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitLabelStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[LabelStatement Label={0}]", Label); +// } +// } +// +// public class LambdaExpression : Expression { +// +// List parameters; +// +// Statement statementBody; +// +// Expression expressionBody; +// +// TypeReference returnType; +// +// public List Parameters { +// get { +// return parameters; +// } +// set { +// parameters = value ?? new List(); +// } +// } +// +// public Statement StatementBody { +// get { +// return statementBody; +// } +// set { +// statementBody = value ?? Statement.Null; +// if (!statementBody.IsNull) statementBody.Parent = this; +// } +// } +// +// public Expression ExpressionBody { +// get { +// return expressionBody; +// } +// set { +// expressionBody = value ?? Expression.Null; +// if (!expressionBody.IsNull) expressionBody.Parent = this; +// } +// } +// +// public TypeReference ReturnType { +// get { +// return returnType; +// } +// set { +// returnType = value ?? TypeReference.Null; +// if (!returnType.IsNull) returnType.Parent = this; +// } +// } +// +// public LambdaExpression() { +// parameters = new List(); +// statementBody = Statement.Null; +// expressionBody = Expression.Null; +// returnType = TypeReference.Null; +// } +// +// public Location ExtendedEndLocation { get; set; } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitLambdaExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[LambdaExpression Parameters={0} StatementBody={1} ExpressionBody={2} ReturnType=" + +// "{3}]", GetCollectionString(Parameters), StatementBody, ExpressionBody, ReturnType); +// } +// } +// +// public class LockStatement : StatementWithEmbeddedStatement { +// +// Expression lockExpression; +// +// public Expression LockExpression { +// get { +// return lockExpression; +// } +// set { +// lockExpression = value ?? Expression.Null; +// if (!lockExpression.IsNull) lockExpression.Parent = this; +// } +// } +// +// public LockStatement(Expression lockExpression, Statement embeddedStatement) { +// LockExpression = lockExpression; +// EmbeddedStatement = embeddedStatement; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitLockStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[LockStatement LockExpression={0} EmbeddedStatement={1}]", LockExpression, EmbeddedStatement); +// } +// } +// +// public class MemberInitializerExpression : Expression { +// +// string name; +// +// bool isKey; +// +// Expression expression; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public bool IsKey { +// get { +// return isKey; +// } +// set { +// isKey = value; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public MemberInitializerExpression() { +// name = ""; +// expression = Expression.Null; +// } +// +// public MemberInitializerExpression(string name, Expression expression) { +// Name = name; +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitMemberInitializerExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[MemberInitializerExpression Name={0} IsKey={1} Expression={2}]", Name, IsKey, Expression); +// } +// } +// +// public abstract class MemberNode : ParametrizedNode { +// +// List interfaceImplementations; +// +// TypeReference typeReference; +// +// public List InterfaceImplementations { +// get { +// return interfaceImplementations; +// } +// set { +// interfaceImplementations = value ?? new List(); +// } +// } +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// protected MemberNode() { +// interfaceImplementations = new List(); +// typeReference = TypeReference.Null; +// } +// +// protected MemberNode(Modifiers modifier, List attributes, string name, List parameters) { +// Modifier = modifier; +// Attributes = attributes; +// Name = name; +// Parameters = parameters; +// interfaceImplementations = new List(); +// typeReference = TypeReference.Null; +// } +// } +// +// public class MemberReferenceExpression : Expression { +// +// Expression targetObject; +// +// string memberName; +// +// List typeArguments; +// +// public Expression TargetObject { +// get { +// return targetObject; +// } +// set { +// targetObject = value ?? Expression.Null; +// if (!targetObject.IsNull) targetObject.Parent = this; +// } +// } +// +// public string MemberName { +// get { +// return memberName; +// } +// set { +// memberName = value ?? ""; +// } +// } +// +// public List TypeArguments { +// get { +// return typeArguments; +// } +// set { +// typeArguments = value ?? new List(); +// } +// } +// +// public MemberReferenceExpression(Expression targetObject, string memberName) { +// TargetObject = targetObject; +// MemberName = memberName; +// typeArguments = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitMemberReferenceExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[MemberReferenceExpression TargetObject={0} MemberName={1} TypeArguments={2}]", TargetObject, MemberName, GetCollectionString(TypeArguments)); +// } +// } +// +// public class MethodDeclaration : MemberNode { +// +// BlockStatement body; +// +// List handlesClause; +// +// List templates; +// +// bool isExtensionMethod; +// +// public BlockStatement Body { +// get { +// return body; +// } +// set { +// body = value ?? BlockStatement.Null; +// if (!body.IsNull) body.Parent = this; +// } +// } +// +// public List HandlesClause { +// get { +// return handlesClause; +// } +// set { +// handlesClause = value ?? new List(); +// } +// } +// +// public List Templates { +// get { +// return templates; +// } +// set { +// templates = value ?? new List(); +// } +// } +// +// public bool IsExtensionMethod { +// get { +// return isExtensionMethod; +// } +// set { +// isExtensionMethod = value; +// } +// } +// +// public MethodDeclaration() { +// body = BlockStatement.Null; +// handlesClause = new List(); +// templates = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitMethodDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[MethodDeclaration Body={0} HandlesClause={1} Templates={2} IsExtensionMethod={3}" + +// " InterfaceImplementations={4} TypeReference={5} Name={6} Parameters={7} Attribut" + +// "es={8} Modifier={9}]", Body, GetCollectionString(HandlesClause), GetCollectionString(Templates), IsExtensionMethod, GetCollectionString(InterfaceImplementations), TypeReference, Name, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class NamedArgumentExpression : Expression { +// +// string name; +// +// Expression expression; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public NamedArgumentExpression() { +// name = ""; +// expression = Expression.Null; +// } +// +// public NamedArgumentExpression(string name, Expression expression) { +// Name = name; +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitNamedArgumentExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[NamedArgumentExpression Name={0} Expression={1}]", Name, Expression); +// } +// } +// +// public class NamespaceDeclaration : AbstractNode { +// +// string name; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public NamespaceDeclaration(string name) { +// Name = name; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitNamespaceDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[NamespaceDeclaration Name={0}]", Name); +// } +// } +// +// public class ObjectCreateExpression : Expression { +// +// TypeReference createType; +// +// List parameters; +// +// CollectionInitializerExpression objectInitializer; +// +// public TypeReference CreateType { +// get { +// return createType; +// } +// set { +// createType = value ?? TypeReference.Null; +// if (!createType.IsNull) createType.Parent = this; +// } +// } +// +// public List Parameters { +// get { +// return parameters; +// } +// set { +// parameters = value ?? new List(); +// } +// } +// +// public CollectionInitializerExpression ObjectInitializer { +// get { +// return objectInitializer; +// } +// set { +// objectInitializer = value ?? CollectionInitializerExpression.Null; +// if (!objectInitializer.IsNull) objectInitializer.Parent = this; +// } +// } +// +// public ObjectCreateExpression(TypeReference createType, List parameters) { +// CreateType = createType; +// Parameters = parameters; +// objectInitializer = CollectionInitializerExpression.Null; +// } +// +// public bool IsAnonymousType { +// get { +// return createType.IsNull || string.IsNullOrEmpty(createType.Type); +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitObjectCreateExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ObjectCreateExpression CreateType={0} Parameters={1} ObjectInitializer={2}]", CreateType, GetCollectionString(Parameters), ObjectInitializer); +// } +// } +// +// public class OnErrorStatement : StatementWithEmbeddedStatement { +// +// public OnErrorStatement(Statement embeddedStatement) { +// EmbeddedStatement = embeddedStatement; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitOnErrorStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[OnErrorStatement EmbeddedStatement={0}]", EmbeddedStatement); +// } +// } +// +// public class OperatorDeclaration : MethodDeclaration { +// +// ConversionType conversionType; +// +// OverloadableOperatorType overloadableOperator; +// +// public ConversionType ConversionType { +// get { +// return conversionType; +// } +// set { +// conversionType = value; +// } +// } +// +// public OverloadableOperatorType OverloadableOperator { +// get { +// return overloadableOperator; +// } +// set { +// overloadableOperator = value; +// } +// } +// +// public OperatorDeclaration() { +// } +// +// public bool IsConversionOperator { +// get { +// return conversionType != ConversionType.None; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitOperatorDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[OperatorDeclaration ConversionType={0} OverloadableOperator={1} Body={2} Handles" + +// "Clause={3} Templates={4} IsExtensionMethod={5} InterfaceImplementations={6} Type" + +// "Reference={7} Name={8} Parameters={9} Attributes={10} Modifier={11}]", ConversionType, OverloadableOperator, Body, GetCollectionString(HandlesClause), GetCollectionString(Templates), IsExtensionMethod, GetCollectionString(InterfaceImplementations), TypeReference, Name, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class ParameterDeclarationExpression : Expression { +// +// List attributes; +// +// string parameterName; +// +// TypeReference typeReference; +// +// ParameterModifiers paramModifier; +// +// Expression defaultValue; +// +// public List Attributes { +// get { +// return attributes; +// } +// set { +// attributes = value ?? new List(); +// } +// } +// +// public string ParameterName { +// get { +// return parameterName; +// } +// set { +// parameterName = string.IsNullOrEmpty(value) ? "?" : value; +// } +// } +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public ParameterModifiers ParamModifier { +// get { +// return paramModifier; +// } +// set { +// paramModifier = value; +// } +// } +// +// public Expression DefaultValue { +// get { +// return defaultValue; +// } +// set { +// defaultValue = value ?? Expression.Null; +// if (!defaultValue.IsNull) defaultValue.Parent = this; +// } +// } +// +// public ParameterDeclarationExpression(TypeReference typeReference, string parameterName) { +// TypeReference = typeReference; +// ParameterName = parameterName; +// attributes = new List(); +// defaultValue = Expression.Null; +// } +// +// public ParameterDeclarationExpression(TypeReference typeReference, string parameterName, ParameterModifiers paramModifier) { +// TypeReference = typeReference; +// ParameterName = parameterName; +// ParamModifier = paramModifier; +// attributes = new List(); +// defaultValue = Expression.Null; +// } +// +// public ParameterDeclarationExpression(TypeReference typeReference, string parameterName, ParameterModifiers paramModifier, Expression defaultValue) { +// TypeReference = typeReference; +// ParameterName = parameterName; +// ParamModifier = paramModifier; +// DefaultValue = defaultValue; +// attributes = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitParameterDeclarationExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ParameterDeclarationExpression Attributes={0} ParameterName={1} TypeReference={2" + +// "} ParamModifier={3} DefaultValue={4}]", GetCollectionString(Attributes), ParameterName, TypeReference, ParamModifier, DefaultValue); +// } +// } +// +// public abstract class ParametrizedNode : AttributedNode { +// +// string name; +// +// List parameters; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public List Parameters { +// get { +// return parameters; +// } +// set { +// parameters = value ?? new List(); +// } +// } +// +// protected ParametrizedNode() { +// name = ""; +// parameters = new List(); +// } +// +// protected ParametrizedNode(Modifiers modifier, List attributes, string name, List parameters) { +// Modifier = modifier; +// Attributes = attributes; +// Name = name; +// Parameters = parameters; +// } +// } +// +// public class ParenthesizedExpression : Expression { +// +// Expression expression; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public ParenthesizedExpression(Expression expression) { +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitParenthesizedExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ParenthesizedExpression Expression={0}]", Expression); +// } +// } +// +// public class PropertyDeclaration : MemberNode { +// +// Location bodyStart; +// +// Location bodyEnd; +// +// PropertyGetRegion getRegion; +// +// PropertySetRegion setRegion; +// +// Expression initializer; +// +// public Location BodyStart { +// get { +// return bodyStart; +// } +// set { +// bodyStart = value; +// } +// } +// +// public Location BodyEnd { +// get { +// return bodyEnd; +// } +// set { +// bodyEnd = value; +// } +// } +// +// public PropertyGetRegion GetRegion { +// get { +// return getRegion; +// } +// set { +// getRegion = value ?? PropertyGetRegion.Null; +// if (!getRegion.IsNull) getRegion.Parent = this; +// } +// } +// +// public PropertySetRegion SetRegion { +// get { +// return setRegion; +// } +// set { +// setRegion = value ?? PropertySetRegion.Null; +// if (!setRegion.IsNull) setRegion.Parent = this; +// } +// } +// +// public Expression Initializer { +// get { +// return initializer; +// } +// set { +// initializer = value ?? Expression.Null; +// if (!initializer.IsNull) initializer.Parent = this; +// } +// } +// +// public PropertyDeclaration(Modifiers modifier, List attributes, string name, List parameters) { +// Modifier = modifier; +// Attributes = attributes; +// Name = name; +// Parameters = parameters; +// bodyStart = Location.Empty; +// bodyEnd = Location.Empty; +// getRegion = PropertyGetRegion.Null; +// setRegion = PropertySetRegion.Null; +// initializer = Expression.Null; +// } +// +// public bool IsReadOnly { +// get { +// return HasGetRegion && !HasSetRegion; +// } +// } +// +// public bool HasGetRegion { +// get { +// return !getRegion.IsNull; +// } +// } +// +// public bool IsWriteOnly { +// get { +// return !HasGetRegion && HasSetRegion; +// } +// } +// +// public bool IsIndexer { +// get { +// return (Modifier & Modifiers.Default) != 0; +// } +// } +// +// +// internal PropertyDeclaration(string name, TypeReference typeReference, Modifiers modifier, List attributes) : this(modifier, attributes, name, null) +// { +// this.TypeReference = typeReference; +// if ((modifier & Modifiers.ReadOnly) != Modifiers.ReadOnly) { +// this.SetRegion = new PropertySetRegion(null, null); +// } +// if ((modifier & Modifiers.WriteOnly) != Modifiers.WriteOnly) { +// this.GetRegion = new PropertyGetRegion(null, null); +// } +// } +// +// public bool HasSetRegion { +// get { +// return !setRegion.IsNull; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitPropertyDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[PropertyDeclaration BodyStart={0} BodyEnd={1} GetRegion={2} SetRegion={3} Initia" + +// "lizer={4} InterfaceImplementations={5} TypeReference={6} Name={7} Parameters={8}" + +// " Attributes={9} Modifier={10}]", BodyStart, BodyEnd, GetRegion, SetRegion, Initializer, GetCollectionString(InterfaceImplementations), TypeReference, Name, GetCollectionString(Parameters), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class PropertyGetRegion : PropertyGetSetRegion { +// +// public PropertyGetRegion(BlockStatement block, List attributes) : +// base(block, attributes) { +// } +// +// public static PropertyGetRegion Null { +// get { +// return NullPropertyGetRegion.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitPropertyGetRegion(this, data); +// } +// +// public override string ToString() { +// return string.Format("[PropertyGetRegion Block={0} Attributes={1} Modifier={2}]", Block, GetCollectionString(Attributes), Modifier); +// } +// } +// +// internal sealed class NullPropertyGetRegion : PropertyGetRegion { +// +// private NullPropertyGetRegion() : +// base(null, null) { +// } +// +// internal static NullPropertyGetRegion Instance = new NullPropertyGetRegion(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullPropertyGetRegion]"; +// } +// } +// +// public abstract class PropertyGetSetRegion : AttributedNode, INullable { +// +// BlockStatement block; +// +// public BlockStatement Block { +// get { +// return block; +// } +// set { +// block = value ?? BlockStatement.Null; +// if (!block.IsNull) block.Parent = this; +// } +// } +// +// protected PropertyGetSetRegion(BlockStatement block, List attributes) { +// Block = block; +// Attributes = attributes; +// } +// +// public virtual bool IsNull { +// get { +// return false; +// } +// } +// } +// +// public class PropertySetRegion : PropertyGetSetRegion { +// +// List parameters; +// +// public List Parameters { +// get { +// return parameters; +// } +// set { +// parameters = value ?? new List(); +// } +// } +// +// public PropertySetRegion(BlockStatement block, List attributes) : +// base(block, attributes) { +// parameters = new List(); +// } +// +// public static PropertySetRegion Null { +// get { +// return NullPropertySetRegion.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitPropertySetRegion(this, data); +// } +// +// public override string ToString() { +// return string.Format("[PropertySetRegion Parameters={0} Block={1} Attributes={2} Modifier={3}]", GetCollectionString(Parameters), Block, GetCollectionString(Attributes), Modifier); +// } +// } +// +// internal sealed class NullPropertySetRegion : PropertySetRegion { +// +// private NullPropertySetRegion() : +// base(null, null) { +// } +// +// internal static NullPropertySetRegion Instance = new NullPropertySetRegion(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullPropertySetRegion]"; +// } +// } +// +// public class QueryExpression : Expression { +// +// List clauses; +// +// public List Clauses { +// get { +// return clauses; +// } +// set { +// clauses = value ?? new List(); +// } +// } +// +// public QueryExpression() { +// clauses = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpression Clauses={0}]", GetCollectionString(Clauses)); +// } +// } +// +// public class QueryExpressionAggregateClause : QueryExpressionClause { +// +// CollectionRangeVariable source; +// +// List middleClauses; +// +// List intoVariables; +// +// public CollectionRangeVariable Source { +// get { +// return source; +// } +// set { +// source = value ?? CollectionRangeVariable.Null; +// if (!source.IsNull) source.Parent = this; +// } +// } +// +// public List MiddleClauses { +// get { +// return middleClauses; +// } +// set { +// middleClauses = value ?? new List(); +// } +// } +// +// public List IntoVariables { +// get { +// return intoVariables; +// } +// set { +// intoVariables = value ?? new List(); +// } +// } +// +// public QueryExpressionAggregateClause() { +// source = CollectionRangeVariable.Null; +// middleClauses = new List(); +// intoVariables = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionAggregateClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionAggregateClause Source={0} MiddleClauses={1} IntoVariables={2}]", Source, GetCollectionString(MiddleClauses), GetCollectionString(IntoVariables)); +// } +// } +// +// public abstract class QueryExpressionClause : AbstractNode, INullable { +// +// protected QueryExpressionClause() { +// } +// +// public virtual bool IsNull { +// get { +// return false; +// } +// } +// +// public static QueryExpressionClause Null { +// get { +// return NullQueryExpressionClause.Instance; +// } +// } +// } +// +// internal sealed class NullQueryExpressionClause : QueryExpressionClause { +// +// internal static NullQueryExpressionClause Instance = new NullQueryExpressionClause(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullQueryExpressionClause]"; +// } +// } +// +// public class QueryExpressionDistinctClause : QueryExpressionClause { +// +// public QueryExpressionDistinctClause() { +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionDistinctClause(this, data); +// } +// +// public override string ToString() { +// return "[QueryExpressionDistinctClause]"; +// } +// } +// +// public class QueryExpressionFromClause : QueryExpressionClause { +// +// List sources; +// +// public List Sources { +// get { +// return sources; +// } +// set { +// sources = value ?? new List(); +// } +// } +// +// public QueryExpressionFromClause() { +// sources = new List(); +// } +// +// public new static QueryExpressionFromClause Null { +// get { +// return NullQueryExpressionFromClause.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionFromClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionFromClause Sources={0}]", GetCollectionString(Sources)); +// } +// } +// +// internal sealed class NullQueryExpressionFromClause : QueryExpressionFromClause { +// +// internal static NullQueryExpressionFromClause Instance = new NullQueryExpressionFromClause(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullQueryExpressionFromClause]"; +// } +// } +// +// public class QueryExpressionGroupClause : QueryExpressionClause { +// +// Expression projection; +// +// Expression groupBy; +// +// public Expression Projection { +// get { +// return projection; +// } +// set { +// projection = value ?? Expression.Null; +// if (!projection.IsNull) projection.Parent = this; +// } +// } +// +// public Expression GroupBy { +// get { +// return groupBy; +// } +// set { +// groupBy = value ?? Expression.Null; +// if (!groupBy.IsNull) groupBy.Parent = this; +// } +// } +// +// public QueryExpressionGroupClause() { +// projection = Expression.Null; +// groupBy = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionGroupClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionGroupClause Projection={0} GroupBy={1}]", Projection, GroupBy); +// } +// } +// +// public class QueryExpressionGroupJoinVBClause : QueryExpressionClause { +// +// QueryExpressionJoinVBClause joinClause; +// +// List intoVariables; +// +// public QueryExpressionJoinVBClause JoinClause { +// get { +// return joinClause; +// } +// set { +// joinClause = value ?? QueryExpressionJoinVBClause.Null; +// if (!joinClause.IsNull) joinClause.Parent = this; +// } +// } +// +// public List IntoVariables { +// get { +// return intoVariables; +// } +// set { +// intoVariables = value ?? new List(); +// } +// } +// +// public QueryExpressionGroupJoinVBClause() { +// joinClause = QueryExpressionJoinVBClause.Null; +// intoVariables = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionGroupJoinVBClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionGroupJoinVBClause JoinClause={0} IntoVariables={1}]", JoinClause, GetCollectionString(IntoVariables)); +// } +// } +// +// public class QueryExpressionGroupVBClause : QueryExpressionClause { +// +// List groupVariables; +// +// List byVariables; +// +// List intoVariables; +// +// public List GroupVariables { +// get { +// return groupVariables; +// } +// set { +// groupVariables = value ?? new List(); +// } +// } +// +// public List ByVariables { +// get { +// return byVariables; +// } +// set { +// byVariables = value ?? new List(); +// } +// } +// +// public List IntoVariables { +// get { +// return intoVariables; +// } +// set { +// intoVariables = value ?? new List(); +// } +// } +// +// public QueryExpressionGroupVBClause() { +// groupVariables = new List(); +// byVariables = new List(); +// intoVariables = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionGroupVBClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionGroupVBClause GroupVariables={0} ByVariables={1} IntoVariables={2" + +// "}]", GetCollectionString(GroupVariables), GetCollectionString(ByVariables), GetCollectionString(IntoVariables)); +// } +// } +// +// public class QueryExpressionJoinClause : QueryExpressionClause { +// +// Expression onExpression; +// +// Expression equalsExpression; +// +// CollectionRangeVariable source; +// +// string intoIdentifier; +// +// public Expression OnExpression { +// get { +// return onExpression; +// } +// set { +// onExpression = value ?? Expression.Null; +// if (!onExpression.IsNull) onExpression.Parent = this; +// } +// } +// +// public Expression EqualsExpression { +// get { +// return equalsExpression; +// } +// set { +// equalsExpression = value ?? Expression.Null; +// if (!equalsExpression.IsNull) equalsExpression.Parent = this; +// } +// } +// +// public CollectionRangeVariable Source { +// get { +// return source; +// } +// set { +// source = value ?? CollectionRangeVariable.Null; +// if (!source.IsNull) source.Parent = this; +// } +// } +// +// public string IntoIdentifier { +// get { +// return intoIdentifier; +// } +// set { +// intoIdentifier = value ?? ""; +// } +// } +// +// public QueryExpressionJoinClause() { +// onExpression = Expression.Null; +// equalsExpression = Expression.Null; +// source = CollectionRangeVariable.Null; +// intoIdentifier = ""; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionJoinClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionJoinClause OnExpression={0} EqualsExpression={1} Source={2} IntoI" + +// "dentifier={3}]", OnExpression, EqualsExpression, Source, IntoIdentifier); +// } +// } +// +// public class QueryExpressionJoinConditionVB : AbstractNode { +// +// Expression leftSide; +// +// Expression rightSide; +// +// public Expression LeftSide { +// get { +// return leftSide; +// } +// set { +// leftSide = value ?? Expression.Null; +// if (!leftSide.IsNull) leftSide.Parent = this; +// } +// } +// +// public Expression RightSide { +// get { +// return rightSide; +// } +// set { +// rightSide = value ?? Expression.Null; +// if (!rightSide.IsNull) rightSide.Parent = this; +// } +// } +// +// public QueryExpressionJoinConditionVB() { +// leftSide = Expression.Null; +// rightSide = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionJoinConditionVB(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionJoinConditionVB LeftSide={0} RightSide={1}]", LeftSide, RightSide); +// } +// } +// +// public class QueryExpressionJoinVBClause : QueryExpressionClause { +// +// CollectionRangeVariable joinVariable; +// +// QueryExpressionJoinVBClause subJoin; +// +// List conditions; +// +// public CollectionRangeVariable JoinVariable { +// get { +// return joinVariable; +// } +// set { +// joinVariable = value ?? CollectionRangeVariable.Null; +// if (!joinVariable.IsNull) joinVariable.Parent = this; +// } +// } +// +// public QueryExpressionJoinVBClause SubJoin { +// get { +// return subJoin; +// } +// set { +// subJoin = value ?? QueryExpressionJoinVBClause.Null; +// if (!subJoin.IsNull) subJoin.Parent = this; +// } +// } +// +// public List Conditions { +// get { +// return conditions; +// } +// set { +// conditions = value ?? new List(); +// } +// } +// +// public QueryExpressionJoinVBClause() { +// joinVariable = CollectionRangeVariable.Null; +// subJoin = QueryExpressionJoinVBClause.Null; +// conditions = new List(); +// } +// +// public new static QueryExpressionJoinVBClause Null { +// get { +// return NullQueryExpressionJoinVBClause.Instance; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionJoinVBClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionJoinVBClause JoinVariable={0} SubJoin={1} Conditions={2}]", JoinVariable, SubJoin, GetCollectionString(Conditions)); +// } +// } +// +// internal sealed class NullQueryExpressionJoinVBClause : QueryExpressionJoinVBClause { +// +// internal static NullQueryExpressionJoinVBClause Instance = new NullQueryExpressionJoinVBClause(); +// +// public override bool IsNull { +// get { +// return true; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return null; +// } +// +// public override string ToString() { +// return "[NullQueryExpressionJoinVBClause]"; +// } +// } +// +// public class QueryExpressionLetClause : QueryExpressionClause { +// +// List variables; +// +// public List Variables { +// get { +// return variables; +// } +// set { +// variables = value ?? new List(); +// } +// } +// +// public QueryExpressionLetClause() { +// variables = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionLetVBClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionLetVBClause Variables={0}]", GetCollectionString(Variables)); +// } +// } +// +// public class QueryExpressionOrderClause : QueryExpressionClause { +// +// List orderings; +// +// public List Orderings { +// get { +// return orderings; +// } +// set { +// orderings = value ?? new List(); +// } +// } +// +// public QueryExpressionOrderClause() { +// orderings = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionOrderClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionOrderClause Orderings={0}]", GetCollectionString(Orderings)); +// } +// } +// +// public class QueryExpressionOrdering : AbstractNode { +// +// Expression criteria; +// +// QueryExpressionOrderingDirection direction; +// +// public Expression Criteria { +// get { +// return criteria; +// } +// set { +// criteria = value ?? Expression.Null; +// if (!criteria.IsNull) criteria.Parent = this; +// } +// } +// +// public QueryExpressionOrderingDirection Direction { +// get { +// return direction; +// } +// set { +// direction = value; +// } +// } +// +// public QueryExpressionOrdering() { +// criteria = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionOrdering(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionOrdering Criteria={0} Direction={1}]", Criteria, Direction); +// } +// } +// +// public class QueryExpressionPartitionVBClause : QueryExpressionClause { +// +// Expression expression; +// +// QueryExpressionPartitionType partitionType; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public QueryExpressionPartitionType PartitionType { +// get { +// return partitionType; +// } +// set { +// partitionType = value; +// } +// } +// +// public QueryExpressionPartitionVBClause() { +// expression = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionPartitionVBClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionPartitionVBClause Expression={0} PartitionType={1}]", Expression, PartitionType); +// } +// } +// +// public class QueryExpressionSelectClause : QueryExpressionClause { +// +// Expression projection; +// +// public Expression Projection { +// get { +// return projection; +// } +// set { +// projection = value ?? Expression.Null; +// if (!projection.IsNull) projection.Parent = this; +// } +// } +// +// public QueryExpressionSelectClause() { +// projection = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionSelectClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionSelectClause Projection={0}]", Projection); +// } +// } +// +// public class QueryExpressionSelectVBClause : QueryExpressionClause { +// +// List variables; +// +// public List Variables { +// get { +// return variables; +// } +// set { +// variables = value ?? new List(); +// } +// } +// +// public QueryExpressionSelectVBClause() { +// variables = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionSelectVBClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionSelectVBClause Variables={0}]", GetCollectionString(Variables)); +// } +// } +// +// public class QueryExpressionWhereClause : QueryExpressionClause { +// +// Expression condition; +// +// public Expression Condition { +// get { +// return condition; +// } +// set { +// condition = value ?? Expression.Null; +// if (!condition.IsNull) condition.Parent = this; +// } +// } +// +// public QueryExpressionWhereClause() { +// condition = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitQueryExpressionWhereClause(this, data); +// } +// +// public override string ToString() { +// return string.Format("[QueryExpressionWhereClause Condition={0}]", Condition); +// } +// } +// +// public class RaiseEventStatement : Statement { +// +// string eventName; +// +// List arguments; +// +// public string EventName { +// get { +// return eventName; +// } +// set { +// eventName = value ?? ""; +// } +// } +// +// public List Arguments { +// get { +// return arguments; +// } +// set { +// arguments = value ?? new List(); +// } +// } +// +// public RaiseEventStatement(string eventName, List arguments) { +// EventName = eventName; +// Arguments = arguments; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitRaiseEventStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[RaiseEventStatement EventName={0} Arguments={1}]", EventName, GetCollectionString(Arguments)); +// } +// } +// +// public class ReDimStatement : Statement { +// +// List reDimClauses; +// +// bool isPreserve; +// +// public List ReDimClauses { +// get { +// return reDimClauses; +// } +// set { +// reDimClauses = value ?? new List(); +// } +// } +// +// public bool IsPreserve { +// get { +// return isPreserve; +// } +// set { +// isPreserve = value; +// } +// } +// +// public ReDimStatement(bool isPreserve) { +// IsPreserve = isPreserve; +// reDimClauses = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitReDimStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ReDimStatement ReDimClauses={0} IsPreserve={1}]", GetCollectionString(ReDimClauses), IsPreserve); +// } +// } +// +// public class RemoveHandlerStatement : Statement { +// +// Expression eventExpression; +// +// Expression handlerExpression; +// +// public Expression EventExpression { +// get { +// return eventExpression; +// } +// set { +// eventExpression = value ?? Expression.Null; +// if (!eventExpression.IsNull) eventExpression.Parent = this; +// } +// } +// +// public Expression HandlerExpression { +// get { +// return handlerExpression; +// } +// set { +// handlerExpression = value ?? Expression.Null; +// if (!handlerExpression.IsNull) handlerExpression.Parent = this; +// } +// } +// +// public RemoveHandlerStatement(Expression eventExpression, Expression handlerExpression) { +// EventExpression = eventExpression; +// HandlerExpression = handlerExpression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitRemoveHandlerStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[RemoveHandlerStatement EventExpression={0} HandlerExpression={1}]", EventExpression, HandlerExpression); +// } +// } +// +// public class ResumeStatement : Statement { +// +// string labelName; +// +// bool isResumeNext; +// +// public string LabelName { +// get { +// return labelName; +// } +// set { +// labelName = value ?? ""; +// } +// } +// +// public bool IsResumeNext { +// get { +// return isResumeNext; +// } +// set { +// isResumeNext = value; +// } +// } +// +// public ResumeStatement(bool isResumeNext) { +// IsResumeNext = isResumeNext; +// labelName = ""; +// } +// +// public ResumeStatement(string labelName) { +// LabelName = labelName; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitResumeStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ResumeStatement LabelName={0} IsResumeNext={1}]", LabelName, IsResumeNext); +// } +// } +// +// public class ReturnStatement : Statement { +// +// Expression expression; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public ReturnStatement(Expression expression) { +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitReturnStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ReturnStatement Expression={0}]", Expression); +// } +// } +// +// public class StopStatement : Statement { +// +// public StopStatement() { +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitStopStatement(this, data); +// } +// +// public override string ToString() { +// return "[StopStatement]"; +// } +// } +// +// public class SwitchSection : BlockStatement { +// +// List switchLabels; +// +// public List SwitchLabels { +// get { +// return switchLabels; +// } +// set { +// switchLabels = value ?? new List(); +// } +// } +// +// public SwitchSection() { +// switchLabels = new List(); +// } +// +// public SwitchSection(List switchLabels) { +// SwitchLabels = switchLabels; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitSwitchSection(this, data); +// } +// +// public override string ToString() { +// return string.Format("[SwitchSection SwitchLabels={0}]", GetCollectionString(SwitchLabels)); +// } +// } +// +// public class SwitchStatement : Statement { +// +// Expression switchExpression; +// +// List switchSections; +// +// public Expression SwitchExpression { +// get { +// return switchExpression; +// } +// set { +// switchExpression = value ?? Expression.Null; +// if (!switchExpression.IsNull) switchExpression.Parent = this; +// } +// } +// +// public List SwitchSections { +// get { +// return switchSections; +// } +// set { +// switchSections = value ?? new List(); +// } +// } +// +// public SwitchStatement(Expression switchExpression, List switchSections) { +// SwitchExpression = switchExpression; +// SwitchSections = switchSections; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitSwitchStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[SwitchStatement SwitchExpression={0} SwitchSections={1}]", SwitchExpression, GetCollectionString(SwitchSections)); +// } +// } +// +// public class TemplateDefinition : AttributedNode { +// +// string name; +// +// VarianceModifier varianceModifier; +// +// List bases; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = string.IsNullOrEmpty(value) ? "?" : value; +// } +// } +// +// public VarianceModifier VarianceModifier { +// get { +// return varianceModifier; +// } +// set { +// varianceModifier = value; +// } +// } +// +// public List Bases { +// get { +// return bases; +// } +// set { +// bases = value ?? new List(); +// } +// } +// +// public TemplateDefinition() { +// name = "?"; +// bases = new List(); +// } +// +// public TemplateDefinition(string name, List attributes) { +// Name = name; +// Attributes = attributes; +// bases = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitTemplateDefinition(this, data); +// } +// +// public override string ToString() { +// return string.Format("[TemplateDefinition Name={0} VarianceModifier={1} Bases={2} Attributes={3} Modifi" + +// "er={4}]", Name, VarianceModifier, GetCollectionString(Bases), GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class ThisReferenceExpression : Expression { +// +// public ThisReferenceExpression() { +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitThisReferenceExpression(this, data); +// } +// +// public override string ToString() { +// return "[ThisReferenceExpression]"; +// } +// } +// +// public class ThrowStatement : Statement { +// +// Expression expression; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public ThrowStatement(Expression expression) { +// Expression = expression; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitThrowStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[ThrowStatement Expression={0}]", Expression); +// } +// } +// +// public class TryCatchStatement : Statement { +// +// Statement statementBlock; +// +// List catchClauses; +// +// Statement finallyBlock; +// +// public Statement StatementBlock { +// get { +// return statementBlock; +// } +// set { +// statementBlock = value ?? Statement.Null; +// if (!statementBlock.IsNull) statementBlock.Parent = this; +// } +// } +// +// public List CatchClauses { +// get { +// return catchClauses; +// } +// set { +// catchClauses = value ?? new List(); +// } +// } +// +// public Statement FinallyBlock { +// get { +// return finallyBlock; +// } +// set { +// finallyBlock = value ?? Statement.Null; +// if (!finallyBlock.IsNull) finallyBlock.Parent = this; +// } +// } +// +// public TryCatchStatement(Statement statementBlock, List catchClauses, Statement finallyBlock) { +// StatementBlock = statementBlock; +// CatchClauses = catchClauses; +// FinallyBlock = finallyBlock; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitTryCatchStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[TryCatchStatement StatementBlock={0} CatchClauses={1} FinallyBlock={2}]", StatementBlock, GetCollectionString(CatchClauses), FinallyBlock); +// } +// } +// +// public class TypeDeclaration : AttributedNode { +// +// string name; +// +// ClassType type; +// +// List baseTypes; +// +// List templates; +// +// Location bodyStartLocation; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public ClassType Type { +// get { +// return type; +// } +// set { +// type = value; +// } +// } +// +// public List BaseTypes { +// get { +// return baseTypes; +// } +// set { +// baseTypes = value ?? new List(); +// } +// } +// +// public List Templates { +// get { +// return templates; +// } +// set { +// templates = value ?? new List(); +// } +// } +// +// public Location BodyStartLocation { +// get { +// return bodyStartLocation; +// } +// set { +// bodyStartLocation = value; +// } +// } +// +// public TypeDeclaration(Modifiers modifier, List attributes) { +// Modifier = modifier; +// Attributes = attributes; +// name = ""; +// baseTypes = new List(); +// templates = new List(); +// bodyStartLocation = Location.Empty; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitTypeDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[TypeDeclaration Name={0} Type={1} BaseTypes={2} Templates={3} BodyStartLocation=" + +// "{4} Attributes={5} Modifier={6}]", Name, Type, GetCollectionString(BaseTypes), GetCollectionString(Templates), BodyStartLocation, GetCollectionString(Attributes), Modifier); +// } +// } +// +// public class TypeOfExpression : Expression { +// +// TypeReference typeReference; +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public TypeOfExpression(TypeReference typeReference) { +// TypeReference = typeReference; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitTypeOfExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[TypeOfExpression TypeReference={0}]", TypeReference); +// } +// } +// +// public class TypeOfIsExpression : Expression { +// +// Expression expression; +// +// TypeReference typeReference; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public TypeOfIsExpression(Expression expression, TypeReference typeReference) { +// Expression = expression; +// TypeReference = typeReference; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitTypeOfIsExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[TypeOfIsExpression Expression={0} TypeReference={1}]", Expression, TypeReference); +// } +// } +// +// public class TypeReferenceExpression : Expression { +// +// TypeReference typeReference; +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public TypeReferenceExpression(TypeReference typeReference) { +// TypeReference = typeReference; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitTypeReferenceExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[TypeReferenceExpression TypeReference={0}]", TypeReference); +// } +// } +// +// public class UnaryOperatorExpression : Expression { +// +// UnaryOperatorType op; +// +// Expression expression; +// +// public UnaryOperatorType Op { +// get { +// return op; +// } +// set { +// op = value; +// } +// } +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public UnaryOperatorExpression(UnaryOperatorType op) { +// Op = op; +// expression = Expression.Null; +// } +// +// public UnaryOperatorExpression(Expression expression, UnaryOperatorType op) { +// Expression = expression; +// Op = op; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitUnaryOperatorExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[UnaryOperatorExpression Op={0} Expression={1}]", Op, Expression); +// } +// } +// +// public class UsingStatement : StatementWithEmbeddedStatement { +// +// Statement resourceAcquisition; +// +// public Statement ResourceAcquisition { +// get { +// return resourceAcquisition; +// } +// set { +// resourceAcquisition = value ?? Statement.Null; +// if (!resourceAcquisition.IsNull) resourceAcquisition.Parent = this; +// } +// } +// +// public UsingStatement(Statement resourceAcquisition, Statement embeddedStatement) { +// ResourceAcquisition = resourceAcquisition; +// EmbeddedStatement = embeddedStatement; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitUsingStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[UsingStatement ResourceAcquisition={0} EmbeddedStatement={1}]", ResourceAcquisition, EmbeddedStatement); +// } +// } +// +// public class VariableDeclaration : AbstractNode { +// +// string name; +// +// Expression initializer; +// +// TypeReference typeReference; +// +// Expression fixedArrayInitialization; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public Expression Initializer { +// get { +// return initializer; +// } +// set { +// initializer = value ?? Expression.Null; +// if (!initializer.IsNull) initializer.Parent = this; +// } +// } +// +// public TypeReference TypeReference { +// get { +// return typeReference; +// } +// set { +// typeReference = value ?? TypeReference.Null; +// if (!typeReference.IsNull) typeReference.Parent = this; +// } +// } +// +// public Expression FixedArrayInitialization { +// get { +// return fixedArrayInitialization; +// } +// set { +// fixedArrayInitialization = value ?? Expression.Null; +// if (!fixedArrayInitialization.IsNull) fixedArrayInitialization.Parent = this; +// } +// } +// +// public VariableDeclaration(string name) { +// Name = name; +// initializer = Expression.Null; +// typeReference = TypeReference.Null; +// fixedArrayInitialization = Expression.Null; +// } +// +// public VariableDeclaration(string name, Expression initializer) { +// Name = name; +// Initializer = initializer; +// typeReference = TypeReference.Null; +// fixedArrayInitialization = Expression.Null; +// } +// +// public VariableDeclaration(string name, Expression initializer, TypeReference typeReference) { +// Name = name; +// Initializer = initializer; +// TypeReference = typeReference; +// fixedArrayInitialization = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitVariableDeclaration(this, data); +// } +// +// public override string ToString() { +// return string.Format("[VariableDeclaration Name={0} Initializer={1} TypeReference={2} FixedArrayInitial" + +// "ization={3}]", Name, Initializer, TypeReference, FixedArrayInitialization); +// } +// } +// +// public class WithStatement : Statement { +// +// Expression expression; +// +// BlockStatement body; +// +// public Expression Expression { +// get { +// return expression; +// } +// set { +// expression = value ?? Expression.Null; +// if (!expression.IsNull) expression.Parent = this; +// } +// } +// +// public BlockStatement Body { +// get { +// return body; +// } +// set { +// body = value ?? BlockStatement.Null; +// if (!body.IsNull) body.Parent = this; +// } +// } +// +// public WithStatement(Expression expression) { +// Expression = expression; +// body = BlockStatement.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitWithStatement(this, data); +// } +// +// public override string ToString() { +// return string.Format("[WithStatement Expression={0} Body={1}]", Expression, Body); +// } +// } +// +// public class XmlAttributeExpression : XmlExpression { +// +// string name; +// +// string literalValue; +// +// bool useDoubleQuotes; +// +// Expression expressionValue; +// +// public string Name { +// get { +// return name; +// } +// set { +// name = value ?? ""; +// } +// } +// +// public string LiteralValue { +// get { +// return literalValue; +// } +// set { +// literalValue = value ?? ""; +// } +// } +// +// public bool UseDoubleQuotes { +// get { +// return useDoubleQuotes; +// } +// set { +// useDoubleQuotes = value; +// } +// } +// +// public Expression ExpressionValue { +// get { +// return expressionValue; +// } +// set { +// expressionValue = value ?? Expression.Null; +// if (!expressionValue.IsNull) expressionValue.Parent = this; +// } +// } +// +// public XmlAttributeExpression() { +// name = ""; +// literalValue = ""; +// expressionValue = Expression.Null; +// } +// +// public bool IsLiteralValue { +// get { +// return expressionValue.IsNull; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitXmlAttributeExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[XmlAttributeExpression Name={0} LiteralValue={1} UseDoubleQuotes={2} ExpressionV" + +// "alue={3}]", Name, LiteralValue, UseDoubleQuotes, ExpressionValue); +// } +// } +// +// public class XmlContentExpression : XmlExpression { +// +// string content; +// +// XmlContentType type; +// +// public string Content { +// get { +// return content; +// } +// set { +// content = value ?? ""; +// } +// } +// +// public XmlContentType Type { +// get { +// return type; +// } +// set { +// type = value; +// } +// } +// +// public XmlContentExpression(string content, XmlContentType type) { +// Content = content; +// Type = type; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitXmlContentExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[XmlContentExpression Content={0} Type={1}]", Content, Type); +// } +// } +// +// public class XmlDocumentExpression : XmlExpression { +// +// List expressions; +// +// public List Expressions { +// get { +// return expressions; +// } +// set { +// expressions = value ?? new List(); +// } +// } +// +// public XmlDocumentExpression() { +// expressions = new List(); +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitXmlDocumentExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[XmlDocumentExpression Expressions={0}]", GetCollectionString(Expressions)); +// } +// } +// +// public class XmlElementExpression : XmlExpression { +// +// Expression content; +// +// Expression nameExpression; +// +// string xmlName; +// +// List attributes; +// +// public Expression Content { +// get { +// return content; +// } +// set { +// content = value ?? Expression.Null; +// if (!content.IsNull) content.Parent = this; +// } +// } +// +// public Expression NameExpression { +// get { +// return nameExpression; +// } +// set { +// nameExpression = value ?? Expression.Null; +// if (!nameExpression.IsNull) nameExpression.Parent = this; +// } +// } +// +// public string XmlName { +// get { +// return xmlName; +// } +// set { +// xmlName = value ?? ""; +// } +// } +// +// public List Attributes { +// get { +// return attributes; +// } +// set { +// attributes = value ?? new List(); +// } +// } +// +// public XmlElementExpression() { +// content = Expression.Null; +// nameExpression = Expression.Null; +// xmlName = ""; +// attributes = new List(); +// } +// +// public bool IsExpression { +// get { +// return !content.IsNull; +// } +// } +// +// public bool NameIsExpression { +// get { +// return !nameExpression.IsNull; +// } +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitXmlElementExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[XmlElementExpression Content={0} NameExpression={1} XmlName={2} Attributes={3}]", Content, NameExpression, XmlName, GetCollectionString(Attributes)); +// } +// } +// +// public class XmlEmbeddedExpression : XmlExpression { +// +// Expression inlineVBExpression; +// +// public Expression InlineVBExpression { +// get { +// return inlineVBExpression; +// } +// set { +// inlineVBExpression = value ?? Expression.Null; +// if (!inlineVBExpression.IsNull) inlineVBExpression.Parent = this; +// } +// } +// +// public XmlEmbeddedExpression() { +// inlineVBExpression = Expression.Null; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitXmlEmbeddedExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[XmlEmbeddedExpression InlineVBExpression={0}]", InlineVBExpression); +// } +// } +// +// public abstract class XmlExpression : Expression { +// +// protected XmlExpression() { +// } +// } +// +// public class XmlMemberAccessExpression : Expression { +// +// Expression targetObject; +// +// XmlAxisType axisType; +// +// bool isXmlIdentifier; +// +// string identifier; +// +// public Expression TargetObject { +// get { +// return targetObject; +// } +// set { +// targetObject = value ?? Expression.Null; +// if (!targetObject.IsNull) targetObject.Parent = this; +// } +// } +// +// public XmlAxisType AxisType { +// get { +// return axisType; +// } +// set { +// axisType = value; +// } +// } +// +// public bool IsXmlIdentifier { +// get { +// return isXmlIdentifier; +// } +// set { +// isXmlIdentifier = value; +// } +// } +// +// public string Identifier { +// get { +// return identifier; +// } +// set { +// identifier = value ?? ""; +// } +// } +// +// public XmlMemberAccessExpression(Expression targetObject, XmlAxisType axisType, string identifier, bool isXmlIdentifier) { +// TargetObject = targetObject; +// AxisType = axisType; +// Identifier = identifier; +// IsXmlIdentifier = isXmlIdentifier; +// } +// +// public override object AcceptVisitor(IAstVisitor visitor, object data) { +// return visitor.VisitXmlMemberAccessExpression(this, data); +// } +// +// public override string ToString() { +// return string.Format("[XmlMemberAccessExpression TargetObject={0} AxisType={1} IsXmlIdentifier={2} Iden" + +// "tifier={3}]", TargetObject, AxisType, IsXmlIdentifier, Identifier); +// } +// } +//} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs new file mode 100644 index 0000000000..bc2d06ca03 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class DelegateDeclaration : AttributedNode + { + public bool IsSub { get; set; } + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole(Roles.TypeParameter); } + } + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ReturnTypeAttributes { + get { return GetChildrenByRole(AttributeBlock.ReturnTypeAttributeBlockRole); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var o = other as DelegateDeclaration; + return o != null && + MatchAttributesAndModifiers(o, match) && + IsSub == o.IsSub && + TypeParameters.DoMatch(o.TypeParameters, match) && + Name.DoMatch(o.Name, match) && + Parameters.DoMatch(o.Parameters, match) && + ReturnTypeAttributes.DoMatch(o.ReturnTypeAttributes, match) && + ReturnType.DoMatch(o.ReturnType, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitDelegateDeclaration(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs new file mode 100644 index 0000000000..49fe3f239c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class EnumDeclaration : AttributedNode + { + public readonly static Role MemberRole = new Role("Member"); + public readonly static Role UnderlyingTypeRole = new Role("UnderlyingType", AstType.Null); + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstType UnderlyingType { + get { return GetChildByRole(UnderlyingTypeRole); } + set { SetChildByRole(UnderlyingTypeRole, value); } + } + + public AstNodeCollection Member { + get { return GetChildrenByRole(MemberRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var decl = other as EnumDeclaration; + return decl != null && + MatchAttributesAndModifiers(decl, match) && + Name.DoMatch(decl.Name, match) && + UnderlyingType.DoMatch(decl.UnderlyingType, match) && + Member.DoMatch(decl.Member, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitEnumDeclaration(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs new file mode 100644 index 0000000000..476ec56360 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class EnumMemberDeclaration : AstNode + { + public AstNodeCollection Attributes { + get { return GetChildrenByRole(AttributeBlock.AttributeBlockRole); } + } + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public Expression Value { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var member = other as EnumMemberDeclaration; + return Attributes.DoMatch(member.Attributes, match) && + Name.DoMatch(member.Name, match) && + Value.DoMatch(member.Value, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitEnumMemberDeclaration(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs new file mode 100644 index 0000000000..15730eab03 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs @@ -0,0 +1,113 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public abstract class ImportsClause : AstNode + { + public new static readonly ImportsClause Null = new NullImportsClause(); + + class NullImportsClause : ImportsClause + { + public override bool IsNull { + get { return true; } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + return other != null && other.IsNull; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return default(S); + } + } + } + + public class AliasImportsClause : ImportsClause + { + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstType Alias { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var clause = other as AliasImportsClause; + return clause != null + && Name.DoMatch(clause.Name, match) + && Alias.DoMatch(clause.Alias, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAliasImportsClause(this, data); + } + + public override string ToString() { + return string.Format("[AliasImportsClause Name={0} Alias={1}]", Name, Alias); + } + } + + public class MemberImportsClause : ImportsClause + { + public AstType Member { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var node = other as MemberImportsClause; + return node != null + && Member.DoMatch(node.Member, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitMembersImportsClause(this, data); + } + + public override string ToString() + { + return string.Format("[MemberImportsClause Member={0}]", Member); + } + } + + public class XmlNamespaceImportsClause : ImportsClause + { + public XmlIdentifier Prefix { + get { return GetChildByRole(Roles.XmlIdentifier); } + set { SetChildByRole(Roles.XmlIdentifier, value); } + } + + public XmlLiteralString Namespace { + get { return GetChildByRole(Roles.XmlLiteralString); } + set { SetChildByRole(Roles.XmlLiteralString, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var clause = other as XmlNamespaceImportsClause; + return clause != null && Namespace.DoMatch(clause.Namespace, match) && Prefix.DoMatch(clause.Prefix, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitXmlNamespaceImportsClause(this, data); + } + + public override string ToString() + { + return string.Format("[XmlNamespaceImportsClause Prefix={0}, Namespace={1}]", Prefix, Namespace); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs new file mode 100644 index 0000000000..6691b852ba --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ImportsStatement : AstNode + { + public static readonly Role ImportsClauseRole = new Role("ImportsClause", ImportsClause.Null); + + public VBTokenNode Imports { + get { return GetChildByRole(Roles.Keyword); } + } + + public AstNodeCollection ImportsClauses { + get { return GetChildrenByRole(ImportsClauseRole); } + } + +// public override string ToString() { +// return string.Format("[ImportsStatement ImportsClauses={0}]", GetCollectionString(ImportsClauses)); +// } + + protected internal override bool DoMatch(AstNode other, Match match) + { + ImportsStatement stmt = other as ImportsStatement; + return stmt != null && stmt.ImportsClauses.DoMatch(ImportsClauses, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitImportsStatement(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs new file mode 100644 index 0000000000..5c392a73af --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs @@ -0,0 +1,78 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Namespace Name + /// Members + /// End Namespace + /// + public class NamespaceDeclaration : AstNode + { + public static readonly Role MemberRole = CompilationUnit.MemberRole; + + public string Name { + get { + StringBuilder builder = new StringBuilder(); + foreach (Identifier identifier in GetChildrenByRole (Roles.Identifier)) { + if (builder.Length > 0) + builder.Append ('.'); + builder.Append (identifier.Name); + } + return builder.ToString (); + } + set { + GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier (ident, AstLocation.Empty))); + } + } + + public AstNodeCollection Identifiers { + get { return GetChildrenByRole (Roles.Identifier); } + } + + /// + /// Gets the full namespace name (including any parent namespaces) + /// + public string FullName { + get { + NamespaceDeclaration parentNamespace = Parent as NamespaceDeclaration; + if (parentNamespace != null) + return BuildQualifiedName (parentNamespace.FullName, Name); + return Name; + } + } + + public AstNodeCollection Members { + get { return GetChildrenByRole(MemberRole); } + } + + public static string BuildQualifiedName (string name1, string name2) + { + if (string.IsNullOrEmpty (name1)) + return name2; + if (string.IsNullOrEmpty (name2)) + return name1; + return name1 + "." + name2; + } + + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitNamespaceDeclaration(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + NamespaceDeclaration o = other as NamespaceDeclaration; + return o != null && MatchString(this.Name, o.Name) && this.Members.DoMatch(o.Members, match); + } + } +}; diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs new file mode 100644 index 0000000000..903439c89a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs @@ -0,0 +1,60 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class OptionStatement : AstNode + { + public static readonly Role OptionTypeRole = new Role("OptionType"); + public static readonly Role OptionValueRole = new Role("OptionValue"); + + public VBTokenNode OptionKeyword { + get { return GetChildByRole(Roles.Keyword); } + } + + public VBTokenNode OptionTypeKeyword { + get { return GetChildByRole(OptionTypeRole); } + } + + public VBTokenNode OptionValueKeyword { + get { return GetChildByRole(OptionValueRole); } + } + + public OptionType OptionType { get; set; } + + public OptionValue OptionValue { get; set; } + + protected internal override bool DoMatch(AstNode other, Match match) + { + var stmt = other as OptionStatement; + return stmt != null && stmt.OptionType == this.OptionType + && stmt.OptionValue == this.OptionValue; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitOptionStatement(this, data); + } + + public override string ToString() { + return string.Format("[OptionStatement OptionType={0} OptionValue={1}]", OptionType, OptionValue); + } + } + + public enum OptionType + { + Explicit, + Strict, + Compare, + Infer + } + + public enum OptionValue + { + On, Off, + Text, Binary + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs new file mode 100644 index 0000000000..eadd4f031f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs @@ -0,0 +1,60 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class TypeDeclaration : AttributedNode + { + public readonly static Role MemberRole = new Role("Member"); + public readonly static Role InheritsTypeRole = new Role("InheritsType", AstType.Null); + public readonly static Role ImplementsTypesRole = new Role("ImplementsTypes", AstType.Null); + + public AstNodeCollection Members { + get { return base.GetChildrenByRole(MemberRole); } + } + + public ClassType ClassType { get; set; } + + public string Name { + get { return GetChildByRole(Roles.Identifier).Name; } + set { + SetChildByRole(Roles.Identifier, new Identifier (value, AstLocation.Empty)); + } + } + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole(Roles.TypeParameter); } + } + + public AstType InheritsType { + get { return GetChildByRole(InheritsTypeRole); } + } + + public AstNodeCollection ImplementsTypes { + get { return GetChildrenByRole(ImplementsTypesRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + TypeDeclaration t = other as TypeDeclaration; + return t != null && + MatchAttributesAndModifiers(t, match) && + Members.DoMatch(t.Members, match) && + ClassType == t.ClassType && + MatchString(Name, t.Name) && + TypeParameters.DoMatch(t.TypeParameters, match) && + InheritsType.DoMatch(t.InheritsType, match) && + ImplementsTypes.DoMatch(t.ImplementsTypes, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeDeclaration(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/INullable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/INullable.cs new file mode 100644 index 0000000000..14a65a444e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/INullable.cs @@ -0,0 +1,12 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public interface INullable + { + bool IsNull { + get; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Identifier.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Identifier.cs new file mode 100644 index 0000000000..ea308b7f9f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Identifier.cs @@ -0,0 +1,91 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Represents an identifier in VB. + /// + public class Identifier : AstNode + { + public static readonly new Identifier Null = new NullIdentifier (); + class NullIdentifier : Identifier + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + string name; + + public string Name { + get { return name; } + set { + if (value == null) + throw new ArgumentNullException("value"); + name = value; + } + } + + public TypeCode TypeCharacter { get; set; } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + } + + public override AstLocation EndLocation { + get { + return new AstLocation (StartLocation.Line, StartLocation.Column + Name.Length); + } + } + + private Identifier() + { + this.name = string.Empty; + } + + public Identifier (string name, AstLocation location) + { + if (name == null) + throw new ArgumentNullException("name"); + this.Name = name; + this.startLocation = location; + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var node = other as Identifier; + return node != null + && MatchString(node.name, name) + && node.TypeCharacter == TypeCharacter; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitIdentifier(this, data); + } + + public override string ToString() + { + return string.Format("[Identifier Name={0}, StartLocation={1}, TypeCharacter{4}]", + name, startLocation, TypeCharacter); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs new file mode 100644 index 0000000000..73610fe707 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs @@ -0,0 +1,125 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// { Statements } + /// + public class BlockStatement : Statement, IEnumerable + { + public static readonly Role StatementRole = new Role("Statement", Statement.Null); + + #region Null + public static readonly new BlockStatement Null = new NullBlockStatement(); + sealed class NullBlockStatement : BlockStatement + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default(S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator BlockStatement(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : BlockStatement, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public AstNodeCollection Statements { + get { return GetChildrenByRole (StatementRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitBlockStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + BlockStatement o = other as BlockStatement; + return o != null && !o.IsNull && this.Statements.DoMatch(o.Statements, match); + } + + #region Builder methods + public void Add(Statement statement) + { + AddChild(statement, StatementRole); + } + + // TODO : uncomment + +// public void Add(Expression expression) +// { +// AddChild(new ExpressionStatement { Expression = expression }, StatementRole); +// } +// + public void AddRange(IEnumerable 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 IEnumerable.GetEnumerator() + { + return this.Statements.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.Statements.GetEnumerator(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs new file mode 100644 index 0000000000..c20407051c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs @@ -0,0 +1,132 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Base class for statements. + /// + /// + /// This class is useful even though it doesn't provide any additional functionality: + /// It can be used to communicate more information in APIs, e.g. "this subnode will always be a statement" + /// + public abstract class Statement : AstNode + { + #region Null + public new static readonly Statement Null = new NullStatement (); + + sealed class NullStatement : Statement + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator Statement(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : Statement, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + /// + /// Gets the previous statement within the current block. + /// This is usually equivalent to , but will skip any non-statements (e.g. comments) + /// + public Statement PreviousStatement { + get { + AstNode node = this; + while ((node = node.PrevSibling) != null) { + Statement stmt = node as Statement; + if (stmt != null) + return stmt; + } + return null; + } + } + + /// + /// Gets the next statement within the current block. + /// This is usually equivalent to , but will skip any non-statements (e.g. comments) + /// + public Statement NextStatement { + get { + AstNode node = this; + while ((node = node.NextSibling) != null) { + Statement stmt = node as Statement; + if (stmt != null) + return stmt; + } + return null; + } + } + + public new Statement Clone() + { + return (Statement)base.Clone(); + } + + public Statement ReplaceWith(Func replaceFunction) + { + if (replaceFunction == null) + throw new ArgumentNullException("replaceFunction"); + return (Statement)base.ReplaceWith(node => replaceFunction((Statement)node)); + } + + // Make debugging easier by giving Statements a ToString() implementation + public override string ToString() + { +// if (IsNull) +// return "Null"; +// StringWriter w = new StringWriter(); +// AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); +// string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); +// if (text.Length > 100) +// return text.Substring(0, 97) + "..."; +// else +// return text; + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs new file mode 100644 index 0000000000..13ba3ee971 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs @@ -0,0 +1,145 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// A type reference in the VB AST. + /// + public abstract class AstType : AstNode + { + #region Null + public new static readonly AstType Null = new NullAstType(); + + sealed class NullAstType : AstType + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator AstType(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : AstType, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public virtual AstType MakeArrayType(int rank = 1) + { + return new ComposedType { BaseType = this }.MakeArrayType(rank); + } + + // TODO : reimplement this +// /// +// /// Builds an expression that can be used to access a static member on this type. +// /// +// public MemberReferenceExpression Member(string memberName) +// { +// return new TypeReferenceExpression { Type = this }.Member(memberName); +// } +// +// /// +// /// Builds an invocation expression using this type as target. +// /// +// public InvocationExpression Invoke(string methodName, IEnumerable arguments) +// { +// return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); +// } +// +// /// +// /// Builds an invocation expression using this type as target. +// /// +// public InvocationExpression Invoke(string methodName, params Expression[] arguments) +// { +// return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); +// } +// +// /// +// /// Builds an invocation expression using this type as target. +// /// +// public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) +// { +// return new TypeReferenceExpression { Type = this }.Invoke(methodName, typeArguments, arguments); +// } + + public static AstType Create(Type type) + { + switch (Type.GetTypeCode(type)) { + case TypeCode.Object: + return new PrimitiveType("Object"); + case TypeCode.Boolean: + return new PrimitiveType("Boolean"); + case TypeCode.Char: + return new PrimitiveType("Char"); + case TypeCode.SByte: + return new PrimitiveType("SByte"); + case TypeCode.Byte: + return new PrimitiveType("Byte"); + case TypeCode.Int16: + return new PrimitiveType("Short"); + case TypeCode.UInt16: + return new PrimitiveType("UShort"); + case TypeCode.Int32: + return new PrimitiveType("Integer"); + case TypeCode.UInt32: + return new PrimitiveType("UInteger"); + case TypeCode.Int64: + return new PrimitiveType("Long"); + case TypeCode.UInt64: + return new PrimitiveType("ULong"); + case TypeCode.Single: + return new PrimitiveType("Single"); + case TypeCode.Double: + return new PrimitiveType("Double"); + case TypeCode.Decimal: + return new PrimitiveType("Decimal"); + case TypeCode.String: + return new PrimitiveType("String"); + case TypeCode.DateTime: + return new PrimitiveType("Date"); + } + return new SimpleType(type.FullName); // TODO: implement this correctly + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs new file mode 100644 index 0000000000..e214a7e4b5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs @@ -0,0 +1,119 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ComposedType : AstType + { + public static readonly Role NullableRole = new Role("Nullable", VBTokenNode.Null); + public static readonly Role ArraySpecifierRole = new Role("ArraySpecifier"); + + public AstType BaseType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public bool HasNullableSpecifier { + get { + return !GetChildByRole(NullableRole).IsNull; + } + set { + SetChildByRole(NullableRole, value ? new VBTokenNode(AstLocation.Empty, 1) : null); + } + } + + public AstNodeCollection ArraySpecifiers { + get { return GetChildrenByRole (ArraySpecifierRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitComposedType (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ComposedType o = other as ComposedType; + return o != null && this.HasNullableSpecifier == o.HasNullableSpecifier && this.ArraySpecifiers.DoMatch(o.ArraySpecifiers, match); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append(this.BaseType.ToString()); + if (this.HasNullableSpecifier) + b.Append('?'); + foreach (var arraySpecifier in this.ArraySpecifiers) { + b.Append('('); + b.Append(',', arraySpecifier.Dimensions - 1); + b.Append(')'); + } + return b.ToString(); + } + + public override AstType MakeArrayType(int dimensions) + { + InsertChildBefore(this.ArraySpecifiers.FirstOrDefault(), new ArraySpecifier(dimensions), ArraySpecifierRole); + return this; + } + } + + /// + /// [,,,] + /// + public class ArraySpecifier : AstNode + { + public ArraySpecifier() + { + } + + public ArraySpecifier(int dimensions) + { + this.Dimensions = dimensions; + } + + public VBTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public int Dimensions { + get { return 1 + GetChildrenByRole(Roles.Comma).Count(); } + set { + int d = this.Dimensions; + while (d > value) { + GetChildByRole(Roles.Comma).Remove(); + d--; + } + while (d < value) { + InsertChildBefore(GetChildByRole(Roles.Comma), new VBTokenNode(AstLocation.Empty, 1), Roles.Comma); + d++; + } + } + } + + public VBTokenNode RParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArraySpecifier(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArraySpecifier o = other as ArraySpecifier; + return o != null && this.Dimensions == o.Dimensions; + } + + public override string ToString() + { + return "(" + new string(',', this.Dimensions - 1) + ")"; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs new file mode 100644 index 0000000000..8d6badc8f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs @@ -0,0 +1,57 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class PrimitiveType : AstType + { + public string Keyword { get; set; } + public AstLocation Location { get; set; } + + public PrimitiveType() + { + } + + public PrimitiveType(string keyword) + { + this.Keyword = keyword; + } + + public PrimitiveType(string keyword, AstLocation location) + { + this.Keyword = keyword; + this.Location = location; + } + + public override AstLocation StartLocation { + get { + return Location; + } + } + public override AstLocation EndLocation { + get { + return new AstLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0)); + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitPrimitiveType(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PrimitiveType o = other as PrimitiveType; + return o != null && MatchString(this.Keyword, o.Keyword); + } + + public override string ToString() + { + return Keyword ?? base.ToString(); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs new file mode 100644 index 0000000000..116f9918c9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs @@ -0,0 +1,66 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of QualifiedType. + /// + public class QualifiedType : AstType + { + public static readonly Role TargetRole = new Role("Target", AstType.Null); + + public AstType Target { + get { return GetChildByRole(TargetRole); } + set { SetChildByRole(TargetRole, value); } + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty)); + } + } + + public QualifiedType(AstType target, Identifier name) + { + Target = target; + SetChildByRole(Roles.Identifier, name); + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQualifiedType(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as QualifiedType; + return o != null && MatchString(this.Name, o.Name) && this.Target.DoMatch(o.Target, match); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append(this.Target); + b.Append('.'); + b.Append(this.Name); + if (this.TypeArguments.Any()) { + b.Append('('); + b.Append(string.Join(", ", this.TypeArguments)); + b.Append(')'); + } + return b.ToString(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs new file mode 100644 index 0000000000..590671b9c7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs @@ -0,0 +1,87 @@ +// +// FullTypeName.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class SimpleType : AstType + { + public SimpleType() + { + } + + public SimpleType(string identifier) + { + this.Identifier = identifier; + } + + public SimpleType(string identifier, AstLocation location) + { + SetChildByRole (Roles.Identifier, new Identifier (identifier, location)); + } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty)); + } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitSimpleType(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SimpleType o = other as SimpleType; + return o != null && MatchString(this.Identifier, o.Identifier) && this.TypeArguments.DoMatch(o.TypeArguments, match); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(this.Identifier); + if (this.TypeArguments.Any()) { + b.Append('('); + b.Append("Of "); + b.Append(string.Join(", ", this.TypeArguments)); + b.Append(')'); + } + return b.ToString(); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs new file mode 100644 index 0000000000..05a22acc44 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs @@ -0,0 +1,125 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of VBModifierToken. + /// + public class VBModifierToken : VBTokenNode + { + Modifiers modifier; + + public Modifiers Modifier { + get { return modifier; } + set { + for (int i = 0; i < lengthTable.Count; i++) { + if (lengthTable[i].Key == value) { + this.modifier = value; + this.tokenLength = lengthTable[i].Value; + return; + } + } + throw new ArgumentException ("Modifier " + value + " is invalid."); + } + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + VBModifierToken o = other as VBModifierToken; + return o != null && this.modifier == o.modifier; + } + + // Not worth using a dictionary for such few elements. + // This table is sorted in the order that modifiers should be output when generating code. + static readonly List> lengthTable = new List> () { + new KeyValuePair(Modifiers.Public, "Public".Length), + new KeyValuePair(Modifiers.Protected, "Protected".Length), + new KeyValuePair(Modifiers.Private, "Private".Length), + new KeyValuePair(Modifiers.Friend, "Friend".Length), + new KeyValuePair(Modifiers.MustInherit, "MustInherit".Length), + new KeyValuePair(Modifiers.MustOverride, "MustOverride".Length), + new KeyValuePair(Modifiers.Overridable, "Overridable".Length), + new KeyValuePair(Modifiers.NotInheritable, "NotInheritable".Length), + new KeyValuePair(Modifiers.NotOverridable, "NotOverridable".Length), + new KeyValuePair(Modifiers.Const, "Const".Length), + new KeyValuePair(Modifiers.Shared, "Shared".Length), + new KeyValuePair(Modifiers.Static, "Static".Length), + new KeyValuePair(Modifiers.Override, "Override".Length), + new KeyValuePair(Modifiers.ReadOnly, "ReadOnly".Length), + new KeyValuePair(Modifiers.WriteOnly, "WriteOnly".Length), + new KeyValuePair(Modifiers.Shadows, "Shadows".Length), + new KeyValuePair(Modifiers.Partial, "Partial".Length), + new KeyValuePair(Modifiers.Overloads, "Overloads".Length), + new KeyValuePair(Modifiers.WithEvents, "WithEvents".Length), + new KeyValuePair(Modifiers.Default, "Default".Length), + new KeyValuePair(Modifiers.Dim, "Dim".Length), + + // even though it's used for patterns only, it needs to be in this table to be usable in the AST + new KeyValuePair(Modifiers.Any, "Any".Length) + }; + + public static IEnumerable AllModifiers { + get { return lengthTable.Select(p => p.Key); } + } + + public VBModifierToken(AstLocation location, Modifiers modifier) : base (location, 0) + { + this.Modifier = modifier; + } + + public static string GetModifierName(Modifiers modifier) + { + switch (modifier) { + case Modifiers.Private: + return "Private"; + case Modifiers.Friend: + return "Friend"; + case Modifiers.Protected: + return "Protected"; + case Modifiers.Public: + return "Public"; + case Modifiers.MustInherit: + return "MustInherit"; + case Modifiers.MustOverride: + return "MustOverride"; + case Modifiers.Overridable: + return "Overridable"; + case Modifiers.NotInheritable: + return "NotInheritable"; + case Modifiers.NotOverridable: + return "NotOverridable"; + case Modifiers.Const: + return "Const"; + case Modifiers.Shared: + return "Shared"; + case Modifiers.Static: + return "Static"; + case Modifiers.Override: + return "Override"; + case Modifiers.ReadOnly: + return "ReadOnly"; + case Modifiers.Shadows: + return "Shadows"; + case Modifiers.Partial: + return "Partial"; + case Modifiers.Overloads: + return "Overloads"; + case Modifiers.WithEvents: + return "WithEvents"; + case Modifiers.Default: + return "Default"; + case Modifiers.Dim: + return "Dim"; + case Modifiers.WriteOnly: + return "WriteOnly"; + default: + throw new NotSupportedException("Invalid value for Modifiers"); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs new file mode 100644 index 0000000000..225484e670 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs @@ -0,0 +1,87 @@ +/* + * Created by SharpDevelop. + * User: Siegfried + * Date: 11.04.2011 + * Time: 20:44 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of VBTokenNode. + /// + public class VBTokenNode : AstNode + { + public static new readonly VBTokenNode Null = new NullVBTokenNode(); + + class NullVBTokenNode : VBTokenNode + { + public override bool IsNull { + get { + return true; + } + } + + public NullVBTokenNode() : base (AstLocation.Empty, 0) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + } + + protected int tokenLength = -1; + + AstLocation endLocation; + public override AstLocation EndLocation { + get { + return tokenLength < 0 ? endLocation : new AstLocation(startLocation.Line, startLocation.Column + tokenLength); + } + } + + public VBTokenNode(AstLocation location, int tokenLength) + { + this.startLocation = location; + this.tokenLength = tokenLength; + } + + public VBTokenNode(AstLocation startLocation, AstLocation endLocation) + { + this.startLocation = startLocation; + this.endLocation = endLocation; + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitVBTokenNode(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var node = other as VBTokenNode; + return node != null && !node.IsNull; + } + + public override string ToString () + { + return string.Format ("[VBTokenNode: StartLocation={0}, EndLocation={1}, Role={2}]", StartLocation, EndLocation, Role); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs new file mode 100644 index 0000000000..402dc449f6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs @@ -0,0 +1,92 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.AstBuilder +{ + /// + /// Extension methods for NRefactory.Dom.Expression. + /// + public static class ExpressionBuilder + {/* + public static SimpleNameExpression Identifier(string identifier) + { + return new SimpleNameExpression(identifier); + } + + public static MemberReferenceExpression Member(this Expression targetObject, string memberName) + { + if (targetObject == null) + throw new ArgumentNullException("targetObject"); + return new MemberReferenceExpression(targetObject, memberName); + } + + public static InvocationExpression Call(this Expression callTarget, string methodName, params Expression[] arguments) + { + if (callTarget == null) + throw new ArgumentNullException("callTarget"); + return Call(Member(callTarget, methodName), arguments); + } + + public static InvocationExpression Call(this Expression callTarget, params Expression[] arguments) + { + if (callTarget == null) + throw new ArgumentNullException("callTarget"); + if (arguments == null) + throw new ArgumentNullException("arguments"); + return new InvocationExpression(callTarget, new List(arguments)); + } + + public static ObjectCreateExpression New(this TypeReference createType, params Expression[] arguments) + { + if (createType == null) + throw new ArgumentNullException("createType"); + if (arguments == null) + throw new ArgumentNullException("arguments"); + return new ObjectCreateExpression(createType, new List(arguments)); + } + + public static Expression CreateDefaultValueForType(TypeReference type) + { + if (type != null && !type.IsArrayType) { + switch (type.Type) { + case "System.SByte": + case "System.Byte": + case "System.Int16": + case "System.UInt16": + case "System.Int32": + case "System.UInt32": + case "System.Int64": + case "System.UInt64": + case "System.Single": + case "System.Double": + return new PrimitiveExpression(0, "0"); + case "System.Char": + return new PrimitiveExpression('\0', "'\\0'"); + case "System.Object": + case "System.String": + return new PrimitiveExpression(null, "null"); + case "System.Boolean": + return new PrimitiveExpression(false, "false"); + default: + return new DefaultValueExpression(type); + } + } else { + return new PrimitiveExpression(null, "null"); + } + } + + /// + /// Just calls the BinaryOperatorExpression constructor, + /// but being an extension method; this allows for a nicer + /// infix syntax in some cases. + /// + public static BinaryOperatorExpression Operator(this Expression left, BinaryOperatorType op, Expression right) + { + return new BinaryOperatorExpression(left, op, right); + }*/ + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs new file mode 100644 index 0000000000..1f3541f15a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs @@ -0,0 +1,55 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.AstBuilder +{ + /// + /// Extension methods for NRefactory.Dom.Expression. + /// +// public static class StatementBuilder +// { +// public static void AddStatement(this BlockStatement block, Statement statement) +// { +// if (block == null) +// throw new ArgumentNullException("block"); +// if (statement == null) +// throw new ArgumentNullException("statement"); +// block.AddChild(statement); +// statement.Parent = block; +// } +// +// public static void AddStatement(this BlockStatement block, Expression expressionStatement) +// { +// if (expressionStatement == null) +// throw new ArgumentNullException("expressionStatement"); +// AddStatement(block, new ExpressionStatement(expressionStatement)); +// } +// +// public static void Throw(this BlockStatement block, Expression expression) +// { +// if (expression == null) +// throw new ArgumentNullException("expression"); +// AddStatement(block, new ThrowStatement(expression)); +// } +// +// public static void Return(this BlockStatement block, Expression expression) +// { +// if (expression == null) +// throw new ArgumentNullException("expression"); +// AddStatement(block, new ReturnStatement(expression)); +// } +// +// public static void Assign(this BlockStatement block, Expression left, Expression right) +// { +// if (left == null) +// throw new ArgumentNullException("left"); +// if (right == null) +// throw new ArgumentNullException("right"); +// AddStatement(block, new AssignmentExpression(left, AssignmentOperatorType.Assign, right)); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs new file mode 100644 index 0000000000..a2f8ac6c75 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -0,0 +1,46 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Ast; +using Attribute = ICSharpCode.NRefactory.VB.Ast.Attribute; + +namespace ICSharpCode.NRefactory.VB { + public interface IAstVisitor + { + S VisitBlockStatement(BlockStatement blockStatement, T data); + S VisitCompilationUnit(CompilationUnit compilationUnit, T data); + S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data); + S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data); + S VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, T data); + S VisitVBTokenNode(VBTokenNode vBTokenNode, T data); + + // Global scope + S VisitAliasImportsClause(AliasImportsClause aliasImportsClause, T data); + S VisitAttribute(Attribute attribute, T data); + S VisitAttributeBlock(AttributeBlock attributeBlock, T data); + S VisitImportsStatement(ImportsStatement importsStatement, T data); + S VisitMembersImportsClause(MemberImportsClause membersImportsClause, T data); + S VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, T data); + S VisitOptionStatement(OptionStatement optionStatement, T data); + S VisitTypeDeclaration(TypeDeclaration typeDeclaration, T data); + S VisitXmlNamespaceImportsClause(XmlNamespaceImportsClause xmlNamespaceImportsClause, T data); + S VisitEnumDeclaration(EnumDeclaration enumDeclaration, T data); + S VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, T data); + S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data); + + // Expression scope + S VisitIdentifier(Identifier identifier, T data); + S VisitXmlIdentifier(XmlIdentifier xmlIdentifier, T data); + S VisitXmlLiteralString(XmlLiteralString xmlLiteralString, T data); + S VisitSimpleNameExpression(SimpleNameExpression identifierExpression, T data); + S VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, T data); + + // TypeName + S VisitPrimitiveType(PrimitiveType primitiveType, T data); + S VisitQualifiedType(QualifiedType qualifiedType, T data); + S VisitComposedType(ComposedType composedType, T data); + S VisitArraySpecifier(ArraySpecifier arraySpecifier, T data); + S VisitSimpleType(SimpleType simpleType, T data); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj new file mode 100644 index 0000000000..1dac9e1d98 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj @@ -0,0 +1,169 @@ + + + + {7B82B671-419F-45F4-B778-D9286F996EFA} + Debug + x86 + Library + ICSharpCode.NRefactory.VB + ICSharpCode.NRefactory.VB + v4.0 + Properties + Client + + + x86 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + + + bin\Release\ + False + None + True + False + TRACE + + + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ExpressionFinder.atg + + + + + + + + + + + + + + + + + + + + vb.atg + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CocoParserGenerator + ICSharpCode.NRefactory.VB.Parser + Parser.cs + + + + ExpressionFinder.atg + + + vb.atg + + + ICSharpCode.NRefactory.VB.Parser + CocoParserGenerator + Parser.cs + + + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Block.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Block.cs new file mode 100644 index 0000000000..c9ffba0d20 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Block.cs @@ -0,0 +1,57 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public enum Context + { + Global, + TypeDeclaration, + ObjectCreation, + ObjectInitializer, + CollectionInitializer, + Type, + Member, + Parameter, + Identifier, + Body, + Xml, + Attribute, + Importable, + Query, + Expression, + Debug, + Default + } + + public class Block : ICloneable + { + public static readonly Block Default = new Block() { + context = Context.Global, + lastExpressionStart = AstLocation.Empty + }; + + public Context context; + public AstLocation lastExpressionStart; + public bool isClosed; + + public override string ToString() + { + return string.Format("[Block Context={0}, LastExpressionStart={1}, IsClosed={2}]", context, lastExpressionStart, isClosed); + } + + public object Clone() + { + return new Block() { + context = this.context, + lastExpressionStart = this.lastExpressionStart, + isClosed = this.isClosed + }; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.atg b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.atg new file mode 100644 index 0000000000..b2768890d3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.atg @@ -0,0 +1,1375 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +PUSHCOMPILER WITH EXPECTEDSETS ExpressionFinder + +/* START AUTOGENERATED TOKENS SECTION */ +TOKENS + /* ----- terminal classes ----- */ + /* EOF is 0 */ + EOL + ident + LiteralString + LiteralCharacter + LiteralInteger + LiteralDouble + LiteralSingle + LiteralDecimal + LiteralDate + XmlOpenTag + XmlCloseTag + XmlStartInlineVB + XmlEndInlineVB + XmlCloseTagEmptyElement + XmlOpenEndTag + XmlContent + XmlComment + XmlCData + XmlProcessingInstruction + + /* ----- special character ----- */ + "=" + ":" + "," + "&" + "/" + "\\" + "." + "..." + ".@" + "!" + "-" + "+" + "^" + "?" + "*" + "{" + "}" + "(" + ")" + ">" + "<" + "<>" + ">=" + "<=" + "<<" + ">>" + "+=" + "^=" + "-=" + "*=" + "/=" + "\\=" + "<<=" + ">>=" + "&=" + ":=" + + /* ----- keywords ----- */ + "AddHandler" + "AddressOf" + "Aggregate" + "Alias" + "And" + "AndAlso" + "Ansi" + "As" + "Ascending" + "Assembly" + "Auto" + "Binary" + "Boolean" + "ByRef" + "By" + "Byte" + "ByVal" + "Call" + "Case" + "Catch" + "CBool" + "CByte" + "CChar" + "CDate" + "CDbl" + "CDec" + "Char" + "CInt" + "Class" + "CLng" + "CObj" + "Compare" + "Const" + "Continue" + "CSByte" + "CShort" + "CSng" + "CStr" + "CType" + "CUInt" + "CULng" + "CUShort" + "Custom" + "Date" + "Decimal" + "Declare" + "Default" + "Delegate" + "Descending" + "Dim" + "DirectCast" + "Distinct" + "Do" + "Double" + "Each" + "Else" + "ElseIf" + "End" + "EndIf" + "Enum" + "Equals" + "Erase" + "Error" + "Event" + "Exit" + "Explicit" + "False" + "Finally" + "For" + "Friend" + "From" + "Function" + "Get" + "GetType" + "Global" + "GoSub" + "GoTo" + "Group" + "Handles" + "If" + "Implements" + "Imports" + "In" + "Infer" + "Inherits" + "Integer" + "Interface" + "Into" + "Is" + "IsNot" + "Join" + "Key" + "Let" + "Lib" + "Like" + "Long" + "Loop" + "Me" + "Mod" + "Module" + "MustInherit" + "MustOverride" + "MyBase" + "MyClass" + "Namespace" + "Narrowing" + "New" + "Next" + "Not" + "Nothing" + "NotInheritable" + "NotOverridable" + "Object" + "Of" + "Off" + "On" + "Operator" + "Option" + "Optional" + "Or" + "Order" + "OrElse" + "Out" + "Overloads" + "Overridable" + "Overrides" + "ParamArray" + "Partial" + "Preserve" + "Private" + "Property" + "Protected" + "Public" + "RaiseEvent" + "ReadOnly" + "ReDim" + "Rem" + "RemoveHandler" + "Resume" + "Return" + "SByte" + "Select" + "Set" + "Shadows" + "Shared" + "Short" + "Single" + "Skip" + "Static" + "Step" + "Stop" + "Strict" + "String" + "Structure" + "Sub" + "SyncLock" + "Take" + "Text" + "Then" + "Throw" + "To" + "True" + "Try" + "TryCast" + "TypeOf" + "UInteger" + "ULong" + "Unicode" + "Until" + "UShort" + "Using" + "Variant" + "Wend" + "When" + "Where" + "While" + "Widening" + "With" + "WithEvents" + "WriteOnly" + "Xor" + "GetXmlNamespace" +/* END AUTOGENERATED TOKENS SECTION */ + +PRODUCTIONS +/*------------------------------------------------------------------------*/ +ExpressionFinder = + (. PushContext(Context.Global, la, t); .) + { OptionStatement } + { ImportsStatement } + { EXPECTEDCONFLICT("<") AttributeBlock } /* Expected LL(1) conflict: we can't tell global attributes */ + /* from those on types. */ + /* This isn't a problem, we can just treat all as global attributes */ + { NamespaceMemberDeclaration } + (. PopContext(); .) +. + +StatementTerminator + (. if (la != null) CurrentBlock.lastExpressionStart = la.Location; .) += + EOL | ":" +. + +OptionStatement = + "Option" ( ( "Explicit" | "Strict" | "Infer" ) [ "Off" | "On" ] | "Compare" ( "Text" | "Binary" ) ) StatementTerminator +. + +ImportsStatement = + "Imports" (. PushContext(Context.Importable, la, t); .) + (. nextTokenIsStartOfImportsOrAccessExpression = true; .) + ( + ( "Global" | Identifier | PrimitiveTypeName ) { TypeSuffix } [ ( "." | "=" ) TypeName ] + | XmlOpenTag Identifier "=" LiteralString XmlCloseTag + ) + { "," + (. nextTokenIsStartOfImportsOrAccessExpression = true; .) + ( + ( "Global" | Identifier | PrimitiveTypeName ) { TypeSuffix } [ ( "." | "=" ) TypeName ] + | XmlOpenTag Identifier "=" LiteralString XmlCloseTag + ) + } + (. PopContext(); .) + StatementTerminator + +. + +AttributeBlock = + "<" (. wasNormalAttribute = true; PushContext(Context.Attribute, la, t); .) [ ( "Assembly" | "Module" ) ":" (. wasNormalAttribute = false; .) ] { ANY } ">" (. PopContext(); .) [ EOL ] +. + +NamespaceMemberDeclaration = + NamespaceDeclaration + | TypeDeclaration +. + +NamespaceDeclaration = + "Namespace" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) { ANY } (. PopContext(); .) StatementTerminator + { NamespaceMemberDeclaration } + "End" "Namespace" StatementTerminator +. + +TypeDeclaration = + { AttributeBlock } + { TypeModifier } + ( ClassOrModuleOrStructureTypeDeclaration | + DelegateTypeDeclaration | + EnumTypeDeclaration | + InterfaceDeclaration ) +. + +ClassOrModuleOrStructureTypeDeclaration = + (. PushContext(Context.TypeDeclaration, la, t); .) + ( "Module" | "Class" | "Structure" ) (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "(" "Of" GenericTypeParameterDeclaration ")" ] StatementTerminator + [ (. isMissingModifier = false; .) "Inherits" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) StatementTerminator ] + [ (. isMissingModifier = false; .) "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) } StatementTerminator ] + { + { AttributeBlock } (.OnEachPossiblePath: isMissingModifier = true; .) + { TypeOrMemberModifier (. isMissingModifier = false; .) } (. isMissingModifier = false; .) + ( ClassOrModuleOrStructureTypeDeclaration | DelegateTypeDeclaration | EnumTypeDeclaration + | InterfaceDeclaration | MemberDeclaration ) + } + (. isMissingModifier = false; .) + "End" ( "Module" | "Class" | "Structure" ) StatementTerminator + (. PopContext(); .) +. + +EnumTypeDeclaration = + (. PushContext(Context.TypeDeclaration, la, t); .) + "Enum" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] StatementTerminator + { + { AttributeBlock } + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "=" Expression ] + StatementTerminator + } + "End" "Enum" StatementTerminator + (. PopContext(); .) +. + +InterfaceDeclaration = + (. PushContext(Context.TypeDeclaration, la, t); .) + "Interface" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "(" "Of" GenericTypeParameterDeclaration ")" ] StatementTerminator + [ "Inherits" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) } StatementTerminator ] + { + { AttributeBlock } (.OnEachPossiblePath: isMissingModifier = true; .) + { TypeOrMemberModifier (. isMissingModifier = false; .) } (. isMissingModifier = false; .) + ( ClassOrModuleOrStructureTypeDeclaration | DelegateTypeDeclaration | EnumTypeDeclaration + | InterfaceDeclaration | InterfaceMemberDeclaration ) + } + (. isMissingModifier = false; .) + "End" "Interface" StatementTerminator + (. PopContext(); .) +. + +InterfaceMemberDeclaration = + InterfaceEvent | InterfaceProperty | InterfaceSubOrFunction +. + +TypeOrMemberModifier = + MemberModifier /* contains all modifiers for types */ +. + +InterfaceEvent = + "Event" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) | ParameterListInParenthesis ] + StatementTerminator +. + +InterfaceProperty = + "Property" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ ParameterListInParenthesis ] [ "As" (. PushContext(Context.Type, la, t); .) { AttributeBlock } TypeName (. PopContext(); .) ] + StatementTerminator +. + +InterfaceSubOrFunction = + ("Sub" | "Function") + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) ANY (. PopContext(); .) + { "(" [ ( "Of" GenericTypeParameterDeclaration | ParameterList ) ] ")" } + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + StatementTerminator +. + +GenericConstraint = + TypeName | "New" | "Class" | "Structure" +. + +GenericConstraintList = + GenericConstraint | "{" GenericConstraint { "," GenericConstraint } "}" +. + +GenericTypeParameterDeclaration = + [ "Out" | "In" ] (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) IdentifierExceptOut (. PopContext(); .) [ "As" (. PushContext(Context.Type, la, t); .) GenericConstraintList (. PopContext(); .) ] + { "," [ "Out" | "In" ] (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) IdentifierExceptOut (. PopContext(); .) [ "As" (. PushContext(Context.Type, la, t); .) GenericConstraintList (. PopContext(); .) ] } +. + +DelegateTypeDeclaration = + "Delegate" ("Sub" | "Function") + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) ANY (. PopContext(); .) + { "(" [ "Of" GenericTypeParameterDeclaration | ParameterList ] ")" } + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + StatementTerminator +. + +MemberDeclaration = + (. PushContext(Context.Member, la, t); .) + ( + MemberVariableOrConstantDeclaration | + SubOrFunctionDeclaration | + ExternalMemberDeclaration | + EventMemberDeclaration | + CustomEventMemberDeclaration | + PropertyDeclaration | + OperatorDeclaration + ) + (. PopContext(); .) +. + +SubOrFunctionDeclaration = + ("Sub" | "Function") + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) ANY (. PopContext(); .) + { "(" [ ( "Of" GenericTypeParameterDeclaration | ParameterList ) ] ")" } + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + [ ( "Implements" | "Handles" ) [ ( "Me" | "MyClass" | "MyBase" ) "." ] TypeName ] + StatementTerminatorAndBlock + "End" ("Sub" | "Function") StatementTerminator +. + +ExternalMemberDeclaration = + "Declare" [ "Ansi" | "Unicode" | "Auto" ] ( "Sub" | "Function" ) + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + "Lib" LiteralString + [ "Alias" LiteralString ] + [ ParameterListInParenthesis ] + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + StatementTerminator +. + +EventMemberDeclaration = + "Event" + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + ( "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) | [ ParameterListInParenthesis ] ) + [ "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ + { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ } ] + /* the TypeName production already allows the "." IdentifierOrKeyword syntax, so to avoid an ambiguous grammar we just leave that out */ + StatementTerminator +. + +CustomEventMemberDeclaration = + "Custom" EventMemberDeclaration + { + { AttributeBlock } ( "AddHandler" | "RemoveHandler" | "RaiseEvent" ) "(" ParameterList ")" + StatementTerminatorAndBlock + "End" ( "AddHandler" | "RemoveHandler" | "RaiseEvent" ) StatementTerminator + } + "End" "Event" StatementTerminator +. + +PropertyDeclaration = + "Property" + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ ParameterListInParenthesis ] + [ "As" (. PushContext(Context.Type, la, t); .) { AttributeBlock } ( NewExpression | TypeName ) (. PopContext(); .) ] + [ "Implements" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ + { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) /*"." IdentifierOrKeyword*/ } ] + [ "=" Expression ] StatementTerminator + (. PopContext(); .) { EXPECTEDCONFLICT("<") AttributeBlock } + { EXPECTEDCONFLICT("Public", "Protected", "Private", "Friend") AccessModifier + // HACK : OnEachPossiblePath cannot detect that this might be the end of an auto property + // so we need to simulate it + (.OnEachPossiblePath: SetIdentifierExpected(la); .) } + [ (. PushContext(Context.Member, la, t); .) + ( "Get" | "Set" ) [ ParameterListInParenthesis ] + StatementTerminatorAndBlock + "End" ( "Get" | "Set" ) StatementTerminator + [ { AttributeBlock } { AccessModifier } ( "Get" | "Set" ) [ ParameterListInParenthesis ] + StatementTerminatorAndBlock + "End" ( "Get" | "Set" ) StatementTerminator ] + + "End" "Property" StatementTerminator ] +. + +OperatorDeclaration = + "Operator" (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) ANY (. PopContext(); .) + "(" ParameterList ")" + [ "As" (. PushContext(Context.Type, la, t); .) { AttributeBlock } TypeName (. PopContext(); .) ] + StatementTerminatorAndBlock + "End" "Operator" StatementTerminator +. + +MemberVariableOrConstantDeclaration = + MemberVariableOrConstantDeclarator { "," MemberVariableOrConstantDeclarator } StatementTerminator +. + +MemberVariableOrConstantDeclarator = + [ "Const" ] + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) IdentifierForFieldDeclaration (. PopContext(); .) + [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" } + [ "As" (. PushContext(Context.Type, la, t); .) ( NewExpression | TypeName ) (. PopContext(); .) ] + [ "=" Expression ] +. + +ParameterList = + Parameter { "," Parameter } +. + +Parameter = + (. PushContext(Context.Parameter, la, t); .) + { AttributeBlock } { ParameterModifier } + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "?" ] { "(" { "," } ")" } + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + [ "=" Expression ] + (. PopContext(); .) +. + +StatementTerminatorAndBlock = + (. PushContext(Context.Body, la, t); .) + StatementTerminator + { EXPECTEDCONFLICT("End") + ( + [ Statement] StatementTerminator + | "End" + ( StatementTerminator /* End+StatementTerminator is end statement */ + | /* End+anything else is the end of this block. */ + (. + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process End again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + .) + ANY /* never reached due to goto above: */ + /* this ANY is just so that Coco knows this branch isn't empty */ + ) + ) + } + (.NamedState:endOfStatementTerminatorAndBlock.) + (. PopContext(); .) +. + +Expression + (.NamedState:startOfExpression.) += + (. PushContext(Context.Expression, la, t); .) + SimpleExpressionWithSuffix { BinaryOperator SimpleExpressionWithSuffix } + (. PopContext(); .) +. + +BinaryOperator = + "+" | "-" | "*" | "\\" | "/" | "^" | "Mod" + | "=" | "<>" | "<" | ">" (. wasNormalAttribute = false; .) | "<=" | ">=" + | "Like" | "&" | "And" | "AndAlso" | "Or" | "OrElse" + | "Xor" | "<<" | ">>" | "Is" | "IsNot" + | "^=" | "*=" | "/=" | "\\=" | "+=" | "-=" | "&=" | "<<=" | ">>=" | "To" | ":=" +. + +UnaryOperator = + "+" | "-" | "Not" | "AddressOf" +. + +SimpleExpressionWithSuffix = + (. PushContext(Context.Expression, la, t); .) + { UnaryOperator } + ( + SimpleExpression { ExpressionSuffix } + | "TypeOf" SimpleExpressionWithSuffix "Is" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) + | NewExpression + | CollectionInitializer + ) + (. PopContext(); .) +. + +SimpleExpression = + (. PushContext(Context.Expression, la, t); .) + ( Literal + | ( "(" (. activeArgument = 0; .) Expression // HACK in ExpressionRangeVariable Identifier is consumed before start + // of Expression so this can be an argument list too + { "," (. activeArgument++; .) Expression } ")" ) + | IdentifierForExpressionStart + | PrimitiveTypeName + | ( "." | "!" | ".@" | "..." ) (. nextTokenIsStartOfImportsOrAccessExpression = true; wasQualifierTokenAtStart = true; .) [ XmlOpenTag ] IdentifierOrKeyword [ XmlCloseTag ] + | "GetType" "(" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ")" + | "GetXmlNamespace" "(" (. readXmlIdentifier = true; .) Identifier ")" + | XmlLiteral + | LambdaExpression + | GREEDY QueryExpression + | CastExpression + | ConditionalExpression + ) + (. PopContext(); .) +. + +NewExpression = + "New" (. PushContext(Context.ObjectCreation, la, t); .) + ( + TypeName + [ + EXPECTEDCONFLICT("From") + ( + (. PushContext(Context.CollectionInitializer, la, t); .) + "From" + ( + CollectionInitializer /* From + CollectionInitializer is a NewExpression */ + | + (. + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process From again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + .) + ANY /* never reached due to goto above: */ + /* this ANY is just so that Coco knows this branch isn't empty */ + ) + (. PopContext(); .) + | + /* handle array initializer after New */ + (. PushContext(Context.CollectionInitializer, la, t); .) + CollectionInitializer + (. PopContext(); .) + | + (. PushContext(Context.ObjectInitializer, la, t); .) + "With" ObjectInitializer + (. PopContext(); .) + ) + ] + | + (. PushContext(Context.ObjectInitializer, la, t); .) + "With" ObjectInitializer + (. PopContext(); .) + ) + (. PopContext(); .) +. + +ObjectInitializer = + "{" [ [ "Key" ] "." IdentifierOrKeyword "=" Expression { "," [ "Key" ] "." IdentifierOrKeyword "=" Expression } ] "}" +. + +CollectionInitializer = + "{" [ Expression { "," Expression } ] "}" +. + +ExpressionSuffix = + "(" (. PushContext(Context.Expression, la, t); .) + ( "Of" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) + { "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) } + | [ ArgumentList ] ) (. PopContext(); .) ")" +| ( "." | "!" | ".@" | "..." ) (. nextTokenIsStartOfImportsOrAccessExpression = true; .) [ XmlOpenTag ] IdentifierOrKeyword [ XmlCloseTag ] +. + +CastExpression = + SimpleCastExpression | ("DirectCast" | "TryCast" | "CType") "(" Expression "," (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ")" +. + +SimpleCastExpression = + ( + "CBool" | + "CByte" | + "CChar" | + "CDate" | + "CDec" | + "CDbl" | + "CInt" | + "CLng" | + "CObj" | + "CSByte" | + "CShort" | + "CSng" | + "CStr" | + "CUInt" | + "CULng" | + "CUShort" + ) + "(" Expression ")" +. + +ConditionalExpression = + "If" "(" Expression "," Expression [ "," Expression ] ")" +. + +LambdaExpression = + SubLambdaExpression | + FunctionLambdaExpression +. + +SubLambdaExpression = + "Sub" ParameterListInParenthesis + ( GREEDY Statement | StatementTerminatorAndBlock "End" "Sub" ) +. + +FunctionLambdaExpression = + "Function" ParameterListInParenthesis + ( GREEDY Expression | [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] StatementTerminatorAndBlock "End" "Function" ) +. + +ParameterListInParenthesis = + "(" (. PushContext(Context.Default, la, t); .) [ ParameterList ] (. PopContext(); .) ")" +. + +QueryExpression + (. PushContext(Context.Query, la, t); .) += + ( FromQueryOperator | AggregateQueryOperator ) + { QueryOperator } + (. PopContext(); .) +. + +QueryOperator = + FromQueryOperator + | AggregateQueryOperator + | SelectQueryOperator + | DistinctQueryOperator + | WhereQueryOperator + | OrderByQueryOperator + | PartitionQueryOperator + | LetQueryOperator + | GroupByOrGroupJoinQueryOperator + | JoinQueryOperator +. + +FromQueryOperator = + "From" CollectionRangeVariable { "," CollectionRangeVariable } +. + +AggregateQueryOperator = + "Aggregate" CollectionRangeVariable { QueryOperator } "Into" ExpressionRangeVariable { "," ExpressionRangeVariable } +. + +SelectQueryOperator = + "Select" ExpressionRangeVariable { "," ExpressionRangeVariable } +. + +DistinctQueryOperator = + "Distinct" +. + +WhereQueryOperator = + "Where" Expression +. + +OrderByQueryOperator = + "Order" "By" Expression ( "Ascending" | "Descending" ) { "," Expression ( "Ascending" | "Descending" ) } +. + +PartitionQueryOperator = + ( "Take" | "Skip" ) [ "While" ] Expression +. + +LetQueryOperator = + "Let" ExpressionRangeVariable { "," ExpressionRangeVariable } +. + +GroupByOrGroupJoinQueryOperator = + "Group" + ( + EXPECTEDCONFLICT("Join") + JoinQueryOperator { ( "Group" JoinQueryOperator GroupJoinSuffix | JoinQueryOperator ) } + GroupJoinSuffix + | + ( EXPECTEDCONFLICT("By") () | ExpressionRangeVariable { "," ExpressionRangeVariable } ) + "By" ExpressionRangeVariable { "," ExpressionRangeVariable } + "Into" ExpressionRangeVariable { "," ExpressionRangeVariable } + ) +. + +JoinQueryOperator = + "Join" CollectionRangeVariable + "On" Expression "Equals" Expression { "," Expression "Equals" Expression } +. + +GroupJoinSuffix = + "Into" ExpressionRangeVariable { "," ExpressionRangeVariable } +. + +ExpressionRangeVariable = + [ + EXPECTEDCONFLICT("Where", "Until", "Unicode", "Text", "Take", "Skip", "Preserve", + "Order", "Off", "Out", "Key", "Join", "Into", "Infer", "Group", "From", + "Explicit", "Equals", "Distinct", "Descending", "Compare", "By", + "Binary", "Auto", "Assembly", "Ascending", "Ansi", "Aggregate", ident) + ( + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier + // HACK: needs to be optional because Expression can start with Identifier too + [ (. PopContext(); isAlreadyInExpr = true; .) + ( "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) "=" + | "=" + | (. + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process Identifier again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + .) + ANY /* never reached due to goto above: */ + /* this ANY is just so that Coco knows this branch isn't empty */ + ) + ] + ) + ] + Expression + (. if (!isAlreadyInExpr) PopContext(); isAlreadyInExpr = false; .) +. + +CollectionRangeVariable = + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + "In" Expression +. + +/* semantic action will be inserted on all paths that possibly lead to XmlLiteral */ +XmlLiteral + (.OnEachPossiblePath: nextTokenIsPotentialStartOfExpression = true; .) += + (. PushContext(Context.Xml, la, t); .) + ( + ( XmlComment | XmlProcessingInstruction | XmlCData ) [ XmlContent ] { ( XmlComment | XmlProcessingInstruction ) [ XmlContent ] } [ XmlElement { XmlComment [ XmlContent ] } ] + | + XmlElement { XmlComment [ XmlContent ] } + ) + (. PopContext(); .) +. + +XmlElement = + (. PushContext(Context.Xml, la, t); .) + XmlOpenTag { ANY | XmlEmbeddedExpression } ( XmlCloseTagEmptyElement | XmlCloseTag { ANY | XmlEmbeddedExpression | XmlElement } XmlOpenEndTag { ANY | XmlEmbeddedExpression } XmlCloseTag ) + (. PopContext(); .) +. + +XmlEmbeddedExpression = + XmlStartInlineVB Expression XmlEndInlineVB +. + +PrimitiveTypeName = + "Byte" | + "SByte" | + "UShort" | + "Short" | + "UInteger" | + "Integer" | + "ULong" | + "Long" | + "Single" | + "Double" | + "Decimal" | + "Boolean" | + "Date" | + "Char" | + "String" | + "Object" +. + +TypeName = ( "Global" | Identifier | PrimitiveTypeName | "?" /* used for ? = completion */ ) { TypeSuffix } { "." IdentifierOrKeyword { TypeSuffix } } . + +TypeSuffix = "(" (. PushContext(Context.Expression, la, t); .) ( "Of" [ (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] { "," [ (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] } | [ ArgumentList ] ) (. PopContext(); .) ")" . + +IdentifierOrKeyword = ident +| "AddHandler" +| "AddressOf" +| "Aggregate" +| "Alias" +| "And" +| "AndAlso" +| "Ansi" +| "As" +| "Ascending" +| "Assembly" +| "Auto" +| "Binary" +| "Boolean" +| "ByRef" +| "By" +| "Byte" +| "ByVal" +| "Call" +| "Case" +| "Catch" +| "CBool" +| "CByte" +| "CChar" +| "CDate" +| "CDbl" +| "CDec" +| "Char" +| "CInt" +| "Class" +| "CLng" +| "CObj" +| "Compare" +| "Const" +| "Continue" +| "CSByte" +| "CShort" +| "CSng" +| "CStr" +| "CType" +| "CUInt" +| "CULng" +| "CUShort" +| "Custom" +| "Date" +| "Decimal" +| "Declare" +| "Default" +| "Delegate" +| "Descending" +| "Dim" +| "DirectCast" +| "Distinct" +| "Do" +| "Double" +| "Each" +| "Else" +| "ElseIf" +| "End" +| "EndIf" +| "Enum" +| "Equals" +| "Erase" +| "Error" +| "Event" +| "Exit" +| "Explicit" +| "False" +| "Finally" +| "For" +| "Friend" +| "From" +| "Function" +| "Get" +| "GetType" +| "Global" +| "GoSub" +| "GoTo" +| "Group" +| "Handles" +| "If" +| "Implements" +| "Imports" +| "In" +| "Infer" +| "Inherits" +| "Integer" +| "Interface" +| "Into" +| "Is" +| "IsNot" +| "Join" +| "Key" +| "Let" +| "Lib" +| "Like" +| "Long" +| "Loop" +| "Me" +| "Mod" +| "Module" +| "MustInherit" +| "MustOverride" +| "MyBase" +| "MyClass" +| "Namespace" +| "Narrowing" +| "New" +| "Next" +| "Not" +| "Nothing" +| "NotInheritable" +| "NotOverridable" +| "Object" +| "Of" +| "Off" +| "On" +| "Operator" +| "Option" +| "Optional" +| "Or" +| "Order" +| "OrElse" +| "Out" +| "Overloads" +| "Overridable" +| "Overrides" +| "ParamArray" +| "Partial" +| "Preserve" +| "Private" +| "Property" +| "Protected" +| "Public" +| "RaiseEvent" +| "ReadOnly" +| "ReDim" +| "Rem" +| "RemoveHandler" +| "Resume" +| "Return" +| "SByte" +| "Select" +| "Set" +| "Shadows" +| "Shared" +| "Short" +| "Single" +| "Skip" +| "Static" +| "Step" +| "Stop" +| "Strict" +| "String" +| "Structure" +| "Sub" +| "SyncLock" +| "Take" +| "Text" +| "Then" +| "Throw" +| "To" +| "True" +| "Try" +| "TryCast" +| "TypeOf" +| "UInteger" +| "ULong" +| "Unicode" +| "Until" +| "UShort" +| "Using" +| "Variant" +| "Wend" +| "When" +| "Where" +| "While" +| "Widening" +| "With" +| "WithEvents" +| "WriteOnly" +| "Xor" +| "GetXmlNamespace" +. + +Literal = + LiteralString | + LiteralCharacter | + LiteralInteger | + LiteralDouble | + LiteralSingle | + LiteralDecimal | + LiteralDate | + "True" | + "False" | + "Nothing" | + /* from InstanceExpression */ + "Me" | + "MyBase" | + "MyClass" +. + +Statement = + VariableDeclarationStatement + | WithOrLockStatement + | AddOrRemoveHandlerStatement + | RaiseEventStatement + | EXPECTEDCONFLICT("If") IfStatement /* prefer if-statement to if-expression */ + | SelectStatement + | WhileStatement + | DoLoopStatement + | ForStatement + | ErrorHandlingStatement + | ThrowStatement + | TryStatement + | BranchStatement + | ReDimStatement + | EraseStatement + | UsingStatement + | InvocationStatement +. + +VariableDeclarationStatement = + ( "Dim" | "Static" | "Const" ) + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) + Identifier (. PopContext(); .) [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" } + [ "As" (. PushContext(Context.Type, la, t); .) ( NewExpression | TypeName ) (. PopContext(); .) ] + [ "=" Expression ] + { "," + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) + Identifier (. PopContext(); .) [ "?" ] { "(" [ Expression ] { "," [ Expression ] } ")" } + [ "As" (. PushContext(Context.Type, la, t); .) ( NewExpression | TypeName ) (. PopContext(); .) ] + [ "=" Expression ] + } +. + +WithOrLockStatement = + ( "With" | "SyncLock" ) Expression StatementTerminatorAndBlock "End" ( "With" | "SyncLock" ) +. + +AddOrRemoveHandlerStatement = + ( "AddHandler" | "RemoveHandler" ) Expression "," Expression +. + +RaiseEventStatement = + "RaiseEvent" IdentifierOrKeyword [ "(" (. PushContext(Context.Expression, la, t); .) [ ArgumentList ] (. PopContext(); .) ")" ] +. + +IfStatement = + "If" Expression + ( "Then" + ( Statement { EXPECTEDCONFLICT(":") ":" [Statement] } [ EXPECTEDCONFLICT("Else") "Else" [Statement] { EXPECTEDCONFLICT(":") ":" [Statement] } ] + | MultilineIfRemainder + ) + | MultilineIfRemainder + ) +. + +MultilineIfRemainder = + StatementTerminatorAndBlock + { + ("Else" [ "If" Expression [ "Then" ] ] + | "ElseIf" Expression [ "Then" ] + ) + StatementTerminatorAndBlock + } + "End" "If" +. + +SelectStatement = + "Select" [ "Case" ] Expression StatementTerminator + { + "Case" ( + "Else" | + ( [ "Is" ] ComparisonOperator SimpleExpressionWithSuffix | Expression ) + { "," ( [ "Is" ] ComparisonOperator SimpleExpressionWithSuffix | Expression ) } + ) + StatementTerminatorAndBlock + } + "End" "Select" +. + +ComparisonOperator = + "=" | "<>" | "<" | ">" (. wasNormalAttribute = false; .) | ">=" | "<=" +. + +WhileStatement = + "While" Expression StatementTerminatorAndBlock "End" "While" +. + +DoLoopStatement = + "Do" ( DoTopLoopStatement | DoBottomLoopStatement ) +. + +DoTopLoopStatement = + ( "While" | "Until" ) Expression + StatementTerminatorAndBlock + "Loop" +. + +DoBottomLoopStatement = + StatementTerminatorAndBlock + "Loop" [ ( "While" | "Until" ) Expression ] +. + +ForStatement = + "For" ( ForLoopStatement | ForEachLoopStatement ) +. + +ForLoopStatement = + ForLoopVariable "=" Expression /* "To" is binary operator */ [ "Step" Expression ] + StatementTerminatorAndBlock + "Next" [ Expression { "," Expression } ] +. + +ForEachLoopStatement = + "Each" ForLoopVariable "In" Expression + StatementTerminatorAndBlock + "Next" [ Expression { "," Expression } ] +. + +ForLoopVariable = + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) SimpleExpression (. PopContext(); .) + [ "?" ] { ExpressionSuffix } + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] +. + +ErrorHandlingStatement = + [ "On" ] "Error" ( Expression | "GoTo" ( LiteralInteger | Identifier ) | "Resume" "Next" ) + | "Resume" ( "Next" | LiteralInteger | Identifier ) +. + +ThrowStatement = + "Throw" [ Expression ] +. + +TryStatement = + "Try" + StatementTerminatorAndBlock + { + "Catch" + [ (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier (. PopContext(); .) + [ "As" (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) ] + ] + [ "When" Expression ] + StatementTerminatorAndBlock + } + [ + "Finally" + StatementTerminatorAndBlock + ] + "End" "Try" +. + +BranchStatement = + "GoTo" ( Identifier | LiteralInteger ) + | "Exit" ( "Do" | "For" | "While" | "Select" | "Sub" | "Function" | "Property" | "Try" ) + | "Continue" ( "Do" | "For" | "While" ) + | "Stop" + /*| "End" HACK End-Statements has special handling in Block */ + | "Return" (. PushContext(Context.Expression, la, t); .) [ Expression ] (. PopContext(); .) +. + +ReDimStatement = + "ReDim" + [ EXPECTEDCONFLICT("Preserve") "Preserve" ] /* Preserve is context-dependend keyword */ + Expression +. + +EraseStatement = + "Erase" Expression { "," Expression } +. + +UsingVariable = + [ + EXPECTEDCONFLICT("Where", "Until", "Unicode", "Text", "Take", "Skip", "Preserve", + "Order", "Off", "Out", "Key", "Join", "Into", "Infer", "Group", "From", + "Explicit", "Equals", "Distinct", "Descending", "Compare", "By", + "Binary", "Auto", "Assembly", "Ascending", "Ansi", "Aggregate", ident) + ( + (. PushContext(Context.Identifier, la, t); .) (.OnEachPossiblePath: SetIdentifierExpected(la); .) Identifier + // HACK: needs to be optional because Expression can start with Identifier too + [ (. PopContext(); isAlreadyInExpr = true; .) + ( "As" [ EXPECTEDCONFLICT("Where", "UShort", "Until", "Unicode", "ULong", "UInteger", "Text", "Take", + "String", "Skip", "Single", "Short", "SByte", "Preserve", "Out", "Order", + "Off", "Object", "Long", "Key", "Join", "Into", "Integer", "Infer", "Group", + "From", "Explicit", "Equals", "Double", "Distinct", "Descending", "Decimal", + "Date", "Compare", "Char", "Byte", "By", "Boolean", "Binary", "Binary", "Auto", + "Assembly", "Ascending", "Ansi", "Aggregate", ident) + (. PushContext(Context.Type, la, t); .) TypeName (. PopContext(); .) "=" ] + | "=" + | (. + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process Identifier again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + .) + ANY /* never reached due to goto above: */ + /* this ANY is just so that Coco knows this branch isn't empty */ + ) + ] + ) + ] + Expression + (. if (!isAlreadyInExpr) PopContext(); isAlreadyInExpr = false; .) +. + +UsingStatement = + "Using" UsingVariable { "," UsingVariable } + StatementTerminatorAndBlock + "End" "Using" +. + +InvocationStatement = + [ "Call" ] Expression +. + +ArgumentList = + (. activeArgument = 0; .) Expression { "," (. activeArgument++; .) [ Expression ] } +| (. activeArgument = 0; .) "," (. activeArgument++; .) [ Expression ] { "," (. activeArgument++; .) [ Expression ] } +. + +/* This production handles pseudo keywords that are needed in the grammar */ +Identifier = + IdentifierForFieldDeclaration + | "Custom" +. + +IdentifierForFieldDeclaration = + IdentifierForExpressionStart + | "Aggregate" + | "From" +. + +IdentifierForExpressionStart = + IdentifierExceptOut + | "Out" +. + +IdentifierExceptOut = + ident + | "Ansi" + | "Ascending" + | "Assembly" + | "Auto" + | "Binary" + | "By" + | "Compare" + | "Descending" + | "Distinct" + | "Equals" + | "Explicit" + | "Group" + | "Infer" + | "Into" + | "Join" + | "Key" + | "Off" + | "Order" + | "Preserve" + | "Skip" + | "Take" + | "Text" + | "Unicode" + | "Until" + | "Where" +. + +AccessModifier = + "Public" | + "Friend" | + "Protected" | + "Private" +. + +TypeModifier = + AccessModifier | + "MustInherit" | + "NotInheritable" | + "Shadows" | + "Partial" +. + +MemberModifier = + AccessModifier | + "Shadows" | + "Shared" | + "Overridable" | + "NotOverridable" | + "NotInheritable" | + "Overrides" | + "Overloads" | + "Partial" | + "WithEvents" | + "MustOverride" | + "Widening" | + "Narrowing" | + "ReadOnly" | + "WriteOnly" | + "Default" | + "Dim" +. + +ParameterModifier = + "ByVal" | + "ByRef" | + "Optional" | + "ParamArray" +. + +END ExpressionFinder . diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs new file mode 100644 index 0000000000..15b9bdd6d2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs @@ -0,0 +1,154 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public partial class ExpressionFinder + { + Stack stack = new Stack(); + StringBuilder output = new StringBuilder(); + + void PopContext() + { + if (stack.Any()) { + string indent = new string('\t', stack.Count - 1); + var item = stack.Pop(); + item.isClosed = true; + Print(indent + "exit " + item.context); + } else { + Print("empty stack"); + } + } + + void PushContext(Context context, Token la, Token t) + { + string indent = new string('\t', stack.Count); + AstLocation l = la == null ? (t == null ? AstLocation.Empty : t.EndLocation) : la.Location; + + stack.Push(new Block() { context = context, lastExpressionStart = l }); + Print(indent + "enter " + context); + } + + public ExpressionFinder(ExpressionFinderState state) + { + wasQualifierTokenAtStart = state.WasQualifierTokenAtStart; + nextTokenIsPotentialStartOfExpression = state.NextTokenIsPotentialStartOfExpression; + nextTokenIsStartOfImportsOrAccessExpression = state.NextTokenIsStartOfImportsOrAccessExpression; + readXmlIdentifier = state.ReadXmlIdentifier; + identifierExpected = state.IdentifierExpected; + stateStack = new Stack(state.StateStack.Reverse()); + stack = new Stack(state.BlockStack.Select(x => (Block)x.Clone()).Reverse()); + currentState = state.CurrentState; + output = new StringBuilder(); + } + + void Print(string text) + { + //Console.WriteLine(text); + output.AppendLine(text); + } + + public void SetContext(SnippetType type) + { + switch (type) { + case SnippetType.Expression: + currentState = startOfExpression; + break; + } + + Advance(); + } + + public string Output { + get { return output.ToString(); } + } + + public string Stacktrace { + get { + string text = ""; + + foreach (Block b in stack) { + text += b.ToString() + "\n"; + } + + return text; + } + } + + public Block CurrentBlock { + get { return stack.Any() ? stack.Peek() : Block.Default; } + } + + public bool IsIdentifierExpected { + get { return identifierExpected; } + } + + void SetIdentifierExpected(Token la) + { + identifierExpected = true; + if (la != null) + CurrentBlock.lastExpressionStart = la.Location; + else if (t != null) + CurrentBlock.lastExpressionStart = t.EndLocation; + } + + public bool InContext(Context expected) + { + return stack + .SkipWhile(f => f.context == Context.Expression) + .IsElement(fx => fx.context == expected); + } + + public bool NextTokenIsPotentialStartOfExpression { + get { return nextTokenIsPotentialStartOfExpression; } + } + + public bool ReadXmlIdentifier { + get { return readXmlIdentifier; } + set { readXmlIdentifier = value; } + } + + public bool NextTokenIsStartOfImportsOrAccessExpression { + get { return nextTokenIsStartOfImportsOrAccessExpression; } + } + + public bool WasQualifierTokenAtStart { + get { return wasQualifierTokenAtStart; } + } + + public bool IsMissingModifier { + get { return isMissingModifier; } + } + + public bool WasNormalAttribute { + get { return wasNormalAttribute; } + } + + public int ActiveArgument { + get { return activeArgument; } + } + + public List Errors { + get { return errors; } + } + + public ExpressionFinderState Export() + { + return new ExpressionFinderState() { + WasQualifierTokenAtStart = wasQualifierTokenAtStart, + NextTokenIsPotentialStartOfExpression = nextTokenIsPotentialStartOfExpression, + NextTokenIsStartOfImportsOrAccessExpression = nextTokenIsStartOfImportsOrAccessExpression, + ReadXmlIdentifier = readXmlIdentifier, + IdentifierExpected = identifierExpected, + StateStack = new Stack(stateStack.Reverse()), + BlockStack = new Stack(stack.Select(x => (Block)x.Clone()).Reverse()), + CurrentState = currentState + }; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs new file mode 100644 index 0000000000..485ed3d237 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public class ExpressionFinderState + { + public bool WasQualifierTokenAtStart { get; set; } + public bool NextTokenIsPotentialStartOfExpression { get; set; } + public bool ReadXmlIdentifier { get; set; } + public bool IdentifierExpected { get; set; } + public bool NextTokenIsStartOfImportsOrAccessExpression { get; set; } + public Stack StateStack { get; set; } + public Stack BlockStack { get; set; } + public int CurrentState { get; set; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs new file mode 100644 index 0000000000..7b5d4163a5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public static class Extensions + { + public static bool IsElement(this IEnumerable items, Func check) + { + T item = items.FirstOrDefault(); + + if (item != null) + return check(item); + return false; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/KeywordList.txt b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/KeywordList.txt new file mode 100644 index 0000000000..a2a29b670d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/KeywordList.txt @@ -0,0 +1,284 @@ +# this list is used for autogeneration of: +# - Keywords.cs +# - Tokens.cs +# - ATGTokensSection.txt - the TOKENS section of the ATG file + +# use BuildKeywords to generate the different lists. + +$Namespace=ICSharpCode.NRefactory.VB.Parser +$UpperCaseKeywords=True + +# TERMINAL_CLASSES +EOF +EOL +Identifier +LiteralString +LiteralCharacter +LiteralInteger +LiteralDouble +LiteralSingle +LiteralDecimal +LiteralDate + +# XML_TERMINALS +XmlOpenTag +XmlCloseTag +XmlStartInlineVB +XmlEndInlineVB +XmlCloseTagEmptyElement +XmlOpenEndTag +XmlContent +XmlComment +XmlCData +XmlProcessingInstruction + +# SPECIAL_CHARACTERS +Assign = "=" +Colon =":" +Comma = "," +ConcatString = "&" +Div ="/" +DivInteger = "\\" +Dot = "." +TripleDot = "..." +DotAt = ".@" +# Exclamation mark = Dictionary access operator (not always a token, sometimes it's a type character) +ExclamationMark = "!" +Minus = "-" +Plus = "+" +Power = "^" +QuestionMark = "?" +Times = "*" + +OpenCurlyBrace = "{" +CloseCurlyBrace = "}" + +OpenParenthesis = "(" +CloseParenthesis = ")" + +GreaterThan = ">" +LessThan = "<" + +NotEqual = "<>" +GreaterEqual = ">=" +LessEqual = "<=" + +ShiftLeft = "<<" +ShiftRight = ">>" + +PlusAssign = "+=" +PowerAssign = "^=" +MinusAssign = "-=" +TimesAssign = "*=" +DivAssign = "/=" +DivIntegerAssign = "\\=" +ShiftLeftAssign = "<<=" +ShiftRightAssign = ">>=" +ConcatStringAssign = "&=" +ColonAssign = ":=" + +# keywords according to the spec: +# Keywordlist +"AddHandler" +"AddressOf" +"Aggregate" +"Alias" +"And" +"AndAlso" +"Ansi" +"As" +"Ascending" +"Assembly" +"Auto" +"Binary" +"Boolean" +"ByRef" +"By" +"Byte" +"ByVal" +"Call" +"Case" +"Catch" +"CBool" +"CByte" +"CChar" +"CDate" +"CDbl" +"CDec" +"Char" +"CInt" +"Class" +"CLng" +"CObj" +"Compare" +"Const" +"Continue" +"CSByte" +"CShort" +"CSng" +"CStr" +"CType" +"CUInt" +"CULng" +"CUShort" +"Custom" +"Date" +"Decimal" +"Declare" +"Default" +"Delegate" +"Descending" +"Dim" +"DirectCast" +"Distinct" +"Do" +"Double" +"Each" +"Else" +"ElseIf" +"End" +"EndIf" +"Enum" +"Equals" +"Erase" +"Error" +"Event" +"Exit" +"Explicit" +"False" +"Finally" +"For" +"Friend" +"From" +"Function" +"Get" +"GetType" +"Global" +"GoSub" +"GoTo" +"Group" +"Handles" +"If" +"Implements" +"Imports" +"In" +"Infer" +"Inherits" +"Integer" +"Interface" +"Into" +"Is" +"IsNot" +# Note: IsTrue and IsFalse are 'NOT' keywords they're only valid in Operator declarations (like get/set/value are no C# 'keywords') +"Join" +"Key" +"Let" +"Lib" +"Like" +"Long" +"Loop" +"Me" +"Mod" +"Module" +"MustInherit" +"MustOverride" +"MyBase" +"MyClass" +"Namespace" +"Narrowing" +"New" +"Next" +"Not" +"Nothing" +"NotInheritable" +"NotOverridable" +"Object" +"Of" +"Off" +"On" +"Operator" +"Option" +"Optional" +"Or" +"Order" +"OrElse" +"Out" +"Overloads" +"Overridable" +"Overrides" +"ParamArray" +"Partial" +"Preserve" +"Private" +"Property" +"Protected" +"Public" +"RaiseEvent" +"ReadOnly" +"ReDim" +# has to be in the keyword list for the output formatter +"Rem" +"RemoveHandler" +"Resume" +"Return" +"SByte" +"Select" +"Set" +"Shadows" +"Shared" +"Short" +"Single" +"Skip" +"Static" +"Step" +"Stop" +"Strict" +"String" +"Structure" +"Sub" +"SyncLock" +"Take" +"Text" +"Then" +"Throw" +"To" +"True" +"Try" +"TryCast" +"TypeOf" +"UInteger" +"ULong" +"Unicode" +"Until" +"UShort" +"Using" +"Variant" +"Wend" +"When" +"Where" +"While" +"Widening" +"With" +"WithEvents" +"WriteOnly" +"Xor" + +#XML specific keywords +"GetXmlNamespace" + +#Sets +Null("Nothing") +BlockSucc("Case", "Catch", "Else", "ElseIf", "End", "Finally", "Loop", "Next") +GlobalLevel("Namespace", "Module", "Class", "Structure", "Imports", "Option") +TypeLevel("Sub", "Function", "Property") + +# List of keywords that are valid identifiers, must be the same as the "Identifier" production in VBNET.ATG +IdentifierTokens("Text", "Binary", "Compare", "Assembly", "Ansi", "Auto", "Preserve", "Unicode", "Until", "Off", "Out", "Key", "Explicit", "Infer", "From", "Join", "Equals", "Distinct", "Where", "Take", "Skip", "Order", "By", "Ascending", "Descending", "Group", "Into", "Aggregate") +ExpressionStart("Me", "MyBase", "MyClass", @BooleanExpressions, @OperatorsAtStart, "New", @Null, "AddressOf", "GetType", "TypeOf", "GetXmlNamespace", "Global", @TypeKW, @LambdaStart, @CastExpressions) +StatementStart(@Null, @ExpressionStart, "Dim", "Const", "Static", "For", "While", "Do", "Select") +SimpleTypeName(@TypeKW, @IdentifierTokens) +CastExpressions("DirectCast", "TryCast", "CType", "CBool", "CByte", "CChar", "CDate", "CDec", "CDbl", "CInt", "CLng", "CObj", "CSByte", "CShort", "CSng", "CStr", "CUInt", "CULng", "CUShort") +BooleanExpressions("True", "False") +LambdaStart("Sub", "Function") +OperatorsAtStart("Not", "From", "Aggregate") +TypeKW("Boolean", "Date", "Char", "String", "Decimal", "Byte", "Short", "Integer", "Long", "Single", "Double", "UInteger", "ULong", "UShort", "SByte") \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Keywords.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Keywords.cs new file mode 100644 index 0000000000..507ab10b4b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Keywords.cs @@ -0,0 +1,215 @@ +// this file was autogenerated by a tool. +using System; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public static class Keywords + { + static readonly string[] keywordList = { + "ADDHANDLER", + "ADDRESSOF", + "AGGREGATE", + "ALIAS", + "AND", + "ANDALSO", + "ANSI", + "AS", + "ASCENDING", + "ASSEMBLY", + "AUTO", + "BINARY", + "BOOLEAN", + "BYREF", + "BY", + "BYTE", + "BYVAL", + "CALL", + "CASE", + "CATCH", + "CBOOL", + "CBYTE", + "CCHAR", + "CDATE", + "CDBL", + "CDEC", + "CHAR", + "CINT", + "CLASS", + "CLNG", + "COBJ", + "COMPARE", + "CONST", + "CONTINUE", + "CSBYTE", + "CSHORT", + "CSNG", + "CSTR", + "CTYPE", + "CUINT", + "CULNG", + "CUSHORT", + "CUSTOM", + "DATE", + "DECIMAL", + "DECLARE", + "DEFAULT", + "DELEGATE", + "DESCENDING", + "DIM", + "DIRECTCAST", + "DISTINCT", + "DO", + "DOUBLE", + "EACH", + "ELSE", + "ELSEIF", + "END", + "ENDIF", + "ENUM", + "EQUALS", + "ERASE", + "ERROR", + "EVENT", + "EXIT", + "EXPLICIT", + "FALSE", + "FINALLY", + "FOR", + "FRIEND", + "FROM", + "FUNCTION", + "GET", + "GETTYPE", + "GLOBAL", + "GOSUB", + "GOTO", + "GROUP", + "HANDLES", + "IF", + "IMPLEMENTS", + "IMPORTS", + "IN", + "INFER", + "INHERITS", + "INTEGER", + "INTERFACE", + "INTO", + "IS", + "ISNOT", + "JOIN", + "KEY", + "LET", + "LIB", + "LIKE", + "LONG", + "LOOP", + "ME", + "MOD", + "MODULE", + "MUSTINHERIT", + "MUSTOVERRIDE", + "MYBASE", + "MYCLASS", + "NAMESPACE", + "NARROWING", + "NEW", + "NEXT", + "NOT", + "NOTHING", + "NOTINHERITABLE", + "NOTOVERRIDABLE", + "OBJECT", + "OF", + "OFF", + "ON", + "OPERATOR", + "OPTION", + "OPTIONAL", + "OR", + "ORDER", + "ORELSE", + "OUT", + "OVERLOADS", + "OVERRIDABLE", + "OVERRIDES", + "PARAMARRAY", + "PARTIAL", + "PRESERVE", + "PRIVATE", + "PROPERTY", + "PROTECTED", + "PUBLIC", + "RAISEEVENT", + "READONLY", + "REDIM", + "REM", + "REMOVEHANDLER", + "RESUME", + "RETURN", + "SBYTE", + "SELECT", + "SET", + "SHADOWS", + "SHARED", + "SHORT", + "SINGLE", + "SKIP", + "STATIC", + "STEP", + "STOP", + "STRICT", + "STRING", + "STRUCTURE", + "SUB", + "SYNCLOCK", + "TAKE", + "TEXT", + "THEN", + "THROW", + "TO", + "TRUE", + "TRY", + "TRYCAST", + "TYPEOF", + "UINTEGER", + "ULONG", + "UNICODE", + "UNTIL", + "USHORT", + "USING", + "VARIANT", + "WEND", + "WHEN", + "WHERE", + "WHILE", + "WIDENING", + "WITH", + "WITHEVENTS", + "WRITEONLY", + "XOR", + "GETXMLNAMESPACE" + }; + + static LookupTable keywords = new LookupTable(false); + + static Keywords() + { + for (int i = 0; i < keywordList.Length; ++i) { + keywords[keywordList[i]] = i + Tokens.AddHandler; + } + } + + public static int GetToken(string keyword) + { + return keywords[keyword]; + } + + public static bool IsNonIdentifierKeyword(string word) + { + int token = GetToken(word); + if (token < 0) + return false; + return !Tokens.IdentifierTokens[token]; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs new file mode 100644 index 0000000000..f11043307b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public class LATextReader : TextReader + { + List buffer; + TextReader reader; + + public LATextReader(TextReader reader) + { + this.buffer = new List(); + this.reader = reader; + } + + public override int Peek() + { + return Peek(0); + } + + public override int Read() + { + int c = Peek(); + buffer.RemoveAt(0); + return c; + } + + public int Peek(int step) + { + while (step >= buffer.Count) { + buffer.Add(reader.Read()); + } + + if (step < 0) + return -1; + + return buffer[step]; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + reader.Dispose(); + base.Dispose(disposing); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs new file mode 100644 index 0000000000..2ec80b687a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs @@ -0,0 +1,116 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Globalization; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + /// + /// This class implements a keyword map. It implements a digital search trees (tries) to find + /// a word. + /// + internal class LookupTable + { + Node root = new Node(-1, null); + bool casesensitive; + int length; + + /// + /// The number of elements in the table + /// + public int Count { + get { + return length; + } + } + + /// + /// Inserts an int in the tree, under keyword + /// + public int this[string keyword] { + get { + Node next = root; + + if (!casesensitive) { + keyword = keyword.ToUpper(CultureInfo.InvariantCulture); + } + + for (int i = 0; i < keyword.Length; ++i) { + int index = ((int)keyword[i]) % 256; + next = next.leaf[index]; + + if (next == null) { + return -1; + } + + if (keyword == next.word) { + return next.val; + } + } + return -1; + } + set { + Node node = root; + Node next = root; + + if (!casesensitive) { + keyword = keyword.ToUpper(CultureInfo.InvariantCulture); + } + + ++length; + + // insert word into the tree + for (int i = 0; i < keyword.Length; ++i) { + int index = ((int)keyword[i]) % 256; // index of curchar + bool d = keyword[i] == '\\'; + + next = next.leaf[index]; // get node to this index + + if (next == null) { // no node created -> insert word here + node.leaf[index] = new Node(value, keyword); + break; + } + + if (next.word != null && next.word.Length != i) { // node there, take node content and insert them again + string tmpword = next.word; // this word will be inserted 1 level deeper (better, don't need too much + int tmpval = next.val; // string comparisons for finding.) + next.val = -1; + next.word = null; + this[tmpword] = tmpval; + } + + if (i == keyword.Length - 1) { // end of keyword reached, insert node there, if a node was here it was + next.word = keyword; // reinserted, if it has the same length (keyword EQUALS this word) it will be overwritten + next.val = value; + break; + } + + node = next; + } + } + } + + /// + /// Creates a new instance of + /// + public LookupTable(bool casesensitive) + { + this.casesensitive = casesensitive; + } + + class Node + { + public Node(int val, string word) + { + this.word = word; + this.val = val; + } + + public string word; + public int val; + + public Node[] leaf = new Node[256]; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Parser.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Parser.cs new file mode 100644 index 0000000000..9fd64e9528 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Parser.cs @@ -0,0 +1,8631 @@ +using System; +using System.Collections; +using System.Collections.Generic; + + + +namespace ICSharpCode.NRefactory.VB.Parser { + + + +partial class ExpressionFinder { + const int startOfExpression = 55; + const int endOfStatementTerminatorAndBlock = 263; + static BitArray GetExpectedSet(int state) + { + switch (state) { + case 0: + case 1: + return set[0]; + case 2: + return set[1]; + case 3: + case 4: + return set[2]; + case 5: + return set[3]; + case 6: + case 88: + case 264: + case 530: + { + BitArray a = new BitArray(239); + return a; + } + case 7: + return set[4]; + case 8: + return set[5]; + case 9: + case 10: + case 20: + { + BitArray a = new BitArray(239); + a.Set(142, true); + return a; + } + case 11: + case 193: + case 199: + case 205: + case 244: + case 248: + case 295: + case 399: + case 405: + case 474: + case 520: + case 527: + case 535: + case 565: + case 601: + case 650: + case 664: + case 743: + return set[6]; + case 12: + case 13: + case 566: + case 567: + case 612: + case 622: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(37, true); + return a; + } + case 14: + case 21: + case 23: + case 24: + case 36: + case 256: + case 259: + case 260: + case 296: + case 300: + case 322: + case 337: + case 348: + case 351: + case 357: + case 362: + case 372: + case 373: + case 396: + case 423: + case 526: + case 532: + case 538: + case 542: + case 550: + case 558: + case 568: + case 577: + case 594: + case 599: + case 607: + case 613: + case 616: + case 623: + case 626: + case 645: + case 648: + case 672: + case 680: + case 716: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + return a; + } + case 15: + case 16: + return set[7]; + case 17: + case 18: + return set[8]; + case 19: + case 257: + case 271: + case 298: + case 352: + case 397: + case 454: + case 575: + case 595: + case 614: + case 618: + case 624: + case 646: + case 681: + { + BitArray a = new BitArray(239); + a.Set(113, true); + return a; + } + case 22: + case 543: + case 578: + return set[9]; + case 25: + { + BitArray a = new BitArray(239); + a.Set(1, true); + return a; + } + case 26: + case 27: + return set[10]; + case 28: + case 720: + return set[11]; + case 29: + return set[12]; + case 30: + return set[13]; + case 31: + case 32: + case 152: + case 217: + case 218: + case 265: + case 276: + case 277: + case 444: + case 445: + case 462: + case 463: + case 464: + case 465: + case 553: + case 554: + case 587: + case 588: + case 675: + case 676: + case 729: + case 730: + return set[14]; + case 33: + case 34: + case 521: + case 522: + case 528: + case 529: + case 555: + case 556: + case 669: + return set[15]; + case 35: + case 37: + case 157: + case 168: + case 171: + case 187: + case 203: + case 221: + case 307: + case 332: + case 422: + case 440: + case 477: + case 531: + case 549: + case 557: + case 629: + case 632: + case 654: + case 657: + case 659: + case 671: + case 684: + case 686: + case 709: + case 712: + case 715: + case 721: + case 724: + case 742: + return set[16]; + case 38: + case 41: + return set[17]; + case 39: + return set[18]; + case 40: + case 97: + case 101: + case 163: + case 388: + case 481: + return set[19]; + case 42: + case 177: + case 184: + case 189: + case 253: + case 424: + case 451: + case 473: + case 476: + case 589: + case 590: + case 642: + { + BitArray a = new BitArray(239); + a.Set(37, true); + return a; + } + case 43: + case 44: + case 165: + case 166: + return set[20]; + case 45: + case 46: + case 167: + case 188: + case 392: + case 427: + case 475: + case 478: + case 498: + case 561: + case 592: + case 644: + case 690: + case 719: + case 728: + { + BitArray a = new BitArray(239); + a.Set(38, true); + return a; + } + case 47: + case 48: + return set[21]; + case 49: + case 179: + case 186: + case 394: + { + BitArray a = new BitArray(239); + a.Set(22, true); + return a; + } + case 50: + case 51: + case 52: + case 54: + case 390: + case 391: + case 412: + case 413: + case 419: + case 420: + case 489: + case 490: + case 703: + case 704: + return set[22]; + case 53: + case 169: + case 170: + case 172: + case 181: + case 414: + case 421: + case 429: + case 438: + case 442: + case 485: + case 488: + case 492: + case 494: + case 495: + case 505: + case 512: + case 519: + case 705: + { + BitArray a = new BitArray(239); + a.Set(22, true); + a.Set(38, true); + return a; + } + case 55: + case 56: + case 70: + case 75: + case 76: + case 77: + case 83: + case 99: + case 155: + case 178: + case 180: + case 182: + case 185: + case 195: + case 197: + case 215: + case 239: + case 274: + case 284: + case 286: + case 287: + case 304: + case 321: + case 326: + case 335: + case 341: + case 343: + case 347: + case 350: + case 356: + case 367: + case 369: + case 370: + case 376: + case 393: + case 395: + case 415: + case 439: + case 467: + case 483: + case 484: + case 486: + case 487: + case 548: + case 628: + return set[23]; + case 57: + case 78: + case 158: + return set[24]; + case 58: + return set[25]; + case 59: + { + BitArray a = new BitArray(239); + a.Set(216, true); + return a; + } + case 60: + { + BitArray a = new BitArray(239); + a.Set(145, true); + return a; + } + case 61: + case 156: + { + BitArray a = new BitArray(239); + a.Set(144, true); + return a; + } + case 62: + { + BitArray a = new BitArray(239); + a.Set(236, true); + return a; + } + case 63: + { + BitArray a = new BitArray(239); + a.Set(177, true); + return a; + } + case 64: + { + BitArray a = new BitArray(239); + a.Set(175, true); + return a; + } + case 65: + { + BitArray a = new BitArray(239); + a.Set(61, true); + return a; + } + case 66: + { + BitArray a = new BitArray(239); + a.Set(60, true); + return a; + } + case 67: + { + BitArray a = new BitArray(239); + a.Set(150, true); + return a; + } + case 68: + { + BitArray a = new BitArray(239); + a.Set(42, true); + return a; + } + case 69: + { + BitArray a = new BitArray(239); + a.Set(43, true); + return a; + } + case 71: + case 443: + { + BitArray a = new BitArray(239); + a.Set(40, true); + return a; + } + case 72: + { + BitArray a = new BitArray(239); + a.Set(41, true); + return a; + } + case 73: + case 98: + case 222: + case 223: + case 282: + case 283: + case 334: + case 744: + { + BitArray a = new BitArray(239); + a.Set(20, true); + return a; + } + case 74: + { + BitArray a = new BitArray(239); + a.Set(154, true); + return a; + } + case 79: + case 91: + case 93: + case 148: + { + BitArray a = new BitArray(239); + a.Set(35, true); + return a; + } + case 80: + case 81: + return set[26]; + case 82: + { + BitArray a = new BitArray(239); + a.Set(36, true); + return a; + } + case 84: + case 100: + case 515: + { + BitArray a = new BitArray(239); + a.Set(22, true); + a.Set(36, true); + return a; + } + case 85: + case 121: + { + BitArray a = new BitArray(239); + a.Set(162, true); + return a; + } + case 86: + case 87: + return set[27]; + case 89: + case 92: + case 149: + case 150: + case 153: + return set[28]; + case 90: + case 102: + case 147: + { + BitArray a = new BitArray(239); + a.Set(233, true); + return a; + } + case 94: + { + BitArray a = new BitArray(239); + a.Set(26, true); + a.Set(36, true); + a.Set(147, true); + return a; + } + case 95: + { + BitArray a = new BitArray(239); + a.Set(26, true); + a.Set(147, true); + return a; + } + case 96: + case 685: + { + BitArray a = new BitArray(239); + a.Set(26, true); + return a; + } + case 103: + case 353: + { + BitArray a = new BitArray(239); + a.Set(231, true); + return a; + } + case 104: + { + BitArray a = new BitArray(239); + a.Set(230, true); + return a; + } + case 105: + { + BitArray a = new BitArray(239); + a.Set(224, true); + return a; + } + case 106: + { + BitArray a = new BitArray(239); + a.Set(223, true); + return a; + } + case 107: + case 299: + { + BitArray a = new BitArray(239); + a.Set(218, true); + return a; + } + case 108: + { + BitArray a = new BitArray(239); + a.Set(213, true); + return a; + } + case 109: + { + BitArray a = new BitArray(239); + a.Set(212, true); + return a; + } + case 110: + { + BitArray a = new BitArray(239); + a.Set(211, true); + return a; + } + case 111: + case 455: + { + BitArray a = new BitArray(239); + a.Set(210, true); + return a; + } + case 112: + { + BitArray a = new BitArray(239); + a.Set(209, true); + return a; + } + case 113: + { + BitArray a = new BitArray(239); + a.Set(206, true); + return a; + } + case 114: + { + BitArray a = new BitArray(239); + a.Set(203, true); + return a; + } + case 115: + case 359: + { + BitArray a = new BitArray(239); + a.Set(197, true); + return a; + } + case 116: + case 600: + case 619: + { + BitArray a = new BitArray(239); + a.Set(186, true); + return a; + } + case 117: + { + BitArray a = new BitArray(239); + a.Set(184, true); + return a; + } + case 118: + { + BitArray a = new BitArray(239); + a.Set(176, true); + return a; + } + case 119: + { + BitArray a = new BitArray(239); + a.Set(170, true); + return a; + } + case 120: + case 316: + case 323: + case 338: + { + BitArray a = new BitArray(239); + a.Set(163, true); + return a; + } + case 122: + { + BitArray a = new BitArray(239); + a.Set(147, true); + return a; + } + case 123: + case 226: + case 231: + case 233: + { + BitArray a = new BitArray(239); + a.Set(146, true); + return a; + } + case 124: + case 228: + case 232: + { + BitArray a = new BitArray(239); + a.Set(143, true); + return a; + } + case 125: + { + BitArray a = new BitArray(239); + a.Set(139, true); + return a; + } + case 126: + { + BitArray a = new BitArray(239); + a.Set(133, true); + return a; + } + case 127: + case 258: + { + BitArray a = new BitArray(239); + a.Set(127, true); + return a; + } + case 128: + case 151: + case 251: + { + BitArray a = new BitArray(239); + a.Set(126, true); + return a; + } + case 129: + { + BitArray a = new BitArray(239); + a.Set(124, true); + return a; + } + case 130: + { + BitArray a = new BitArray(239); + a.Set(121, true); + return a; + } + case 131: + case 196: + { + BitArray a = new BitArray(239); + a.Set(116, true); + return a; + } + case 132: + { + BitArray a = new BitArray(239); + a.Set(108, true); + return a; + } + case 133: + { + BitArray a = new BitArray(239); + a.Set(107, true); + return a; + } + case 134: + { + BitArray a = new BitArray(239); + a.Set(104, true); + return a; + } + case 135: + case 637: + { + BitArray a = new BitArray(239); + a.Set(98, true); + return a; + } + case 136: + { + BitArray a = new BitArray(239); + a.Set(87, true); + return a; + } + case 137: + { + BitArray a = new BitArray(239); + a.Set(84, true); + return a; + } + case 138: + case 208: + case 238: + { + BitArray a = new BitArray(239); + a.Set(70, true); + return a; + } + case 139: + { + BitArray a = new BitArray(239); + a.Set(67, true); + return a; + } + case 140: + { + BitArray a = new BitArray(239); + a.Set(66, true); + return a; + } + case 141: + { + BitArray a = new BitArray(239); + a.Set(65, true); + return a; + } + case 142: + { + BitArray a = new BitArray(239); + a.Set(64, true); + return a; + } + case 143: + { + BitArray a = new BitArray(239); + a.Set(62, true); + return a; + } + case 144: + case 250: + { + BitArray a = new BitArray(239); + a.Set(58, true); + return a; + } + case 145: + { + BitArray a = new BitArray(239); + a.Set(2, true); + return a; + } + case 146: + return set[29]; + case 154: + return set[30]; + case 159: + return set[31]; + case 160: + return set[32]; + case 161: + case 162: + case 479: + case 480: + return set[33]; + case 164: + return set[34]; + case 173: + case 174: + case 319: + case 328: + return set[35]; + case 175: + case 457: + return set[36]; + case 176: + case 375: + { + BitArray a = new BitArray(239); + a.Set(135, true); + return a; + } + case 183: + return set[37]; + case 190: + { + BitArray a = new BitArray(239); + a.Set(58, true); + a.Set(126, true); + return a; + } + case 191: + case 192: + return set[38]; + case 194: + { + BitArray a = new BitArray(239); + a.Set(171, true); + return a; + } + case 198: + case 212: + case 230: + case 235: + case 241: + case 243: + case 247: + case 249: + return set[39]; + case 200: + case 201: + { + BitArray a = new BitArray(239); + a.Set(63, true); + a.Set(138, true); + return a; + } + case 202: + case 204: + case 320: + { + BitArray a = new BitArray(239); + a.Set(138, true); + return a; + } + case 206: + case 207: + case 209: + case 211: + case 213: + case 214: + case 224: + case 229: + case 234: + case 242: + case 246: + case 269: + case 273: + return set[40]; + case 210: + { + BitArray a = new BitArray(239); + a.Set(22, true); + a.Set(143, true); + return a; + } + case 216: + return set[41]; + case 219: + case 278: + return set[42]; + case 220: + case 279: + return set[43]; + case 225: + { + BitArray a = new BitArray(239); + a.Set(22, true); + a.Set(70, true); + return a; + } + case 227: + { + BitArray a = new BitArray(239); + a.Set(133, true); + a.Set(143, true); + a.Set(146, true); + return a; + } + case 236: + case 237: + return set[44]; + case 240: + { + BitArray a = new BitArray(239); + a.Set(64, true); + a.Set(104, true); + return a; + } + case 245: + return set[45]; + case 252: + case 552: + case 663: + case 674: + case 682: + { + BitArray a = new BitArray(239); + a.Set(127, true); + a.Set(210, true); + return a; + } + case 254: + case 255: + return set[46]; + case 261: + case 262: + return set[47]; + case 263: + return set[48]; + case 266: + return set[49]; + case 267: + case 268: + case 381: + return set[50]; + case 270: + case 275: + case 365: + case 655: + case 656: + case 658: + case 693: + case 710: + case 711: + case 713: + case 722: + case 723: + case 725: + case 737: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(22, true); + return a; + } + case 272: + { + BitArray a = new BitArray(239); + a.Set(226, true); + return a; + } + case 280: + case 281: + return set[51]; + case 285: + case 327: + case 342: + case 404: + return set[52]; + case 288: + case 289: + case 309: + case 310: + case 324: + case 325: + case 339: + case 340: + return set[53]; + case 290: + case 382: + case 385: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(111, true); + return a; + } + case 291: + { + BitArray a = new BitArray(239); + a.Set(108, true); + a.Set(124, true); + a.Set(231, true); + return a; + } + case 292: + return set[54]; + case 293: + case 312: + return set[55]; + case 294: + { + BitArray a = new BitArray(239); + a.Set(5, true); + return a; + } + case 297: + { + BitArray a = new BitArray(239); + a.Set(75, true); + a.Set(113, true); + a.Set(123, true); + return a; + } + case 301: + case 302: + return set[56]; + case 303: + case 308: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(229, true); + return a; + } + case 305: + case 306: + return set[57]; + case 311: + return set[58]; + case 313: + { + BitArray a = new BitArray(239); + a.Set(118, true); + return a; + } + case 314: + case 315: + return set[59]; + case 317: + case 318: + return set[60]; + case 329: + case 330: + return set[61]; + case 331: + return set[62]; + case 333: + { + BitArray a = new BitArray(239); + a.Set(20, true); + a.Set(138, true); + return a; + } + case 336: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(205, true); + return a; + } + case 344: + return set[63]; + case 345: + case 349: + { + BitArray a = new BitArray(239); + a.Set(152, true); + return a; + } + case 346: + return set[64]; + case 354: + case 355: + return set[65]; + case 358: + { + BitArray a = new BitArray(239); + a.Set(74, true); + a.Set(113, true); + return a; + } + case 360: + case 361: + return set[66]; + case 363: + case 364: + return set[67]; + case 366: + case 368: + return set[68]; + case 371: + case 377: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(214, true); + return a; + } + case 374: + { + BitArray a = new BitArray(239); + a.Set(111, true); + a.Set(112, true); + a.Set(113, true); + return a; + } + case 378: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(135, true); + return a; + } + case 379: + case 380: + case 452: + case 453: + return set[69]; + case 383: + case 384: + case 386: + case 387: + return set[70]; + case 389: + return set[71]; + case 398: + { + BitArray a = new BitArray(239); + a.Set(211, true); + a.Set(233, true); + return a; + } + case 400: + case 401: + case 406: + case 407: + return set[72]; + case 402: + case 408: + return set[73]; + case 403: + case 411: + case 418: + return set[74]; + case 409: + case 410: + case 416: + case 417: + case 700: + case 701: + return set[75]; + case 425: + case 426: + return set[76]; + case 428: + case 430: + case 431: + case 591: + case 643: + return set[77]; + case 432: + case 433: + return set[78]; + case 434: + case 435: + return set[79]; + case 436: + return set[80]; + case 437: + case 441: + { + BitArray a = new BitArray(239); + a.Set(20, true); + a.Set(22, true); + a.Set(38, true); + return a; + } + case 446: + case 450: + return set[81]; + case 447: + case 448: + return set[82]; + case 449: + { + BitArray a = new BitArray(239); + a.Set(21, true); + return a; + } + case 456: + return set[83]; + case 458: + case 471: + return set[84]; + case 459: + case 472: + return set[85]; + case 460: + case 461: + case 736: + { + BitArray a = new BitArray(239); + a.Set(10, true); + return a; + } + case 466: + { + BitArray a = new BitArray(239); + a.Set(12, true); + return a; + } + case 468: + { + BitArray a = new BitArray(239); + a.Set(13, true); + return a; + } + case 469: + return set[86]; + case 470: + return set[87]; + case 482: + return set[88]; + case 491: + case 493: + return set[89]; + case 496: + case 497: + case 559: + case 560: + case 688: + case 689: + return set[90]; + case 499: + case 500: + case 501: + case 506: + case 507: + case 562: + case 691: + case 718: + case 727: + return set[91]; + case 502: + case 508: + case 517: + return set[92]; + case 503: + case 504: + case 509: + case 510: + { + BitArray a = new BitArray(239); + a.Set(22, true); + a.Set(38, true); + a.Set(63, true); + return a; + } + case 511: + case 513: + case 518: + return set[93]; + case 514: + case 516: + return set[94]; + case 523: + case 536: + case 537: + case 593: + case 670: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(63, true); + return a; + } + case 524: + case 525: + case 597: + case 598: + return set[95]; + case 533: + case 534: + case 541: + { + BitArray a = new BitArray(239); + a.Set(115, true); + return a; + } + case 539: + case 540: + return set[96]; + case 544: + case 545: + return set[97]; + case 546: + case 547: + case 606: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(20, true); + a.Set(21, true); + return a; + } + case 551: + { + BitArray a = new BitArray(239); + a.Set(103, true); + return a; + } + case 563: + case 564: + case 576: + { + BitArray a = new BitArray(239); + a.Set(84, true); + a.Set(155, true); + a.Set(209, true); + return a; + } + case 569: + case 570: + return set[98]; + case 571: + case 572: + return set[99]; + case 573: + case 574: + case 585: + return set[100]; + case 579: + case 580: + return set[101]; + case 581: + case 582: + case 707: + return set[102]; + case 583: + return set[103]; + case 584: + return set[104]; + case 586: + case 596: + { + BitArray a = new BitArray(239); + a.Set(172, true); + return a; + } + case 602: + case 603: + return set[105]; + case 604: + return set[106]; + case 605: + case 636: + return set[107]; + case 608: + case 609: + case 610: + case 627: + return set[108]; + case 611: + case 615: + case 625: + { + BitArray a = new BitArray(239); + a.Set(128, true); + a.Set(198, true); + return a; + } + case 617: + return set[109]; + case 620: + return set[110]; + case 621: + return set[111]; + case 630: + case 631: + case 633: + case 699: + case 702: + return set[112]; + case 634: + case 635: + return set[113]; + case 638: + case 640: + case 649: + { + BitArray a = new BitArray(239); + a.Set(119, true); + return a; + } + case 639: + return set[114]; + case 641: + return set[115]; + case 647: + { + BitArray a = new BitArray(239); + a.Set(56, true); + a.Set(189, true); + a.Set(193, true); + return a; + } + case 651: + case 652: + return set[116]; + case 653: + case 660: + { + BitArray a = new BitArray(239); + a.Set(1, true); + a.Set(21, true); + a.Set(136, true); + return a; + } + case 661: + { + BitArray a = new BitArray(239); + a.Set(101, true); + return a; + } + case 662: + return set[117]; + case 665: + case 666: + { + BitArray a = new BitArray(239); + a.Set(149, true); + return a; + } + case 667: + case 673: + case 745: + { + BitArray a = new BitArray(239); + a.Set(3, true); + return a; + } + case 668: + return set[118]; + case 677: + case 678: + return set[119]; + case 679: + case 687: + return set[120]; + case 683: + return set[121]; + case 692: + case 694: + return set[122]; + case 695: + case 706: + return set[123]; + case 696: + case 697: + return set[124]; + case 698: + return set[125]; + case 708: + { + BitArray a = new BitArray(239); + a.Set(136, true); + return a; + } + case 714: + { + BitArray a = new BitArray(239); + a.Set(140, true); + return a; + } + case 717: + case 726: + { + BitArray a = new BitArray(239); + a.Set(169, true); + return a; + } + case 731: + return set[126]; + case 732: + { + BitArray a = new BitArray(239); + a.Set(160, true); + return a; + } + case 733: + { + BitArray a = new BitArray(239); + a.Set(137, true); + return a; + } + case 734: + case 735: + case 738: + case 739: + return set[127]; + case 740: + case 747: + return set[128]; + case 741: + return set[129]; + case 746: + { + BitArray a = new BitArray(239); + a.Set(11, true); + return a; + } + case 748: + { + BitArray a = new BitArray(239); + a.Set(173, true); + return a; + } + case 749: + return set[130]; + case 750: + { + BitArray a = new BitArray(239); + a.Set(67, true); + a.Set(213, true); + return a; + } + case 751: + return set[131]; + default: throw new InvalidOperationException(); + } + } + + const bool T = true; + const bool x = false; + + int currentState = 0; + + readonly Stack stateStack = new Stack(); + bool wasQualifierTokenAtStart = false; + bool nextTokenIsPotentialStartOfExpression = false; + bool readXmlIdentifier = false; + bool identifierExpected = false; + bool nextTokenIsStartOfImportsOrAccessExpression = false; + bool isMissingModifier = false; + bool isAlreadyInExpr = false; + bool wasNormalAttribute = false; + int activeArgument = 0; + List errors = new List(); + + public ExpressionFinder() + { + stateStack.Push(-1); // required so that we don't crash when leaving the root production + } + + void Expect(int expectedKind, Token la) + { + if (la.kind != expectedKind) { + Error(la); + output.AppendLine("expected: " + expectedKind); + //Console.WriteLine("expected: " + expectedKind); + } + } + + void Error(Token la) + { + output.AppendLine("not expected: " + la); + //Console.WriteLine("not expected: " + la); + errors.Add(la); + } + + Token t; + + public void InformToken(Token la) + { + switchlbl: switch (currentState) { + case 0: { + PushContext(Context.Global, la, t); + goto case 1; + } + case 1: { + if (la == null) { currentState = 1; break; } + if (la.kind == 173) { + stateStack.Push(1); + goto case 748; + } else { + goto case 2; + } + } + case 2: { + if (la == null) { currentState = 2; break; } + if (la.kind == 137) { + stateStack.Push(2); + goto case 733; + } else { + goto case 3; + } + } + case 3: { + if (la == null) { currentState = 3; break; } + if (la.kind == 40) { + stateStack.Push(3); + goto case 443; + } else { + goto case 4; + } + } + case 4: { + if (la == null) { currentState = 4; break; } + if (set[3].Get(la.kind)) { + stateStack.Push(4); + goto case 5; + } else { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 5: { + if (la == null) { currentState = 5; break; } + if (la.kind == 160) { + currentState = 729; + break; + } else { + if (set[4].Get(la.kind)) { + goto case 7; + } else { + goto case 6; + } + } + } + case 6: { + Error(la); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 7: { + if (la == null) { currentState = 7; break; } + if (la.kind == 40) { + stateStack.Push(7); + goto case 443; + } else { + goto case 8; + } + } + case 8: { + if (la == null) { currentState = 8; break; } + if (set[132].Get(la.kind)) { + currentState = 8; + break; + } else { + if (la.kind == 84 || la.kind == 155 || la.kind == 209) { + goto case 563; + } else { + if (la.kind == 103) { + currentState = 552; + break; + } else { + if (la.kind == 115) { + goto case 533; + } else { + if (la.kind == 142) { + goto case 9; + } else { + goto case 6; + } + } + } + } + } + } + case 9: { + PushContext(Context.TypeDeclaration, la, t); + goto case 10; + } + case 10: { + if (la == null) { currentState = 10; break; } + Expect(142, la); // "Interface" + currentState = 11; + break; + } + case 11: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(12); + goto case 205; + } + case 12: { + PopContext(); + goto case 13; + } + case 13: { + if (la == null) { currentState = 13; break; } + if (la.kind == 37) { + currentState = 726; + break; + } else { + goto case 14; + } + } + case 14: { + stateStack.Push(15); + goto case 23; + } + case 15: { + isMissingModifier = true; + goto case 16; + } + case 16: { + if (la == null) { currentState = 16; break; } + if (la.kind == 140) { + currentState = 721; + break; + } else { + goto case 17; + } + } + case 17: { + isMissingModifier = true; + goto case 18; + } + case 18: { + if (la == null) { currentState = 18; break; } + if (set[10].Get(la.kind)) { + goto case 26; + } else { + isMissingModifier = false; + goto case 19; + } + } + case 19: { + if (la == null) { currentState = 19; break; } + Expect(113, la); // "End" + currentState = 20; + break; + } + case 20: { + if (la == null) { currentState = 20; break; } + Expect(142, la); // "Interface" + currentState = 21; + break; + } + case 21: { + stateStack.Push(22); + goto case 23; + } + case 22: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 23: { + if (la != null) CurrentBlock.lastExpressionStart = la.Location; + goto case 24; + } + case 24: { + if (la == null) { currentState = 24; break; } + if (la.kind == 1) { + goto case 25; + } else { + if (la.kind == 21) { + currentState = stateStack.Pop(); + break; + } else { + goto case 6; + } + } + } + case 25: { + if (la == null) { currentState = 25; break; } + currentState = stateStack.Pop(); + break; + } + case 26: { + isMissingModifier = true; + goto case 27; + } + case 27: { + if (la == null) { currentState = 27; break; } + if (la.kind == 40) { + stateStack.Push(26); + goto case 443; + } else { + isMissingModifier = true; + goto case 28; + } + } + case 28: { + if (la == null) { currentState = 28; break; } + if (set[133].Get(la.kind)) { + currentState = 720; + break; + } else { + isMissingModifier = false; + goto case 29; + } + } + case 29: { + if (la == null) { currentState = 29; break; } + if (la.kind == 84 || la.kind == 155 || la.kind == 209) { + stateStack.Push(17); + goto case 563; + } else { + if (la.kind == 103) { + stateStack.Push(17); + goto case 551; + } else { + if (la.kind == 115) { + stateStack.Push(17); + goto case 533; + } else { + if (la.kind == 142) { + stateStack.Push(17); + goto case 9; + } else { + if (set[13].Get(la.kind)) { + stateStack.Push(17); + goto case 30; + } else { + Error(la); + goto case 17; + } + } + } + } + } + } + case 30: { + if (la == null) { currentState = 30; break; } + if (la.kind == 119) { + currentState = 527; + break; + } else { + if (la.kind == 186) { + currentState = 520; + break; + } else { + if (la.kind == 127 || la.kind == 210) { + currentState = 31; + break; + } else { + goto case 6; + } + } + } + } + case 31: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + goto case 32; + } + case 32: { + if (la == null) { currentState = 32; break; } + currentState = 33; + break; + } + case 33: { + PopContext(); + goto case 34; + } + case 34: { + if (la == null) { currentState = 34; break; } + if (la.kind == 37) { + currentState = 496; + break; + } else { + if (la.kind == 63) { + currentState = 35; + break; + } else { + goto case 23; + } + } + } + case 35: { + PushContext(Context.Type, la, t); + stateStack.Push(36); + goto case 37; + } + case 36: { + PopContext(); + goto case 23; + } + case 37: { + if (la == null) { currentState = 37; break; } + if (la.kind == 130) { + currentState = 38; + break; + } else { + if (set[6].Get(la.kind)) { + currentState = 38; + break; + } else { + if (set[134].Get(la.kind)) { + currentState = 38; + break; + } else { + if (la.kind == 33) { + currentState = 38; + break; + } else { + Error(la); + goto case 38; + } + } + } + } + } + case 38: { + if (la == null) { currentState = 38; break; } + if (la.kind == 37) { + stateStack.Push(38); + goto case 42; + } else { + goto case 39; + } + } + case 39: { + if (la == null) { currentState = 39; break; } + if (la.kind == 26) { + currentState = 40; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 40: { + stateStack.Push(41); + goto case 101; + } + case 41: { + if (la == null) { currentState = 41; break; } + if (la.kind == 37) { + stateStack.Push(41); + goto case 42; + } else { + goto case 39; + } + } + case 42: { + if (la == null) { currentState = 42; break; } + Expect(37, la); // "(" + currentState = 43; + break; + } + case 43: { + PushContext(Context.Expression, la, t); + nextTokenIsPotentialStartOfExpression = true; + goto case 44; + } + case 44: { + if (la == null) { currentState = 44; break; } + if (la.kind == 169) { + currentState = 491; + break; + } else { + if (set[22].Get(la.kind)) { + if (set[21].Get(la.kind)) { + stateStack.Push(45); + goto case 47; + } else { + goto case 45; + } + } else { + Error(la); + goto case 45; + } + } + } + case 45: { + PopContext(); + goto case 46; + } + case 46: { + if (la == null) { currentState = 46; break; } + Expect(38, la); // ")" + currentState = stateStack.Pop(); + break; + } + case 47: { + nextTokenIsPotentialStartOfExpression = true; + goto case 48; + } + case 48: { + if (la == null) { currentState = 48; break; } + if (set[23].Get(la.kind)) { + activeArgument = 0; + goto case 487; + } else { + if (la.kind == 22) { + activeArgument = 0; + goto case 49; + } else { + goto case 6; + } + } + } + case 49: { + if (la == null) { currentState = 49; break; } + Expect(22, la); // "," + currentState = 50; + break; + } + case 50: { + activeArgument++; + goto case 51; + } + case 51: { + nextTokenIsPotentialStartOfExpression = true; + goto case 52; + } + case 52: { + if (la == null) { currentState = 52; break; } + if (set[23].Get(la.kind)) { + stateStack.Push(53); + goto case 55; + } else { + goto case 53; + } + } + case 53: { + if (la == null) { currentState = 53; break; } + if (la.kind == 22) { + currentState = 54; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 54: { + activeArgument++; + goto case 51; + } + case 55: { + PushContext(Context.Expression, la, t); + goto case 56; + } + case 56: { + stateStack.Push(57); + goto case 75; + } + case 57: { + if (la == null) { currentState = 57; break; } + if (set[25].Get(la.kind)) { + stateStack.Push(56); + goto case 58; + } else { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 58: { + if (la == null) { currentState = 58; break; } + if (la.kind == 31) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 30) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 34) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 25) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 24) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 32) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 154) { + goto case 74; + } else { + if (la.kind == 20) { + goto case 73; + } else { + if (la.kind == 41) { + goto case 72; + } else { + if (la.kind == 40) { + goto case 71; + } else { + if (la.kind == 39) { + currentState = 70; + break; + } else { + if (la.kind == 43) { + goto case 69; + } else { + if (la.kind == 42) { + goto case 68; + } else { + if (la.kind == 150) { + goto case 67; + } else { + if (la.kind == 23) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 60) { + goto case 66; + } else { + if (la.kind == 61) { + goto case 65; + } else { + if (la.kind == 175) { + goto case 64; + } else { + if (la.kind == 177) { + goto case 63; + } else { + if (la.kind == 236) { + goto case 62; + } else { + if (la.kind == 44) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 45) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 144) { + goto case 61; + } else { + if (la.kind == 145) { + goto case 60; + } else { + if (la.kind == 47) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 49) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 50) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 51) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 46) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 48) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 54) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 52) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 53) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 216) { + goto case 59; + } else { + if (la.kind == 55) { + currentState = stateStack.Pop(); + break; + } else { + goto case 6; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + case 59: { + if (la == null) { currentState = 59; break; } + currentState = stateStack.Pop(); + break; + } + case 60: { + if (la == null) { currentState = 60; break; } + currentState = stateStack.Pop(); + break; + } + case 61: { + if (la == null) { currentState = 61; break; } + currentState = stateStack.Pop(); + break; + } + case 62: { + if (la == null) { currentState = 62; break; } + currentState = stateStack.Pop(); + break; + } + case 63: { + if (la == null) { currentState = 63; break; } + currentState = stateStack.Pop(); + break; + } + case 64: { + if (la == null) { currentState = 64; break; } + currentState = stateStack.Pop(); + break; + } + case 65: { + if (la == null) { currentState = 65; break; } + currentState = stateStack.Pop(); + break; + } + case 66: { + if (la == null) { currentState = 66; break; } + currentState = stateStack.Pop(); + break; + } + case 67: { + if (la == null) { currentState = 67; break; } + currentState = stateStack.Pop(); + break; + } + case 68: { + if (la == null) { currentState = 68; break; } + currentState = stateStack.Pop(); + break; + } + case 69: { + if (la == null) { currentState = 69; break; } + currentState = stateStack.Pop(); + break; + } + case 70: { + wasNormalAttribute = false; + currentState = stateStack.Pop(); + goto switchlbl; + } + case 71: { + if (la == null) { currentState = 71; break; } + currentState = stateStack.Pop(); + break; + } + case 72: { + if (la == null) { currentState = 72; break; } + currentState = stateStack.Pop(); + break; + } + case 73: { + if (la == null) { currentState = 73; break; } + currentState = stateStack.Pop(); + break; + } + case 74: { + if (la == null) { currentState = 74; break; } + currentState = stateStack.Pop(); + break; + } + case 75: { + PushContext(Context.Expression, la, t); + goto case 76; + } + case 76: { + nextTokenIsPotentialStartOfExpression = true; + goto case 77; + } + case 77: { + if (la == null) { currentState = 77; break; } + if (set[135].Get(la.kind)) { + currentState = 76; + break; + } else { + if (set[35].Get(la.kind)) { + stateStack.Push(159); + goto case 173; + } else { + if (la.kind == 220) { + currentState = 155; + break; + } else { + if (la.kind == 162) { + stateStack.Push(78); + goto case 85; + } else { + if (la.kind == 35) { + stateStack.Push(78); + goto case 79; + } else { + Error(la); + goto case 78; + } + } + } + } + } + } + case 78: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 79: { + if (la == null) { currentState = 79; break; } + Expect(35, la); // "{" + currentState = 80; + break; + } + case 80: { + nextTokenIsPotentialStartOfExpression = true; + goto case 81; + } + case 81: { + if (la == null) { currentState = 81; break; } + if (set[23].Get(la.kind)) { + goto case 83; + } else { + goto case 82; + } + } + case 82: { + if (la == null) { currentState = 82; break; } + Expect(36, la); // "}" + currentState = stateStack.Pop(); + break; + } + case 83: { + stateStack.Push(84); + goto case 55; + } + case 84: { + if (la == null) { currentState = 84; break; } + if (la.kind == 22) { + currentState = 83; + break; + } else { + goto case 82; + } + } + case 85: { + if (la == null) { currentState = 85; break; } + Expect(162, la); // "New" + currentState = 86; + break; + } + case 86: { + PushContext(Context.ObjectCreation, la, t); + goto case 87; + } + case 87: { + if (la == null) { currentState = 87; break; } + if (set[16].Get(la.kind)) { + stateStack.Push(146); + goto case 37; + } else { + if (la.kind == 233) { + PushContext(Context.ObjectInitializer, la, t); + goto case 90; + } else { + goto case 88; + } + } + } + case 88: { + Error(la); + goto case 89; + } + case 89: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 90: { + if (la == null) { currentState = 90; break; } + Expect(233, la); // "With" + currentState = 91; + break; + } + case 91: { + stateStack.Push(92); + goto case 93; + } + case 92: { + PopContext(); + goto case 89; + } + case 93: { + if (la == null) { currentState = 93; break; } + Expect(35, la); // "{" + currentState = 94; + break; + } + case 94: { + if (la == null) { currentState = 94; break; } + if (la.kind == 26 || la.kind == 147) { + goto case 95; + } else { + goto case 82; + } + } + case 95: { + if (la == null) { currentState = 95; break; } + if (la.kind == 147) { + currentState = 96; + break; + } else { + goto case 96; + } + } + case 96: { + if (la == null) { currentState = 96; break; } + Expect(26, la); // "." + currentState = 97; + break; + } + case 97: { + stateStack.Push(98); + goto case 101; + } + case 98: { + if (la == null) { currentState = 98; break; } + Expect(20, la); // "=" + currentState = 99; + break; + } + case 99: { + stateStack.Push(100); + goto case 55; + } + case 100: { + if (la == null) { currentState = 100; break; } + if (la.kind == 22) { + currentState = 95; + break; + } else { + goto case 82; + } + } + case 101: { + if (la == null) { currentState = 101; break; } + if (la.kind == 2) { + goto case 145; + } else { + if (la.kind == 56) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 57) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 58) { + goto case 144; + } else { + if (la.kind == 59) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 60) { + goto case 66; + } else { + if (la.kind == 61) { + goto case 65; + } else { + if (la.kind == 62) { + goto case 143; + } else { + if (la.kind == 63) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 64) { + goto case 142; + } else { + if (la.kind == 65) { + goto case 141; + } else { + if (la.kind == 66) { + goto case 140; + } else { + if (la.kind == 67) { + goto case 139; + } else { + if (la.kind == 68) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 69) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 70) { + goto case 138; + } else { + if (la.kind == 71) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 72) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 73) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 74) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 75) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 76) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 77) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 78) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 79) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 80) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 81) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 82) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 83) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 84) { + goto case 137; + } else { + if (la.kind == 85) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 86) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 87) { + goto case 136; + } else { + if (la.kind == 88) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 89) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 90) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 91) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 92) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 93) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 94) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 95) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 96) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 97) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 98) { + goto case 135; + } else { + if (la.kind == 99) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 100) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 101) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 102) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 103) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 104) { + goto case 134; + } else { + if (la.kind == 105) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 106) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 107) { + goto case 133; + } else { + if (la.kind == 108) { + goto case 132; + } else { + if (la.kind == 109) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 110) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 111) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 112) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 113) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 114) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 115) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 116) { + goto case 131; + } else { + if (la.kind == 117) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 118) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 119) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 120) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 121) { + goto case 130; + } else { + if (la.kind == 122) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 123) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 124) { + goto case 129; + } else { + if (la.kind == 125) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 126) { + goto case 128; + } else { + if (la.kind == 127) { + goto case 127; + } else { + if (la.kind == 128) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 129) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 130) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 131) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 132) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 133) { + goto case 126; + } else { + if (la.kind == 134) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 135) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 136) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 137) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 138) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 139) { + goto case 125; + } else { + if (la.kind == 140) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 141) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 142) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 143) { + goto case 124; + } else { + if (la.kind == 144) { + goto case 61; + } else { + if (la.kind == 145) { + goto case 60; + } else { + if (la.kind == 146) { + goto case 123; + } else { + if (la.kind == 147) { + goto case 122; + } else { + if (la.kind == 148) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 149) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 150) { + goto case 67; + } else { + if (la.kind == 151) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 152) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 153) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 154) { + goto case 74; + } else { + if (la.kind == 155) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 156) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 157) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 158) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 159) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 160) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 161) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 162) { + goto case 121; + } else { + if (la.kind == 163) { + goto case 120; + } else { + if (la.kind == 164) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 165) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 166) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 167) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 168) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 169) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 170) { + goto case 119; + } else { + if (la.kind == 171) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 172) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 173) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 174) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 175) { + goto case 64; + } else { + if (la.kind == 176) { + goto case 118; + } else { + if (la.kind == 177) { + goto case 63; + } else { + if (la.kind == 178) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 179) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 180) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 181) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 182) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 183) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 184) { + goto case 117; + } else { + if (la.kind == 185) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 186) { + goto case 116; + } else { + if (la.kind == 187) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 188) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 189) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 190) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 191) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 192) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 193) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 194) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 195) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 196) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 197) { + goto case 115; + } else { + if (la.kind == 198) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 199) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 200) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 201) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 202) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 203) { + goto case 114; + } else { + if (la.kind == 204) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 205) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 206) { + goto case 113; + } else { + if (la.kind == 207) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 208) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 209) { + goto case 112; + } else { + if (la.kind == 210) { + goto case 111; + } else { + if (la.kind == 211) { + goto case 110; + } else { + if (la.kind == 212) { + goto case 109; + } else { + if (la.kind == 213) { + goto case 108; + } else { + if (la.kind == 214) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 215) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 216) { + goto case 59; + } else { + if (la.kind == 217) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 218) { + goto case 107; + } else { + if (la.kind == 219) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 220) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 221) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 222) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 223) { + goto case 106; + } else { + if (la.kind == 224) { + goto case 105; + } else { + if (la.kind == 225) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 226) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 227) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 228) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 229) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 230) { + goto case 104; + } else { + if (la.kind == 231) { + goto case 103; + } else { + if (la.kind == 232) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 233) { + goto case 102; + } else { + if (la.kind == 234) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 235) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 236) { + goto case 62; + } else { + if (la.kind == 237) { + currentState = stateStack.Pop(); + break; + } else { + goto case 6; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + case 102: { + if (la == null) { currentState = 102; break; } + currentState = stateStack.Pop(); + break; + } + case 103: { + if (la == null) { currentState = 103; break; } + currentState = stateStack.Pop(); + break; + } + case 104: { + if (la == null) { currentState = 104; break; } + currentState = stateStack.Pop(); + break; + } + case 105: { + if (la == null) { currentState = 105; break; } + currentState = stateStack.Pop(); + break; + } + case 106: { + if (la == null) { currentState = 106; break; } + currentState = stateStack.Pop(); + break; + } + case 107: { + if (la == null) { currentState = 107; break; } + currentState = stateStack.Pop(); + break; + } + case 108: { + if (la == null) { currentState = 108; break; } + currentState = stateStack.Pop(); + break; + } + case 109: { + if (la == null) { currentState = 109; break; } + currentState = stateStack.Pop(); + break; + } + case 110: { + if (la == null) { currentState = 110; break; } + currentState = stateStack.Pop(); + break; + } + case 111: { + if (la == null) { currentState = 111; break; } + currentState = stateStack.Pop(); + break; + } + case 112: { + if (la == null) { currentState = 112; break; } + currentState = stateStack.Pop(); + break; + } + case 113: { + if (la == null) { currentState = 113; break; } + currentState = stateStack.Pop(); + break; + } + case 114: { + if (la == null) { currentState = 114; break; } + currentState = stateStack.Pop(); + break; + } + case 115: { + if (la == null) { currentState = 115; break; } + currentState = stateStack.Pop(); + break; + } + case 116: { + if (la == null) { currentState = 116; break; } + currentState = stateStack.Pop(); + break; + } + case 117: { + if (la == null) { currentState = 117; break; } + currentState = stateStack.Pop(); + break; + } + case 118: { + if (la == null) { currentState = 118; break; } + currentState = stateStack.Pop(); + break; + } + case 119: { + if (la == null) { currentState = 119; break; } + currentState = stateStack.Pop(); + break; + } + case 120: { + if (la == null) { currentState = 120; break; } + currentState = stateStack.Pop(); + break; + } + case 121: { + if (la == null) { currentState = 121; break; } + currentState = stateStack.Pop(); + break; + } + case 122: { + if (la == null) { currentState = 122; break; } + currentState = stateStack.Pop(); + break; + } + case 123: { + if (la == null) { currentState = 123; break; } + currentState = stateStack.Pop(); + break; + } + case 124: { + if (la == null) { currentState = 124; break; } + currentState = stateStack.Pop(); + break; + } + case 125: { + if (la == null) { currentState = 125; break; } + currentState = stateStack.Pop(); + break; + } + case 126: { + if (la == null) { currentState = 126; break; } + currentState = stateStack.Pop(); + break; + } + case 127: { + if (la == null) { currentState = 127; break; } + currentState = stateStack.Pop(); + break; + } + case 128: { + if (la == null) { currentState = 128; break; } + currentState = stateStack.Pop(); + break; + } + case 129: { + if (la == null) { currentState = 129; break; } + currentState = stateStack.Pop(); + break; + } + case 130: { + if (la == null) { currentState = 130; break; } + currentState = stateStack.Pop(); + break; + } + case 131: { + if (la == null) { currentState = 131; break; } + currentState = stateStack.Pop(); + break; + } + case 132: { + if (la == null) { currentState = 132; break; } + currentState = stateStack.Pop(); + break; + } + case 133: { + if (la == null) { currentState = 133; break; } + currentState = stateStack.Pop(); + break; + } + case 134: { + if (la == null) { currentState = 134; break; } + currentState = stateStack.Pop(); + break; + } + case 135: { + if (la == null) { currentState = 135; break; } + currentState = stateStack.Pop(); + break; + } + case 136: { + if (la == null) { currentState = 136; break; } + currentState = stateStack.Pop(); + break; + } + case 137: { + if (la == null) { currentState = 137; break; } + currentState = stateStack.Pop(); + break; + } + case 138: { + if (la == null) { currentState = 138; break; } + currentState = stateStack.Pop(); + break; + } + case 139: { + if (la == null) { currentState = 139; break; } + currentState = stateStack.Pop(); + break; + } + case 140: { + if (la == null) { currentState = 140; break; } + currentState = stateStack.Pop(); + break; + } + case 141: { + if (la == null) { currentState = 141; break; } + currentState = stateStack.Pop(); + break; + } + case 142: { + if (la == null) { currentState = 142; break; } + currentState = stateStack.Pop(); + break; + } + case 143: { + if (la == null) { currentState = 143; break; } + currentState = stateStack.Pop(); + break; + } + case 144: { + if (la == null) { currentState = 144; break; } + currentState = stateStack.Pop(); + break; + } + case 145: { + if (la == null) { currentState = 145; break; } + currentState = stateStack.Pop(); + break; + } + case 146: { + if (la == null) { currentState = 146; break; } + if (la.kind == 35 || la.kind == 126 || la.kind == 233) { + if (la.kind == 126) { + PushContext(Context.CollectionInitializer, la, t); + goto case 151; + } else { + if (la.kind == 35) { + PushContext(Context.CollectionInitializer, la, t); + stateStack.Push(150); + goto case 79; + } else { + if (la.kind == 233) { + PushContext(Context.ObjectInitializer, la, t); + goto case 147; + } else { + goto case 88; + } + } + } + } else { + goto case 89; + } + } + case 147: { + if (la == null) { currentState = 147; break; } + Expect(233, la); // "With" + currentState = 148; + break; + } + case 148: { + stateStack.Push(149); + goto case 93; + } + case 149: { + PopContext(); + goto case 89; + } + case 150: { + PopContext(); + goto case 89; + } + case 151: { + if (la == null) { currentState = 151; break; } + Expect(126, la); // "From" + currentState = 152; + break; + } + case 152: { + if (la == null) { currentState = 152; break; } + if (la.kind == 35) { + stateStack.Push(153); + goto case 79; + } else { + if (set[30].Get(la.kind)) { + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process From again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + + } else { + Error(la); + goto case 153; + } + } + } + case 153: { + PopContext(); + goto case 89; + } + case 154: { + if (la == null) { currentState = 154; break; } + currentState = 153; + break; + } + case 155: { + stateStack.Push(156); + goto case 75; + } + case 156: { + if (la == null) { currentState = 156; break; } + Expect(144, la); // "Is" + currentState = 157; + break; + } + case 157: { + PushContext(Context.Type, la, t); + stateStack.Push(158); + goto case 37; + } + case 158: { + PopContext(); + goto case 78; + } + case 159: { + if (la == null) { currentState = 159; break; } + if (set[32].Get(la.kind)) { + stateStack.Push(159); + goto case 160; + } else { + goto case 78; + } + } + case 160: { + if (la == null) { currentState = 160; break; } + if (la.kind == 37) { + currentState = 165; + break; + } else { + if (set[136].Get(la.kind)) { + currentState = 161; + break; + } else { + goto case 6; + } + } + } + case 161: { + nextTokenIsStartOfImportsOrAccessExpression = true; + goto case 162; + } + case 162: { + if (la == null) { currentState = 162; break; } + if (la.kind == 10) { + currentState = 163; + break; + } else { + goto case 163; + } + } + case 163: { + stateStack.Push(164); + goto case 101; + } + case 164: { + if (la == null) { currentState = 164; break; } + if (la.kind == 11) { + currentState = stateStack.Pop(); + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 165: { + PushContext(Context.Expression, la, t); + nextTokenIsPotentialStartOfExpression = true; + goto case 166; + } + case 166: { + if (la == null) { currentState = 166; break; } + if (la.kind == 169) { + currentState = 168; + break; + } else { + if (set[22].Get(la.kind)) { + if (set[21].Get(la.kind)) { + stateStack.Push(167); + goto case 47; + } else { + goto case 167; + } + } else { + Error(la); + goto case 167; + } + } + } + case 167: { + PopContext(); + goto case 46; + } + case 168: { + PushContext(Context.Type, la, t); + stateStack.Push(169); + goto case 37; + } + case 169: { + PopContext(); + goto case 170; + } + case 170: { + if (la == null) { currentState = 170; break; } + if (la.kind == 22) { + currentState = 171; + break; + } else { + goto case 167; + } + } + case 171: { + PushContext(Context.Type, la, t); + stateStack.Push(172); + goto case 37; + } + case 172: { + PopContext(); + goto case 170; + } + case 173: { + PushContext(Context.Expression, la, t); + nextTokenIsPotentialStartOfExpression = true; + goto case 174; + } + case 174: { + if (la == null) { currentState = 174; break; } + if (set[137].Get(la.kind)) { + currentState = 175; + break; + } else { + if (la.kind == 37) { + currentState = 483; + break; + } else { + if (set[138].Get(la.kind)) { + currentState = 175; + break; + } else { + if (set[134].Get(la.kind)) { + currentState = 175; + break; + } else { + if (set[136].Get(la.kind)) { + currentState = 479; + break; + } else { + if (la.kind == 129) { + currentState = 476; + break; + } else { + if (la.kind == 237) { + currentState = 473; + break; + } else { + if (set[83].Get(la.kind)) { + stateStack.Push(175); + nextTokenIsPotentialStartOfExpression = true; + PushContext(Context.Xml, la, t); + goto case 456; + } else { + if (la.kind == 127 || la.kind == 210) { + stateStack.Push(175); + goto case 252; + } else { + if (la.kind == 58 || la.kind == 126) { + stateStack.Push(175); + PushContext(Context.Query, la, t); + goto case 190; + } else { + if (set[37].Get(la.kind)) { + stateStack.Push(175); + goto case 183; + } else { + if (la.kind == 135) { + stateStack.Push(175); + goto case 176; + } else { + Error(la); + goto case 175; + } + } + } + } + } + } + } + } + } + } + } + } + } + case 175: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 176: { + if (la == null) { currentState = 176; break; } + Expect(135, la); // "If" + currentState = 177; + break; + } + case 177: { + if (la == null) { currentState = 177; break; } + Expect(37, la); // "(" + currentState = 178; + break; + } + case 178: { + stateStack.Push(179); + goto case 55; + } + case 179: { + if (la == null) { currentState = 179; break; } + Expect(22, la); // "," + currentState = 180; + break; + } + case 180: { + stateStack.Push(181); + goto case 55; + } + case 181: { + if (la == null) { currentState = 181; break; } + if (la.kind == 22) { + currentState = 182; + break; + } else { + goto case 46; + } + } + case 182: { + stateStack.Push(46); + goto case 55; + } + case 183: { + if (la == null) { currentState = 183; break; } + if (set[139].Get(la.kind)) { + currentState = 189; + break; + } else { + if (la.kind == 94 || la.kind == 106 || la.kind == 219) { + currentState = 184; + break; + } else { + goto case 6; + } + } + } + case 184: { + if (la == null) { currentState = 184; break; } + Expect(37, la); // "(" + currentState = 185; + break; + } + case 185: { + stateStack.Push(186); + goto case 55; + } + case 186: { + if (la == null) { currentState = 186; break; } + Expect(22, la); // "," + currentState = 187; + break; + } + case 187: { + PushContext(Context.Type, la, t); + stateStack.Push(188); + goto case 37; + } + case 188: { + PopContext(); + goto case 46; + } + case 189: { + if (la == null) { currentState = 189; break; } + Expect(37, la); // "(" + currentState = 182; + break; + } + case 190: { + if (la == null) { currentState = 190; break; } + if (la.kind == 126) { + stateStack.Push(191); + goto case 251; + } else { + if (la.kind == 58) { + stateStack.Push(191); + goto case 250; + } else { + Error(la); + goto case 191; + } + } + } + case 191: { + if (la == null) { currentState = 191; break; } + if (set[38].Get(la.kind)) { + stateStack.Push(191); + goto case 192; + } else { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 192: { + if (la == null) { currentState = 192; break; } + if (la.kind == 126) { + currentState = 248; + break; + } else { + if (la.kind == 58) { + currentState = 244; + break; + } else { + if (la.kind == 197) { + currentState = 242; + break; + } else { + if (la.kind == 107) { + goto case 133; + } else { + if (la.kind == 230) { + currentState = 55; + break; + } else { + if (la.kind == 176) { + currentState = 238; + break; + } else { + if (la.kind == 203 || la.kind == 212) { + currentState = 236; + break; + } else { + if (la.kind == 148) { + currentState = 234; + break; + } else { + if (la.kind == 133) { + currentState = 206; + break; + } else { + if (la.kind == 146) { + currentState = 193; + break; + } else { + goto case 6; + } + } + } + } + } + } + } + } + } + } + } + case 193: { + stateStack.Push(194); + goto case 199; + } + case 194: { + if (la == null) { currentState = 194; break; } + Expect(171, la); // "On" + currentState = 195; + break; + } + case 195: { + stateStack.Push(196); + goto case 55; + } + case 196: { + if (la == null) { currentState = 196; break; } + Expect(116, la); // "Equals" + currentState = 197; + break; + } + case 197: { + stateStack.Push(198); + goto case 55; + } + case 198: { + if (la == null) { currentState = 198; break; } + if (la.kind == 22) { + currentState = 195; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 199: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(200); + goto case 205; + } + case 200: { + PopContext(); + goto case 201; + } + case 201: { + if (la == null) { currentState = 201; break; } + if (la.kind == 63) { + currentState = 203; + break; + } else { + goto case 202; + } + } + case 202: { + if (la == null) { currentState = 202; break; } + Expect(138, la); // "In" + currentState = 55; + break; + } + case 203: { + PushContext(Context.Type, la, t); + stateStack.Push(204); + goto case 37; + } + case 204: { + PopContext(); + goto case 202; + } + case 205: { + if (la == null) { currentState = 205; break; } + if (set[123].Get(la.kind)) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 98) { + goto case 135; + } else { + goto case 6; + } + } + } + case 206: { + SetIdentifierExpected(la); + nextTokenIsPotentialStartOfExpression = true; + goto case 207; + } + case 207: { + if (la == null) { currentState = 207; break; } + if (la.kind == 146) { + goto case 226; + } else { + if (set[40].Get(la.kind)) { + if (la.kind == 70) { + currentState = 209; + break; + } else { + if (set[40].Get(la.kind)) { + goto case 224; + } else { + Error(la); + goto case 208; + } + } + } else { + goto case 6; + } + } + } + case 208: { + if (la == null) { currentState = 208; break; } + Expect(70, la); // "By" + currentState = 209; + break; + } + case 209: { + stateStack.Push(210); + goto case 213; + } + case 210: { + if (la == null) { currentState = 210; break; } + if (la.kind == 22) { + currentState = 209; + break; + } else { + Expect(143, la); // "Into" + currentState = 211; + break; + } + } + case 211: { + stateStack.Push(212); + goto case 213; + } + case 212: { + if (la == null) { currentState = 212; break; } + if (la.kind == 22) { + currentState = 211; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 213: { + SetIdentifierExpected(la); + nextTokenIsPotentialStartOfExpression = true; + goto case 214; + } + case 214: { + if (la == null) { currentState = 214; break; } + if (set[6].Get(la.kind)) { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(217); + goto case 205; + } else { + goto case 215; + } + } + case 215: { + stateStack.Push(216); + goto case 55; + } + case 216: { + if (!isAlreadyInExpr) PopContext(); isAlreadyInExpr = false; + currentState = stateStack.Pop(); + goto switchlbl; + } + case 217: { + nextTokenIsPotentialStartOfExpression = true; + goto case 218; + } + case 218: { + if (la == null) { currentState = 218; break; } + if (set[42].Get(la.kind)) { + PopContext(); isAlreadyInExpr = true; + goto case 219; + } else { + goto case 215; + } + } + case 219: { + if (la == null) { currentState = 219; break; } + if (la.kind == 63) { + currentState = 221; + break; + } else { + if (la.kind == 20) { + currentState = 215; + break; + } else { + if (set[43].Get(la.kind)) { + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process Identifier again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + + } else { + Error(la); + goto case 215; + } + } + } + } + case 220: { + if (la == null) { currentState = 220; break; } + currentState = 215; + break; + } + case 221: { + PushContext(Context.Type, la, t); + stateStack.Push(222); + goto case 37; + } + case 222: { + PopContext(); + goto case 223; + } + case 223: { + if (la == null) { currentState = 223; break; } + Expect(20, la); // "=" + currentState = 215; + break; + } + case 224: { + stateStack.Push(225); + goto case 213; + } + case 225: { + if (la == null) { currentState = 225; break; } + if (la.kind == 22) { + currentState = 224; + break; + } else { + goto case 208; + } + } + case 226: { + stateStack.Push(227); + goto case 233; + } + case 227: { + if (la == null) { currentState = 227; break; } + if (la.kind == 133 || la.kind == 146) { + if (la.kind == 133) { + currentState = 231; + break; + } else { + if (la.kind == 146) { + goto case 226; + } else { + Error(la); + goto case 227; + } + } + } else { + goto case 228; + } + } + case 228: { + if (la == null) { currentState = 228; break; } + Expect(143, la); // "Into" + currentState = 229; + break; + } + case 229: { + stateStack.Push(230); + goto case 213; + } + case 230: { + if (la == null) { currentState = 230; break; } + if (la.kind == 22) { + currentState = 229; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 231: { + stateStack.Push(232); + goto case 233; + } + case 232: { + stateStack.Push(227); + goto case 228; + } + case 233: { + if (la == null) { currentState = 233; break; } + Expect(146, la); // "Join" + currentState = 193; + break; + } + case 234: { + stateStack.Push(235); + goto case 213; + } + case 235: { + if (la == null) { currentState = 235; break; } + if (la.kind == 22) { + currentState = 234; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 236: { + nextTokenIsPotentialStartOfExpression = true; + goto case 237; + } + case 237: { + if (la == null) { currentState = 237; break; } + if (la.kind == 231) { + currentState = 55; + break; + } else { + goto case 55; + } + } + case 238: { + if (la == null) { currentState = 238; break; } + Expect(70, la); // "By" + currentState = 239; + break; + } + case 239: { + stateStack.Push(240); + goto case 55; + } + case 240: { + if (la == null) { currentState = 240; break; } + if (la.kind == 64) { + currentState = 241; + break; + } else { + if (la.kind == 104) { + currentState = 241; + break; + } else { + Error(la); + goto case 241; + } + } + } + case 241: { + if (la == null) { currentState = 241; break; } + if (la.kind == 22) { + currentState = 239; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 242: { + stateStack.Push(243); + goto case 213; + } + case 243: { + if (la == null) { currentState = 243; break; } + if (la.kind == 22) { + currentState = 242; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 244: { + stateStack.Push(245); + goto case 199; + } + case 245: { + if (la == null) { currentState = 245; break; } + if (set[38].Get(la.kind)) { + stateStack.Push(245); + goto case 192; + } else { + Expect(143, la); // "Into" + currentState = 246; + break; + } + } + case 246: { + stateStack.Push(247); + goto case 213; + } + case 247: { + if (la == null) { currentState = 247; break; } + if (la.kind == 22) { + currentState = 246; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 248: { + stateStack.Push(249); + goto case 199; + } + case 249: { + if (la == null) { currentState = 249; break; } + if (la.kind == 22) { + currentState = 248; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 250: { + if (la == null) { currentState = 250; break; } + Expect(58, la); // "Aggregate" + currentState = 244; + break; + } + case 251: { + if (la == null) { currentState = 251; break; } + Expect(126, la); // "From" + currentState = 248; + break; + } + case 252: { + if (la == null) { currentState = 252; break; } + if (la.kind == 210) { + currentState = 451; + break; + } else { + if (la.kind == 127) { + currentState = 253; + break; + } else { + goto case 6; + } + } + } + case 253: { + stateStack.Push(254); + goto case 424; + } + case 254: { + nextTokenIsPotentialStartOfExpression = true; + goto case 255; + } + case 255: { + if (la == null) { currentState = 255; break; } + if (set[23].Get(la.kind)) { + goto case 55; + } else { + if (la.kind == 1 || la.kind == 21 || la.kind == 63) { + if (la.kind == 63) { + currentState = 422; + break; + } else { + goto case 256; + } + } else { + goto case 6; + } + } + } + case 256: { + stateStack.Push(257); + goto case 259; + } + case 257: { + if (la == null) { currentState = 257; break; } + Expect(113, la); // "End" + currentState = 258; + break; + } + case 258: { + if (la == null) { currentState = 258; break; } + Expect(127, la); // "Function" + currentState = stateStack.Pop(); + break; + } + case 259: { + PushContext(Context.Body, la, t); + goto case 260; + } + case 260: { + stateStack.Push(261); + goto case 23; + } + case 261: { + nextTokenIsPotentialStartOfExpression = true; + goto case 262; + } + case 262: { + if (la == null) { currentState = 262; break; } + if (set[140].Get(la.kind)) { + if (set[69].Get(la.kind)) { + if (set[50].Get(la.kind)) { + stateStack.Push(260); + goto case 267; + } else { + goto case 260; + } + } else { + if (la.kind == 113) { + currentState = 265; + break; + } else { + goto case 264; + } + } + } else { + goto case 263; + } + } + case 263: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 264: { + Error(la); + goto case 261; + } + case 265: { + if (la == null) { currentState = 265; break; } + if (la.kind == 1 || la.kind == 21) { + goto case 260; + } else { + if (set[49].Get(la.kind)) { + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process End again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + + } else { + goto case 264; + } + } + } + case 266: { + if (la == null) { currentState = 266; break; } + currentState = 261; + break; + } + case 267: { + nextTokenIsPotentialStartOfExpression = true; + goto case 268; + } + case 268: { + if (la == null) { currentState = 268; break; } + if (la.kind == 88 || la.kind == 105 || la.kind == 204) { + currentState = 399; + break; + } else { + if (la.kind == 211 || la.kind == 233) { + currentState = 395; + break; + } else { + if (la.kind == 56 || la.kind == 193) { + currentState = 393; + break; + } else { + if (la.kind == 189) { + currentState = 388; + break; + } else { + if (la.kind == 135) { + currentState = 370; + break; + } else { + if (la.kind == 197) { + currentState = 354; + break; + } else { + if (la.kind == 231) { + currentState = 350; + break; + } else { + if (la.kind == 108) { + currentState = 344; + break; + } else { + if (la.kind == 124) { + currentState = 317; + break; + } else { + if (la.kind == 118 || la.kind == 171 || la.kind == 194) { + if (la.kind == 118 || la.kind == 171) { + if (la.kind == 171) { + currentState = 313; + break; + } else { + goto case 313; + } + } else { + if (la.kind == 194) { + currentState = 311; + break; + } else { + goto case 6; + } + } + } else { + if (la.kind == 215) { + currentState = 309; + break; + } else { + if (la.kind == 218) { + currentState = 296; + break; + } else { + if (set[141].Get(la.kind)) { + if (la.kind == 132) { + currentState = 293; + break; + } else { + if (la.kind == 120) { + currentState = 292; + break; + } else { + if (la.kind == 89) { + currentState = 291; + break; + } else { + if (la.kind == 206) { + goto case 113; + } else { + if (la.kind == 195) { + currentState = 288; + break; + } else { + goto case 6; + } + } + } + } + } + } else { + if (la.kind == 191) { + currentState = 286; + break; + } else { + if (la.kind == 117) { + currentState = 284; + break; + } else { + if (la.kind == 226) { + currentState = 269; + break; + } else { + if (set[142].Get(la.kind)) { + if (la.kind == 73) { + currentState = 55; + break; + } else { + goto case 55; + } + } else { + goto case 6; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + case 269: { + stateStack.Push(270); + SetIdentifierExpected(la); + nextTokenIsPotentialStartOfExpression = true; + goto case 273; + } + case 270: { + if (la == null) { currentState = 270; break; } + if (la.kind == 22) { + currentState = 269; + break; + } else { + stateStack.Push(271); + goto case 259; + } + } + case 271: { + if (la == null) { currentState = 271; break; } + Expect(113, la); // "End" + currentState = 272; + break; + } + case 272: { + if (la == null) { currentState = 272; break; } + Expect(226, la); // "Using" + currentState = stateStack.Pop(); + break; + } + case 273: { + if (la == null) { currentState = 273; break; } + if (set[6].Get(la.kind)) { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(276); + goto case 205; + } else { + goto case 274; + } + } + case 274: { + stateStack.Push(275); + goto case 55; + } + case 275: { + if (!isAlreadyInExpr) PopContext(); isAlreadyInExpr = false; + currentState = stateStack.Pop(); + goto switchlbl; + } + case 276: { + nextTokenIsPotentialStartOfExpression = true; + goto case 277; + } + case 277: { + if (la == null) { currentState = 277; break; } + if (set[42].Get(la.kind)) { + PopContext(); isAlreadyInExpr = true; + goto case 278; + } else { + goto case 274; + } + } + case 278: { + if (la == null) { currentState = 278; break; } + if (la.kind == 63) { + currentState = 280; + break; + } else { + if (la.kind == 20) { + currentState = 274; + break; + } else { + if (set[43].Get(la.kind)) { + currentState = endOfStatementTerminatorAndBlock; /* leave this block */ + InformToken(t); /* process Identifier again*/ + /* for processing current token (la): go to the position after processing End */ + goto switchlbl; + + } else { + Error(la); + goto case 274; + } + } + } + } + case 279: { + if (la == null) { currentState = 279; break; } + currentState = 274; + break; + } + case 280: { + nextTokenIsPotentialStartOfExpression = true; + goto case 281; + } + case 281: { + if (la == null) { currentState = 281; break; } + if (set[16].Get(la.kind)) { + PushContext(Context.Type, la, t); + stateStack.Push(282); + goto case 37; + } else { + goto case 274; + } + } + case 282: { + PopContext(); + goto case 283; + } + case 283: { + if (la == null) { currentState = 283; break; } + Expect(20, la); // "=" + currentState = 274; + break; + } + case 284: { + stateStack.Push(285); + goto case 55; + } + case 285: { + if (la == null) { currentState = 285; break; } + if (la.kind == 22) { + currentState = 284; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 286: { + nextTokenIsPotentialStartOfExpression = true; + goto case 287; + } + case 287: { + if (la == null) { currentState = 287; break; } + if (la.kind == 184) { + currentState = 55; + break; + } else { + goto case 55; + } + } + case 288: { + PushContext(Context.Expression, la, t); + nextTokenIsPotentialStartOfExpression = true; + goto case 289; + } + case 289: { + if (la == null) { currentState = 289; break; } + if (set[23].Get(la.kind)) { + stateStack.Push(290); + goto case 55; + } else { + goto case 290; + } + } + case 290: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 291: { + if (la == null) { currentState = 291; break; } + if (la.kind == 108) { + goto case 132; + } else { + if (la.kind == 124) { + goto case 129; + } else { + if (la.kind == 231) { + goto case 103; + } else { + goto case 6; + } + } + } + } + case 292: { + if (la == null) { currentState = 292; break; } + if (la.kind == 108) { + goto case 132; + } else { + if (la.kind == 124) { + goto case 129; + } else { + if (la.kind == 231) { + goto case 103; + } else { + if (la.kind == 197) { + goto case 115; + } else { + if (la.kind == 210) { + goto case 111; + } else { + if (la.kind == 127) { + goto case 127; + } else { + if (la.kind == 186) { + goto case 116; + } else { + if (la.kind == 218) { + goto case 107; + } else { + goto case 6; + } + } + } + } + } + } + } + } + } + case 293: { + if (la == null) { currentState = 293; break; } + if (set[6].Get(la.kind)) { + goto case 295; + } else { + if (la.kind == 5) { + goto case 294; + } else { + goto case 6; + } + } + } + case 294: { + if (la == null) { currentState = 294; break; } + currentState = stateStack.Pop(); + break; + } + case 295: { + if (la == null) { currentState = 295; break; } + currentState = stateStack.Pop(); + break; + } + case 296: { + stateStack.Push(297); + goto case 259; + } + case 297: { + if (la == null) { currentState = 297; break; } + if (la.kind == 75) { + currentState = 301; + break; + } else { + if (la.kind == 123) { + currentState = 300; + break; + } else { + goto case 298; + } + } + } + case 298: { + if (la == null) { currentState = 298; break; } + Expect(113, la); // "End" + currentState = 299; + break; + } + case 299: { + if (la == null) { currentState = 299; break; } + Expect(218, la); // "Try" + currentState = stateStack.Pop(); + break; + } + case 300: { + stateStack.Push(298); + goto case 259; + } + case 301: { + SetIdentifierExpected(la); + goto case 302; + } + case 302: { + if (la == null) { currentState = 302; break; } + if (set[6].Get(la.kind)) { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(305); + goto case 205; + } else { + goto case 303; + } + } + case 303: { + if (la == null) { currentState = 303; break; } + if (la.kind == 229) { + currentState = 304; + break; + } else { + goto case 296; + } + } + case 304: { + stateStack.Push(296); + goto case 55; + } + case 305: { + PopContext(); + goto case 306; + } + case 306: { + if (la == null) { currentState = 306; break; } + if (la.kind == 63) { + currentState = 307; + break; + } else { + goto case 303; + } + } + case 307: { + PushContext(Context.Type, la, t); + stateStack.Push(308); + goto case 37; + } + case 308: { + PopContext(); + goto case 303; + } + case 309: { + nextTokenIsPotentialStartOfExpression = true; + goto case 310; + } + case 310: { + if (la == null) { currentState = 310; break; } + if (set[23].Get(la.kind)) { + goto case 55; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 311: { + if (la == null) { currentState = 311; break; } + if (la.kind == 163) { + goto case 120; + } else { + goto case 312; + } + } + case 312: { + if (la == null) { currentState = 312; break; } + if (la.kind == 5) { + goto case 294; + } else { + if (set[6].Get(la.kind)) { + goto case 295; + } else { + goto case 6; + } + } + } + case 313: { + if (la == null) { currentState = 313; break; } + Expect(118, la); // "Error" + currentState = 314; + break; + } + case 314: { + nextTokenIsPotentialStartOfExpression = true; + goto case 315; + } + case 315: { + if (la == null) { currentState = 315; break; } + if (set[23].Get(la.kind)) { + goto case 55; + } else { + if (la.kind == 132) { + currentState = 312; + break; + } else { + if (la.kind == 194) { + currentState = 316; + break; + } else { + goto case 6; + } + } + } + } + case 316: { + if (la == null) { currentState = 316; break; } + Expect(163, la); // "Next" + currentState = stateStack.Pop(); + break; + } + case 317: { + nextTokenIsPotentialStartOfExpression = true; + SetIdentifierExpected(la); + goto case 318; + } + case 318: { + if (la == null) { currentState = 318; break; } + if (set[35].Get(la.kind)) { + stateStack.Push(334); + goto case 328; + } else { + if (la.kind == 110) { + currentState = 319; + break; + } else { + goto case 6; + } + } + } + case 319: { + stateStack.Push(320); + goto case 328; + } + case 320: { + if (la == null) { currentState = 320; break; } + Expect(138, la); // "In" + currentState = 321; + break; + } + case 321: { + stateStack.Push(322); + goto case 55; + } + case 322: { + stateStack.Push(323); + goto case 259; + } + case 323: { + if (la == null) { currentState = 323; break; } + Expect(163, la); // "Next" + currentState = 324; + break; + } + case 324: { + nextTokenIsPotentialStartOfExpression = true; + goto case 325; + } + case 325: { + if (la == null) { currentState = 325; break; } + if (set[23].Get(la.kind)) { + goto case 326; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 326: { + stateStack.Push(327); + goto case 55; + } + case 327: { + if (la == null) { currentState = 327; break; } + if (la.kind == 22) { + currentState = 326; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 328: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(329); + goto case 173; + } + case 329: { + PopContext(); + goto case 330; + } + case 330: { + if (la == null) { currentState = 330; break; } + if (la.kind == 33) { + currentState = 331; + break; + } else { + goto case 331; + } + } + case 331: { + if (la == null) { currentState = 331; break; } + if (set[32].Get(la.kind)) { + stateStack.Push(331); + goto case 160; + } else { + if (la.kind == 63) { + currentState = 332; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + } + case 332: { + PushContext(Context.Type, la, t); + stateStack.Push(333); + goto case 37; + } + case 333: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 334: { + if (la == null) { currentState = 334; break; } + Expect(20, la); // "=" + currentState = 335; + break; + } + case 335: { + stateStack.Push(336); + goto case 55; + } + case 336: { + if (la == null) { currentState = 336; break; } + if (la.kind == 205) { + currentState = 343; + break; + } else { + goto case 337; + } + } + case 337: { + stateStack.Push(338); + goto case 259; + } + case 338: { + if (la == null) { currentState = 338; break; } + Expect(163, la); // "Next" + currentState = 339; + break; + } + case 339: { + nextTokenIsPotentialStartOfExpression = true; + goto case 340; + } + case 340: { + if (la == null) { currentState = 340; break; } + if (set[23].Get(la.kind)) { + goto case 341; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 341: { + stateStack.Push(342); + goto case 55; + } + case 342: { + if (la == null) { currentState = 342; break; } + if (la.kind == 22) { + currentState = 341; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 343: { + stateStack.Push(337); + goto case 55; + } + case 344: { + if (la == null) { currentState = 344; break; } + if (la.kind == 224 || la.kind == 231) { + currentState = 347; + break; + } else { + if (la.kind == 1 || la.kind == 21) { + stateStack.Push(345); + goto case 259; + } else { + goto case 6; + } + } + } + case 345: { + if (la == null) { currentState = 345; break; } + Expect(152, la); // "Loop" + currentState = 346; + break; + } + case 346: { + if (la == null) { currentState = 346; break; } + if (la.kind == 224 || la.kind == 231) { + currentState = 55; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 347: { + stateStack.Push(348); + goto case 55; + } + case 348: { + stateStack.Push(349); + goto case 259; + } + case 349: { + if (la == null) { currentState = 349; break; } + Expect(152, la); // "Loop" + currentState = stateStack.Pop(); + break; + } + case 350: { + stateStack.Push(351); + goto case 55; + } + case 351: { + stateStack.Push(352); + goto case 259; + } + case 352: { + if (la == null) { currentState = 352; break; } + Expect(113, la); // "End" + currentState = 353; + break; + } + case 353: { + if (la == null) { currentState = 353; break; } + Expect(231, la); // "While" + currentState = stateStack.Pop(); + break; + } + case 354: { + nextTokenIsPotentialStartOfExpression = true; + goto case 355; + } + case 355: { + if (la == null) { currentState = 355; break; } + if (la.kind == 74) { + currentState = 356; + break; + } else { + goto case 356; + } + } + case 356: { + stateStack.Push(357); + goto case 55; + } + case 357: { + stateStack.Push(358); + goto case 23; + } + case 358: { + if (la == null) { currentState = 358; break; } + if (la.kind == 74) { + currentState = 360; + break; + } else { + Expect(113, la); // "End" + currentState = 359; + break; + } + } + case 359: { + if (la == null) { currentState = 359; break; } + Expect(197, la); // "Select" + currentState = stateStack.Pop(); + break; + } + case 360: { + nextTokenIsPotentialStartOfExpression = true; + goto case 361; + } + case 361: { + if (la == null) { currentState = 361; break; } + if (la.kind == 111) { + currentState = 362; + break; + } else { + if (set[67].Get(la.kind)) { + goto case 363; + } else { + Error(la); + goto case 362; + } + } + } + case 362: { + stateStack.Push(358); + goto case 259; + } + case 363: { + nextTokenIsPotentialStartOfExpression = true; + goto case 364; + } + case 364: { + if (la == null) { currentState = 364; break; } + if (set[143].Get(la.kind)) { + if (la.kind == 144) { + currentState = 366; + break; + } else { + goto case 366; + } + } else { + if (set[23].Get(la.kind)) { + stateStack.Push(365); + goto case 55; + } else { + Error(la); + goto case 365; + } + } + } + case 365: { + if (la == null) { currentState = 365; break; } + if (la.kind == 22) { + currentState = 363; + break; + } else { + goto case 362; + } + } + case 366: { + stateStack.Push(367); + goto case 368; + } + case 367: { + stateStack.Push(365); + goto case 75; + } + case 368: { + if (la == null) { currentState = 368; break; } + if (la.kind == 20) { + goto case 73; + } else { + if (la.kind == 41) { + goto case 72; + } else { + if (la.kind == 40) { + goto case 71; + } else { + if (la.kind == 39) { + currentState = 369; + break; + } else { + if (la.kind == 42) { + goto case 68; + } else { + if (la.kind == 43) { + goto case 69; + } else { + goto case 6; + } + } + } + } + } + } + } + case 369: { + wasNormalAttribute = false; + currentState = stateStack.Pop(); + goto switchlbl; + } + case 370: { + stateStack.Push(371); + goto case 55; + } + case 371: { + if (la == null) { currentState = 371; break; } + if (la.kind == 214) { + currentState = 379; + break; + } else { + goto case 372; + } + } + case 372: { + if (la == null) { currentState = 372; break; } + if (la.kind == 1 || la.kind == 21) { + goto case 373; + } else { + goto case 6; + } + } + case 373: { + stateStack.Push(374); + goto case 259; + } + case 374: { + if (la == null) { currentState = 374; break; } + if (la.kind == 111 || la.kind == 112) { + if (la.kind == 111) { + currentState = 378; + break; + } else { + if (la.kind == 112) { + currentState = 376; + break; + } else { + Error(la); + goto case 373; + } + } + } else { + Expect(113, la); // "End" + currentState = 375; + break; + } + } + case 375: { + if (la == null) { currentState = 375; break; } + Expect(135, la); // "If" + currentState = stateStack.Pop(); + break; + } + case 376: { + stateStack.Push(377); + goto case 55; + } + case 377: { + if (la == null) { currentState = 377; break; } + if (la.kind == 214) { + currentState = 373; + break; + } else { + goto case 373; + } + } + case 378: { + if (la == null) { currentState = 378; break; } + if (la.kind == 135) { + currentState = 376; + break; + } else { + goto case 373; + } + } + case 379: { + nextTokenIsPotentialStartOfExpression = true; + goto case 380; + } + case 380: { + if (la == null) { currentState = 380; break; } + if (set[50].Get(la.kind)) { + goto case 381; + } else { + goto case 372; + } + } + case 381: { + stateStack.Push(382); + goto case 267; + } + case 382: { + if (la == null) { currentState = 382; break; } + if (la.kind == 21) { + currentState = 386; + break; + } else { + if (la.kind == 111) { + currentState = 383; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + } + case 383: { + nextTokenIsPotentialStartOfExpression = true; + goto case 384; + } + case 384: { + if (la == null) { currentState = 384; break; } + if (set[50].Get(la.kind)) { + stateStack.Push(385); + goto case 267; + } else { + goto case 385; + } + } + case 385: { + if (la == null) { currentState = 385; break; } + if (la.kind == 21) { + currentState = 383; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 386: { + nextTokenIsPotentialStartOfExpression = true; + goto case 387; + } + case 387: { + if (la == null) { currentState = 387; break; } + if (set[50].Get(la.kind)) { + goto case 381; + } else { + goto case 382; + } + } + case 388: { + stateStack.Push(389); + goto case 101; + } + case 389: { + if (la == null) { currentState = 389; break; } + if (la.kind == 37) { + currentState = 390; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 390: { + PushContext(Context.Expression, la, t); + nextTokenIsPotentialStartOfExpression = true; + goto case 391; + } + case 391: { + if (la == null) { currentState = 391; break; } + if (set[21].Get(la.kind)) { + stateStack.Push(392); + goto case 47; + } else { + goto case 392; + } + } + case 392: { + PopContext(); + goto case 46; + } + case 393: { + stateStack.Push(394); + goto case 55; + } + case 394: { + if (la == null) { currentState = 394; break; } + Expect(22, la); // "," + currentState = 55; + break; + } + case 395: { + stateStack.Push(396); + goto case 55; + } + case 396: { + stateStack.Push(397); + goto case 259; + } + case 397: { + if (la == null) { currentState = 397; break; } + Expect(113, la); // "End" + currentState = 398; + break; + } + case 398: { + if (la == null) { currentState = 398; break; } + if (la.kind == 233) { + goto case 102; + } else { + if (la.kind == 211) { + goto case 110; + } else { + goto case 6; + } + } + } + case 399: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(400); + goto case 205; + } + case 400: { + PopContext(); + goto case 401; + } + case 401: { + if (la == null) { currentState = 401; break; } + if (la.kind == 33) { + currentState = 402; + break; + } else { + goto case 402; + } + } + case 402: { + if (la == null) { currentState = 402; break; } + if (la.kind == 37) { + currentState = 419; + break; + } else { + if (la.kind == 63) { + currentState = 416; + break; + } else { + goto case 403; + } + } + } + case 403: { + if (la == null) { currentState = 403; break; } + if (la.kind == 20) { + currentState = 415; + break; + } else { + goto case 404; + } + } + case 404: { + if (la == null) { currentState = 404; break; } + if (la.kind == 22) { + currentState = 405; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 405: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(406); + goto case 205; + } + case 406: { + PopContext(); + goto case 407; + } + case 407: { + if (la == null) { currentState = 407; break; } + if (la.kind == 33) { + currentState = 408; + break; + } else { + goto case 408; + } + } + case 408: { + if (la == null) { currentState = 408; break; } + if (la.kind == 37) { + currentState = 412; + break; + } else { + if (la.kind == 63) { + currentState = 409; + break; + } else { + goto case 403; + } + } + } + case 409: { + PushContext(Context.Type, la, t); + goto case 410; + } + case 410: { + if (la == null) { currentState = 410; break; } + if (la.kind == 162) { + stateStack.Push(411); + goto case 85; + } else { + if (set[16].Get(la.kind)) { + stateStack.Push(411); + goto case 37; + } else { + Error(la); + goto case 411; + } + } + } + case 411: { + PopContext(); + goto case 403; + } + case 412: { + nextTokenIsPotentialStartOfExpression = true; + goto case 413; + } + case 413: { + if (la == null) { currentState = 413; break; } + if (set[23].Get(la.kind)) { + stateStack.Push(414); + goto case 55; + } else { + goto case 414; + } + } + case 414: { + if (la == null) { currentState = 414; break; } + if (la.kind == 22) { + currentState = 412; + break; + } else { + Expect(38, la); // ")" + currentState = 408; + break; + } + } + case 415: { + stateStack.Push(404); + goto case 55; + } + case 416: { + PushContext(Context.Type, la, t); + goto case 417; + } + case 417: { + if (la == null) { currentState = 417; break; } + if (la.kind == 162) { + stateStack.Push(418); + goto case 85; + } else { + if (set[16].Get(la.kind)) { + stateStack.Push(418); + goto case 37; + } else { + Error(la); + goto case 418; + } + } + } + case 418: { + PopContext(); + goto case 403; + } + case 419: { + nextTokenIsPotentialStartOfExpression = true; + goto case 420; + } + case 420: { + if (la == null) { currentState = 420; break; } + if (set[23].Get(la.kind)) { + stateStack.Push(421); + goto case 55; + } else { + goto case 421; + } + } + case 421: { + if (la == null) { currentState = 421; break; } + if (la.kind == 22) { + currentState = 419; + break; + } else { + Expect(38, la); // ")" + currentState = 402; + break; + } + } + case 422: { + PushContext(Context.Type, la, t); + stateStack.Push(423); + goto case 37; + } + case 423: { + PopContext(); + goto case 256; + } + case 424: { + if (la == null) { currentState = 424; break; } + Expect(37, la); // "(" + currentState = 425; + break; + } + case 425: { + PushContext(Context.Default, la, t); + SetIdentifierExpected(la); + goto case 426; + } + case 426: { + if (la == null) { currentState = 426; break; } + if (set[77].Get(la.kind)) { + stateStack.Push(427); + goto case 428; + } else { + goto case 427; + } + } + case 427: { + PopContext(); + goto case 46; + } + case 428: { + stateStack.Push(429); + PushContext(Context.Parameter, la, t); + goto case 430; + } + case 429: { + if (la == null) { currentState = 429; break; } + if (la.kind == 22) { + currentState = 428; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 430: { + SetIdentifierExpected(la); + goto case 431; + } + case 431: { + if (la == null) { currentState = 431; break; } + if (la.kind == 40) { + stateStack.Push(430); + goto case 443; + } else { + goto case 432; + } + } + case 432: { + SetIdentifierExpected(la); + goto case 433; + } + case 433: { + if (la == null) { currentState = 433; break; } + if (set[144].Get(la.kind)) { + currentState = 432; + break; + } else { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(434); + goto case 205; + } + } + case 434: { + PopContext(); + goto case 435; + } + case 435: { + if (la == null) { currentState = 435; break; } + if (la.kind == 33) { + currentState = 436; + break; + } else { + goto case 436; + } + } + case 436: { + if (la == null) { currentState = 436; break; } + if (la.kind == 37) { + currentState = 442; + break; + } else { + if (la.kind == 63) { + currentState = 440; + break; + } else { + goto case 437; + } + } + } + case 437: { + if (la == null) { currentState = 437; break; } + if (la.kind == 20) { + currentState = 439; + break; + } else { + goto case 438; + } + } + case 438: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 439: { + stateStack.Push(438); + goto case 55; + } + case 440: { + PushContext(Context.Type, la, t); + stateStack.Push(441); + goto case 37; + } + case 441: { + PopContext(); + goto case 437; + } + case 442: { + if (la == null) { currentState = 442; break; } + if (la.kind == 22) { + currentState = 442; + break; + } else { + Expect(38, la); // ")" + currentState = 436; + break; + } + } + case 443: { + if (la == null) { currentState = 443; break; } + Expect(40, la); // "<" + currentState = 444; + break; + } + case 444: { + wasNormalAttribute = true; PushContext(Context.Attribute, la, t); + goto case 445; + } + case 445: { + if (la == null) { currentState = 445; break; } + if (la.kind == 65 || la.kind == 155) { + currentState = 449; + break; + } else { + goto case 446; + } + } + case 446: { + if (la == null) { currentState = 446; break; } + if (set[145].Get(la.kind)) { + currentState = 446; + break; + } else { + Expect(39, la); // ">" + currentState = 447; + break; + } + } + case 447: { + PopContext(); + goto case 448; + } + case 448: { + if (la == null) { currentState = 448; break; } + if (la.kind == 1) { + goto case 25; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 449: { + if (la == null) { currentState = 449; break; } + Expect(21, la); // ":" + currentState = 450; + break; + } + case 450: { + wasNormalAttribute = false; + goto case 446; + } + case 451: { + stateStack.Push(452); + goto case 424; + } + case 452: { + nextTokenIsPotentialStartOfExpression = true; + goto case 453; + } + case 453: { + if (la == null) { currentState = 453; break; } + if (set[50].Get(la.kind)) { + goto case 267; + } else { + if (la.kind == 1 || la.kind == 21) { + stateStack.Push(454); + goto case 259; + } else { + goto case 6; + } + } + } + case 454: { + if (la == null) { currentState = 454; break; } + Expect(113, la); // "End" + currentState = 455; + break; + } + case 455: { + if (la == null) { currentState = 455; break; } + Expect(210, la); // "Sub" + currentState = stateStack.Pop(); + break; + } + case 456: { + if (la == null) { currentState = 456; break; } + if (la.kind == 17 || la.kind == 18 || la.kind == 19) { + currentState = 469; + break; + } else { + if (la.kind == 10) { + stateStack.Push(458); + goto case 460; + } else { + Error(la); + goto case 457; + } + } + } + case 457: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 458: { + if (la == null) { currentState = 458; break; } + if (la.kind == 17) { + currentState = 459; + break; + } else { + goto case 457; + } + } + case 459: { + if (la == null) { currentState = 459; break; } + if (la.kind == 16) { + currentState = 458; + break; + } else { + goto case 458; + } + } + case 460: { + PushContext(Context.Xml, la, t); + goto case 461; + } + case 461: { + if (la == null) { currentState = 461; break; } + Expect(10, la); // XmlOpenTag + currentState = 462; + break; + } + case 462: { + if (la == null) { currentState = 462; break; } + if (set[146].Get(la.kind)) { + if (set[147].Get(la.kind)) { + currentState = 462; + break; + } else { + if (la.kind == 12) { + stateStack.Push(462); + goto case 466; + } else { + Error(la); + goto case 462; + } + } + } else { + if (la.kind == 14) { + currentState = 463; + break; + } else { + if (la.kind == 11) { + currentState = 464; + break; + } else { + Error(la); + goto case 463; + } + } + } + } + case 463: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 464: { + if (la == null) { currentState = 464; break; } + if (set[148].Get(la.kind)) { + if (set[149].Get(la.kind)) { + currentState = 464; + break; + } else { + if (la.kind == 12) { + stateStack.Push(464); + goto case 466; + } else { + if (la.kind == 10) { + stateStack.Push(464); + goto case 460; + } else { + Error(la); + goto case 464; + } + } + } + } else { + Expect(15, la); // XmlOpenEndTag + currentState = 465; + break; + } + } + case 465: { + if (la == null) { currentState = 465; break; } + if (set[150].Get(la.kind)) { + if (set[151].Get(la.kind)) { + currentState = 465; + break; + } else { + if (la.kind == 12) { + stateStack.Push(465); + goto case 466; + } else { + Error(la); + goto case 465; + } + } + } else { + Expect(11, la); // XmlCloseTag + currentState = 463; + break; + } + } + case 466: { + if (la == null) { currentState = 466; break; } + Expect(12, la); // XmlStartInlineVB + currentState = 467; + break; + } + case 467: { + stateStack.Push(468); + goto case 55; + } + case 468: { + if (la == null) { currentState = 468; break; } + Expect(13, la); // XmlEndInlineVB + currentState = stateStack.Pop(); + break; + } + case 469: { + if (la == null) { currentState = 469; break; } + if (la.kind == 16) { + currentState = 470; + break; + } else { + goto case 470; + } + } + case 470: { + if (la == null) { currentState = 470; break; } + if (la.kind == 17 || la.kind == 19) { + currentState = 469; + break; + } else { + if (la.kind == 10) { + stateStack.Push(471); + goto case 460; + } else { + goto case 457; + } + } + } + case 471: { + if (la == null) { currentState = 471; break; } + if (la.kind == 17) { + currentState = 472; + break; + } else { + goto case 457; + } + } + case 472: { + if (la == null) { currentState = 472; break; } + if (la.kind == 16) { + currentState = 471; + break; + } else { + goto case 471; + } + } + case 473: { + if (la == null) { currentState = 473; break; } + Expect(37, la); // "(" + currentState = 474; + break; + } + case 474: { + readXmlIdentifier = true; + stateStack.Push(475); + goto case 205; + } + case 475: { + if (la == null) { currentState = 475; break; } + Expect(38, la); // ")" + currentState = 175; + break; + } + case 476: { + if (la == null) { currentState = 476; break; } + Expect(37, la); // "(" + currentState = 477; + break; + } + case 477: { + PushContext(Context.Type, la, t); + stateStack.Push(478); + goto case 37; + } + case 478: { + PopContext(); + goto case 475; + } + case 479: { + nextTokenIsStartOfImportsOrAccessExpression = true; wasQualifierTokenAtStart = true; + goto case 480; + } + case 480: { + if (la == null) { currentState = 480; break; } + if (la.kind == 10) { + currentState = 481; + break; + } else { + goto case 481; + } + } + case 481: { + stateStack.Push(482); + goto case 101; + } + case 482: { + if (la == null) { currentState = 482; break; } + if (la.kind == 11) { + currentState = 175; + break; + } else { + goto case 175; + } + } + case 483: { + activeArgument = 0; + goto case 484; + } + case 484: { + stateStack.Push(485); + goto case 55; + } + case 485: { + if (la == null) { currentState = 485; break; } + if (la.kind == 22) { + currentState = 486; + break; + } else { + goto case 475; + } + } + case 486: { + activeArgument++; + goto case 484; + } + case 487: { + stateStack.Push(488); + goto case 55; + } + case 488: { + if (la == null) { currentState = 488; break; } + if (la.kind == 22) { + currentState = 489; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 489: { + activeArgument++; + nextTokenIsPotentialStartOfExpression = true; + goto case 490; + } + case 490: { + if (la == null) { currentState = 490; break; } + if (set[23].Get(la.kind)) { + goto case 487; + } else { + goto case 488; + } + } + case 491: { + if (la == null) { currentState = 491; break; } + if (set[16].Get(la.kind)) { + PushContext(Context.Type, la, t); + stateStack.Push(495); + goto case 37; + } else { + goto case 492; + } + } + case 492: { + if (la == null) { currentState = 492; break; } + if (la.kind == 22) { + currentState = 493; + break; + } else { + goto case 45; + } + } + case 493: { + if (la == null) { currentState = 493; break; } + if (set[16].Get(la.kind)) { + PushContext(Context.Type, la, t); + stateStack.Push(494); + goto case 37; + } else { + goto case 492; + } + } + case 494: { + PopContext(); + goto case 492; + } + case 495: { + PopContext(); + goto case 492; + } + case 496: { + SetIdentifierExpected(la); + goto case 497; + } + case 497: { + if (la == null) { currentState = 497; break; } + if (set[152].Get(la.kind)) { + if (la.kind == 169) { + currentState = 499; + break; + } else { + if (set[77].Get(la.kind)) { + stateStack.Push(498); + goto case 428; + } else { + Error(la); + goto case 498; + } + } + } else { + goto case 498; + } + } + case 498: { + if (la == null) { currentState = 498; break; } + Expect(38, la); // ")" + currentState = 34; + break; + } + case 499: { + stateStack.Push(498); + goto case 500; + } + case 500: { + SetIdentifierExpected(la); + goto case 501; + } + case 501: { + if (la == null) { currentState = 501; break; } + if (la.kind == 138 || la.kind == 178) { + currentState = 502; + break; + } else { + goto case 502; + } + } + case 502: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(503); + goto case 517; + } + case 503: { + PopContext(); + goto case 504; + } + case 504: { + if (la == null) { currentState = 504; break; } + if (la.kind == 63) { + currentState = 518; + break; + } else { + goto case 505; + } + } + case 505: { + if (la == null) { currentState = 505; break; } + if (la.kind == 22) { + currentState = 506; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 506: { + SetIdentifierExpected(la); + goto case 507; + } + case 507: { + if (la == null) { currentState = 507; break; } + if (la.kind == 138 || la.kind == 178) { + currentState = 508; + break; + } else { + goto case 508; + } + } + case 508: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(509); + goto case 517; + } + case 509: { + PopContext(); + goto case 510; + } + case 510: { + if (la == null) { currentState = 510; break; } + if (la.kind == 63) { + currentState = 511; + break; + } else { + goto case 505; + } + } + case 511: { + PushContext(Context.Type, la, t); + stateStack.Push(512); + goto case 513; + } + case 512: { + PopContext(); + goto case 505; + } + case 513: { + if (la == null) { currentState = 513; break; } + if (set[94].Get(la.kind)) { + goto case 516; + } else { + if (la.kind == 35) { + currentState = 514; + break; + } else { + goto case 6; + } + } + } + case 514: { + stateStack.Push(515); + goto case 516; + } + case 515: { + if (la == null) { currentState = 515; break; } + if (la.kind == 22) { + currentState = 514; + break; + } else { + goto case 82; + } + } + case 516: { + if (la == null) { currentState = 516; break; } + if (set[16].Get(la.kind)) { + currentState = 38; + break; + } else { + if (la.kind == 162) { + goto case 121; + } else { + if (la.kind == 84) { + goto case 137; + } else { + if (la.kind == 209) { + goto case 112; + } else { + goto case 6; + } + } + } + } + } + case 517: { + if (la == null) { currentState = 517; break; } + if (la.kind == 2) { + goto case 145; + } else { + if (la.kind == 62) { + goto case 143; + } else { + if (la.kind == 64) { + goto case 142; + } else { + if (la.kind == 65) { + goto case 141; + } else { + if (la.kind == 66) { + goto case 140; + } else { + if (la.kind == 67) { + goto case 139; + } else { + if (la.kind == 70) { + goto case 138; + } else { + if (la.kind == 87) { + goto case 136; + } else { + if (la.kind == 104) { + goto case 134; + } else { + if (la.kind == 107) { + goto case 133; + } else { + if (la.kind == 116) { + goto case 131; + } else { + if (la.kind == 121) { + goto case 130; + } else { + if (la.kind == 133) { + goto case 126; + } else { + if (la.kind == 139) { + goto case 125; + } else { + if (la.kind == 143) { + goto case 124; + } else { + if (la.kind == 146) { + goto case 123; + } else { + if (la.kind == 147) { + goto case 122; + } else { + if (la.kind == 170) { + goto case 119; + } else { + if (la.kind == 176) { + goto case 118; + } else { + if (la.kind == 184) { + goto case 117; + } else { + if (la.kind == 203) { + goto case 114; + } else { + if (la.kind == 212) { + goto case 109; + } else { + if (la.kind == 213) { + goto case 108; + } else { + if (la.kind == 223) { + goto case 106; + } else { + if (la.kind == 224) { + goto case 105; + } else { + if (la.kind == 230) { + goto case 104; + } else { + goto case 6; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + case 518: { + PushContext(Context.Type, la, t); + stateStack.Push(519); + goto case 513; + } + case 519: { + PopContext(); + goto case 505; + } + case 520: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(521); + goto case 205; + } + case 521: { + PopContext(); + goto case 522; + } + case 522: { + if (la == null) { currentState = 522; break; } + if (la.kind == 37) { + stateStack.Push(523); + goto case 424; + } else { + goto case 523; + } + } + case 523: { + if (la == null) { currentState = 523; break; } + if (la.kind == 63) { + currentState = 524; + break; + } else { + goto case 23; + } + } + case 524: { + PushContext(Context.Type, la, t); + goto case 525; + } + case 525: { + if (la == null) { currentState = 525; break; } + if (la.kind == 40) { + stateStack.Push(525); + goto case 443; + } else { + stateStack.Push(526); + goto case 37; + } + } + case 526: { + PopContext(); + goto case 23; + } + case 527: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(528); + goto case 205; + } + case 528: { + PopContext(); + goto case 529; + } + case 529: { + if (la == null) { currentState = 529; break; } + if (la.kind == 37 || la.kind == 63) { + if (la.kind == 63) { + currentState = 531; + break; + } else { + if (la.kind == 37) { + stateStack.Push(23); + goto case 424; + } else { + goto case 530; + } + } + } else { + goto case 23; + } + } + case 530: { + Error(la); + goto case 23; + } + case 531: { + PushContext(Context.Type, la, t); + stateStack.Push(532); + goto case 37; + } + case 532: { + PopContext(); + goto case 23; + } + case 533: { + PushContext(Context.TypeDeclaration, la, t); + goto case 534; + } + case 534: { + if (la == null) { currentState = 534; break; } + Expect(115, la); // "Enum" + currentState = 535; + break; + } + case 535: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(536); + goto case 205; + } + case 536: { + PopContext(); + goto case 537; + } + case 537: { + if (la == null) { currentState = 537; break; } + if (la.kind == 63) { + currentState = 549; + break; + } else { + goto case 538; + } + } + case 538: { + stateStack.Push(539); + goto case 23; + } + case 539: { + SetIdentifierExpected(la); + goto case 540; + } + case 540: { + if (la == null) { currentState = 540; break; } + if (set[97].Get(la.kind)) { + goto case 544; + } else { + Expect(113, la); // "End" + currentState = 541; + break; + } + } + case 541: { + if (la == null) { currentState = 541; break; } + Expect(115, la); // "Enum" + currentState = 542; + break; + } + case 542: { + stateStack.Push(543); + goto case 23; + } + case 543: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 544: { + SetIdentifierExpected(la); + goto case 545; + } + case 545: { + if (la == null) { currentState = 545; break; } + if (la.kind == 40) { + stateStack.Push(544); + goto case 443; + } else { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(546); + goto case 205; + } + } + case 546: { + PopContext(); + goto case 547; + } + case 547: { + if (la == null) { currentState = 547; break; } + if (la.kind == 20) { + currentState = 548; + break; + } else { + goto case 538; + } + } + case 548: { + stateStack.Push(538); + goto case 55; + } + case 549: { + PushContext(Context.Type, la, t); + stateStack.Push(550); + goto case 37; + } + case 550: { + PopContext(); + goto case 538; + } + case 551: { + if (la == null) { currentState = 551; break; } + Expect(103, la); // "Delegate" + currentState = 552; + break; + } + case 552: { + if (la == null) { currentState = 552; break; } + if (la.kind == 210) { + currentState = 553; + break; + } else { + if (la.kind == 127) { + currentState = 553; + break; + } else { + Error(la); + goto case 553; + } + } + } + case 553: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + goto case 554; + } + case 554: { + if (la == null) { currentState = 554; break; } + currentState = 555; + break; + } + case 555: { + PopContext(); + goto case 556; + } + case 556: { + if (la == null) { currentState = 556; break; } + if (la.kind == 37) { + currentState = 559; + break; + } else { + if (la.kind == 63) { + currentState = 557; + break; + } else { + goto case 23; + } + } + } + case 557: { + PushContext(Context.Type, la, t); + stateStack.Push(558); + goto case 37; + } + case 558: { + PopContext(); + goto case 23; + } + case 559: { + SetIdentifierExpected(la); + goto case 560; + } + case 560: { + if (la == null) { currentState = 560; break; } + if (set[152].Get(la.kind)) { + if (la.kind == 169) { + currentState = 562; + break; + } else { + if (set[77].Get(la.kind)) { + stateStack.Push(561); + goto case 428; + } else { + Error(la); + goto case 561; + } + } + } else { + goto case 561; + } + } + case 561: { + if (la == null) { currentState = 561; break; } + Expect(38, la); // ")" + currentState = 556; + break; + } + case 562: { + stateStack.Push(561); + goto case 500; + } + case 563: { + PushContext(Context.TypeDeclaration, la, t); + goto case 564; + } + case 564: { + if (la == null) { currentState = 564; break; } + if (la.kind == 155) { + currentState = 565; + break; + } else { + if (la.kind == 84) { + currentState = 565; + break; + } else { + if (la.kind == 209) { + currentState = 565; + break; + } else { + Error(la); + goto case 565; + } + } + } + } + case 565: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(566); + goto case 205; + } + case 566: { + PopContext(); + goto case 567; + } + case 567: { + if (la == null) { currentState = 567; break; } + if (la.kind == 37) { + currentState = 717; + break; + } else { + goto case 568; + } + } + case 568: { + stateStack.Push(569); + goto case 23; + } + case 569: { + SetIdentifierExpected(la); + isMissingModifier = true; + goto case 570; + } + case 570: { + if (la == null) { currentState = 570; break; } + if (la.kind == 140) { + isMissingModifier = false; + goto case 714; + } else { + goto case 571; + } + } + case 571: { + SetIdentifierExpected(la); + isMissingModifier = true; + goto case 572; + } + case 572: { + if (la == null) { currentState = 572; break; } + if (la.kind == 136) { + isMissingModifier = false; + goto case 708; + } else { + goto case 573; + } + } + case 573: { + SetIdentifierExpected(la); + isMissingModifier = true; + goto case 574; + } + case 574: { + if (la == null) { currentState = 574; break; } + if (set[101].Get(la.kind)) { + goto case 579; + } else { + isMissingModifier = false; + goto case 575; + } + } + case 575: { + if (la == null) { currentState = 575; break; } + Expect(113, la); // "End" + currentState = 576; + break; + } + case 576: { + if (la == null) { currentState = 576; break; } + if (la.kind == 155) { + currentState = 577; + break; + } else { + if (la.kind == 84) { + currentState = 577; + break; + } else { + if (la.kind == 209) { + currentState = 577; + break; + } else { + Error(la); + goto case 577; + } + } + } + } + case 577: { + stateStack.Push(578); + goto case 23; + } + case 578: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 579: { + SetIdentifierExpected(la); + isMissingModifier = true; + goto case 580; + } + case 580: { + if (la == null) { currentState = 580; break; } + if (la.kind == 40) { + stateStack.Push(579); + goto case 443; + } else { + isMissingModifier = true; + goto case 581; + } + } + case 581: { + SetIdentifierExpected(la); + goto case 582; + } + case 582: { + if (la == null) { currentState = 582; break; } + if (set[133].Get(la.kind)) { + currentState = 707; + break; + } else { + isMissingModifier = false; + SetIdentifierExpected(la); + goto case 583; + } + } + case 583: { + if (la == null) { currentState = 583; break; } + if (la.kind == 84 || la.kind == 155 || la.kind == 209) { + stateStack.Push(573); + goto case 563; + } else { + if (la.kind == 103) { + stateStack.Push(573); + goto case 551; + } else { + if (la.kind == 115) { + stateStack.Push(573); + goto case 533; + } else { + if (la.kind == 142) { + stateStack.Push(573); + goto case 9; + } else { + if (set[104].Get(la.kind)) { + stateStack.Push(573); + PushContext(Context.Member, la, t); + SetIdentifierExpected(la); + goto case 584; + } else { + Error(la); + goto case 573; + } + } + } + } + } + } + case 584: { + if (la == null) { currentState = 584; break; } + if (set[122].Get(la.kind)) { + stateStack.Push(585); + goto case 692; + } else { + if (la.kind == 127 || la.kind == 210) { + stateStack.Push(585); + goto case 674; + } else { + if (la.kind == 101) { + stateStack.Push(585); + goto case 661; + } else { + if (la.kind == 119) { + stateStack.Push(585); + goto case 649; + } else { + if (la.kind == 98) { + stateStack.Push(585); + goto case 637; + } else { + if (la.kind == 186) { + stateStack.Push(585); + goto case 600; + } else { + if (la.kind == 172) { + stateStack.Push(585); + goto case 586; + } else { + Error(la); + goto case 585; + } + } + } + } + } + } + } + } + case 585: { + PopContext(); + currentState = stateStack.Pop(); + goto switchlbl; + } + case 586: { + if (la == null) { currentState = 586; break; } + Expect(172, la); // "Operator" + currentState = 587; + break; + } + case 587: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + goto case 588; + } + case 588: { + if (la == null) { currentState = 588; break; } + currentState = 589; + break; + } + case 589: { + PopContext(); + goto case 590; + } + case 590: { + if (la == null) { currentState = 590; break; } + Expect(37, la); // "(" + currentState = 591; + break; + } + case 591: { + stateStack.Push(592); + goto case 428; + } + case 592: { + if (la == null) { currentState = 592; break; } + Expect(38, la); // ")" + currentState = 593; + break; + } + case 593: { + if (la == null) { currentState = 593; break; } + if (la.kind == 63) { + currentState = 597; + break; + } else { + goto case 594; + } + } + case 594: { + stateStack.Push(595); + goto case 259; + } + case 595: { + if (la == null) { currentState = 595; break; } + Expect(113, la); // "End" + currentState = 596; + break; + } + case 596: { + if (la == null) { currentState = 596; break; } + Expect(172, la); // "Operator" + currentState = 23; + break; + } + case 597: { + PushContext(Context.Type, la, t); + goto case 598; + } + case 598: { + if (la == null) { currentState = 598; break; } + if (la.kind == 40) { + stateStack.Push(598); + goto case 443; + } else { + stateStack.Push(599); + goto case 37; + } + } + case 599: { + PopContext(); + goto case 594; + } + case 600: { + if (la == null) { currentState = 600; break; } + Expect(186, la); // "Property" + currentState = 601; + break; + } + case 601: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(602); + goto case 205; + } + case 602: { + PopContext(); + goto case 603; + } + case 603: { + if (la == null) { currentState = 603; break; } + if (la.kind == 37) { + stateStack.Push(604); + goto case 424; + } else { + goto case 604; + } + } + case 604: { + if (la == null) { currentState = 604; break; } + if (la.kind == 63) { + currentState = 634; + break; + } else { + goto case 605; + } + } + case 605: { + if (la == null) { currentState = 605; break; } + if (la.kind == 136) { + currentState = 629; + break; + } else { + goto case 606; + } + } + case 606: { + if (la == null) { currentState = 606; break; } + if (la.kind == 20) { + currentState = 628; + break; + } else { + goto case 607; + } + } + case 607: { + stateStack.Push(608); + goto case 23; + } + case 608: { + PopContext(); + goto case 609; + } + case 609: { + if (la == null) { currentState = 609; break; } + if (la.kind == 40) { + stateStack.Push(609); + goto case 443; + } else { + goto case 610; + } + } + case 610: { + if (la == null) { currentState = 610; break; } + if (set[153].Get(la.kind)) { + currentState = 627; + break; + } else { + if (la.kind == 128 || la.kind == 198) { + PushContext(Context.Member, la, t); + goto case 611; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + } + case 611: { + if (la == null) { currentState = 611; break; } + if (la.kind == 128) { + currentState = 612; + break; + } else { + if (la.kind == 198) { + currentState = 612; + break; + } else { + Error(la); + goto case 612; + } + } + } + case 612: { + if (la == null) { currentState = 612; break; } + if (la.kind == 37) { + stateStack.Push(613); + goto case 424; + } else { + goto case 613; + } + } + case 613: { + stateStack.Push(614); + goto case 259; + } + case 614: { + if (la == null) { currentState = 614; break; } + Expect(113, la); // "End" + currentState = 615; + break; + } + case 615: { + if (la == null) { currentState = 615; break; } + if (la.kind == 128) { + currentState = 616; + break; + } else { + if (la.kind == 198) { + currentState = 616; + break; + } else { + Error(la); + goto case 616; + } + } + } + case 616: { + stateStack.Push(617); + goto case 23; + } + case 617: { + if (la == null) { currentState = 617; break; } + if (set[110].Get(la.kind)) { + goto case 620; + } else { + goto case 618; + } + } + case 618: { + if (la == null) { currentState = 618; break; } + Expect(113, la); // "End" + currentState = 619; + break; + } + case 619: { + if (la == null) { currentState = 619; break; } + Expect(186, la); // "Property" + currentState = 23; + break; + } + case 620: { + if (la == null) { currentState = 620; break; } + if (la.kind == 40) { + stateStack.Push(620); + goto case 443; + } else { + goto case 621; + } + } + case 621: { + if (la == null) { currentState = 621; break; } + if (set[153].Get(la.kind)) { + currentState = 621; + break; + } else { + if (la.kind == 128) { + currentState = 622; + break; + } else { + if (la.kind == 198) { + currentState = 622; + break; + } else { + Error(la); + goto case 622; + } + } + } + } + case 622: { + if (la == null) { currentState = 622; break; } + if (la.kind == 37) { + stateStack.Push(623); + goto case 424; + } else { + goto case 623; + } + } + case 623: { + stateStack.Push(624); + goto case 259; + } + case 624: { + if (la == null) { currentState = 624; break; } + Expect(113, la); // "End" + currentState = 625; + break; + } + case 625: { + if (la == null) { currentState = 625; break; } + if (la.kind == 128) { + currentState = 626; + break; + } else { + if (la.kind == 198) { + currentState = 626; + break; + } else { + Error(la); + goto case 626; + } + } + } + case 626: { + stateStack.Push(618); + goto case 23; + } + case 627: { + SetIdentifierExpected(la); + goto case 610; + } + case 628: { + stateStack.Push(607); + goto case 55; + } + case 629: { + PushContext(Context.Type, la, t); + stateStack.Push(630); + goto case 37; + } + case 630: { + PopContext(); + goto case 631; + } + case 631: { + if (la == null) { currentState = 631; break; } + if (la.kind == 22) { + currentState = 632; + break; + } else { + goto case 606; + } + } + case 632: { + PushContext(Context.Type, la, t); + stateStack.Push(633); + goto case 37; + } + case 633: { + PopContext(); + goto case 631; + } + case 634: { + PushContext(Context.Type, la, t); + goto case 635; + } + case 635: { + if (la == null) { currentState = 635; break; } + if (la.kind == 40) { + stateStack.Push(635); + goto case 443; + } else { + if (la.kind == 162) { + stateStack.Push(636); + goto case 85; + } else { + if (set[16].Get(la.kind)) { + stateStack.Push(636); + goto case 37; + } else { + Error(la); + goto case 636; + } + } + } + } + case 636: { + PopContext(); + goto case 605; + } + case 637: { + if (la == null) { currentState = 637; break; } + Expect(98, la); // "Custom" + currentState = 638; + break; + } + case 638: { + stateStack.Push(639); + goto case 649; + } + case 639: { + if (la == null) { currentState = 639; break; } + if (set[115].Get(la.kind)) { + goto case 641; + } else { + Expect(113, la); // "End" + currentState = 640; + break; + } + } + case 640: { + if (la == null) { currentState = 640; break; } + Expect(119, la); // "Event" + currentState = 23; + break; + } + case 641: { + if (la == null) { currentState = 641; break; } + if (la.kind == 40) { + stateStack.Push(641); + goto case 443; + } else { + if (la.kind == 56) { + currentState = 642; + break; + } else { + if (la.kind == 193) { + currentState = 642; + break; + } else { + if (la.kind == 189) { + currentState = 642; + break; + } else { + Error(la); + goto case 642; + } + } + } + } + } + case 642: { + if (la == null) { currentState = 642; break; } + Expect(37, la); // "(" + currentState = 643; + break; + } + case 643: { + stateStack.Push(644); + goto case 428; + } + case 644: { + if (la == null) { currentState = 644; break; } + Expect(38, la); // ")" + currentState = 645; + break; + } + case 645: { + stateStack.Push(646); + goto case 259; + } + case 646: { + if (la == null) { currentState = 646; break; } + Expect(113, la); // "End" + currentState = 647; + break; + } + case 647: { + if (la == null) { currentState = 647; break; } + if (la.kind == 56) { + currentState = 648; + break; + } else { + if (la.kind == 193) { + currentState = 648; + break; + } else { + if (la.kind == 189) { + currentState = 648; + break; + } else { + Error(la); + goto case 648; + } + } + } + } + case 648: { + stateStack.Push(639); + goto case 23; + } + case 649: { + if (la == null) { currentState = 649; break; } + Expect(119, la); // "Event" + currentState = 650; + break; + } + case 650: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(651); + goto case 205; + } + case 651: { + PopContext(); + goto case 652; + } + case 652: { + if (la == null) { currentState = 652; break; } + if (la.kind == 63) { + currentState = 659; + break; + } else { + if (set[154].Get(la.kind)) { + if (la.kind == 37) { + stateStack.Push(653); + goto case 424; + } else { + goto case 653; + } + } else { + Error(la); + goto case 653; + } + } + } + case 653: { + if (la == null) { currentState = 653; break; } + if (la.kind == 136) { + currentState = 654; + break; + } else { + goto case 23; + } + } + case 654: { + PushContext(Context.Type, la, t); + stateStack.Push(655); + goto case 37; + } + case 655: { + PopContext(); + goto case 656; + } + case 656: { + if (la == null) { currentState = 656; break; } + if (la.kind == 22) { + currentState = 657; + break; + } else { + goto case 23; + } + } + case 657: { + PushContext(Context.Type, la, t); + stateStack.Push(658); + goto case 37; + } + case 658: { + PopContext(); + goto case 656; + } + case 659: { + PushContext(Context.Type, la, t); + stateStack.Push(660); + goto case 37; + } + case 660: { + PopContext(); + goto case 653; + } + case 661: { + if (la == null) { currentState = 661; break; } + Expect(101, la); // "Declare" + currentState = 662; + break; + } + case 662: { + if (la == null) { currentState = 662; break; } + if (la.kind == 62 || la.kind == 66 || la.kind == 223) { + currentState = 663; + break; + } else { + goto case 663; + } + } + case 663: { + if (la == null) { currentState = 663; break; } + if (la.kind == 210) { + currentState = 664; + break; + } else { + if (la.kind == 127) { + currentState = 664; + break; + } else { + Error(la); + goto case 664; + } + } + } + case 664: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(665); + goto case 205; + } + case 665: { + PopContext(); + goto case 666; + } + case 666: { + if (la == null) { currentState = 666; break; } + Expect(149, la); // "Lib" + currentState = 667; + break; + } + case 667: { + if (la == null) { currentState = 667; break; } + Expect(3, la); // LiteralString + currentState = 668; + break; + } + case 668: { + if (la == null) { currentState = 668; break; } + if (la.kind == 59) { + currentState = 673; + break; + } else { + goto case 669; + } + } + case 669: { + if (la == null) { currentState = 669; break; } + if (la.kind == 37) { + stateStack.Push(670); + goto case 424; + } else { + goto case 670; + } + } + case 670: { + if (la == null) { currentState = 670; break; } + if (la.kind == 63) { + currentState = 671; + break; + } else { + goto case 23; + } + } + case 671: { + PushContext(Context.Type, la, t); + stateStack.Push(672); + goto case 37; + } + case 672: { + PopContext(); + goto case 23; + } + case 673: { + if (la == null) { currentState = 673; break; } + Expect(3, la); // LiteralString + currentState = 669; + break; + } + case 674: { + if (la == null) { currentState = 674; break; } + if (la.kind == 210) { + currentState = 675; + break; + } else { + if (la.kind == 127) { + currentState = 675; + break; + } else { + Error(la); + goto case 675; + } + } + } + case 675: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + goto case 676; + } + case 676: { + if (la == null) { currentState = 676; break; } + currentState = 677; + break; + } + case 677: { + PopContext(); + goto case 678; + } + case 678: { + if (la == null) { currentState = 678; break; } + if (la.kind == 37) { + currentState = 688; + break; + } else { + if (la.kind == 63) { + currentState = 686; + break; + } else { + goto case 679; + } + } + } + case 679: { + if (la == null) { currentState = 679; break; } + if (la.kind == 134 || la.kind == 136) { + currentState = 683; + break; + } else { + goto case 680; + } + } + case 680: { + stateStack.Push(681); + goto case 259; + } + case 681: { + if (la == null) { currentState = 681; break; } + Expect(113, la); // "End" + currentState = 682; + break; + } + case 682: { + if (la == null) { currentState = 682; break; } + if (la.kind == 210) { + currentState = 23; + break; + } else { + if (la.kind == 127) { + currentState = 23; + break; + } else { + goto case 530; + } + } + } + case 683: { + if (la == null) { currentState = 683; break; } + if (la.kind == 153 || la.kind == 158 || la.kind == 159) { + currentState = 685; + break; + } else { + goto case 684; + } + } + case 684: { + stateStack.Push(680); + goto case 37; + } + case 685: { + if (la == null) { currentState = 685; break; } + Expect(26, la); // "." + currentState = 684; + break; + } + case 686: { + PushContext(Context.Type, la, t); + stateStack.Push(687); + goto case 37; + } + case 687: { + PopContext(); + goto case 679; + } + case 688: { + SetIdentifierExpected(la); + goto case 689; + } + case 689: { + if (la == null) { currentState = 689; break; } + if (set[152].Get(la.kind)) { + if (la.kind == 169) { + currentState = 691; + break; + } else { + if (set[77].Get(la.kind)) { + stateStack.Push(690); + goto case 428; + } else { + Error(la); + goto case 690; + } + } + } else { + goto case 690; + } + } + case 690: { + if (la == null) { currentState = 690; break; } + Expect(38, la); // ")" + currentState = 678; + break; + } + case 691: { + stateStack.Push(690); + goto case 500; + } + case 692: { + stateStack.Push(693); + SetIdentifierExpected(la); + goto case 694; + } + case 693: { + if (la == null) { currentState = 693; break; } + if (la.kind == 22) { + currentState = 692; + break; + } else { + goto case 23; + } + } + case 694: { + if (la == null) { currentState = 694; break; } + if (la.kind == 88) { + currentState = 695; + break; + } else { + goto case 695; + } + } + case 695: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + stateStack.Push(696); + goto case 706; + } + case 696: { + PopContext(); + goto case 697; + } + case 697: { + if (la == null) { currentState = 697; break; } + if (la.kind == 33) { + currentState = 698; + break; + } else { + goto case 698; + } + } + case 698: { + if (la == null) { currentState = 698; break; } + if (la.kind == 37) { + currentState = 703; + break; + } else { + if (la.kind == 63) { + currentState = 700; + break; + } else { + goto case 699; + } + } + } + case 699: { + if (la == null) { currentState = 699; break; } + if (la.kind == 20) { + currentState = 55; + break; + } else { + currentState = stateStack.Pop(); + goto switchlbl; + } + } + case 700: { + PushContext(Context.Type, la, t); + goto case 701; + } + case 701: { + if (la == null) { currentState = 701; break; } + if (la.kind == 162) { + stateStack.Push(702); + goto case 85; + } else { + if (set[16].Get(la.kind)) { + stateStack.Push(702); + goto case 37; + } else { + Error(la); + goto case 702; + } + } + } + case 702: { + PopContext(); + goto case 699; + } + case 703: { + nextTokenIsPotentialStartOfExpression = true; + goto case 704; + } + case 704: { + if (la == null) { currentState = 704; break; } + if (set[23].Get(la.kind)) { + stateStack.Push(705); + goto case 55; + } else { + goto case 705; + } + } + case 705: { + if (la == null) { currentState = 705; break; } + if (la.kind == 22) { + currentState = 703; + break; + } else { + Expect(38, la); // ")" + currentState = 698; + break; + } + } + case 706: { + if (la == null) { currentState = 706; break; } + if (set[138].Get(la.kind)) { + currentState = stateStack.Pop(); + break; + } else { + if (la.kind == 58) { + goto case 144; + } else { + if (la.kind == 126) { + goto case 128; + } else { + goto case 6; + } + } + } + } + case 707: { + isMissingModifier = false; + goto case 581; + } + case 708: { + if (la == null) { currentState = 708; break; } + Expect(136, la); // "Implements" + currentState = 709; + break; + } + case 709: { + PushContext(Context.Type, la, t); + stateStack.Push(710); + goto case 37; + } + case 710: { + PopContext(); + goto case 711; + } + case 711: { + if (la == null) { currentState = 711; break; } + if (la.kind == 22) { + currentState = 712; + break; + } else { + stateStack.Push(573); + goto case 23; + } + } + case 712: { + PushContext(Context.Type, la, t); + stateStack.Push(713); + goto case 37; + } + case 713: { + PopContext(); + goto case 711; + } + case 714: { + if (la == null) { currentState = 714; break; } + Expect(140, la); // "Inherits" + currentState = 715; + break; + } + case 715: { + PushContext(Context.Type, la, t); + stateStack.Push(716); + goto case 37; + } + case 716: { + PopContext(); + stateStack.Push(571); + goto case 23; + } + case 717: { + if (la == null) { currentState = 717; break; } + Expect(169, la); // "Of" + currentState = 718; + break; + } + case 718: { + stateStack.Push(719); + goto case 500; + } + case 719: { + if (la == null) { currentState = 719; break; } + Expect(38, la); // ")" + currentState = 568; + break; + } + case 720: { + isMissingModifier = false; + goto case 28; + } + case 721: { + PushContext(Context.Type, la, t); + stateStack.Push(722); + goto case 37; + } + case 722: { + PopContext(); + goto case 723; + } + case 723: { + if (la == null) { currentState = 723; break; } + if (la.kind == 22) { + currentState = 724; + break; + } else { + stateStack.Push(17); + goto case 23; + } + } + case 724: { + PushContext(Context.Type, la, t); + stateStack.Push(725); + goto case 37; + } + case 725: { + PopContext(); + goto case 723; + } + case 726: { + if (la == null) { currentState = 726; break; } + Expect(169, la); // "Of" + currentState = 727; + break; + } + case 727: { + stateStack.Push(728); + goto case 500; + } + case 728: { + if (la == null) { currentState = 728; break; } + Expect(38, la); // ")" + currentState = 14; + break; + } + case 729: { + PushContext(Context.Identifier, la, t); + SetIdentifierExpected(la); + goto case 730; + } + case 730: { + if (la == null) { currentState = 730; break; } + if (set[49].Get(la.kind)) { + currentState = 730; + break; + } else { + PopContext(); + stateStack.Push(731); + goto case 23; + } + } + case 731: { + if (la == null) { currentState = 731; break; } + if (set[3].Get(la.kind)) { + stateStack.Push(731); + goto case 5; + } else { + Expect(113, la); // "End" + currentState = 732; + break; + } + } + case 732: { + if (la == null) { currentState = 732; break; } + Expect(160, la); // "Namespace" + currentState = 23; + break; + } + case 733: { + if (la == null) { currentState = 733; break; } + Expect(137, la); // "Imports" + currentState = 734; + break; + } + case 734: { + PushContext(Context.Importable, la, t); + nextTokenIsStartOfImportsOrAccessExpression = true; + goto case 735; + } + case 735: { + if (la == null) { currentState = 735; break; } + if (set[155].Get(la.kind)) { + currentState = 747; + break; + } else { + goto case 736; + } + } + case 736: { + if (la == null) { currentState = 736; break; } + if (la.kind == 10) { + currentState = 743; + break; + } else { + Error(la); + goto case 737; + } + } + case 737: { + if (la == null) { currentState = 737; break; } + if (la.kind == 22) { + currentState = 738; + break; + } else { + PopContext(); + goto case 23; + } + } + case 738: { + nextTokenIsStartOfImportsOrAccessExpression = true; + goto case 739; + } + case 739: { + if (la == null) { currentState = 739; break; } + if (set[155].Get(la.kind)) { + currentState = 740; + break; + } else { + goto case 736; + } + } + case 740: { + if (la == null) { currentState = 740; break; } + if (la.kind == 37) { + stateStack.Push(740); + goto case 42; + } else { + goto case 741; + } + } + case 741: { + if (la == null) { currentState = 741; break; } + if (la.kind == 20 || la.kind == 26) { + currentState = 742; + break; + } else { + goto case 737; + } + } + case 742: { + stateStack.Push(737); + goto case 37; + } + case 743: { + stateStack.Push(744); + goto case 205; + } + case 744: { + if (la == null) { currentState = 744; break; } + Expect(20, la); // "=" + currentState = 745; + break; + } + case 745: { + if (la == null) { currentState = 745; break; } + Expect(3, la); // LiteralString + currentState = 746; + break; + } + case 746: { + if (la == null) { currentState = 746; break; } + Expect(11, la); // XmlCloseTag + currentState = 737; + break; + } + case 747: { + if (la == null) { currentState = 747; break; } + if (la.kind == 37) { + stateStack.Push(747); + goto case 42; + } else { + goto case 741; + } + } + case 748: { + if (la == null) { currentState = 748; break; } + Expect(173, la); // "Option" + currentState = 749; + break; + } + case 749: { + if (la == null) { currentState = 749; break; } + if (la.kind == 121 || la.kind == 139 || la.kind == 207) { + currentState = 751; + break; + } else { + if (la.kind == 87) { + currentState = 750; + break; + } else { + goto case 530; + } + } + } + case 750: { + if (la == null) { currentState = 750; break; } + if (la.kind == 213) { + currentState = 23; + break; + } else { + if (la.kind == 67) { + currentState = 23; + break; + } else { + goto case 530; + } + } + } + case 751: { + if (la == null) { currentState = 751; break; } + if (la.kind == 170 || la.kind == 171) { + currentState = 23; + break; + } else { + goto case 23; + } + } + } + + if (la != null) { + t = la; + nextTokenIsPotentialStartOfExpression = false; + readXmlIdentifier = false; + nextTokenIsStartOfImportsOrAccessExpression = false; + wasQualifierTokenAtStart = false; + identifierExpected = false; + } + } + + public void Advance() + { + //Console.WriteLine("Advance"); + InformToken(null); + } + + public BitArray GetExpectedSet() { return GetExpectedSet(currentState); } + + static readonly BitArray[] set = { + new BitArray(new int[] {1, 256, 1048576, 537395328, 402670080, 444604481, 131200, 0}), + new BitArray(new int[] {1, 256, 1048576, 537395328, 402670080, 444596289, 131200, 0}), + new BitArray(new int[] {1, 256, 1048576, 537395328, 402669568, 444596289, 131200, 0}), + new BitArray(new int[] {0, 256, 1048576, 537395328, 402669568, 444596289, 131200, 0}), + new BitArray(new int[] {0, 256, 1048576, 537395328, 402669568, 444596288, 131200, 0}), + new BitArray(new int[] {0, 0, 1048576, 537395328, 402669568, 444596288, 131200, 0}), + new BitArray(new int[] {4, 1140850688, 8388687, 1108347140, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {0, 256, 1048576, -1601568064, 671109120, 1589117122, 393600, 3328}), + new BitArray(new int[] {0, 256, 1048576, -1601568064, 671105024, 1589117122, 393600, 3328}), + new BitArray(new int[] {5, 1140850944, 26214479, -493220892, 940361760, 1606227139, -2143942272, 3393}), + new BitArray(new int[] {0, 256, 1048576, -1601699136, 671105024, 1589117122, 393600, 3328}), + new BitArray(new int[] {0, 0, 1048576, -1601699136, 671105024, 1589117122, 393600, 3328}), + new BitArray(new int[] {0, 0, 1048576, -2138570624, 134234112, 67108864, 393216, 0}), + new BitArray(new int[] {0, 0, 0, -2139095040, 0, 67108864, 262144, 0}), + new BitArray(new int[] {-2, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {2097154, -2147483616, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {4, 1140850690, 8650975, 1108355356, 9218084, 17106176, -533656048, 67}), + new BitArray(new int[] {-940564478, 889192445, 65, 1074825472, 72844640, 231424, 22030368, 4704}), + new BitArray(new int[] {-940564478, 889192413, 65, 1074825472, 72844640, 231424, 22030368, 4704}), + new BitArray(new int[] {4, -16777216, -1, -1, -1, -1, -1, 16383}), + new BitArray(new int[] {-61995012, 1174405224, -51384097, -972018405, -1030969182, 17106740, -97186288, 8259}), + new BitArray(new int[] {-61995012, 1174405160, -51384097, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {-61995012, 1174405224, -51384097, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {-66189316, 1174405160, -51384097, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {-1007673342, 889192405, 65, 1074825472, 72843296, 231424, 22030368, 4160}), + new BitArray(new int[] {-1013972992, 822083461, 0, 0, 71499776, 163840, 16777216, 4096}), + new BitArray(new int[] {-66189316, 1174405176, -51384097, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {4, 1140850690, 8650975, 1108355356, 9218084, 17106176, -533656048, 579}), + new BitArray(new int[] {-1007673342, 889192405, 65, 1074825472, 72843552, 231424, 22030368, 4160}), + new BitArray(new int[] {-1007673342, 889192413, 65, 1074825472, 72843552, 231424, 22030368, 4672}), + new BitArray(new int[] {-2, -9, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-1040382, 889192437, 65, 1074825472, 72843296, 231424, 22030368, 4160}), + new BitArray(new int[] {1006632960, 32, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {1028, -16777216, -1, -1, -1, -1, -1, 16383}), + new BitArray(new int[] {-1038334, -1258291211, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {1007552508, 1140850720, -51384097, -972018405, -1030969182, 17106208, -365621744, 8259}), + new BitArray(new int[] {-1040382, -1258291209, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {0, 0, -60035072, 1027, 0, 0, 134217728, 0}), + new BitArray(new int[] {0, 67108864, 0, 1073743872, 1310752, 65536, 1050656, 64}), + new BitArray(new int[] {4194304, 67108864, 0, 1073743872, 1343520, 65536, 1050656, 64}), + new BitArray(new int[] {-66189316, 1174405160, -51384097, -972018401, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {4194304, 67108864, 64, 1073743872, 1343520, 65536, 1050656, 64}), + new BitArray(new int[] {66189314, -1174405161, 51384096, 972018404, 1030969181, -17106229, 97186287, -8260}), + new BitArray(new int[] {65140738, 973078487, 51384096, 972018404, 1030969181, -17106229, 97186287, -8260}), + new BitArray(new int[] {-66189316, 1174405160, -51384097, -972018405, -1030969182, 17106228, -97186288, 8387}), + new BitArray(new int[] {0, 67108864, 0, 1073743872, 1343520, 65536, 1050656, 64}), + new BitArray(new int[] {-64092162, -973078488, -51384097, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {-64092162, 1191182376, -1048865, -546062565, -1014191950, -1593504452, -21144002, 8903}), + new BitArray(new int[] {0, 0, 3072, 134447104, 16777216, 8, 0, 0}), + new BitArray(new int[] {-2097156, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-66189316, 1191182376, -1051937, -680509669, -1030969166, -1593504460, -21144002, 8903}), + new BitArray(new int[] {-66189316, 1174405162, -51384097, -972018401, -1030969178, 17106228, -97186288, 8259}), + new BitArray(new int[] {6291458, 0, 0, 32768, 0, 0, 0, 0}), + new BitArray(new int[] {-64092162, 1174405160, -51384097, -971985637, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {0, 0, 0, -1879044096, 0, 67108864, 67371040, 128}), + new BitArray(new int[] {36, 1140850688, 8388687, 1108347140, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {2097158, 1140850688, 8388687, 1108347140, 821280, 17105920, -2144335872, 97}), + new BitArray(new int[] {2097154, -2147483648, 0, 0, 0, 0, 0, 32}), + new BitArray(new int[] {36, 1140850688, 8388687, 1108347140, 821280, 17105928, -2144335872, 65}), + new BitArray(new int[] {-66189316, 1174405160, -51384097, -972018405, -1030969166, 17106228, -97186284, 8259}), + new BitArray(new int[] {1007552508, 1140850720, -51384097, -972002021, -1030969182, 17106208, -365621744, 8259}), + new BitArray(new int[] {1007681536, -2147483614, 0, 0, 1024, 0, 0, 0}), + new BitArray(new int[] {1007681536, -2147483616, 0, 0, 1024, 0, 0, 0}), + new BitArray(new int[] {2097154, 0, 0, 0, 0, 0, 0, 129}), + new BitArray(new int[] {2097154, 0, 0, 32768, 0, 0, 0, 129}), + new BitArray(new int[] {-66189316, 1174405160, -51383073, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {-65140740, 1174409128, -51384097, -971985637, -1030903646, 17106228, -97186288, 8259}), + new BitArray(new int[] {-65140740, 1174409128, -51384097, -972018405, -1030903646, 17106228, -97186288, 8259}), + new BitArray(new int[] {1048576, 3968, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {-64092162, 1191182376, -1051937, -680509669, -1030969166, -1593504460, -21144002, 8903}), + new BitArray(new int[] {-64092162, 1191182376, -1051937, -680476901, -1030969166, -1593504460, -21144002, 8903}), + new BitArray(new int[] {2097154, 32, 0, 32768, 0, 0, 0, 0}), + new BitArray(new int[] {7340034, -2147483614, 0, 32768, 0, 0, 0, 0}), + new BitArray(new int[] {7340034, -2147483616, 0, 32768, 0, 0, 0, 0}), + new BitArray(new int[] {7340034, 0, 0, 32768, 0, 0, 0, 0}), + new BitArray(new int[] {4, 1140850690, 8650975, 1108355356, 9218084, 17106180, -533656048, 67}), + new BitArray(new int[] {4, 1140851008, 8388975, 1108347140, 821280, 21316608, -2144335872, 65}), + new BitArray(new int[] {4, 1140850944, 8388975, 1108347140, 821280, 21316608, -2144335872, 65}), + new BitArray(new int[] {4, 1140850688, 8388975, 1108347140, 821280, 21316608, -2144335872, 65}), + new BitArray(new int[] {5242880, -2147483550, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {5242880, -2147483552, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {-2, -1, -3, -1, -134217729, -1, -1, -1}), + new BitArray(new int[] {7, 1157628162, 26477055, -493212676, 948758565, 2147308999, -533262382, 3395}), + new BitArray(new int[] {918528, 0, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {-909310, -1258291209, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {-843774, -1258291209, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {-318462, -1258291209, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {-383998, -1258291209, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {-1038334, -1258291209, 65, 1074825472, 72844320, 231424, 22030368, 4160}), + new BitArray(new int[] {4194308, 1140850754, 8650975, 1108355356, 9218084, 17106176, -533656048, 67}), + new BitArray(new int[] {4, 1140851008, 8388975, 1108347140, 821280, 21317120, -2144335872, 65}), + new BitArray(new int[] {4, 1073741824, 8388687, 34605312, 822304, 17105920, -2144335872, 65}), + new BitArray(new int[] {4, 1073741824, 8388687, 34605312, 821280, 16843776, -2144335872, 65}), + new BitArray(new int[] {4, 1140850698, 9699551, 1108355356, 9218084, 17106180, -533524976, 67}), + new BitArray(new int[] {4, 1140850690, 9699551, 1108355356, 9218084, 17106180, -533524976, 67}), + new BitArray(new int[] {4, 1140850946, 8650975, 1108355356, 9218084, 17106176, -533656048, 67}), + new BitArray(new int[] {4, 1140850944, 8388687, 1108478212, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {4, 1140850944, 8388687, 1108347140, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {4, 1140850944, 26214479, -493220892, 671930656, 1606227138, -2143942272, 3393}), + new BitArray(new int[] {4, 1140850944, 26214479, -493220892, 671926560, 1606227138, -2143942272, 3393}), + new BitArray(new int[] {4, 1140850944, 26214479, -493220892, 671926304, 1606227138, -2143942272, 3393}), + new BitArray(new int[] {4, 1140850944, 26214479, -493351964, 671926304, 1606227138, -2143942272, 3393}), + new BitArray(new int[] {4, 1140850688, 26214479, -493351964, 671926304, 1606227138, -2143942272, 3393}), + new BitArray(new int[] {4, 1140850688, 26214479, -1030223452, 135055392, 84218880, -2143942656, 65}), + new BitArray(new int[] {4, 1140850688, 25165903, -1030747868, 821280, 84218880, -2144073728, 65}), + new BitArray(new int[] {3145730, -2147483616, 0, 0, 256, 0, 0, 0}), + new BitArray(new int[] {3145730, -2147483648, 0, 0, 256, 0, 0, 0}), + new BitArray(new int[] {3145730, 0, 0, 0, 256, 0, 0, 0}), + new BitArray(new int[] {4, 1140850944, 26214479, -493220892, 671926305, 1606227138, -2143942208, 3393}), + new BitArray(new int[] {0, 256, 0, 537001984, 1, 436207616, 64, 0}), + new BitArray(new int[] {0, 256, 0, 536870912, 1, 436207616, 64, 0}), + new BitArray(new int[] {0, 0, 0, 536870912, 1, 436207616, 64, 0}), + new BitArray(new int[] {7340034, 0, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {4, 1140850946, 8650975, 1108355356, 9218084, 17106180, -533656048, 67}), + new BitArray(new int[] {0, 16777472, 0, 131072, 0, 536870912, 2, 0}), + new BitArray(new int[] {0, 16777472, 0, 0, 0, 536870912, 2, 0}), + new BitArray(new int[] {2097154, -2147483616, 0, 0, 256, 0, 0, 0}), + new BitArray(new int[] {0, 1073741824, 4, -2147483648, 0, 0, -2147221504, 0}), + new BitArray(new int[] {2097154, -2013265888, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {2097154, -2147483616, 0, 0, 320, 0, 0, 0}), + new BitArray(new int[] {2097154, 0, 0, 0, 320, 0, 0, 0}), + new BitArray(new int[] {4, 1140850690, 8650975, 1108355356, -1030969308, 17106176, -533656048, 67}), + new BitArray(new int[] {4, 1140850688, 25165903, 1108347136, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {4, 1140850688, 8388687, 1108347136, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {7340034, -2147483614, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {7340034, -2147483616, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {0, 256, 1048576, 537526400, 402669568, 444596289, 131200, 0}), + new BitArray(new int[] {1028, 1140850688, 8650975, 1108355356, 9218084, 17106176, -533656048, 67}), + new BitArray(new int[] {74448898, 32, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {74448898, 0, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {0, 0, 8388608, 33554432, 2048, 0, 32768, 0}), + new BitArray(new int[] {2097154, 0, 0, 0, 0, 3072, 0, 0}), + new BitArray(new int[] {0, 0, 0, 536870912, 268435456, 444596288, 128, 0}), + new BitArray(new int[] {0, 0, 0, 536871488, 536870912, 1522008258, 384, 3328}), + new BitArray(new int[] {0, 0, 262288, 8216, 8396800, 256, 1610679824, 2}), + new BitArray(new int[] {-1073741824, 33554432, 0, 0, 0, 16, 0, 0}), + new BitArray(new int[] {1006632960, 0, 0, 0, 0, 0, 0, 0}), + new BitArray(new int[] {1016, 0, 0, 67108864, -1040187392, 32, 33554432, 0}), + new BitArray(new int[] {4, 1073741824, 8388687, 34605312, 821280, 17105920, -2144335872, 65}), + new BitArray(new int[] {0, 0, -1133776896, 3, 0, 0, 0, 0}), + new BitArray(new int[] {-64092162, 1191182376, -1051937, -680378597, -1030969166, -1593504460, -21144002, 8903}), + new BitArray(new int[] {0, 0, 33554432, 16777216, 16, 0, 16392, 0}), + new BitArray(new int[] {-66189316, 1174405160, -51383585, -972018405, -1030969182, 17106228, -97186288, 8259}), + new BitArray(new int[] {1048576, 3968, 0, 0, 65536, 0, 0, 0}), + new BitArray(new int[] {0, 0, 288, 0, 0, 4210688, 0, 0}), + new BitArray(new int[] {-2, -129, -3, -1, -134217729, -1, -1, -1}), + new BitArray(new int[] {-18434, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-22530, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-32770, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-37890, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-2050, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {-6146, -1, -1, -1, -1, -1, -1, -1}), + new BitArray(new int[] {4, 1140850944, 8388975, 1108347140, 821280, 21317120, -2144335872, 65}), + new BitArray(new int[] {0, 0, 0, 536870912, 0, 436207616, 0, 0}), + new BitArray(new int[] {2097154, 32, 0, 0, 256, 0, 0, 0}), + new BitArray(new int[] {4, 1140850688, 8650975, 1108355356, 9218084, 17106176, -533656048, 67}) + + }; + +} // end Parser + + +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/PushParser.frame b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/PushParser.frame new file mode 100644 index 0000000000..2e7fcca080 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/PushParser.frame @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------- +Compiler Generator Coco/R, +Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz +extended by M. Loeberbauer & A. Woess, Univ. of Linz +with improvements by Pat Terry, Rhodes University + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +As an exception, it is allowed to write an extension of Coco/R that is +used as a plugin in non-free software. + +If not otherwise stated, any source code generated by Coco/R (other than +Coco/R itself) does not fall under the GNU General Public License. +----------------------------------------------------------------------*/ +-->begin +-->namespace + +partial class ExpressionFinder { +-->constants + const bool T = true; + const bool x = false; + +-->declarations + readonly Stack stateStack = new Stack(); + bool wasQualifierTokenAtStart = false; + bool nextTokenIsPotentialStartOfExpression = false; + bool readXmlIdentifier = false; + bool identifierExpected = false; + bool nextTokenIsStartOfImportsOrAccessExpression = false; + bool isMissingModifier = false; + bool isAlreadyInExpr = false; + bool wasNormalAttribute = false; + int activeArgument = 0; + List errors = new List(); + + public ExpressionFinder() + { + stateStack.Push(-1); // required so that we don't crash when leaving the root production + } + + void Expect(int expectedKind, Token la) + { + if (la.kind != expectedKind) { + Error(la); + output.AppendLine("expected: " + expectedKind); + //Console.WriteLine("expected: " + expectedKind); + } + } + + void Error(Token la) + { + output.AppendLine("not expected: " + la); + //Console.WriteLine("not expected: " + la); + errors.Add(la); + } + + Token t; + + public void InformToken(Token la) + { + -->informToken + if (la != null) { + t = la; + nextTokenIsPotentialStartOfExpression = false; + readXmlIdentifier = false; + nextTokenIsStartOfImportsOrAccessExpression = false; + wasQualifierTokenAtStart = false; + identifierExpected = false; + } + } + + public void Advance() + { + //Console.WriteLine("Advance"); + InformToken(null); + } + + public BitArray GetExpectedSet() { return GetExpectedSet(currentState); } + + static readonly BitArray[] set = { +-->initialization + }; + +} // end Parser + + +$$$ \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs new file mode 100644 index 0000000000..f3ee77a93f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs @@ -0,0 +1,20 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public class SavepointEventArgs : EventArgs + { + public AstLocation SavepointLocation { get; private set; } + public VBLexerMemento State { get; private set; } + + public SavepointEventArgs(AstLocation savepointLocation, VBLexerMemento state) + { + this.SavepointLocation = savepointLocation; + this.State = state; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs new file mode 100644 index 0000000000..5120bd7650 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs @@ -0,0 +1,19 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB +{ +// public class BlankLine : AbstractSpecial +// { +// public BlankLine(Location point) : base(point) +// { +// } +// +// public override object AcceptVisitor(ISpecialVisitor visitor, object data) +// { +// return visitor.Visit(this, data); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs new file mode 100644 index 0000000000..82772f2d42 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs @@ -0,0 +1,59 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB +{ +// public class Comment : AbstractSpecial +// { +// CommentType commentType; +// string comment; +// +// public CommentType CommentType { +// get { +// return commentType; +// } +// set { +// commentType = value; +// } +// } +// +// public string CommentText { +// get { +// return comment; +// } +// set { +// comment = value; +// } +// } +// +// /// +// /// Is true, when the comment is at line start or only whitespaces +// /// between line and comment start. +// /// +// public bool CommentStartsLine { +// get; +// set; +// } +// +// public Comment(CommentType commentType, string comment, bool commentStartsLine, Location startPosition, Location endPosition) +// : base(startPosition, endPosition) +// { +// this.commentType = commentType; +// this.comment = comment; +// this.CommentStartsLine = commentStartsLine; +// } +// +// public override string ToString() +// { +// return String.Format("[{0}: Type = {1}, Text = {2}, Start = {3}, End = {4}]", +// GetType().Name, CommentType, CommentText, StartPosition, EndPosition); +// } +// +// public override object AcceptVisitor(ISpecialVisitor visitor, object data) +// { +// return visitor.Visit(this, data); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs new file mode 100644 index 0000000000..1c9bb63e92 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs @@ -0,0 +1,14 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB +{ +// public enum CommentType +// { +// Block, +// SingleLine, +// Documentation +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs new file mode 100644 index 0000000000..a589642112 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB +{ +// /// +// /// Interface for all specials. +// /// +// public interface ISpecial +// { +// Location StartPosition { get; } +// Location EndPosition { get; } +// +// object AcceptVisitor(ISpecialVisitor visitor, object data); +// } +// +// public interface ISpecialVisitor +// { +// object Visit(ISpecial special, object data); +// object Visit(BlankLine special, object data); +// object Visit(Comment special, object data); +// object Visit(PreprocessingDirective special, object data); +// } +// +// public abstract class AbstractSpecial : ISpecial +// { +// public abstract object AcceptVisitor(ISpecialVisitor visitor, object data); +// +// protected AbstractSpecial(Location position) +// { +// this.StartPosition = position; +// this.EndPosition = position; +// } +// +// protected AbstractSpecial(Location startPosition, Location endPosition) +// { +// this.StartPosition = startPosition; +// this.EndPosition = endPosition; +// } +// +// public Location StartPosition { get; set; } +// public Location EndPosition { get; set; } +// +// public override string ToString() +// { +// return String.Format("[{0}: Start = {1}, End = {2}]", +// GetType().Name, StartPosition, EndPosition); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs new file mode 100644 index 0000000000..97c0a7481a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs @@ -0,0 +1,156 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB +{ +// public class PreprocessingDirective : AbstractSpecial +// { +// #region Conversion C# <-> VB +// public static void VBToCSharp(IList list) +// { +// for (int i = 0; i < list.Count; ++i) { +// if (list[i] is PreprocessingDirective) +// list[i] = VBToCSharp((PreprocessingDirective)list[i]); +// } +// } +// +// public static PreprocessingDirective VBToCSharp(PreprocessingDirective dir) +// { +// string cmd = dir.Cmd; +// string arg = dir.Arg; +// if (cmd.Equals("#End", StringComparison.InvariantCultureIgnoreCase)) { +// if (arg.ToLowerInvariant().StartsWith("region")) { +// cmd = "#endregion"; +// arg = ""; +// } else if ("if".Equals(arg, StringComparison.InvariantCultureIgnoreCase)) { +// cmd = "#endif"; +// arg = ""; +// } +// } else if (cmd.Equals("#Region", StringComparison.InvariantCultureIgnoreCase)) { +// cmd = "#region"; +// } else if (cmd.Equals("#If", StringComparison.InvariantCultureIgnoreCase)) { +// cmd = "#if"; +// if (arg.ToLowerInvariant().EndsWith(" then")) +// arg = arg.Substring(0, arg.Length - 5); +// } else if (cmd.Equals("#Else", StringComparison.InvariantCultureIgnoreCase)) { +// if (dir.Expression != null) +// cmd = "#elif"; +// else +// cmd = "#else"; +// } else if (cmd.Equals("#ElseIf", StringComparison.InvariantCultureIgnoreCase)) { +// cmd = "#elif"; +// } +// return new PreprocessingDirective(cmd, arg, dir.StartPosition, dir.EndPosition) { +// Expression = dir.Expression +// }; +// } +// +// public static void CSharpToVB(List list) +// { +// for (int i = 0; i < list.Count; ++i) { +// if (list[i] is PreprocessingDirective) +// list[i] = CSharpToVB((PreprocessingDirective)list[i]); +// } +// } +// +// public static PreprocessingDirective CSharpToVB(PreprocessingDirective dir) +// { +// string cmd = dir.Cmd; +// string arg = dir.Arg; +// switch (cmd) { +// case "#region": +// cmd = "#Region"; +// if (!arg.StartsWith("\"")) { +// arg = "\"" + arg.Trim() + "\""; +// } +// break; +// case "#endregion": +// cmd = "#End"; +// arg = "Region"; +// break; +// case "#endif": +// cmd = "#End"; +// arg = "If"; +// break; +// case "#if": +// arg += " Then"; +// break; +// } +// if (cmd.Length > 1) { +// cmd = cmd.Substring(0, 2).ToUpperInvariant() + cmd.Substring(2); +// } +// return new PreprocessingDirective(cmd, arg, dir.StartPosition, dir.EndPosition) { +// Expression = dir.Expression +// }; +// } +// #endregion +// +// string cmd; +// string arg; +// Ast.Expression expression = Ast.Expression.Null; +// +// /// +// /// Gets the directive name, including '#'. +// /// +// public string Cmd { +// get { +// return cmd; +// } +// set { +// cmd = value ?? string.Empty; +// } +// } +// +// /// +// /// Gets the directive argument. +// /// +// public string Arg { +// get { +// return arg; +// } +// set { +// arg = value ?? string.Empty; +// } +// } +// +// /// +// /// Gets/sets the expression (for directives that take an expression, e.g. #if and #elif). +// /// +// public Ast.Expression Expression { +// get { return expression; } +// set { expression = value ?? Ast.Expression.Null; } +// } +// +// /// +// /// The end position of the pre processor directive line. +// /// May be != EndPosition. +// /// +// public Location LastLineEnd { +// get; +// set; +// } +// +// +// public override string ToString() +// { +// return String.Format("[PreProcessingDirective: Cmd = {0}, Arg = {1}]", +// Cmd, +// Arg); +// } +// +// public PreprocessingDirective(string cmd, string arg, Location start, Location end) +// : base(start, end) +// { +// this.Cmd = cmd; +// this.Arg = arg; +// } +// +// public override object AcceptVisitor(ISpecialVisitor visitor, object data) +// { +// return visitor.Visit(this, data); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs new file mode 100644 index 0000000000..2107163e4c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs @@ -0,0 +1,71 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Parser +{ +// public class SpecialTracker +// { +// List currentSpecials = new List(); +// +// CommentType currentCommentType; +// StringBuilder sb = new StringBuilder(); +// Location startPosition; +// bool commentStartsLine; +// +// public List CurrentSpecials { +// get { +// return currentSpecials; +// } +// } +// +// /// +// /// Gets the specials from the SpecialTracker and resets the lists. +// /// +// public List RetrieveSpecials() +// { +// List tmp = currentSpecials; +// currentSpecials = new List(); +// return tmp; +// } +// +// public void AddEndOfLine(Location point) +// { +// currentSpecials.Add(new BlankLine(point)); +// } +// +// public void AddPreprocessingDirective(PreprocessingDirective directive) +// { +// if (directive == null) +// throw new ArgumentNullException("directive"); +// currentSpecials.Add(directive); +// } +// +// // used for comment tracking +// public void StartComment(CommentType commentType, bool commentStartsLine, Location startPosition) +// { +// this.currentCommentType = commentType; +// this.startPosition = startPosition; +// this.sb.Length = 0; +// this.commentStartsLine = commentStartsLine; +// } +// +// public void AddChar(char c) +// { +// sb.Append(c); +// } +// +// public void AddString(string s) +// { +// sb.Append(s); +// } +// +// public void FinishComment(Location endPosition) +// { +// currentSpecials.Add(new Comment(currentCommentType, sb.ToString(), commentStartsLine, startPosition, endPosition)); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs new file mode 100644 index 0000000000..3209cf162e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + /// + /// Description of TagComment. + /// +// public class TagComment : Comment +// { +// string tag; +// +// public string Tag { +// get { +// return tag; +// } +// set { +// tag = value; +// } +// } +// +// public TagComment(string tag, string comment, bool commentStartsLine, Location startPosition, Location endPosition) : base(CommentType.SingleLine, comment, commentStartsLine, startPosition, endPosition) +// { +// this.tag = tag; +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Token.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Token.cs new file mode 100644 index 0000000000..ae4ed7d63e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Token.cs @@ -0,0 +1,93 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public class Token + { + internal readonly int kind; + + internal readonly int col; + internal readonly int line; + + internal readonly object literalValue; + internal readonly string val; + internal Token next; + readonly AstLocation endLocation; + + public int Kind { + get { return kind; } + } + + public object LiteralValue { + get { return literalValue; } + } + + public string Value { + get { return val; } + } + + public AstLocation EndLocation { + get { return endLocation; } + } + + public AstLocation Location { + get { + return new AstLocation(line, col); + } + } + + public Token() + : this(0, 1, 1) + { + } + + public Token(int kind, int col, int line) : this (kind, col, line, null) + { + } + + public Token(int kind, AstLocation startLocation, AstLocation endLocation) : this(kind, startLocation, endLocation, "", null) + { + } + + public Token(int kind, int col, int line, string val) + { + this.kind = kind; + this.col = col; + this.line = line; + this.val = val; + this.endLocation = new AstLocation(line, col + (val == null ? 1 : val.Length)); + } + + internal Token(int kind, int x, int y, string val, object literalValue) + : this(kind, new AstLocation(y, x), new AstLocation(y, x + val.Length), val, literalValue) + { + } + + public Token(int kind, AstLocation startLocation, AstLocation endLocation, string val, object literalValue) + { + this.kind = kind; + this.col = startLocation.Column; + this.line = startLocation.Line; + this.endLocation = endLocation; + this.val = val; + this.literalValue = literalValue; + } + + public override string ToString() + { + string vbToken; + + try { + vbToken = Tokens.GetTokenString(kind); + } catch (NotSupportedException) { + vbToken = ""; + } + + return string.Format("[Token {0} Location={1} EndLocation={2} val={3}]", + vbToken, Location, EndLocation, val); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Tokens.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Tokens.cs new file mode 100644 index 0000000000..484534a156 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/Tokens.cs @@ -0,0 +1,527 @@ +// this file was autogenerated by a tool. +using System; +using System.Collections; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public static class Tokens + { + // ----- terminal classes ----- + public const int EOF = 0; + public const int EOL = 1; + public const int Identifier = 2; + public const int LiteralString = 3; + public const int LiteralCharacter = 4; + public const int LiteralInteger = 5; + public const int LiteralDouble = 6; + public const int LiteralSingle = 7; + public const int LiteralDecimal = 8; + public const int LiteralDate = 9; + public const int XmlOpenTag = 10; + public const int XmlCloseTag = 11; + public const int XmlStartInlineVB = 12; + public const int XmlEndInlineVB = 13; + public const int XmlCloseTagEmptyElement = 14; + public const int XmlOpenEndTag = 15; + public const int XmlContent = 16; + public const int XmlComment = 17; + public const int XmlCData = 18; + public const int XmlProcessingInstruction = 19; + + // ----- special character ----- + public const int Assign = 20; + public const int Colon = 21; + public const int Comma = 22; + public const int ConcatString = 23; + public const int Div = 24; + public const int DivInteger = 25; + public const int Dot = 26; + public const int TripleDot = 27; + public const int DotAt = 28; + public const int ExclamationMark = 29; + public const int Minus = 30; + public const int Plus = 31; + public const int Power = 32; + public const int QuestionMark = 33; + public const int Times = 34; + public const int OpenCurlyBrace = 35; + public const int CloseCurlyBrace = 36; + public const int OpenParenthesis = 37; + public const int CloseParenthesis = 38; + public const int GreaterThan = 39; + public const int LessThan = 40; + public const int NotEqual = 41; + public const int GreaterEqual = 42; + public const int LessEqual = 43; + public const int ShiftLeft = 44; + public const int ShiftRight = 45; + public const int PlusAssign = 46; + public const int PowerAssign = 47; + public const int MinusAssign = 48; + public const int TimesAssign = 49; + public const int DivAssign = 50; + public const int DivIntegerAssign = 51; + public const int ShiftLeftAssign = 52; + public const int ShiftRightAssign = 53; + public const int ConcatStringAssign = 54; + public const int ColonAssign = 55; + + // ----- keywords ----- + public const int AddHandler = 56; + public const int AddressOf = 57; + public const int Aggregate = 58; + public const int Alias = 59; + public const int And = 60; + public const int AndAlso = 61; + public const int Ansi = 62; + public const int As = 63; + public const int Ascending = 64; + public const int Assembly = 65; + public const int Auto = 66; + public const int Binary = 67; + public const int Boolean = 68; + public const int ByRef = 69; + public const int By = 70; + public const int Byte = 71; + public const int ByVal = 72; + public const int Call = 73; + public const int Case = 74; + public const int Catch = 75; + public const int CBool = 76; + public const int CByte = 77; + public const int CChar = 78; + public const int CDate = 79; + public const int CDbl = 80; + public const int CDec = 81; + public const int Char = 82; + public const int CInt = 83; + public const int Class = 84; + public const int CLng = 85; + public const int CObj = 86; + public const int Compare = 87; + public const int Const = 88; + public const int Continue = 89; + public const int CSByte = 90; + public const int CShort = 91; + public const int CSng = 92; + public const int CStr = 93; + public const int CType = 94; + public const int CUInt = 95; + public const int CULng = 96; + public const int CUShort = 97; + public const int Custom = 98; + public const int Date = 99; + public const int Decimal = 100; + public const int Declare = 101; + public const int Default = 102; + public const int Delegate = 103; + public const int Descending = 104; + public const int Dim = 105; + public const int DirectCast = 106; + public const int Distinct = 107; + public const int Do = 108; + public const int Double = 109; + public const int Each = 110; + public const int Else = 111; + public const int ElseIf = 112; + public const int End = 113; + public const int EndIf = 114; + public const int Enum = 115; + new public const int Equals = 116; + public const int Erase = 117; + public const int Error = 118; + public const int Event = 119; + public const int Exit = 120; + public const int Explicit = 121; + public const int False = 122; + public const int Finally = 123; + public const int For = 124; + public const int Friend = 125; + public const int From = 126; + public const int Function = 127; + public const int Get = 128; + new public const int GetType = 129; + public const int Global = 130; + public const int GoSub = 131; + public const int GoTo = 132; + public const int Group = 133; + public const int Handles = 134; + public const int If = 135; + public const int Implements = 136; + public const int Imports = 137; + public const int In = 138; + public const int Infer = 139; + public const int Inherits = 140; + public const int Integer = 141; + public const int Interface = 142; + public const int Into = 143; + public const int Is = 144; + public const int IsNot = 145; + public const int Join = 146; + public const int Key = 147; + public const int Let = 148; + public const int Lib = 149; + public const int Like = 150; + public const int Long = 151; + public const int Loop = 152; + public const int Me = 153; + public const int Mod = 154; + public const int Module = 155; + public const int MustInherit = 156; + public const int MustOverride = 157; + public const int MyBase = 158; + public const int MyClass = 159; + public const int Namespace = 160; + public const int Narrowing = 161; + public const int New = 162; + public const int Next = 163; + public const int Not = 164; + public const int Nothing = 165; + public const int NotInheritable = 166; + public const int NotOverridable = 167; + public const int Object = 168; + public const int Of = 169; + public const int Off = 170; + public const int On = 171; + public const int Operator = 172; + public const int Option = 173; + public const int Optional = 174; + public const int Or = 175; + public const int Order = 176; + public const int OrElse = 177; + public const int Out = 178; + public const int Overloads = 179; + public const int Overridable = 180; + public const int Overrides = 181; + public const int ParamArray = 182; + public const int Partial = 183; + public const int Preserve = 184; + public const int Private = 185; + public const int Property = 186; + public const int Protected = 187; + public const int Public = 188; + public const int RaiseEvent = 189; + public const int ReadOnly = 190; + public const int ReDim = 191; + public const int Rem = 192; + public const int RemoveHandler = 193; + public const int Resume = 194; + public const int Return = 195; + public const int SByte = 196; + public const int Select = 197; + public const int Set = 198; + public const int Shadows = 199; + public const int Shared = 200; + public const int Short = 201; + public const int Single = 202; + public const int Skip = 203; + public const int Static = 204; + public const int Step = 205; + public const int Stop = 206; + public const int Strict = 207; + public const int String = 208; + public const int Structure = 209; + public const int Sub = 210; + public const int SyncLock = 211; + public const int Take = 212; + public const int Text = 213; + public const int Then = 214; + public const int Throw = 215; + public const int To = 216; + public const int True = 217; + public const int Try = 218; + public const int TryCast = 219; + public const int TypeOf = 220; + public const int UInteger = 221; + public const int ULong = 222; + public const int Unicode = 223; + public const int Until = 224; + public const int UShort = 225; + public const int Using = 226; + public const int Variant = 227; + public const int Wend = 228; + public const int When = 229; + public const int Where = 230; + public const int While = 231; + public const int Widening = 232; + public const int With = 233; + public const int WithEvents = 234; + public const int WriteOnly = 235; + public const int Xor = 236; + public const int GetXmlNamespace = 237; + + public const int MaxToken = 238; + static BitArray NewSet(params int[] values) + { + BitArray bitArray = new BitArray(MaxToken); + foreach (int val in values) { + bitArray[val] = true; + } + return bitArray; + } + public static BitArray Null = NewSet(Nothing); + public static BitArray BlockSucc = NewSet(Case, Catch, Else, ElseIf, End, Finally, Loop, Next); + public static BitArray GlobalLevel = NewSet(Namespace, Module, Class, Structure, Imports, Option); + public static BitArray TypeLevel = NewSet(Sub, Function, Property); + public static BitArray IdentifierTokens = NewSet(Text, Binary, Compare, Assembly, Ansi, Auto, Preserve, Unicode, Until, Off, Out, Key, Explicit, Infer, From, Join, Equals, Distinct, Where, Take, Skip, Order, By, Ascending, Descending, Group, Into, Aggregate); + public static BitArray ExpressionStart = NewSet(Me, MyBase, MyClass, True, False, Not, From, Aggregate, New, Nothing, AddressOf, GetType, TypeOf, GetXmlNamespace, Global, Boolean, Date, Char, String, Decimal, Byte, Short, Integer, Long, Single, Double, UInteger, ULong, UShort, SByte, Sub, Function, DirectCast, TryCast, CType, CBool, CByte, CChar, CDate, CDec, CDbl, CInt, CLng, CObj, CSByte, CShort, CSng, CStr, CUInt, CULng, CUShort); + public static BitArray StatementStart = NewSet(Nothing, Me, MyBase, MyClass, True, False, Not, From, Aggregate, New, Nothing, AddressOf, GetType, TypeOf, GetXmlNamespace, Global, Boolean, Date, Char, String, Decimal, Byte, Short, Integer, Long, Single, Double, UInteger, ULong, UShort, SByte, Sub, Function, DirectCast, TryCast, CType, CBool, CByte, CChar, CDate, CDec, CDbl, CInt, CLng, CObj, CSByte, CShort, CSng, CStr, CUInt, CULng, CUShort, Dim, Const, Static, For, While, Do, Select); + public static BitArray SimpleTypeName = NewSet(Boolean, Date, Char, String, Decimal, Byte, Short, Integer, Long, Single, Double, UInteger, ULong, UShort, SByte, Text, Binary, Compare, Assembly, Ansi, Auto, Preserve, Unicode, Until, Off, Out, Key, Explicit, Infer, From, Join, Equals, Distinct, Where, Take, Skip, Order, By, Ascending, Descending, Group, Into, Aggregate); + public static BitArray CastExpressions = NewSet(DirectCast, TryCast, CType, CBool, CByte, CChar, CDate, CDec, CDbl, CInt, CLng, CObj, CSByte, CShort, CSng, CStr, CUInt, CULng, CUShort); + public static BitArray BooleanExpressions = NewSet(True, False); + public static BitArray LambdaStart = NewSet(Sub, Function); + public static BitArray OperatorsAtStart = NewSet(Not, From, Aggregate); + public static BitArray TypeKW = NewSet(Boolean, Date, Char, String, Decimal, Byte, Short, Integer, Long, Single, Double, UInteger, ULong, UShort, SByte); + + static string[] tokenList = new string[] { + // ----- terminal classes ----- + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + // ----- special character ----- + "=", + ":", + ",", + "&", + "/", + "\\", + ".", + "...", + ".@", + "!", + "-", + "+", + "^", + "?", + "*", + "{", + "}", + "(", + ")", + ">", + "<", + "<>", + ">=", + "<=", + "<<", + ">>", + "+=", + "^=", + "-=", + "*=", + "/=", + "\\=", + "<<=", + ">>=", + "&=", + ":=", + // ----- keywords ----- + "AddHandler", + "AddressOf", + "Aggregate", + "Alias", + "And", + "AndAlso", + "Ansi", + "As", + "Ascending", + "Assembly", + "Auto", + "Binary", + "Boolean", + "ByRef", + "By", + "Byte", + "ByVal", + "Call", + "Case", + "Catch", + "CBool", + "CByte", + "CChar", + "CDate", + "CDbl", + "CDec", + "Char", + "CInt", + "Class", + "CLng", + "CObj", + "Compare", + "Const", + "Continue", + "CSByte", + "CShort", + "CSng", + "CStr", + "CType", + "CUInt", + "CULng", + "CUShort", + "Custom", + "Date", + "Decimal", + "Declare", + "Default", + "Delegate", + "Descending", + "Dim", + "DirectCast", + "Distinct", + "Do", + "Double", + "Each", + "Else", + "ElseIf", + "End", + "EndIf", + "Enum", + "Equals", + "Erase", + "Error", + "Event", + "Exit", + "Explicit", + "False", + "Finally", + "For", + "Friend", + "From", + "Function", + "Get", + "GetType", + "Global", + "GoSub", + "GoTo", + "Group", + "Handles", + "If", + "Implements", + "Imports", + "In", + "Infer", + "Inherits", + "Integer", + "Interface", + "Into", + "Is", + "IsNot", + "Join", + "Key", + "Let", + "Lib", + "Like", + "Long", + "Loop", + "Me", + "Mod", + "Module", + "MustInherit", + "MustOverride", + "MyBase", + "MyClass", + "Namespace", + "Narrowing", + "New", + "Next", + "Not", + "Nothing", + "NotInheritable", + "NotOverridable", + "Object", + "Of", + "Off", + "On", + "Operator", + "Option", + "Optional", + "Or", + "Order", + "OrElse", + "Out", + "Overloads", + "Overridable", + "Overrides", + "ParamArray", + "Partial", + "Preserve", + "Private", + "Property", + "Protected", + "Public", + "RaiseEvent", + "ReadOnly", + "ReDim", + "Rem", + "RemoveHandler", + "Resume", + "Return", + "SByte", + "Select", + "Set", + "Shadows", + "Shared", + "Short", + "Single", + "Skip", + "Static", + "Step", + "Stop", + "Strict", + "String", + "Structure", + "Sub", + "SyncLock", + "Take", + "Text", + "Then", + "Throw", + "To", + "True", + "Try", + "TryCast", + "TypeOf", + "UInteger", + "ULong", + "Unicode", + "Until", + "UShort", + "Using", + "Variant", + "Wend", + "When", + "Where", + "While", + "Widening", + "With", + "WithEvents", + "WriteOnly", + "Xor", + "GetXmlNamespace", + }; + public static string GetTokenString(int token) + { + if (token >= 0 && token < tokenList.Length) { + return tokenList[token]; + } + throw new System.NotSupportedException("Unknown token:" + token); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs new file mode 100644 index 0000000000..6aac502c21 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs @@ -0,0 +1,1487 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public class VBLexer : IDisposable + { + bool lineEnd = true; + bool isAtLineBegin = false; // TODO: handle line begin, if neccessarry + bool misreadExclamationMarkAsTypeCharacter; + bool encounteredLineContinuation; + + ExpressionFinder ef; + + bool inXmlMode; + + Stack xmlModeStack = new Stack(); + + public VBLexer(TextReader reader) + { + this.reader = new LATextReader(reader); + ef = new ExpressionFinder(); + } + + public VBLexer(TextReader reader, VBLexerMemento state) : this(reader) + { + SetInitialLocation(new AstLocation(state.Line, state.Column)); + lastToken = new Token(state.PrevTokenKind, 0, 0); + ef = new ExpressionFinder(state.ExpressionFinder); + lineEnd = state.LineEnd; + isAtLineBegin = state.IsAtLineBegin; + encounteredLineContinuation = state.EncounteredLineContinuation; + misreadExclamationMarkAsTypeCharacter = state.MisreadExclamationMarkAsTypeCharacter; + xmlModeStack = new Stack(state.XmlModeInfoStack.Select(i => (XmlModeInfo)i.Clone()).Reverse()); + inXmlMode = state.InXmlMode; + } + + Token NextInternal() + { + if (misreadExclamationMarkAsTypeCharacter) { + misreadExclamationMarkAsTypeCharacter = false; + return new Token(Tokens.ExclamationMark, Col - 1, Line); + } + + unchecked { + while (true) { + AstLocation startLocation = new AstLocation(Line, Col); + int nextChar = ReaderRead(); + if (nextChar == -1) + return new Token(Tokens.EOF, Col, Line, string.Empty); + char ch = (char)nextChar; + #region XML mode + CheckXMLState(startLocation); + if (inXmlMode && xmlModeStack.Peek().level <= 0 && !xmlModeStack.Peek().isDocumentStart && !xmlModeStack.Peek().inXmlTag) { + XmlModeInfo info = xmlModeStack.Peek(); + int peek = nextChar; + while (true) { + int step = -1; + while (peek != -1 && XmlConvert.IsWhitespaceChar((char)peek)) { + step++; + peek = ReaderPeek(step); + } + + if (peek == '<' && (ReaderPeek(step + 1) == '!' || ReaderPeek(step + 1) == '?')) { + char lastCh = '\0'; + for (int i = 0; i < step + 2; i++) + lastCh = (char)ReaderRead(); + + if (lastCh == '!') + return ReadXmlCommentOrCData(Col - 2, Line); + else + return ReadXmlProcessingInstruction(Col - 2, Line); + } + + break; + } + inXmlMode = false; + xmlModeStack.Pop(); + } + if (inXmlMode) { + XmlModeInfo info = xmlModeStack.Peek(); + int x = Col - 1; + int y = Line; + switch (ch) { + case '<': + if (ReaderPeek() == '/') { + ReaderRead(); + info.inXmlCloseTag = true; + return new Token(Tokens.XmlOpenEndTag, new AstLocation(y, x), new AstLocation(Line, Col)); + } + if (ReaderPeek() == '%' && ReaderPeek(1) == '=') { + inXmlMode = false; + ReaderRead(); ReaderRead(); + return new Token(Tokens.XmlStartInlineVB, new AstLocation(y, x), new AstLocation(Line, Col)); + } + if (ReaderPeek() == '?') { + ReaderRead(); + Token t = ReadXmlProcessingInstruction(x, y); + return t; + } + if (ReaderPeek() == '!') { + ReaderRead(); + Token token = ReadXmlCommentOrCData(x, y); + return token; + } + info.level++; + info.isDocumentStart = false; + info.inXmlTag = true; + return new Token(Tokens.XmlOpenTag, x, y); + case '/': + if (ReaderPeek() == '>') { + ReaderRead(); + info.inXmlTag = false; + info.level--; + return new Token(Tokens.XmlCloseTagEmptyElement, new AstLocation(y, x), new AstLocation(Line, Col)); + } + break; + case '>': + if (info.inXmlCloseTag) + info.level--; + info.inXmlTag = info.inXmlCloseTag = false; + return new Token(Tokens.XmlCloseTag, x, y); + case '=': + return new Token(Tokens.Assign, x, y); + case '\'': + case '"': + string s = ReadXmlString(ch); + return new Token(Tokens.LiteralString, x, y, ch + s + ch, s); + default: + if (info.inXmlCloseTag || info.inXmlTag) { + if (XmlConvert.IsWhitespaceChar(ch)) + continue; + return new Token(Tokens.Identifier, x, y, ReadXmlIdent(ch)); + } else { + string content = ReadXmlContent(ch); + return new Token(Tokens.XmlContent, startLocation, new AstLocation(Line, Col), content, null); + } + } + #endregion + } else { + #region Standard Mode + if (Char.IsWhiteSpace(ch)) { + if (HandleLineEnd(ch)) { + if (lineEnd) { + // second line end before getting to a token + // -> here was a blank line +// specialTracker.AddEndOfLine(startLocation); + } else { + lineEnd = true; + return new Token(Tokens.EOL, startLocation, new AstLocation(Line, Col), null, null); + } + } + continue; + } + if (ch == '_') { + if (ReaderPeek() == -1) { + errors.Error(Line, Col, String.Format("No EOF expected after _")); + return new Token(Tokens.EOF, Col, Line, string.Empty); + } + if (!Char.IsWhiteSpace((char)ReaderPeek())) { + int x = Col - 1; + int y = Line; + string s = ReadIdent('_'); + lineEnd = false; + return new Token(Tokens.Identifier, x, y, s); + } + encounteredLineContinuation = true; + ch = (char)ReaderRead(); + + bool oldLineEnd = lineEnd; + lineEnd = false; + while (Char.IsWhiteSpace(ch)) { + if (HandleLineEnd(ch)) { + lineEnd = true; + break; + } + if (ReaderPeek() != -1) { + ch = (char)ReaderRead(); + } else { + errors.Error(Line, Col, String.Format("No EOF expected after _")); + return new Token(Tokens.EOF, Col, Line, string.Empty); + } + } + if (!lineEnd) { + errors.Error(Line, Col, String.Format("NewLine expected")); + } + lineEnd = oldLineEnd; + continue; + } + + if (ch == '#') { + while (Char.IsWhiteSpace((char)ReaderPeek())) { + ReaderRead(); + } + if (Char.IsDigit((char)ReaderPeek())) { + int x = Col - 1; + int y = Line; + string s = ReadDate(); + DateTime time = new DateTime(1, 1, 1, 0, 0, 0); + try { + time = DateTime.Parse(s, System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault); + } catch (Exception e) { + errors.Error(Line, Col, String.Format("Invalid date time {0}", e)); + } + return new Token(Tokens.LiteralDate, x, y, s, time); + } else { + ReadPreprocessorDirective(); + continue; + } + } + + if (ch == '[') { // Identifier + lineEnd = false; + if (ReaderPeek() == -1) { + errors.Error(Line, Col, String.Format("Identifier expected")); + } + ch = (char)ReaderRead(); + if (ch == ']' || Char.IsWhiteSpace(ch)) { + errors.Error(Line, Col, String.Format("Identifier expected")); + } + int x = Col - 1; + int y = Line; + string s = ReadIdent(ch); + if (ReaderPeek() == -1) { + errors.Error(Line, Col, String.Format("']' expected")); + } + ch = (char)ReaderRead(); + if (!(ch == ']')) { + errors.Error(Line, Col, String.Format("']' expected")); + } + return new Token(Tokens.Identifier, x, y, s); + } + if (Char.IsLetter(ch)) { + int x = Col - 1; + int y = Line; + char typeCharacter; + string s = ReadIdent(ch, out typeCharacter); + if (typeCharacter == '\0') { + int keyWordToken = Keywords.GetToken(s); + if (keyWordToken >= 0) { + // handle 'REM' comments + if (keyWordToken == Tokens.Rem) { + ReadComment(); + if (!lineEnd) { + lineEnd = true; + return new Token(Tokens.EOL, Col, Line, "\n"); + } + continue; + } + + lineEnd = false; + return new Token(keyWordToken, x, y, s); + } + } + + lineEnd = false; + return new Token(Tokens.Identifier, x, y, s); + + } + if (Char.IsDigit(ch)) { + lineEnd = false; + return ReadDigit(ch, Col - 1); + } + if (ch == '&') { + lineEnd = false; + if (ReaderPeek() == -1) { + return ReadOperator('&'); + } + ch = (char)ReaderPeek(); + if (Char.ToUpper(ch, CultureInfo.InvariantCulture) == 'H' || Char.ToUpper(ch, CultureInfo.InvariantCulture) == 'O') { + return ReadDigit('&', Col - 1); + } + return ReadOperator('&'); + } + if (ch == '\'' || ch == '\u2018' || ch == '\u2019') { + int x = Col - 1; + int y = Line; + ReadComment(); + if (!lineEnd) { + lineEnd = true; + return new Token(Tokens.EOL, x, y, "\n"); + } + continue; + } + if (ch == '"') { + lineEnd = false; + int x = Col - 1; + int y = Line; + string s = ReadString(); + if (ReaderPeek() != -1 && (ReaderPeek() == 'C' || ReaderPeek() == 'c')) { + ReaderRead(); + if (s.Length != 1) { + errors.Error(Line, Col, String.Format("Chars can only have Length 1 ")); + } + if (s.Length == 0) { + s = "\0"; + } + return new Token(Tokens.LiteralCharacter, x, y, '"' + s + "\"C", s[0]); + } + return new Token(Tokens.LiteralString, x, y, '"' + s + '"', s); + } + if (ch == '%' && ReaderPeek() == '>') { + int x = Col - 1; + int y = Line; + inXmlMode = true; + ReaderRead(); + return new Token(Tokens.XmlEndInlineVB, new AstLocation(y, x), new AstLocation(Line, Col)); + } + #endregion + if (ch == '<' && (ef.NextTokenIsPotentialStartOfExpression || ef.NextTokenIsStartOfImportsOrAccessExpression)) { + xmlModeStack.Push(new XmlModeInfo(ef.NextTokenIsStartOfImportsOrAccessExpression)); + XmlModeInfo info = xmlModeStack.Peek(); + int x = Col - 1; + int y = Line; + inXmlMode = true; + if (ReaderPeek() == '/') { + ReaderRead(); + info.inXmlCloseTag = true; + return new Token(Tokens.XmlOpenEndTag, new AstLocation(y, x), new AstLocation(Line, Col)); + } + // should we allow <%= at start of an expression? not valid with vbc ... + if (ReaderPeek() == '%' && ReaderPeek(1) == '=') { + inXmlMode = false; + ReaderRead(); ReaderRead(); + return new Token(Tokens.XmlStartInlineVB, new AstLocation(y, x), new AstLocation(Line, Col)); + } + if (ReaderPeek() == '!') { + ReaderRead(); + Token t = ReadXmlCommentOrCData(x, y); + return t; + } + if (ReaderPeek() == '?') { + ReaderRead(); + Token t = ReadXmlProcessingInstruction(x, y); + info.isDocumentStart = t.val.Trim().StartsWith("xml", StringComparison.OrdinalIgnoreCase); + return t; + } + info.inXmlTag = true; + info.level++; + return new Token(Tokens.XmlOpenTag, x, y); + } + Token token = ReadOperator(ch); + if (token != null) { + lineEnd = false; + return token; + } + } + + errors.Error(Line, Col, String.Format("Unknown char({0}) which can't be read", ch)); + } + } + } + + void CheckXMLState(AstLocation startLocation) + { + if (inXmlMode && !xmlModeStack.Any()) + throw new InvalidOperationException("invalid XML stack state at " + startLocation); + } + + Token prevToken; + + Token Next() + { + Token t = NextInternal(); + if (t.kind == Tokens.EOL) { + Debug.Assert(t.next == null); // NextInternal() must return only 1 token + t.next = NextInternal(); + Debug.Assert(t.next.next == null); + if (SkipEOL(prevToken.kind, t.next.kind)) { + t = t.next; + } + } else + encounteredLineContinuation = false; + // inform EF only once we're sure it's really a token + // this means we inform it about EOL tokens "1 token too late", but that's not a problem because + // XML literals cannot start immediately after an EOL token + ef.InformToken(t); + if (t.next != null) { + // Next() isn't called again when it returns 2 tokens, so we need to process both tokens + ef.InformToken(t.next); + prevToken = t.next; + } else { + prevToken = t; + } + ef.Advance(); + Debug.Assert(t != null); + return t; + } + + /// see VB language specification 10; pg. 6 + bool SkipEOL(int prevTokenKind, int nextTokenKind) + { + // exception directly after _ + if (encounteredLineContinuation) { + return encounteredLineContinuation = false; + } + + // 1st rule + // after a comma (,), open parenthesis ((), open curly brace ({), or open embedded expression (<%=) + if (new[] { Tokens.Comma, Tokens.OpenParenthesis, Tokens.OpenCurlyBrace, Tokens.XmlStartInlineVB } + .Contains(prevTokenKind)) + return true; + + // 2nd rule + // after a member qualifier (. or .@ or ...), provided that something is being qualified (i.e. is not + // using an implicit With context) + if (new[] { Tokens.Dot, Tokens.DotAt, Tokens.TripleDot }.Contains(prevTokenKind) + && !ef.WasQualifierTokenAtStart) + return true; + + // 3rd rule + // before a close parenthesis ()), close curly brace (}), or close embedded expression (%>) + if (new[] { Tokens.CloseParenthesis, Tokens.CloseCurlyBrace, Tokens.XmlEndInlineVB } + .Contains(nextTokenKind)) + return true; + + // 4th rule + // after a less-than (<) in an attribute context + if (prevTokenKind == Tokens.LessThan && ef.InContext(Context.Attribute)) + return true; + + // 5th rule + // before a greater-than (>) in an attribute context + if (nextTokenKind == Tokens.GreaterThan && ef.InContext(Context.Attribute)) + return true; + + // 6th rule + // after a greater-than (>) in a non-file-level attribute context + if (ef.WasNormalAttribute && prevTokenKind == Tokens.GreaterThan) + return true; + + // 7th rule + // before and after query operators (Where, Order, Select, etc.) + var queryOperators = new int[] { Tokens.From, Tokens.Aggregate, Tokens.Select, Tokens.Distinct, + Tokens.Where, Tokens.Order, Tokens.By, Tokens.Ascending, Tokens.Descending, Tokens.Take, + Tokens.Skip, Tokens.Let, Tokens.Group, Tokens.Into, Tokens.On, Tokens.While, Tokens.Join }; + if (ef.InContext(Context.Query)) { + // Ascending, Descending, Distinct are special + // fixes http://community.sharpdevelop.net/forums/p/12068/32893.aspx#32893 + var specialQueryOperators = new int[] { Tokens.Ascending, Tokens.Descending, Tokens.Distinct }; + if (specialQueryOperators.Contains(prevTokenKind) && !queryOperators.Contains(nextTokenKind)) + return false; + + if ((queryOperators.Contains(prevTokenKind) || queryOperators.Contains(nextTokenKind))) + return true; + } + + // 8th rule + // after binary operators (+, -, /, *, etc.) in an expression context + if (new[] { Tokens.Plus, Tokens.Minus, Tokens.Div, Tokens.DivInteger, Tokens.Times, Tokens.Mod, Tokens.Power, + Tokens.Assign, Tokens.NotEqual, Tokens.LessThan, Tokens.LessEqual, Tokens.GreaterThan, Tokens.GreaterEqual, + Tokens.Like, Tokens.ConcatString, Tokens.AndAlso, Tokens.OrElse, Tokens.And, Tokens.Or, Tokens.Xor, + Tokens.ShiftLeft, Tokens.ShiftRight }.Contains(prevTokenKind) && ef.CurrentBlock.context == Context.Expression) + return true; + + // 9th rule + // after assignment operators (=, :=, +=, -=, etc.) in any context. + if (new[] { Tokens.Assign, Tokens.ColonAssign, Tokens.ConcatStringAssign, Tokens.DivAssign, + Tokens.DivIntegerAssign, Tokens.MinusAssign, Tokens.PlusAssign, Tokens.PowerAssign, + Tokens.ShiftLeftAssign, Tokens.ShiftRightAssign, Tokens.TimesAssign }.Contains(prevTokenKind)) + return true; + + return false; + } + + /// + /// Reads the next token. + /// + /// A object. + public Token NextToken() + { + if (curToken == null) { // first call of NextToken() + curToken = Next(); + //Console.WriteLine("Tok:" + Tokens.GetTokenString(curToken.kind) + " --- " + curToken.val); + return curToken; + } + + lastToken = curToken; + + if (curToken.next == null) { + curToken.next = Next(); + } + + curToken = curToken.next; + + if (curToken.kind == Tokens.EOF && !(lastToken.kind == Tokens.EOL)) { // be sure that before EOF there is an EOL token + curToken = new Token(Tokens.EOL, curToken.col, curToken.line, string.Empty); + curToken.next = new Token(Tokens.EOF, curToken.col, curToken.line, string.Empty); + } + //Console.WriteLine("Tok:" + Tokens.GetTokenString(curToken.kind) + " --- " + curToken.val); + return curToken; + } + + #region VB Readers + string ReadIdent(char ch) + { + char typeCharacter; + return ReadIdent(ch, out typeCharacter); + } + + string ReadIdent(char ch, out char typeCharacter) + { + typeCharacter = '\0'; + + if (ef.ReadXmlIdentifier) { + ef.ReadXmlIdentifier = false; + return ReadXmlIdent(ch); + } + + sb.Length = 0; + sb.Append(ch); + int peek; + while ((peek = ReaderPeek()) != -1 && (Char.IsLetterOrDigit(ch = (char)peek) || ch == '_')) { + ReaderRead(); + sb.Append(ch.ToString()); + } + if (peek == -1) { + return sb.ToString(); + } + + if ("%&@!#$".IndexOf((char)peek) != -1) { + typeCharacter = (char)peek; + ReaderRead(); + if (typeCharacter == '!') { + peek = ReaderPeek(); + if (peek != -1 && (peek == '_' || peek == '[' || char.IsLetter((char)peek))) { + misreadExclamationMarkAsTypeCharacter = true; + } + } + } + return sb.ToString(); + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1818:DoNotConcatenateStringsInsideLoops")] + Token ReadDigit(char ch, int x) + { + sb.Length = 0; + sb.Append(ch); + + int y = Line; + string digit = ""; + if (ch != '&') { + digit += ch; + } + + bool isHex = false; + bool isOct = false; + bool isSingle = false; + bool isDouble = false; + bool isDecimal = false; + + if (ReaderPeek() == -1) { + if (ch == '&') { + errors.Error(Line, Col, String.Format("digit expected")); + } + return new Token(Tokens.LiteralInteger, x, y, sb.ToString() ,ch - '0'); + } + if (ch == '.') { + if (Char.IsDigit((char)ReaderPeek())) { + isDouble = true; // double is default + if (isHex || isOct) { + errors.Error(Line, Col, String.Format("No hexadecimal or oktadecimal floating point values allowed")); + } + while (ReaderPeek() != -1 && Char.IsDigit((char)ReaderPeek())){ // read decimal digits beyond the dot + digit += (char)ReaderRead(); + } + } + } else if (ch == '&' && PeekUpperChar() == 'H') { + const string hex = "0123456789ABCDEF"; + sb.Append((char)ReaderRead()); // skip 'H' + while (ReaderPeek() != -1 && hex.IndexOf(PeekUpperChar()) != -1) { + ch = (char)ReaderRead(); + sb.Append(ch); + digit += Char.ToUpper(ch, CultureInfo.InvariantCulture); + } + isHex = true; + } else if (ReaderPeek() != -1 && ch == '&' && PeekUpperChar() == 'O') { + const string okt = "01234567"; + sb.Append((char)ReaderRead()); // skip 'O' + while (ReaderPeek() != -1 && okt.IndexOf(PeekUpperChar()) != -1) { + ch = (char)ReaderRead(); + sb.Append(ch); + digit += Char.ToUpper(ch, CultureInfo.InvariantCulture); + } + isOct = true; + } else { + while (ReaderPeek() != -1 && Char.IsDigit((char)ReaderPeek())) { + ch = (char)ReaderRead();; + digit += ch; + sb.Append(ch); + } + } + + if (digit.Length == 0) { + errors.Error(Line, Col, String.Format("digit expected")); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), 0); + } + + if (ReaderPeek() != -1 && "%&SILU".IndexOf(PeekUpperChar()) != -1 || isHex || isOct) { + bool unsigned = false; + if (ReaderPeek() != -1) { + ch = (char)ReaderPeek(); + sb.Append(ch); + ch = Char.ToUpper(ch, CultureInfo.InvariantCulture); + unsigned = ch == 'U'; + if (unsigned) { + ReaderRead(); // read the U + ch = (char)ReaderPeek(); + sb.Append(ch); + ch = Char.ToUpper(ch, CultureInfo.InvariantCulture); + if (ch != 'I' && ch != 'L' && ch != 'S') { + errors.Error(Line, Col, "Invalid type character: U" + ch); + } + } + } + try { + if (isOct) { + ReaderRead(); + ulong number = 0L; + for (int i = 0; i < digit.Length; ++i) { + number = number * 8 + digit[i] - '0'; + } + if (ch == 'S') { + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (ushort)number); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (short)number); + } else if (ch == '%' || ch == 'I') { + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (uint)number); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (int)number); + } else if (ch == '&' || ch == 'L') { + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (ulong)number); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), (long)number); + } else { + if (number > uint.MaxValue) { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((long)number)); + } else { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((int)number)); + } + } + } + if (ch == 'S') { + ReaderRead(); + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt16.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int16.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + } else if (ch == '%' || ch == 'I') { + ReaderRead(); + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt32.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int32.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + } else if (ch == '&' || ch == 'L') { + ReaderRead(); + if (unsigned) + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), UInt64.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + else + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int64.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + } else if (isHex) { + ulong number = UInt64.Parse(digit, NumberStyles.HexNumber); + if (number > uint.MaxValue) { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((long)number)); + } else { + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), unchecked((int)number)); + } + } + } catch (OverflowException ex) { + errors.Error(Line, Col, ex.Message); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), 0); + } catch (FormatException) { + errors.Error(Line, Col, String.Format("{0} is not a parseable number", digit)); + return new Token(Tokens.LiteralInteger, x, y, sb.ToString(), 0); + } + } + Token nextToken = null; // if we accidently read a 'dot' + if (!isDouble && ReaderPeek() == '.') { // read floating point number + ReaderRead(); + if (ReaderPeek() != -1 && Char.IsDigit((char)ReaderPeek())) { + isDouble = true; // double is default + if (isHex || isOct) { + errors.Error(Line, Col, String.Format("No hexadecimal or oktadecimal floating point values allowed")); + } + digit += '.'; + while (ReaderPeek() != -1 && Char.IsDigit((char)ReaderPeek())){ // read decimal digits beyond the dot + digit += (char)ReaderRead(); + } + } else { + nextToken = new Token(Tokens.Dot, Col - 1, Line); + } + } + + if (ReaderPeek() != -1 && PeekUpperChar() == 'E') { // read exponent + isDouble = true; + digit += (char)ReaderRead(); + if (ReaderPeek() != -1 && (ReaderPeek() == '-' || ReaderPeek() == '+')) { + digit += (char)ReaderRead(); + } + while (ReaderPeek() != -1 && Char.IsDigit((char)ReaderPeek())) { // read exponent value + digit += (char)ReaderRead(); + } + } + + if (ReaderPeek() != -1) { + switch (PeekUpperChar()) { + case 'R': + case '#': + ReaderRead(); + isDouble = true; + break; + case 'D': + case '@': + ReaderRead(); + isDecimal = true; + break; + case 'F': + case '!': + ReaderRead(); + isSingle = true; + break; + } + } + + try { + if (isSingle) { + return new Token(Tokens.LiteralSingle, x, y, sb.ToString(), Single.Parse(digit, CultureInfo.InvariantCulture)); + } + if (isDecimal) { + return new Token(Tokens.LiteralDecimal, x, y, sb.ToString(), Decimal.Parse(digit, NumberStyles.Currency | NumberStyles.AllowExponent, CultureInfo.InvariantCulture)); + } + if (isDouble) { + return new Token(Tokens.LiteralDouble, x, y, sb.ToString(), Double.Parse(digit, CultureInfo.InvariantCulture)); + } + } catch (FormatException) { + errors.Error(Line, Col, String.Format("{0} is not a parseable number", digit)); + if (isSingle) + return new Token(Tokens.LiteralSingle, x, y, sb.ToString(), 0f); + if (isDecimal) + return new Token(Tokens.LiteralDecimal, x, y, sb.ToString(), 0m); + if (isDouble) + return new Token(Tokens.LiteralDouble, x, y, sb.ToString(), 0.0); + } + Token token; + try { + token = new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int32.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + } catch (Exception) { + try { + token = new Token(Tokens.LiteralInteger, x, y, sb.ToString(), Int64.Parse(digit, isHex ? NumberStyles.HexNumber : NumberStyles.Number)); + } catch (FormatException) { + errors.Error(Line, Col, String.Format("{0} is not a parseable number", digit)); + // fallback, when nothing helps :) + token = new Token(Tokens.LiteralInteger, x, y, sb.ToString(), 0); + } catch (OverflowException) { + errors.Error(Line, Col, String.Format("{0} is too long for a integer literal", digit)); + // fallback, when nothing helps :) + token = new Token(Tokens.LiteralInteger, x, y, sb.ToString(), 0); + } + } + token.next = nextToken; + return token; + } + + void ReadPreprocessorDirective() + { + AstLocation start = new AstLocation(Line, Col - 1); + string directive = ReadIdent('#'); + // TODO : expression parser for PP directives + // needed for proper conversion to e. g. C# + string argument = ReadToEndOfLine(); +// this.specialTracker.AddPreprocessingDirective(new PreprocessingDirective(directive, argument.Trim(), start, new AstLocation(start.Line, start.Column + directive.Length + argument.Length))); + } + + string ReadDate() + { + char ch = '\0'; + sb.Length = 0; + int nextChar; + while ((nextChar = ReaderRead()) != -1) { + ch = (char)nextChar; + if (ch == '#') { + break; + } else if (ch == '\n') { + errors.Error(Line, Col, String.Format("No return allowed inside Date literal")); + } else { + sb.Append(ch); + } + } + if (ch != '#') { + errors.Error(Line, Col, String.Format("End of File reached before Date literal terminated")); + } + return sb.ToString(); + } + + string ReadString() + { + char ch = '\0'; + sb.Length = 0; + int nextChar; + while ((nextChar = ReaderRead()) != -1) { + ch = (char)nextChar; + if (ch == '"') { + if (ReaderPeek() != -1 && ReaderPeek() == '"') { + sb.Append('"'); + ReaderRead(); + } else { + break; + } + } else if (ch == '\n') { + errors.Error(Line, Col, String.Format("No return allowed inside String literal")); + } else { + sb.Append(ch); + } + } + if (ch != '"') { + errors.Error(Line, Col, String.Format("End of File reached before String terminated ")); + } + return sb.ToString(); + } + + void ReadComment() + { + AstLocation startPos = new AstLocation(Line, Col); + sb.Length = 0; + StringBuilder curWord = specialCommentHash != null ? new StringBuilder() : null; + int missingApostrophes = 2; // no. of ' missing until it is a documentation comment + int nextChar; + while ((nextChar = ReaderRead()) != -1) { + char ch = (char)nextChar; + + if (HandleLineEnd(ch)) { + break; + } + + sb.Append(ch); + + if (missingApostrophes > 0) { + if (ch == '\'' || ch == '\u2018' || ch == '\u2019') { + if (--missingApostrophes == 0) { +// specialTracker.StartComment(CommentType.Documentation, isAtLineBegin, startPos); + sb.Length = 0; + } + } else { +// specialTracker.StartComment(CommentType.SingleLine, isAtLineBegin, startPos); + missingApostrophes = 0; + } + } + + if (specialCommentHash != null) { + if (Char.IsLetter(ch)) { + curWord.Append(ch); + } else { + string tag = curWord.ToString(); + curWord.Length = 0; + if (specialCommentHash.ContainsKey(tag)) { + AstLocation p = new AstLocation(Line, Col); + string comment = ch + ReadToEndOfLine(); +// this.TagComments.Add(new TagComment(tag, comment, isAtLineBegin, p, new Location(Col, Line))); + sb.Append(comment); + break; + } + } + } + } +// if (missingApostrophes > 0) { +// specialTracker.StartComment(CommentType.SingleLine, isAtLineBegin, startPos); +// } +// specialTracker.AddString(sb.ToString()); +// specialTracker.FinishComment(new Location(Col, Line)); + } + + Token ReadOperator(char ch) + { + int x = Col - 1; + int y = Line; + switch(ch) { + case '+': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.PlusAssign, x, y); + default: + break; + } + return new Token(Tokens.Plus, x, y); + case '-': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.MinusAssign, x, y); + default: + break; + } + return new Token(Tokens.Minus, x, y); + case '*': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.TimesAssign, x, y); + default: + break; + } + return new Token(Tokens.Times, x, y, "*"); + case '/': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.DivAssign, x, y); + default: + break; + } + return new Token(Tokens.Div, x, y); + case '\\': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.DivIntegerAssign, x, y); + default: + break; + } + return new Token(Tokens.DivInteger, x, y); + case '&': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.ConcatStringAssign, x, y); + default: + break; + } + return new Token(Tokens.ConcatString, x, y); + case '^': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.PowerAssign, x, y); + default: + break; + } + return new Token(Tokens.Power, x, y); + case ':': + if (ReaderPeek() == '=') { + ReaderRead(); + return new Token(Tokens.ColonAssign, x, y); + } + return new Token(Tokens.Colon, x, y); + case '=': + return new Token(Tokens.Assign, x, y); + case '<': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.LessEqual, x, y); + case '>': + ReaderRead(); + return new Token(Tokens.NotEqual, x, y); + case '<': + ReaderRead(); + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.ShiftLeftAssign, x, y); + default: + break; + } + return new Token(Tokens.ShiftLeft, x, y); + } + return new Token(Tokens.LessThan, x, y); + case '>': + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.GreaterEqual, x, y); + case '>': + ReaderRead(); + if (ReaderPeek() != -1) { + switch (ReaderPeek()) { + case '=': + ReaderRead(); + return new Token(Tokens.ShiftRightAssign, x, y); + default: + break; + } + } + return new Token(Tokens.ShiftRight, x, y); + } + return new Token(Tokens.GreaterThan, x, y); + case ',': + return new Token(Tokens.Comma, x, y); + case '.': + // Prevent OverflowException when Peek returns -1 + int tmp = ReaderPeek(); int tmp2 = ReaderPeek(1); + if (tmp > 0) { + if (char.IsDigit((char)tmp)) + return ReadDigit('.', Col); + else if ((char)tmp == '@') { + ReaderRead(); + return new Token(Tokens.DotAt, x, y); + } else if ((char)tmp == '.' && tmp2 > 0 && (char)tmp2 == '.') { + ReaderRead(); ReaderRead(); + return new Token(Tokens.TripleDot, x, y); + } + } + return new Token(Tokens.Dot, x, y); + case '(': + return new Token(Tokens.OpenParenthesis, x, y); + case ')': + return new Token(Tokens.CloseParenthesis, x, y); + case '{': + return new Token(Tokens.OpenCurlyBrace, x, y); + case '}': + return new Token(Tokens.CloseCurlyBrace, x, y); + case '?': + return new Token(Tokens.QuestionMark, x, y); + case '!': + return new Token(Tokens.ExclamationMark, x, y); + } + return null; + } + #endregion + + #region XML Readers + Token ReadXmlProcessingInstruction(int x, int y) + { + sb.Length = 0; + int nextChar = -1; + + while (ReaderPeek() != '?' || ReaderPeek(1) != '>') { + nextChar = ReaderRead(); + if (nextChar == -1) + break; + sb.Append((char)nextChar); + } + + ReaderSkip("?>".Length); + + return new Token(Tokens.XmlProcessingInstruction, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + } + + Token ReadXmlCommentOrCData(int x, int y) + { + sb.Length = 0; + int nextChar = -1; + + if (string.CompareOrdinal(ReaderPeekString("--".Length), "--") == 0) { + ReaderSkip("--".Length); + while ((nextChar = ReaderRead()) != -1) { + sb.Append((char)nextChar); + if (string.CompareOrdinal(ReaderPeekString("-->".Length), "-->") == 0) { + ReaderSkip("-->".Length); + return new Token(Tokens.XmlComment, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + } + } + } + + if (string.CompareOrdinal(ReaderPeekString("[CDATA[".Length), "[CDATA[") == 0) { + ReaderSkip("[CDATA[".Length); + while ((nextChar = ReaderRead()) != -1) { + sb.Append((char)nextChar); + if (string.CompareOrdinal(ReaderPeekString("]]>".Length), "]]>") == 0) { + ReaderSkip("]]>".Length); + return new Token(Tokens.XmlCData, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + } + } + } + + return new Token(Tokens.XmlComment, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + } + + string ReadXmlContent(char ch) + { + sb.Length = 0; + while (true) { + sb.Append(ch); + int next = ReaderPeek(); + + if (next == -1 || next == '<') + break; + ch = (char)ReaderRead(); + } + + return sb.ToString(); + } + + string ReadXmlString(char terminator) + { + char ch = '\0'; + sb.Length = 0; + int nextChar; + while ((nextChar = ReaderRead()) != -1) { + ch = (char)nextChar; + if (ch == terminator) { + break; + } else if (ch == '\n') { + errors.Error(Line, Col, String.Format("No return allowed inside String literal")); + } else { + sb.Append(ch); + } + } + if (ch != terminator) { + errors.Error(Line, Col, String.Format("End of File reached before String terminated ")); + } + return sb.ToString(); + } + + string ReadXmlIdent(char ch) + { + sb.Length = 0; + sb.Append(ch); + + int peek; + + while ((peek = ReaderPeek()) != -1 && (peek == ':' || XmlConvert.IsNCNameChar((char)peek))) { + sb.Append((char)ReaderRead()); + } + + return sb.ToString(); + } + #endregion + + char PeekUpperChar() + { + return Char.ToUpper((char)ReaderPeek(), CultureInfo.InvariantCulture); + } + + /// + /// Skips to the end of the current code block. + /// For this, the lexer must have read the next token AFTER the token opening the + /// block (so that Lexer.Token is the block-opening token, not Lexer.LookAhead). + /// After the call, Lexer.LookAhead will be the block-closing token. + /// + public void SkipCurrentBlock(int targetToken) + { + int lastKind = -1; + int kind = lastToken.kind; + while (kind != Tokens.EOF && + !(lastKind == Tokens.End && kind == targetToken)) + { + lastKind = kind; + NextToken(); + kind = lastToken.kind; + } + } + + public void SetInitialContext(SnippetType type) + { + ef.SetContext(type); + } + + public VBLexerMemento Export() + { + return new VBLexerMemento() { + Column = Col, + Line = Line, + EncounteredLineContinuation = encounteredLineContinuation, + ExpressionFinder = ef.Export(), + InXmlMode = inXmlMode, + IsAtLineBegin = isAtLineBegin, + LineEnd = lineEnd, + PrevTokenKind = prevToken.kind, + MisreadExclamationMarkAsTypeCharacter = misreadExclamationMarkAsTypeCharacter, + XmlModeInfoStack = new Stack(xmlModeStack.Select(i => (XmlModeInfo)i.Clone()).Reverse()) + }; + } + + LATextReader reader; + int col = 1; + int line = 1; + + protected Errors errors = new Errors(); + + protected Token lastToken = null; + protected Token curToken = null; + protected Token peekToken = null; + + string[] specialCommentTags = null; + protected Hashtable specialCommentHash = null; +// List tagComments = new List(); + protected StringBuilder sb = new StringBuilder(); +// protected SpecialTracker specialTracker = new SpecialTracker(); + + // used for the original value of strings (with escape sequences). + protected StringBuilder originalValue = new StringBuilder(); + + public bool SkipAllComments { get; set; } + public bool EvaluateConditionalCompilation { get; set; } + public virtual IDictionary ConditionalCompilationSymbols { + get { throw new NotSupportedException(); } + } + + protected static IEnumerable GetSymbols (string symbols) + { + if (!string.IsNullOrEmpty(symbols)) { + foreach (string symbol in symbols.Split (';', ' ', '\t')) { + string s = symbol.Trim (); + if (s.Length == 0) + continue; + yield return s; + } + } + } + + public void SetConditionalCompilationSymbols (string symbols) + { + throw new NotSupportedException (); + } + + protected int Line { + get { + return line; + } + } + protected int Col { + get { + return col; + } + } + + protected bool recordRead = false; + protected StringBuilder recordedText = new StringBuilder (); + + protected int ReaderRead() + { + int val = reader.Read(); + if (recordRead && val >= 0) + recordedText.Append ((char)val); + if ((val == '\r' && reader.Peek() != '\n') || val == '\n') { + ++line; + col = 1; + LineBreak(); + } else if (val >= 0) { + col++; + } + return val; + } + + protected int ReaderPeek() + { + return reader.Peek(); + } + + protected int ReaderPeek(int step) + { + return reader.Peek(step); + } + + protected void ReaderSkip(int steps) + { + for (int i = 0; i < steps; i++) { + ReaderRead(); + } + } + + protected string ReaderPeekString(int length) + { + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < length; i++) { + int peek = ReaderPeek(i); + if (peek != -1) + builder.Append((char)peek); + } + + return builder.ToString(); + } + + public void SetInitialLocation(AstLocation location) + { + if (lastToken != null || curToken != null || peekToken != null) + throw new InvalidOperationException(); + this.line = location.Line; + this.col = location.Column; + } + + public Errors Errors { + get { + return errors; + } + } + + /// + /// Returns the comments that had been read and containing tag key words. + /// +// public List TagComments { +// get { +// return tagComments; +// } +// } + +// public SpecialTracker SpecialTracker { +// get { +// return specialTracker; +// } +// } + + /// + /// Special comment tags are tags like TODO, HACK or UNDONE which are read by the lexer and stored in . + /// + public string[] SpecialCommentTags { + get { + return specialCommentTags; + } + set { + specialCommentTags = value; + specialCommentHash = null; + if (specialCommentTags != null && specialCommentTags.Length > 0) { + specialCommentHash = new Hashtable(); + foreach (string str in specialCommentTags) { + specialCommentHash.Add(str, null); + } + } + } + } + + /// + /// The current Token. + /// + public Token Token { + get { +// Console.WriteLine("Call to Token"); + return lastToken; + } + } + + /// + /// The next Token (The after call) . + /// + public Token LookAhead { + get { +// Console.WriteLine("Call to LookAhead"); + return curToken; + } + } + + #region System.IDisposable interface implementation + public virtual void Dispose() + { + reader.Close(); + reader = null; + errors = null; + lastToken = curToken = peekToken = null; + specialCommentHash = null; + sb = originalValue = null; + } + #endregion + + /// + /// Must be called before a peek operation. + /// + public void StartPeek() + { + peekToken = curToken; + } + + /// + /// Gives back the next token. A second call to Peek() gives the next token after the last call for Peek() and so on. + /// + /// An object. + public Token Peek() + { +// Console.WriteLine("Call to Peek"); + if (peekToken.next == null) { + peekToken.next = Next(); + } + peekToken = peekToken.next; + return peekToken; + } + + protected static bool IsIdentifierPart(int ch) + { + if (ch == 95) return true; // 95 = '_' + if (ch == -1) return false; + return char.IsLetterOrDigit((char)ch); // accept unicode letters + } + + protected static bool IsHex(char digit) + { + return Char.IsDigit(digit) || ('A' <= digit && digit <= 'F') || ('a' <= digit && digit <= 'f'); + } + + protected int GetHexNumber(char digit) + { + if (Char.IsDigit(digit)) { + return digit - '0'; + } + if ('A' <= digit && digit <= 'F') { + return digit - 'A' + 0xA; + } + if ('a' <= digit && digit <= 'f') { + return digit - 'a' + 0xA; + } + errors.Error(line, col, String.Format("Invalid hex number '" + digit + "'")); + return 0; + } + protected AstLocation lastLineEnd = new AstLocation(1, 1); + protected AstLocation curLineEnd = new AstLocation(1, 1); + protected void LineBreak () + { + lastLineEnd = curLineEnd; + curLineEnd = new AstLocation (line, col - 1); + } + protected bool HandleLineEnd(char ch) + { + // Handle MS-DOS or MacOS line ends. + if (ch == '\r') { + if (reader.Peek() == '\n') { // MS-DOS line end '\r\n' + ReaderRead(); // LineBreak (); called by ReaderRead (); + return true; + } else { // assume MacOS line end which is '\r' + LineBreak (); + return true; + } + } + if (ch == '\n') { + LineBreak (); + return true; + } + return false; + } + + protected void SkipToEndOfLine() + { + int nextChar; + while ((nextChar = reader.Read()) != -1) { + if (nextChar == '\r') { + if (reader.Peek() == '\n') + reader.Read(); + nextChar = '\n'; + } + if (nextChar == '\n') { + ++line; + col = 1; + break; + } + } + } + + protected string ReadToEndOfLine() + { + sb.Length = 0; + int nextChar; + while ((nextChar = reader.Read()) != -1) { + char ch = (char)nextChar; + + if (nextChar == '\r') { + if (reader.Peek() == '\n') + reader.Read(); + nextChar = '\n'; + } + // Return read string, if EOL is reached + if (nextChar == '\n') { + ++line; + col = 1; + return sb.ToString(); + } + + sb.Append(ch); + } + + // Got EOF before EOL + string retStr = sb.ToString(); + col += retStr.Length; + return retStr; + } + + public event EventHandler SavepointReached; + + protected virtual void OnSavepointReached(SavepointEventArgs e) + { + if (SavepointReached != null) { + SavepointReached(this, e); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs new file mode 100644 index 0000000000..148475ccd8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs @@ -0,0 +1,22 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public sealed class VBLexerMemento + { + public int Line { get; set; } + public int Column { get; set; } + public int PrevTokenKind { get; set; } + public bool LineEnd { get; set; } + public bool IsAtLineBegin { get; set; } + public bool MisreadExclamationMarkAsTypeCharacter { get; set; } + public bool EncounteredLineContinuation { get; set; } + public ExpressionFinderState ExpressionFinder { get; set; } + public Stack XmlModeInfoStack { get; set; } + public bool InXmlMode { get; set; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs new file mode 100644 index 0000000000..4f3ef71e97 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs @@ -0,0 +1,29 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public class XmlModeInfo : ICloneable + { + public bool inXmlTag, inXmlCloseTag, isDocumentStart; + public int level; + + public XmlModeInfo(bool isSpecial) + { + level = isSpecial ? -1 : 0; + inXmlTag = inXmlCloseTag = isDocumentStart = false; + } + + public object Clone() + { + return new XmlModeInfo(false) { + inXmlCloseTag = this.inXmlCloseTag, + inXmlTag = this.inXmlTag, + isDocumentStart = this.isDocumentStart, + level = this.level + }; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs new file mode 100644 index 0000000000..a544eb0d00 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB +{ + /// + /// Output formatter for the Output visitor. + /// + public interface IOutputFormatter + { + void StartNode(AstNode node); + void EndNode(AstNode node); + + /// + /// Writes an identifier. + /// If the identifier conflicts with a keyword, the output visitor will + /// call WriteToken("@") before calling WriteIdentifier(). + /// + void WriteIdentifier(string identifier); + + /// + /// Writes a keyword to the output. + /// + void WriteKeyword(string keyword); + + /// + /// Writes a token to the output. + /// + void WriteToken(string token); + void Space(); + + void Indent(); + void Unindent(); + + void NewLine(); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs new file mode 100644 index 0000000000..f4085b6bc7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -0,0 +1,222 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.IO; + +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB +{ + /// + /// Description of OutputVisitor. + /// + public class OutputVisitor : IAstVisitor, IPatternAstVisitor + { + readonly IOutputFormatter formatter; + readonly VBFormattingOptions policy; + + readonly Stack containerStack = new Stack(); + readonly Stack positionStack = new Stack(); + + public OutputVisitor(TextWriter textWriter, VBFormattingOptions formattingPolicy) + { + if (textWriter == null) + throw new ArgumentNullException("textWriter"); + if (formattingPolicy == null) + throw new ArgumentNullException("formattingPolicy"); + this.formatter = new TextWriterOutputFormatter(textWriter); + this.policy = formattingPolicy; + } + + public OutputVisitor(IOutputFormatter formatter, VBFormattingOptions formattingPolicy) + { + if (formatter == null) + throw new ArgumentNullException("formatter"); + if (formattingPolicy == null) + throw new ArgumentNullException("formattingPolicy"); + this.formatter = formatter; + this.policy = formattingPolicy; + } + + public object VisitCompilationUnit(ICSharpCode.NRefactory.VB.Ast.CompilationUnit compilationUnit, object data) + { + // don't do node tracking as we visit all children directly + foreach (AstNode node in compilationUnit.Children) + node.AcceptVisitor(this, data); + return null; + } + + public object VisitBlockStatement(BlockStatement blockStatement, object data) + { + throw new NotImplementedException(); + } + + public object VisitPatternPlaceholder(AstNode placeholder, Pattern pattern, object data) + { + throw new NotImplementedException(); + } + + public object VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitVBTokenNode(VBTokenNode vBTokenNode, object data) + { + throw new NotImplementedException(); + } + + public object VisitAliasImportsClause(AliasImportsClause aliasImportsClause, object data) + { + throw new NotImplementedException(); + } + + public object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) + { + throw new NotImplementedException(); + } + + public object VisitAttributeBlock(AttributeBlock attributeBlock, object data) + { + throw new NotImplementedException(); + } + + public object VisitImportsStatement(ImportsStatement importsStatement, object data) + { + throw new NotImplementedException(); + } + + public object VisitMembersImportsClause(MemberImportsClause membersImportsClause, object data) + { + throw new NotImplementedException(); + } + + public object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitOptionStatement(OptionStatement optionStatement, object data) + { + throw new NotImplementedException(); + } + + public object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitXmlNamespaceImportsClause(XmlNamespaceImportsClause xmlNamespaceImportsClause, object data) + { + throw new NotImplementedException(); + } + + public object VisitEnumDeclaration(EnumDeclaration enumDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + { + throw new NotImplementedException(); + } + + public object VisitIdentifier(Identifier identifier, object data) + { + throw new NotImplementedException(); + } + + public object VisitXmlIdentifier(XmlIdentifier xmlIdentifier, object data) + { + throw new NotImplementedException(); + } + + public object VisitXmlLiteralString(XmlLiteralString xmlLiteralString, object data) + { + throw new NotImplementedException(); + } + + public object VisitSimpleNameExpression(SimpleNameExpression identifierExpression, object data) + { + throw new NotImplementedException(); + } + + public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + throw new NotImplementedException(); + } + + public object VisitPrimitiveType(PrimitiveType primitiveType, object data) + { + throw new NotImplementedException(); + } + + public object VisitQualifiedType(QualifiedType qualifiedType, object data) + { + throw new NotImplementedException(); + } + + public object VisitComposedType(ComposedType composedType, object data) + { + throw new NotImplementedException(); + } + + public object VisitArraySpecifier(ArraySpecifier arraySpecifier, object data) + { + throw new NotImplementedException(); + } + + public object VisitSimpleType(SimpleType simpleType, object data) + { + throw new NotImplementedException(); + } + + public object VisitAnyNode(AnyNode anyNode, object data) + { + throw new NotImplementedException(); + } + + public object VisitBackreference(Backreference backreference, object data) + { + throw new NotImplementedException(); + } + + public object VisitChoice(Choice choice, object data) + { + throw new NotImplementedException(); + } + + public object VisitNamedNode(NamedNode namedNode, object data) + { + throw new NotImplementedException(); + } + + public object VisitRepeat(Repeat repeat, object data) + { + throw new NotImplementedException(); + } + + public object VisitOptionalNode(OptionalNode optionalNode, object data) + { + throw new NotImplementedException(); + } + + public object VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference, object data) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs new file mode 100644 index 0000000000..cc2df64ed0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs @@ -0,0 +1,83 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB +{ + /// + /// Writes VB code into a TextWriter. + /// + public class TextWriterOutputFormatter : IOutputFormatter + { + readonly TextWriter textWriter; + int indentation; + bool needsIndent = true; + + public TextWriterOutputFormatter(TextWriter textWriter) + { + if (textWriter == null) + throw new ArgumentNullException("textWriter"); + this.textWriter = textWriter; + } + + public void WriteIdentifier(string ident) + { + WriteIndentation(); + textWriter.Write(ident); + } + + public void WriteKeyword(string keyword) + { + WriteIndentation(); + textWriter.Write(keyword); + } + + public void WriteToken(string token) + { + WriteIndentation(); + textWriter.Write(token); + } + + public void Space() + { + WriteIndentation(); + textWriter.Write(' '); + } + + void WriteIndentation() + { + if (needsIndent) { + needsIndent = false; + for (int i = 0; i < indentation; i++) { + textWriter.Write('\t'); + } + } + } + + public void NewLine() + { + textWriter.WriteLine(); + needsIndent = true; + } + + public void Indent() + { + indentation++; + } + + public void Unindent() + { + indentation--; + } + + public virtual void StartNode(AstNode node) + { + } + + public virtual void EndNode(AstNode node) + { + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs new file mode 100644 index 0000000000..8888bf2ffe --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs @@ -0,0 +1,17 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB +{ + /// + /// Description of VBFormattingOptions. + /// + public class VBFormattingOptions + { + public VBFormattingOptions() + { + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Errors.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Errors.cs new file mode 100644 index 0000000000..6cd0b2e249 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Errors.cs @@ -0,0 +1,50 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + public delegate void ErrorCodeProc(int line, int col, int n); + public delegate void ErrorMsgProc(int line, int col, string msg); + + public class Errors + { + int count = 0; // number of errors detected + public ErrorCodeProc SynErr; + public ErrorCodeProc SemErr; + public ErrorMsgProc Error; + StringBuilder errorText = new StringBuilder(); + + public string ErrorOutput { + get { + return errorText.ToString(); + } + } + + public Errors() + { + SynErr = new ErrorCodeProc(DefaultCodeError); // syntactic errors + SemErr = new ErrorCodeProc(DefaultCodeError); // semantic errors + Error = new ErrorMsgProc(DefaultMsgError); // user defined string based errors + } + + public int Count { + get { + return count; + } + } + + void DefaultCodeError(int line, int col, int n) + { + errorText.AppendLine(String.Format("-- line {0} col {1}: error {2}", line, col, n)); + count++; + } + + void DefaultMsgError(int line, int col, string s) { + errorText.AppendLine(String.Format("-- line {0} col {1}: {2}", line, col, s)); + count++; + } + } // Errors +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Parser.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Parser.cs new file mode 100644 index 0000000000..aa12c27f37 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Parser.cs @@ -0,0 +1,760 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using ASTAttribute = ICSharpCode.NRefactory.VB.Ast.Attribute; +using Roles = ICSharpCode.NRefactory.VB.AstNode.Roles; + + + + +namespace ICSharpCode.NRefactory.VB.Parser { + + +// ---------------------------------------------------------------------------- +// Parser +// ---------------------------------------------------------------------------- +//! A Coco/R Parser +partial class VBParser +{ + public const int _EOF = 0; + public const int _EOL = 1; + public const int _ident = 2; + public const int _LiteralString = 3; + public const int _LiteralCharacter = 4; + public const int _LiteralInteger = 5; + public const int _LiteralDouble = 6; + public const int _LiteralSingle = 7; + public const int _LiteralDecimal = 8; + public const int _LiteralDate = 9; + public const int _XmlOpenTag = 10; + public const int _XmlCloseTag = 11; + public const int _XmlStartInlineVB = 12; + public const int _XmlEndInlineVB = 13; + public const int _XmlCloseTagEmptyElement = 14; + public const int _XmlOpenEndTag = 15; + public const int _XmlContent = 16; + public const int _XmlComment = 17; + public const int _XmlCData = 18; + public const int _XmlProcessingInstruction = 19; + public const int maxT = 238; //\" expected"; + case 40: return "\"<\" expected"; + case 41: return "\"<>\" expected"; + case 42: return "\">=\" expected"; + case 43: return "\"<=\" expected"; + case 44: return "\"<<\" expected"; + case 45: return "\">>\" expected"; + case 46: return "\"+=\" expected"; + case 47: return "\"^=\" expected"; + case 48: return "\"-=\" expected"; + case 49: return "\"*=\" expected"; + case 50: return "\"/=\" expected"; + case 51: return "\"\\\\=\" expected"; + case 52: return "\"<<=\" expected"; + case 53: return "\">>=\" expected"; + case 54: return "\"&=\" expected"; + case 55: return "\":=\" expected"; + case 56: return "\"AddHandler\" expected"; + case 57: return "\"AddressOf\" expected"; + case 58: return "\"Aggregate\" expected"; + case 59: return "\"Alias\" expected"; + case 60: return "\"And\" expected"; + case 61: return "\"AndAlso\" expected"; + case 62: return "\"Ansi\" expected"; + case 63: return "\"As\" expected"; + case 64: return "\"Ascending\" expected"; + case 65: return "\"Assembly\" expected"; + case 66: return "\"Auto\" expected"; + case 67: return "\"Binary\" expected"; + case 68: return "\"Boolean\" expected"; + case 69: return "\"ByRef\" expected"; + case 70: return "\"By\" expected"; + case 71: return "\"Byte\" expected"; + case 72: return "\"ByVal\" expected"; + case 73: return "\"Call\" expected"; + case 74: return "\"Case\" expected"; + case 75: return "\"Catch\" expected"; + case 76: return "\"CBool\" expected"; + case 77: return "\"CByte\" expected"; + case 78: return "\"CChar\" expected"; + case 79: return "\"CDate\" expected"; + case 80: return "\"CDbl\" expected"; + case 81: return "\"CDec\" expected"; + case 82: return "\"Char\" expected"; + case 83: return "\"CInt\" expected"; + case 84: return "\"Class\" expected"; + case 85: return "\"CLng\" expected"; + case 86: return "\"CObj\" expected"; + case 87: return "\"Compare\" expected"; + case 88: return "\"Const\" expected"; + case 89: return "\"Continue\" expected"; + case 90: return "\"CSByte\" expected"; + case 91: return "\"CShort\" expected"; + case 92: return "\"CSng\" expected"; + case 93: return "\"CStr\" expected"; + case 94: return "\"CType\" expected"; + case 95: return "\"CUInt\" expected"; + case 96: return "\"CULng\" expected"; + case 97: return "\"CUShort\" expected"; + case 98: return "\"Custom\" expected"; + case 99: return "\"Date\" expected"; + case 100: return "\"Decimal\" expected"; + case 101: return "\"Declare\" expected"; + case 102: return "\"Default\" expected"; + case 103: return "\"Delegate\" expected"; + case 104: return "\"Descending\" expected"; + case 105: return "\"Dim\" expected"; + case 106: return "\"DirectCast\" expected"; + case 107: return "\"Distinct\" expected"; + case 108: return "\"Do\" expected"; + case 109: return "\"Double\" expected"; + case 110: return "\"Each\" expected"; + case 111: return "\"Else\" expected"; + case 112: return "\"ElseIf\" expected"; + case 113: return "\"End\" expected"; + case 114: return "\"EndIf\" expected"; + case 115: return "\"Enum\" expected"; + case 116: return "\"Equals\" expected"; + case 117: return "\"Erase\" expected"; + case 118: return "\"Error\" expected"; + case 119: return "\"Event\" expected"; + case 120: return "\"Exit\" expected"; + case 121: return "\"Explicit\" expected"; + case 122: return "\"False\" expected"; + case 123: return "\"Finally\" expected"; + case 124: return "\"For\" expected"; + case 125: return "\"Friend\" expected"; + case 126: return "\"From\" expected"; + case 127: return "\"Function\" expected"; + case 128: return "\"Get\" expected"; + case 129: return "\"GetType\" expected"; + case 130: return "\"Global\" expected"; + case 131: return "\"GoSub\" expected"; + case 132: return "\"GoTo\" expected"; + case 133: return "\"Group\" expected"; + case 134: return "\"Handles\" expected"; + case 135: return "\"If\" expected"; + case 136: return "\"Implements\" expected"; + case 137: return "\"Imports\" expected"; + case 138: return "\"In\" expected"; + case 139: return "\"Infer\" expected"; + case 140: return "\"Inherits\" expected"; + case 141: return "\"Integer\" expected"; + case 142: return "\"Interface\" expected"; + case 143: return "\"Into\" expected"; + case 144: return "\"Is\" expected"; + case 145: return "\"IsNot\" expected"; + case 146: return "\"Join\" expected"; + case 147: return "\"Key\" expected"; + case 148: return "\"Let\" expected"; + case 149: return "\"Lib\" expected"; + case 150: return "\"Like\" expected"; + case 151: return "\"Long\" expected"; + case 152: return "\"Loop\" expected"; + case 153: return "\"Me\" expected"; + case 154: return "\"Mod\" expected"; + case 155: return "\"Module\" expected"; + case 156: return "\"MustInherit\" expected"; + case 157: return "\"MustOverride\" expected"; + case 158: return "\"MyBase\" expected"; + case 159: return "\"MyClass\" expected"; + case 160: return "\"Namespace\" expected"; + case 161: return "\"Narrowing\" expected"; + case 162: return "\"New\" expected"; + case 163: return "\"Next\" expected"; + case 164: return "\"Not\" expected"; + case 165: return "\"Nothing\" expected"; + case 166: return "\"NotInheritable\" expected"; + case 167: return "\"NotOverridable\" expected"; + case 168: return "\"Object\" expected"; + case 169: return "\"Of\" expected"; + case 170: return "\"Off\" expected"; + case 171: return "\"On\" expected"; + case 172: return "\"Operator\" expected"; + case 173: return "\"Option\" expected"; + case 174: return "\"Optional\" expected"; + case 175: return "\"Or\" expected"; + case 176: return "\"Order\" expected"; + case 177: return "\"OrElse\" expected"; + case 178: return "\"Out\" expected"; + case 179: return "\"Overloads\" expected"; + case 180: return "\"Overridable\" expected"; + case 181: return "\"Overrides\" expected"; + case 182: return "\"ParamArray\" expected"; + case 183: return "\"Partial\" expected"; + case 184: return "\"Preserve\" expected"; + case 185: return "\"Private\" expected"; + case 186: return "\"Property\" expected"; + case 187: return "\"Protected\" expected"; + case 188: return "\"Public\" expected"; + case 189: return "\"RaiseEvent\" expected"; + case 190: return "\"ReadOnly\" expected"; + case 191: return "\"ReDim\" expected"; + case 192: return "\"Rem\" expected"; + case 193: return "\"RemoveHandler\" expected"; + case 194: return "\"Resume\" expected"; + case 195: return "\"Return\" expected"; + case 196: return "\"SByte\" expected"; + case 197: return "\"Select\" expected"; + case 198: return "\"Set\" expected"; + case 199: return "\"Shadows\" expected"; + case 200: return "\"Shared\" expected"; + case 201: return "\"Short\" expected"; + case 202: return "\"Single\" expected"; + case 203: return "\"Skip\" expected"; + case 204: return "\"Static\" expected"; + case 205: return "\"Step\" expected"; + case 206: return "\"Stop\" expected"; + case 207: return "\"Strict\" expected"; + case 208: return "\"String\" expected"; + case 209: return "\"Structure\" expected"; + case 210: return "\"Sub\" expected"; + case 211: return "\"SyncLock\" expected"; + case 212: return "\"Take\" expected"; + case 213: return "\"Text\" expected"; + case 214: return "\"Then\" expected"; + case 215: return "\"Throw\" expected"; + case 216: return "\"To\" expected"; + case 217: return "\"True\" expected"; + case 218: return "\"Try\" expected"; + case 219: return "\"TryCast\" expected"; + case 220: return "\"TypeOf\" expected"; + case 221: return "\"UInteger\" expected"; + case 222: return "\"ULong\" expected"; + case 223: return "\"Unicode\" expected"; + case 224: return "\"Until\" expected"; + case 225: return "\"UShort\" expected"; + case 226: return "\"Using\" expected"; + case 227: return "\"Variant\" expected"; + case 228: return "\"Wend\" expected"; + case 229: return "\"When\" expected"; + case 230: return "\"Where\" expected"; + case 231: return "\"While\" expected"; + case 232: return "\"Widening\" expected"; + case 233: return "\"With\" expected"; + case 234: return "\"WithEvents\" expected"; + case 235: return "\"WriteOnly\" expected"; + case 236: return "\"Xor\" expected"; + case 237: return "\"GetXmlNamespace\" expected"; + case 238: return "??? expected"; + case 239: return "this symbol not expected in StatementTerminator"; + case 240: return "invalid StatementTerminator"; + case 241: return "invalid OptionStatement"; + case 242: return "invalid Identifier"; + case 243: return "invalid IdentifierForFieldDeclaration"; + case 244: return "invalid TypeName"; + case 245: return "invalid PrimitiveTypeName"; + case 246: return "invalid QualifiedTypeName"; + case 247: return "invalid OnOff"; + case 248: return "invalid BinaryText"; + case 249: return "invalid ImportsClause"; + case 250: return "this symbol not expected in ImportsClause"; + + default: return "error " + errorNumber; + } + } +} // end Parser + +} // end namespace diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Parser.frame b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Parser.frame new file mode 100644 index 0000000000..4abbfccef2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/Parser.frame @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------------*\ + Compiler Generator Coco/R, + Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz + extended by M. Loeberbauer & A. Woess, Univ. of Linz + with improvements by Pat Terry, Rhodes University +------------------------------------------------------------------------------- +License + This file is part of Compiler Generator Coco/R + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As an exception, it is allowed to write an extension of Coco/R that is + used as a plugin in non-free software. + + If not otherwise stated, any source code generated by Coco/R (other than + Coco/R itself) does not fall under the GNU General Public License. + +About this file + This is a so-called 'frame' file that contains skeleton code for + generating a final Scanner/Parser code. + + The '-->TAG' text markers are used to delimit code chunks and typically + correspond to places where additional information is added by the + DFA or ParserGen code. + + All information prior to the first 'begin' text marker is discarded. + If the grammar contains a '[copy]' .. '[/copy]' section, its contents + will added instead. +\*---------------------------------------------------------------------------*/ +-->begin + +-->namespace + +// ---------------------------------------------------------------------------- +// Parser +// ---------------------------------------------------------------------------- +//! A Coco/R Parser +partial class VBParser +{ +-->constants + const bool T = true; + const bool x = false; + const int minErrDist = 2; + + public Errors errors; + + +-->declarations + + void Get () { + lexer.NextToken(); +-->pragmas + } + + bool StartOf (int s) { + return set[s].Get(la.kind); + } + + void ExpectWeak (int n, int follow) { + if (la.kind == n) Get(); + else { + SynErr(n); + while (!StartOf(follow)) Get(); + } + } + + + bool WeakSeparator(int n, int syFol, int repFol) { + int kind = la.kind; + if (kind == n) {Get(); return true;} + else if (StartOf(repFol)) {return false;} + else { + SynErr(n); + while (!(set[syFol].Get(kind) || set[repFol].Get(kind) || set[0].Get(kind))) { + Get(); + kind = la.kind; + } + return StartOf(syFol); + } + } + + +-->productions + + public void ParseRoot() { +-->parseRoot + } + + static readonly BitArray[] set = { +-->initialization + }; + + void SynErr(int line, int col, int errorNumber) + { + this.Errors.Error(line, col, GetMessage(errorNumber)); + } + + string GetMessage(int errorNumber) + { + switch (errorNumber) { + -->errors + default: return "error " + errorNumber; + } + } +} // end Parser + +$$$ diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/VBParser.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/VBParser.cs new file mode 100644 index 0000000000..c099d7981d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/VBParser.cs @@ -0,0 +1,436 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Visitors; + +namespace ICSharpCode.NRefactory.VB.Parser +{ + internal partial class VBParser : IDisposable + { + VBLexer lexer; + Stack stack; + CompilationUnit compilationUnit; + int errDist = MinErrDist; + + const int MinErrDist = 2; + const string ErrMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text + + public VBParser(VBLexer lexer) + { + this.errors = lexer.Errors; + errors.SynErr = new ErrorCodeProc(SynErr); + this.lexer = (VBLexer)lexer; + this.stack = new Stack(); + } + + #region Infrastructure + void NodeStart(AstNode node) + { + stack.Push(node); + } + + void NodeEnd(AstNode currentNode, Role role) + { + AstNode node = stack.Pop(); + Debug.Assert(currentNode == node); + stack.Peek().AddChildUntyped(node, role); + } + + void AddTerminal(Role role) + { + stack.Peek().AddChild(new VBTokenNode(t.Location, t.EndLocation), role); + } + + void AddChild(T childNode, Role role) where T : AstNode + { + if (childNode != null) { + stack.Peek().AddChild(childNode, role); + } + } + + StringBuilder qualidentBuilder = new StringBuilder(); + + Token t + { + [System.Diagnostics.DebuggerStepThrough] + get { + return lexer.Token; + } + } + + Token la + { + [System.Diagnostics.DebuggerStepThrough] + get { + return lexer.LookAhead; + } + } + + Token Peek(int n) + { + lexer.StartPeek(); + Token x = la; + while (n > 0) { + x = lexer.Peek(); + n--; + } + return x; + } + + public void Error(string s) + { + if (errDist >= MinErrDist) { + this.Errors.Error(la.line, la.col, s); + } + errDist = 0; + } + #endregion + + #region Parse + public void Parse() + { + ParseRoot(); + } + + public AstType ParseAstType() + { + // TODO + return null; + } + +// public Expression ParseExpression() +// { +// lexer.SetInitialContext(SnippetType.Expression); +// lexer.NextToken(); +// Location startLocation = la.Location; +// Expression expr; +// Expr(out expr); +// while (la.kind == Tokens.EOL) lexer.NextToken(); +// if (expr != null) { +// expr.StartLocation = startLocation; +// expr.EndLocation = t.EndLocation; +// expr.AcceptVisitor(new SetParentVisitor(), null); +// } +// Expect(Tokens.EOF); +// return expr; +// } + +// public BlockStatement ParseBlock() +// { +// lexer.NextToken(); +// compilationUnit = new CompilationUnit(); +// +// Location startLocation = la.Location; +// Statement st; +// Block(out st); +// if (st != null) { +// st.StartLocation = startLocation; +// if (t != null) +// st.EndLocation = t.EndLocation; +// else +// st.EndLocation = la.Location; +// st.AcceptVisitor(new SetParentVisitor(), null); +// } +// Expect(Tokens.EOF); +// return st as BlockStatement; +// } + +// public List ParseTypeMembers() +// { +// lexer.NextToken(); +// TypeDeclaration newType = new TypeDeclaration(Modifiers.None, null); +// BlockStart(newType); +// ClassBody(newType); +// BlockEnd(); +// Expect(Tokens.EOF); +// newType.AcceptVisitor(new SetParentVisitor(), null); +// return newType.Children; +// } + #endregion + + #region Conflict Resolvers + bool IsAliasImportsClause() + { + return IsIdentifierToken(la) && Peek(1).Kind == Tokens.Assign; + } + + static bool IsIdentifierToken(Token tk) + { + return Tokens.IdentifierTokens[tk.kind] || tk.kind == Tokens.Identifier; + } + #endregion + + /* True, if "." is followed by an ident */ + bool DotAndIdentOrKw () { + int peek = Peek(1).kind; + return la.kind == Tokens.Dot && (peek == Tokens.Identifier || peek >= Tokens.AddHandler); + } + + bool IsIdentifiedExpressionRange() + { + // t = Select + // la = Identifier + // Peek(1) = As or Assign + Token token = Peek(1); + return IsIdentifierToken(la) && (token.kind == Tokens.As || token.kind == Tokens.Assign); + } + + bool IsQueryExpression() + { + return (la.kind == Tokens.From || la.kind == Tokens.Aggregate) && IsIdentifierToken(Peek(1)); + } + + bool IsEndStmtAhead() + { + int peek = Peek(1).kind; + return la.kind == Tokens.End && (peek == Tokens.EOL || peek == Tokens.Colon); + } + + bool IsNotClosingParenthesis() { + return la.kind != Tokens.CloseParenthesis; + } + + /* + True, if ident is followed by "=" or by ":" and "=" + */ + bool IsNamedAssign() { + return Peek(1).kind == Tokens.ColonAssign; + } + + bool IsObjectCreation() { + return la.kind == Tokens.As && Peek(1).kind == Tokens.New; + } + + bool IsNewExpression() { + return la.kind == Tokens.New; + } + + /* + True, if "<" is followed by the ident "assembly" or "module" + */ + bool IsGlobalAttrTarget () { + Token pt = Peek(1); + return la.kind == Tokens.LessThan && ( string.Equals(pt.val, "assembly", StringComparison.InvariantCultureIgnoreCase) || string.Equals(pt.val, "module", StringComparison.InvariantCultureIgnoreCase)); + } + + /* + True if the next token is a "(" and is followed by "," or ")" + */ + bool IsDims() + { + int peek = Peek(1).kind; + return la.kind == Tokens.OpenParenthesis + && (peek == Tokens.Comma || peek == Tokens.CloseParenthesis); + } + + /* + True if the next token is an identifier + */ + bool IsLoopVariableDeclaration() + { + if (!IsIdentifierToken(la)) + return false; + lexer.StartPeek(); + Token x = lexer.Peek(); + if (x.kind == Tokens.OpenParenthesis) { + do { + x = lexer.Peek(); + } while (x.kind == Tokens.Comma); + if (x.kind != Tokens.CloseParenthesis) + return false; + x = lexer.Peek(); + } + return x.kind == Tokens.As || x.kind == Tokens.Assign; + } + + bool IsSize() + { + return la.kind == Tokens.OpenParenthesis; + } + + /* + True, if the comma is not a trailing one, + like the last one in: a, b, c, + */ + bool NotFinalComma() { + int peek = Peek(1).kind; + return la.kind == Tokens.Comma && + peek != Tokens.CloseCurlyBrace; + } + + /* + True, if the next token is "Else" and this one + if followed by "If" + */ + bool IsElseIf() + { + int peek = Peek(1).kind; + return la.kind == Tokens.Else && peek == Tokens.If; + } + + /* + True if the next token is goto and this one is + followed by minus ("-") (this is allowd in in + error clauses) + */ + bool IsNegativeLabelName() + { + int peek = Peek(1).kind; + return la.kind == Tokens.GoTo && peek == Tokens.Minus; + } + + /* + True if the next statement is a "Resume next" statement + */ + bool IsResumeNext() + { + int peek = Peek(1).kind; + return la.kind == Tokens.Resume && peek == Tokens.Next; + } + + /// + /// Returns True, if ident/literal integer is followed by ":" + /// + bool IsLabel() + { + return (la.kind == Tokens.Identifier || la.kind == Tokens.LiteralInteger) + && Peek(1).kind == Tokens.Colon; + } + + /// + /// Returns true if a property declaration is an automatic property. + /// + bool IsAutomaticProperty() + { + lexer.StartPeek(); + Token tn = la; + int braceCount = 0; + + // look for attributes + while (tn.kind == Tokens.LessThan) { + while (braceCount > 0 || tn.kind != Tokens.GreaterThan) { + tn = lexer.Peek(); + if (tn.kind == Tokens.OpenParenthesis) + braceCount++; + if (tn.kind == Tokens.CloseParenthesis) + braceCount--; + } + Debug.Assert(tn.kind == Tokens.GreaterThan); + tn = lexer.Peek(); + } + + // look for modifiers + var allowedTokens = new[] { + Tokens.Public, Tokens.Protected, + Tokens.Friend, Tokens.Private + }; + + while (allowedTokens.Contains(tn.kind)) + tn = lexer.Peek(); + + if (tn.Kind != Tokens.Get && tn.Kind != Tokens.Set) + return true; + + return false; + } + + bool IsNotStatementSeparator() + { + return la.kind == Tokens.Colon && Peek(1).kind == Tokens.EOL; + } + + static bool IsMustOverride(AttributedNode node) + { + return node.Modifiers.HasFlag(Modifiers.MustOverride); + } + + /* Writes the type name represented through the expression into the string builder. */ + /* Returns true when the expression was converted successfully, returns false when */ + /* There was an unknown expression (e.g. TypeReferenceExpression) in it */ +// bool WriteFullTypeName(StringBuilder b, Expression expr) +// { +// MemberReferenceExpression fre = expr as MemberReferenceExpression; +// if (fre != null) { +// bool result = WriteFullTypeName(b, fre.TargetObject); +// if (b.Length > 0) b.Append('.'); +// b.Append(fre.MemberName); +// return result; +// } else if (expr is SimpleNameExpression) { +// b.Append(((SimpleNameExpression)expr).Identifier); +// return true; +// } else { +// return false; +// } +// } + + void EnsureIsZero(Expression expr) + { + if (!(expr is PrimitiveExpression) || (expr as PrimitiveExpression).StringValue != "0") + Error("lower bound of array must be zero"); + } + + public bool ParseMethodBodies { get; set; } + + public VBLexer Lexer { + get { + return lexer; + } + } + + public Errors Errors { + get { + return errors; + } + } + + public CompilationUnit CompilationUnit { + get { + return compilationUnit; + } + } + + void SynErr(int n) + { + if (errDist >= MinErrDist) { + errors.SynErr(lexer.LookAhead.line, lexer.LookAhead.col, n); + } + errDist = 0; + } + + void SemErr(string msg) + { + if (errDist >= MinErrDist) { + errors.Error(lexer.Token.line, lexer.Token.col, msg); + } + errDist = 0; + } + + void Expect(int n) + { + if (lexer.LookAhead.kind == n) { + lexer.NextToken(); + } else { + SynErr(n); + } + } + + #region System.IDisposable interface implementation + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")] + public void Dispose() + { + errors = null; + if (lexer != null) { + lexer.Dispose(); + } + lexer = null; + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/vb.atg b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/vb.atg new file mode 100644 index 0000000000..f6787ab95e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Parser/vb.atg @@ -0,0 +1,460 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using ASTAttribute = ICSharpCode.NRefactory.VB.Ast.Attribute; +using Roles = ICSharpCode.NRefactory.VB.AstNode.Roles; + +COMPILER VB + +#region AUTOGENERATED TOKENS SECTION +TOKENS + /* ----- terminal classes ----- */ + /* EOF is 0 */ + EOL + ident + LiteralString + LiteralCharacter + LiteralInteger + LiteralDouble + LiteralSingle + LiteralDecimal + LiteralDate + XmlOpenTag // < + XmlCloseTag // > + XmlStartInlineVB // <%= + XmlEndInlineVB // %> + XmlCloseTagEmptyElement // /> + XmlOpenEndTag // + XmlCData // + XmlProcessingInstruction + + /* ----- special character ----- */ + "=" + ":" + "," + "&" + "/" + "\\" + "." + "..." + ".@" + "!" + "-" + "+" + "^" + "?" + "*" + "{" + "}" + "(" + ")" + ">" + "<" + "<>" + ">=" + "<=" + "<<" + ">>" + "+=" + "^=" + "-=" + "*=" + "/=" + "\\=" + "<<=" + ">>=" + "&=" + ":=" + + /* ----- keywords ----- */ + "AddHandler" + "AddressOf" + "Aggregate" + "Alias" + "And" + "AndAlso" + "Ansi" + "As" + "Ascending" + "Assembly" + "Auto" + "Binary" + "Boolean" + "ByRef" + "By" + "Byte" + "ByVal" + "Call" + "Case" + "Catch" + "CBool" + "CByte" + "CChar" + "CDate" + "CDbl" + "CDec" + "Char" + "CInt" + "Class" + "CLng" + "CObj" + "Compare" + "Const" + "Continue" + "CSByte" + "CShort" + "CSng" + "CStr" + "CType" + "CUInt" + "CULng" + "CUShort" + "Custom" + "Date" + "Decimal" + "Declare" + "Default" + "Delegate" + "Descending" + "Dim" + "DirectCast" + "Distinct" + "Do" + "Double" + "Each" + "Else" + "ElseIf" + "End" + "EndIf" + "Enum" + "Equals" + "Erase" + "Error" + "Event" + "Exit" + "Explicit" + "False" + "Finally" + "For" + "Friend" + "From" + "Function" + "Get" + "GetType" + "Global" + "GoSub" + "GoTo" + "Group" + "Handles" + "If" + "Implements" + "Imports" + "In" + "Infer" + "Inherits" + "Integer" + "Interface" + "Into" + "Is" + "IsNot" + "Join" + "Key" + "Let" + "Lib" + "Like" + "Long" + "Loop" + "Me" + "Mod" + "Module" + "MustInherit" + "MustOverride" + "MyBase" + "MyClass" + "Namespace" + "Narrowing" + "New" + "Next" + "Not" + "Nothing" + "NotInheritable" + "NotOverridable" + "Object" + "Of" + "Off" + "On" + "Operator" + "Option" + "Optional" + "Or" + "Order" + "OrElse" + "Out" + "Overloads" + "Overridable" + "Overrides" + "ParamArray" + "Partial" + "Preserve" + "Private" + "Property" + "Protected" + "Public" + "RaiseEvent" + "ReadOnly" + "ReDim" + "Rem" + "RemoveHandler" + "Resume" + "Return" + "SByte" + "Select" + "Set" + "Shadows" + "Shared" + "Short" + "Single" + "Skip" + "Static" + "Step" + "Stop" + "Strict" + "String" + "Structure" + "Sub" + "SyncLock" + "Take" + "Text" + "Then" + "Throw" + "To" + "True" + "Try" + "TryCast" + "TypeOf" + "UInteger" + "ULong" + "Unicode" + "Until" + "UShort" + "Using" + "Variant" + "Wend" + "When" + "Where" + "While" + "Widening" + "With" + "WithEvents" + "WriteOnly" + "Xor" + "GetXmlNamespace" +#endregion + +PRODUCTIONS + +#region General + +VB = +(. + compilationUnit = new CompilationUnit(); + NodeStart(compilationUnit); + Get(); +.) + { StatementTerminator } + { OptionStatement { StatementTerminator } } + { ImportsStatement { StatementTerminator } } +/* { IF (IsGlobalAttrTarget()) GlobalAttributeSection { StatementTerminator } } + { NamespaceMemberDecl { StatementTerminator } } */ +. + +StatementTerminator = SYNC ( EOL | ":" ) . + +#region Identifier + +//IdentifierOrKeyword = ANY (. identifier = t.val; .) . + +// This production handles pseudo keywords that are needed in the grammar +Identifier = + IdentifierForFieldDeclaration + | "Custom" +. + +IdentifierForFieldDeclaration = + ident + | "Aggregate" + | "Ansi" + | "Ascending" + | "Assembly" + | "Auto" + | "Binary" + | "By" + | "Compare" + | "Descending" + | "Distinct" + | "Equals" + | "Explicit" + | "From" + | "Group" + | "Infer" + | "Into" + | "Join" + | "Key" + | "Off" + | "Order" + | "Out" + | "Preserve" + | "Skip" + | "Take" + | "Text" + | "Unicode" + | "Until" + | "Where" +. +#endregion + +TypeName (. type = null; .) = + PrimitiveTypeName | + QualifiedTypeName +. +QualifiedTypeName = + ( "Global" | Identifier ) (. type = new SimpleType(t.val, t.Location); .) + { "." Identifier (. type = new QualifiedType(type, new Identifier(t.val, t.Location)); .) } + // TODO : add TypeArguments +. + +PrimitiveTypeName (. type = null; .) = + "Object" (. type = new PrimitiveType("Object", t.Location); .) + | "Boolean" (. type = new PrimitiveType("Boolean", t.Location); .) + | "Date" (. type = new PrimitiveType("Date", t.Location); .) + | "Char" (. type = new PrimitiveType("Char", t.Location); .) + | "String" (. type = new PrimitiveType("String", t.Location); .) + | "Decimal" (. type = new PrimitiveType("Decimal", t.Location); .) + | "Byte" (. type = new PrimitiveType("Byte", t.Location); .) + | "Short" (. type = new PrimitiveType("Short", t.Location); .) + | "Integer" (. type = new PrimitiveType("Integer", t.Location); .) + | "Long" (. type = new PrimitiveType("Long", t.Location); .) + | "Single" (. type = new PrimitiveType("Single", t.Location); .) + | "Double" (. type = new PrimitiveType("Double", t.Location); .) + | "UInteger" (. type = new PrimitiveType("UInteger", t.Location); .) + | "ULong" (. type = new PrimitiveType("ULong", t.Location); .) + | "UShort" (. type = new PrimitiveType("UShort", t.Location); .) + | "SByte" (. type = new PrimitiveType("SByte", t.Location); .) +. + +/* +ParameterModifier = + "ByVal" (. m.Add(ParameterModifiers.In); .) + | "ByRef" (. m.Add(ParameterModifiers.Ref); .) + | "Optional" (. m.Add(ParameterModifiers.Optional); .) + | "ParamArray" (. m.Add(ParameterModifiers.Params); .) +. + +TypeModifier = + "Public" (. m.Add(Modifiers.Public, t.Location); .) + | "Protected" (. m.Add(Modifiers.Protected, t.Location); .) + | "Friend" (. m.Add(Modifiers.Internal, t.Location); .) + | "Private" (. m.Add(Modifiers.Private, t.Location); .) + | "Shared" (. m.Add(Modifiers.Static, t.Location); .) + | "Shadows" (. m.Add(Modifiers.New, t.Location); .) + | "MustInherit" (. m.Add(Modifiers.Abstract, t.Location); .) + | "NotInheritable" (. m.Add(Modifiers.Sealed, t.Location); .) + | "Partial" (. m.Add(Modifiers.Partial, t.Location); .) +. + +MemberModifier = + "MustInherit" (.m.Add(Modifiers.Abstract, t.Location);.) + | "Default" (.m.Add(Modifiers.Default, t.Location);.) + | "Friend" (.m.Add(Modifiers.Internal, t.Location);.) + | "Shadows" (.m.Add(Modifiers.New, t.Location);.) + | "Overrides" (.m.Add(Modifiers.Override, t.Location);.) + | "MustOverride" (.m.Add(Modifiers.Abstract, t.Location);.) + | "Private" (.m.Add(Modifiers.Private, t.Location);.) + | "Protected" (.m.Add(Modifiers.Protected, t.Location);.) + | "Public" (.m.Add(Modifiers.Public, t.Location);.) + | "NotInheritable" (.m.Add(Modifiers.Sealed, t.Location);.) + | "NotOverridable" (.m.Add(Modifiers.Sealed, t.Location);.) + | "Shared" (.m.Add(Modifiers.Static, t.Location);.) + | "Overridable" (.m.Add(Modifiers.Virtual, t.Location);.) + | "Overloads" (.m.Add(Modifiers.Overloads, t.Location);.) + | "ReadOnly" (.m.Add(Modifiers.ReadOnly, t.Location);.) + | "WriteOnly" (.m.Add(Modifiers.WriteOnly, t.Location);.) + | "WithEvents" (.m.Add(Modifiers.WithEvents, t.Location);.) + | "Dim" (.m.Add(Modifiers.Dim, t.Location);.) + | "Partial" (.m.Add(Modifiers.Partial, t.Location);.) +. + +PropertyAccessorAccessModifier = + (. m = Modifiers.None; .) + { + "Public" (. m |= Modifiers.Public; .) + | "Protected" (. m |= Modifiers.Protected; .) + | "Friend" (. m |= Modifiers.Internal; .) + | "Private" (. m |= Modifiers.Private; .) + } +. +*/ +#endregion + +#region Global + +#region OptionStatement + +OptionStatement = + "Option" ( + "Explicit" (. result.OptionType = OptionType.Explicit; .) [ OnOff ] + | "Strict" (. result.OptionType = OptionType.Strict; .) [ OnOff ] + | "Infer" (. result.OptionType = OptionType.Infer; .) [ OnOff ] + | "Compare" (. result.OptionType = OptionType.Compare; .) BinaryText + ) StatementTerminator +. + +OnOff = + "On" (. os.OptionValue = OptionValue.On; .) + | "Off" (. os.OptionValue = OptionValue.Off; .) +. + +BinaryText = + "Text" (. os.OptionValue = OptionValue.Text; .) + | "Binary" (. os.OptionValue = OptionValue.Binary; .) +. + +#endregion + +#region ImportsStatement + +ImportsStatement = + "Imports" ImportsClause { "," ImportsClause } StatementTerminator +. + +ImportsClause = + ( IF (IsAliasImportsClause()) + AliasImportsClause | + MemberImportsClause | + XmlNamespaceImportsClause ) SYNC . + +AliasImportsClause (. AstType alias; .) = + // Type characters are not allowed in identifiers here + Identifier (. result.Name = new Identifier(t.val, t.Location); .) "=" TypeName (. result.Alias = alias; .) +. + +MemberImportsClause (. AstType member; .) = + TypeName (. result.Member = member; .) +. + +XmlNamespaceImportsClause = + XmlOpenTag Identifier/**/ "=" LiteralString/**/ XmlCloseTag +. + +#endregion + +#endregion + +END VB . diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs new file mode 100644 index 0000000000..c69a56b126 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs @@ -0,0 +1,228 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Text; + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ + /// + /// Base class of output formatters. + /// + public abstract class AbstractOutputFormatter : IOutputFormatter + { + StringBuilder text = new StringBuilder(); + + int indentationLevel = 0; + bool indent = true; + bool doNewLine = true; + AbstractPrettyPrintOptions prettyPrintOptions; + + public bool IsInMemberBody { get; set; } + + public int IndentationLevel { + get { + return indentationLevel; + } + set { + indentationLevel = value; + } + } + + public string Text { + get { + return text.ToString(); + } + } + + public int TextLength { + get { + return text.Length; + } + } + + + public bool DoIndent { + get { + return indent; + } + set { + indent = value; + } + } + + public bool DoNewLine { + get { + return doNewLine; + } + set { + doNewLine = value; + } + } + + protected AbstractOutputFormatter(AbstractPrettyPrintOptions prettyPrintOptions) + { + this.prettyPrintOptions = prettyPrintOptions; + } + + internal bool isIndented = false; + public void Indent() + { + if (DoIndent) { + int indent = 0; + while (indent < prettyPrintOptions.IndentSize * indentationLevel) { + char ch = prettyPrintOptions.IndentationChar; + if (ch == '\t' && indent + prettyPrintOptions.TabSize > prettyPrintOptions.IndentSize * indentationLevel) { + ch = ' '; + } + text.Append(ch); + if (ch == '\t') { + indent += prettyPrintOptions.TabSize; + } else { + ++indent; + } + } + isIndented = true; + } + } + + public void Reset () + { + text.Length = 0; + isIndented = false; + } + + public void Space() + { + text.Append(' '); + isIndented = false; + } + + internal int lastLineStart = 0; + internal int lineBeforeLastStart = 0; + + public bool LastCharacterIsNewLine { + get { + return text.Length == lastLineStart; + } + } + + public bool LastCharacterIsWhiteSpace { + get { + return text.Length == 0 || char.IsWhiteSpace(text[text.Length - 1]); + } + } + + public virtual void NewLine() + { + if (DoNewLine) { + if (!LastCharacterIsNewLine) { + lineBeforeLastStart = lastLineStart; + } + text.AppendLine(); + lastLineStart = text.Length; + isIndented = false; + } + } + + public virtual void EndFile() + { + } + + protected void WriteLineInPreviousLine(string txt, bool forceWriteInPreviousBlock) + { + WriteInPreviousLine(txt + Environment.NewLine, forceWriteInPreviousBlock); + } + protected void WriteLineInPreviousLine(string txt, bool forceWriteInPreviousBlock, bool indent) + { + WriteInPreviousLine(txt + Environment.NewLine, forceWriteInPreviousBlock, indent); + } + + protected void WriteInPreviousLine(string txt, bool forceWriteInPreviousBlock) + { + WriteInPreviousLine(txt, forceWriteInPreviousBlock, true); + } + protected void WriteInPreviousLine(string txt, bool forceWriteInPreviousBlock, bool indent) + { + if (txt.Length == 0) return; + + bool lastCharacterWasNewLine = LastCharacterIsNewLine; + if (lastCharacterWasNewLine) { + if (forceWriteInPreviousBlock == false) { + if (indent && txt != Environment.NewLine) Indent(); + text.Append(txt); + lineBeforeLastStart = lastLineStart; + lastLineStart = text.Length; + return; + } + lastLineStart = lineBeforeLastStart; + } + string lastLine = text.ToString(lastLineStart, text.Length - lastLineStart); + text.Remove(lastLineStart, text.Length - lastLineStart); + if (indent && txt != Environment.NewLine) { + if (forceWriteInPreviousBlock) ++indentationLevel; + Indent(); + if (forceWriteInPreviousBlock) --indentationLevel; + } + text.Append(txt); + lineBeforeLastStart = lastLineStart; + lastLineStart = text.Length; + text.Append(lastLine); + if (lastCharacterWasNewLine) { + lineBeforeLastStart = lastLineStart; + lastLineStart = text.Length; + } + isIndented = false; + } + + /// + /// Prints a text that cannot be inserted before using WriteInPreviousLine + /// into the current line + /// + protected void PrintSpecialText(string specialText) + { + lineBeforeLastStart = text.Length; + text.Append(specialText); + lastLineStart = text.Length; + isIndented = false; + } + + public void PrintTokenList(ArrayList tokenList) + { + foreach (int token in tokenList) { + PrintToken(token); + Space(); + } + } + +// public abstract void PrintComment(Comment comment, bool forceWriteInPreviousBlock); + +// public virtual void PrintPreprocessingDirective(PreprocessingDirective directive, bool forceWriteInPreviousBlock) +// { +// if (!directive.Expression.IsNull) { +//// CSharpOutputVisitor visitor = new CSharpOutputVisitor(); +//// directive.Expression.AcceptVisitor(visitor, null); +//// WriteLineInPreviousLine(directive.Cmd + " " + visitor.Text, forceWriteInPreviousBlock); +// } else if (string.IsNullOrEmpty(directive.Arg)) +// WriteLineInPreviousLine(directive.Cmd, forceWriteInPreviousBlock); +// else +// WriteLineInPreviousLine(directive.Cmd + " " + directive.Arg, forceWriteInPreviousBlock); +// } + + public void PrintBlankLine(bool forceWriteInPreviousBlock) + { + WriteInPreviousLine(Environment.NewLine, forceWriteInPreviousBlock); + } + + public abstract void PrintToken(int token); + + public void PrintText(string text) + { + this.text.Append(text); + isIndented = false; + } + + public abstract void PrintIdentifier(string identifier); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs new file mode 100644 index 0000000000..438fc54a3b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs @@ -0,0 +1,42 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ + /// + /// Description of PrettyPrintOptions. + /// + public class AbstractPrettyPrintOptions + { + char indentationChar = '\t'; + int tabSize = 4; + int indentSize = 4; + + public char IndentationChar { + get { + return indentationChar; + } + set { + indentationChar = value; + } + } + + public int TabSize { + get { + return tabSize; + } + set { + tabSize = value; + } + } + + public int IndentSize { + get { + return indentSize; + } + set { + indentSize = value; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs new file mode 100644 index 0000000000..71ccb5d0f0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs @@ -0,0 +1,50 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ +// public interface IOutputDomVisitor : IAstVisitor +// { +// event Action BeforeNodeVisit; +// event Action AfterNodeVisit; +// +// string Text { +// get; +// } +// +// Errors Errors { +// get; +// } +// +// AbstractPrettyPrintOptions Options { +// get; +// } +// IOutputFormatter OutputFormatter { +// get; +// } +// } + + public interface IOutputFormatter + { + int IndentationLevel { + get; + set; + } + string Text { + get; + } + bool IsInMemberBody { + get; + set; + } + void NewLine(); + void Indent(); +// void PrintComment(Comment comment, bool forceWriteInPreviousBlock); +// void PrintPreprocessingDirective(PreprocessingDirective directive, bool forceWriteInPreviousBlock); + void PrintBlankLine(bool forceWriteInPreviousBlock); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs new file mode 100644 index 0000000000..95fdcf389c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs @@ -0,0 +1,142 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ +// public class SpecialOutputVisitor : ISpecialVisitor +// { +// readonly IOutputFormatter formatter; +// +// public SpecialOutputVisitor(IOutputFormatter formatter) +// { +// this.formatter = formatter; +// } +// +// public bool ForceWriteInPreviousLine; +// +// public object Visit(ISpecial special, object data) +// { +// Console.WriteLine("Warning: SpecialOutputVisitor.Visit(ISpecial) called with " + special); +// return data; +// } +// +// public object Visit(BlankLine special, object data) +// { +// formatter.PrintBlankLine(ForceWriteInPreviousLine); +// return data; +// } +// +// public object Visit(Comment special, object data) +// { +// formatter.PrintComment(special, ForceWriteInPreviousLine); +// return data; +// } +// +// public object Visit(PreprocessingDirective special, object data) +// { +// formatter.PrintPreprocessingDirective(special, ForceWriteInPreviousLine); +// return data; +// } +// } +// +// /// +// /// This class inserts specials between INodes. +// /// +// public sealed class SpecialNodesInserter : IDisposable +// { +// IEnumerator enumerator; +// SpecialOutputVisitor visitor; +// bool available; // true when more specials are available +// +// public SpecialNodesInserter(IEnumerable specials, SpecialOutputVisitor visitor) +// { +// if (specials == null) throw new ArgumentNullException("specials"); +// if (visitor == null) throw new ArgumentNullException("visitor"); +// enumerator = specials.GetEnumerator(); +// this.visitor = visitor; +// available = enumerator.MoveNext(); +// } +// +// void WriteCurrent() +// { +// enumerator.Current.AcceptVisitor(visitor, null); +// available = enumerator.MoveNext(); +// } +// +// AttributedNode currentAttributedNode; +// +// /// +// /// Writes all specials up to the start position of the node. +// /// +// public void AcceptNodeStart(INode node) +// { +// if (node is AttributedNode) { +// currentAttributedNode = node as AttributedNode; +// if (currentAttributedNode.Attributes.Count == 0) { +// AcceptPoint(node.StartLocation); +// currentAttributedNode = null; +// } +// } else { +// AcceptPoint(node.StartLocation); +// } +// } +// +// /// +// /// Writes all specials up to the end position of the node. +// /// +// public void AcceptNodeEnd(INode node) +// { +// visitor.ForceWriteInPreviousLine = true; +// AcceptPoint(node.EndLocation); +// visitor.ForceWriteInPreviousLine = false; +// if (currentAttributedNode != null) { +// if (node == currentAttributedNode.Attributes[currentAttributedNode.Attributes.Count - 1]) { +// AcceptPoint(currentAttributedNode.StartLocation); +// currentAttributedNode = null; +// } +// } +// } +// +// /// +// /// Writes all specials up to the specified location. +// /// +// public void AcceptPoint(Location loc) +// { +// while (available && enumerator.Current.StartPosition <= loc) { +// WriteCurrent(); +// } +// } +// +// /// +// /// Outputs all missing specials to the writer. +// /// +// public void Finish() +// { +// while (available) { +// WriteCurrent(); +// } +// } +// +// void IDisposable.Dispose() +// { +// Finish(); +// } +// +// /// +// /// Registers a new SpecialNodesInserter with the output visitor. +// /// Make sure to call Finish() (or Dispose()) on the returned SpecialNodesInserter +// /// when the output is finished. +// /// +// public static SpecialNodesInserter Install(IEnumerable specials, IOutputDomVisitor outputVisitor) +// { +// SpecialNodesInserter sni = new SpecialNodesInserter(specials, new SpecialOutputVisitor(outputVisitor.OutputFormatter)); +// outputVisitor.BeforeNodeVisit += sni.AcceptNodeStart; +// outputVisitor.AfterNodeVisit += sni.AcceptNodeEnd; +// return sni; +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs new file mode 100644 index 0000000000..ca2325bbad --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs @@ -0,0 +1,73 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.VB.Parser; + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ + /// + /// Description of VBNetOutputFormatter. + /// + public sealed class VBNetOutputFormatter : AbstractOutputFormatter + { + public VBNetOutputFormatter(VBNetPrettyPrintOptions prettyPrintOptions) : base(prettyPrintOptions) + { + } + + public override void PrintToken(int token) + { + PrintText(Tokens.GetTokenString(token)); + } + + public override void PrintIdentifier(string identifier) + { + if (Keywords.IsNonIdentifierKeyword(identifier)) { + PrintText("["); + PrintText(identifier); + PrintText("]"); + } else { + PrintText(identifier); + } + } + +// public override void PrintComment(Comment comment, bool forceWriteInPreviousBlock) +// { +// switch (comment.CommentType) { +// case CommentType.Block: +// WriteLineInPreviousLine("'" + comment.CommentText.Replace("\n", "\n'"), forceWriteInPreviousBlock); +// break; +// case CommentType.Documentation: +// WriteLineInPreviousLine("'''" + comment.CommentText, forceWriteInPreviousBlock); +// break; +// default: +// WriteLineInPreviousLine("'" + comment.CommentText, forceWriteInPreviousBlock); +// break; +// } +// } + +// public override void PrintPreprocessingDirective(PreprocessingDirective directive, bool forceWriteInPreviousBlock) +// { +// if (IsInMemberBody +// && (string.Equals(directive.Cmd, "#Region", StringComparison.InvariantCultureIgnoreCase) +// || string.Equals(directive.Cmd, "#End", StringComparison.InvariantCultureIgnoreCase) +// && directive.Arg.StartsWith("Region", StringComparison.InvariantCultureIgnoreCase))) +// { +// WriteLineInPreviousLine("'" + directive.Cmd + " " + directive.Arg, forceWriteInPreviousBlock); +// } else if (!directive.Expression.IsNull) { +// VBNetOutputVisitor visitor = new VBNetOutputVisitor(); +// directive.Expression.AcceptVisitor(visitor, null); +// WriteLineInPreviousLine(directive.Cmd + " " + visitor.Text + " Then", forceWriteInPreviousBlock); +// } else { +// base.PrintPreprocessingDirective(directive, forceWriteInPreviousBlock); +// } +// } + + public void PrintLineContinuation() + { + if (!LastCharacterIsWhiteSpace) + Space(); + PrintText("_" + Environment.NewLine); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs new file mode 100644 index 0000000000..972c09260f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs @@ -0,0 +1,3023 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Text; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; +using ICSharpCode.NRefactory.VB.Visitors; + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ +// public sealed class VBNetOutputVisitor : NodeTrackingAstVisitor, IOutputDomVisitor +// { +// Errors errors = new Errors(); +// VBNetOutputFormatter outputFormatter; +// VBNetPrettyPrintOptions prettyPrintOptions = new VBNetPrettyPrintOptions(); +// TypeDeclaration currentType; +// +// Stack exitTokenStack = new Stack(); +// +// public string Text { +// get { +// return outputFormatter.Text; +// } +// } +// +// public Errors Errors { +// get { +// return errors; +// } +// } +// +// AbstractPrettyPrintOptions IOutputDomVisitor.Options { +// get { return prettyPrintOptions; } +// } +// +// public VBNetPrettyPrintOptions Options { +// get { return prettyPrintOptions; } +// } +// +// public IOutputFormatter OutputFormatter { +// get { +// return outputFormatter; +// } +// } +// +// public VBNetOutputVisitor() +// { +// outputFormatter = new VBNetOutputFormatter(prettyPrintOptions); +// } +// +// public event Action BeforeNodeVisit; +// public event Action AfterNodeVisit; +// +// protected override void BeginVisit(INode node) +// { +// if (BeforeNodeVisit != null) { +// BeforeNodeVisit(node); +// } +// base.BeginVisit(node); +// } +// +// protected override void EndVisit(INode node) +// { +// base.EndVisit(node); +// if (AfterNodeVisit != null) { +// AfterNodeVisit(node); +// } +// } +// +// object TrackedVisit(INode node, object data) +// { +// return node.AcceptVisitor(this, data); +// } +// +// void Error(string text, Location position) +// { +// errors.Error(position.Line, position.Column, text); +// } +// +// void UnsupportedNode(INode node) +// { +// Error(node.GetType().Name + " is unsupported", node.StartLocation); +// } +// +// #region ICSharpCode.NRefactory.Parser.IAstVisitor interface implementation +// public override object TrackedVisitCompilationUnit(CompilationUnit compilationUnit, object data) +// { +// compilationUnit.AcceptChildren(this, data); +// outputFormatter.EndFile(); +// return null; +// } +// +// /// +// /// Converts type name to primitive type name. Returns typeString if typeString is not +// /// a primitive type. +// /// +// static string ConvertTypeString(string typeString) +// { +// string primitiveType; +// if (TypeReference.PrimitiveTypesVBReverse.TryGetValue(typeString, out primitiveType)) +// return primitiveType; +// else +// return typeString; +// } +// +// public override object TrackedVisitTypeReference(TypeReference typeReference, object data) +// { +// if (typeReference == TypeReference.ClassConstraint) { +// outputFormatter.PrintToken(Tokens.Class); +// } else if (typeReference == TypeReference.StructConstraint) { +// outputFormatter.PrintToken(Tokens.Structure); +// } else if (typeReference == TypeReference.NewConstraint) { +// outputFormatter.PrintToken(Tokens.New); +// } else { +// PrintTypeReferenceWithoutArray(typeReference); +// if (typeReference.IsArrayType) { +// PrintArrayRank(typeReference.RankSpecifier, 0); +// } +// } +// return null; +// } +// +// void PrintTypeReferenceWithoutArray(TypeReference typeReference) +// { +// if (typeReference.IsGlobal) { +// outputFormatter.PrintToken(Tokens.Global); +// outputFormatter.PrintToken(Tokens.Dot); +// } +// bool printGenerics = true; +// if (typeReference.IsKeyword) { +// outputFormatter.PrintText(ConvertTypeString(typeReference.Type)); +// } else { +// outputFormatter.PrintIdentifier(typeReference.Type); +// } +// if (printGenerics && typeReference.GenericTypes != null && typeReference.GenericTypes.Count > 0) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// outputFormatter.PrintToken(Tokens.Of); +// outputFormatter.Space(); +// AppendCommaSeparatedList(typeReference.GenericTypes); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// for (int i = 0; i < typeReference.PointerNestingLevel; ++i) { +// outputFormatter.PrintToken(Tokens.Times); +// } +// } +// +// void PrintArrayRank(int[] rankSpecifier, int startRank) +// { +// for (int i = startRank; i < rankSpecifier.Length; ++i) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// for (int j = 0; j < rankSpecifier[i]; ++j) { +// outputFormatter.PrintToken(Tokens.Comma); +// } +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// } +// +// public override object TrackedVisitInnerClassTypeReference(InnerClassTypeReference innerClassTypeReference, object data) +// { +// TrackedVisit(innerClassTypeReference.BaseType, data); +// outputFormatter.PrintToken(Tokens.Dot); +// return VisitTypeReference((TypeReference)innerClassTypeReference, data); +// } +// +// #region Global scope +// bool printAttributeSectionInline; // is set to true when printing parameter's attributes +// +// public override object TrackedVisitAttributeSection(AttributeSection attributeSection, object data) +// { +// if (!printAttributeSectionInline) +// outputFormatter.Indent(); +// outputFormatter.PrintText("<"); +// if (!string.IsNullOrEmpty(attributeSection.AttributeTarget) && !string.Equals(attributeSection.AttributeTarget, "return", StringComparison.OrdinalIgnoreCase)) { +// outputFormatter.PrintText(char.ToUpperInvariant(attributeSection.AttributeTarget[0]) + attributeSection.AttributeTarget.Substring(1)); +// outputFormatter.PrintToken(Tokens.Colon); +// outputFormatter.Space(); +// } +// Debug.Assert(attributeSection.Attributes != null); +// AppendCommaSeparatedList(attributeSection.Attributes); +// +// outputFormatter.PrintText(">"); +// +// if ("assembly".Equals(attributeSection.AttributeTarget, StringComparison.InvariantCultureIgnoreCase) +// || "module".Equals(attributeSection.AttributeTarget, StringComparison.InvariantCultureIgnoreCase)) { +// outputFormatter.NewLine(); +// } else { +// if (printAttributeSectionInline) +// outputFormatter.Space(); +// else +// outputFormatter.PrintLineContinuation(); +// } +// +// return null; +// } +// +// public override object TrackedVisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) +// { +// outputFormatter.PrintIdentifier(attribute.Type); +// if (attribute.PositionalArguments.Count > 0 || attribute.NamedArguments.Count > 0) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(attribute.PositionalArguments); +// +// if (attribute.NamedArguments.Count > 0) { +// if (attribute.PositionalArguments.Count > 0) { +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// } +// AppendCommaSeparatedList(attribute.NamedArguments); +// } +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// return null; +// } +// +// public override object TrackedVisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) +// { +// outputFormatter.PrintIdentifier(namedArgumentExpression.Name); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Colon); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(namedArgumentExpression.Expression, data); +// return null; +// } +// +// public override object TrackedVisitUsing(ImportsClause @using, object data) +// { +// Debug.Fail("Should never be called. The usings should be handled in Visit(UsingDeclaration)"); +// return null; +// } +// +// public override object TrackedVisitUsingDeclaration(ImportsStatement usingDeclaration, object data) +// { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Imports); +// outputFormatter.Space(); +// for (int i = 0; i < usingDeclaration.ImportsClauses.Count; ++i) { +// outputFormatter.PrintIdentifier(((ImportsClause)usingDeclaration.ImportsClauses[i]).Name); +// if (((ImportsClause)usingDeclaration.ImportsClauses[i]).IsAlias) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(((ImportsClause)usingDeclaration.ImportsClauses[i]).Alias, data); +// } +// if (i + 1 < usingDeclaration.ImportsClauses.Count) { +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// } +// } +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) +// { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Namespace); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(namespaceDeclaration.Name); +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// namespaceDeclaration.AcceptChildren(this, data); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Namespace); +// outputFormatter.NewLine(); +// return null; +// } +// +// static int GetTypeToken(TypeDeclaration typeDeclaration) +// { +// switch (typeDeclaration.Type) { +// case ClassType.Class: +// return Tokens.Class; +// case ClassType.Enum: +// return Tokens.Enum; +// case ClassType.Interface: +// return Tokens.Interface; +// case ClassType.Struct: +// return Tokens.Structure; +// case ClassType.Module: +// return Tokens.Module; +// default: +// return Tokens.Class; +// } +// } +// +// void PrintTemplates(List templates) +// { +// if (templates != null && templates.Count > 0) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// outputFormatter.PrintToken(Tokens.Of); +// outputFormatter.Space(); +// AppendCommaSeparatedList(templates); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// } +// +// public override object TrackedVisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) +// { +// VisitAttributes(typeDeclaration.Attributes, data); +// +// outputFormatter.Indent(); +// OutputModifier(typeDeclaration.Modifier, true, false); +// +// int typeToken = GetTypeToken(typeDeclaration); +// outputFormatter.PrintToken(typeToken); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(typeDeclaration.Name); +// +// PrintTemplates(typeDeclaration.Templates); +// +// if (typeDeclaration.Type == ClassType.Enum +// && typeDeclaration.BaseTypes != null && typeDeclaration.BaseTypes.Count > 0) +// { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// foreach (TypeReference baseTypeRef in typeDeclaration.BaseTypes) { +// TrackedVisit(baseTypeRef, data); +// } +// } +// +// outputFormatter.NewLine(); +// ++outputFormatter.IndentationLevel; +// +// if (typeDeclaration.BaseTypes != null && typeDeclaration.Type != ClassType.Enum) { +// foreach (TypeReference baseTypeRef in typeDeclaration.BaseTypes) { +// outputFormatter.Indent(); +// +// string baseType = baseTypeRef.Type; +// if (baseType.IndexOf('.') >= 0) { +// baseType = baseType.Substring(baseType.LastIndexOf('.') + 1); +// } +// bool baseTypeIsInterface = baseType.Length >= 2 && baseType[0] == 'I' && Char.IsUpper(baseType[1]); +// +// if (!baseTypeIsInterface || typeDeclaration.Type == ClassType.Interface) { +// outputFormatter.PrintToken(Tokens.Inherits); +// } else { +// outputFormatter.PrintToken(Tokens.Implements); +// } +// outputFormatter.Space(); +// TrackedVisit(baseTypeRef, data); +// outputFormatter.NewLine(); +// } +// } +// +// TypeDeclaration oldType = currentType; +// currentType = typeDeclaration; +// +// if (typeDeclaration.Type == ClassType.Enum) { +// OutputEnumMembers(typeDeclaration, data); +// } else { +// typeDeclaration.AcceptChildren(this, data); +// } +// currentType = oldType; +// +// --outputFormatter.IndentationLevel; +// +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(typeToken); +// outputFormatter.NewLine(); +// return null; +// } +// +// void OutputEnumMembers(TypeDeclaration typeDeclaration, object data) +// { +// foreach (FieldDeclaration fieldDeclaration in typeDeclaration.Children) { +// BeginVisit(fieldDeclaration); +// VariableDeclaration f = (VariableDeclaration)fieldDeclaration.Fields[0]; +// VisitAttributes(fieldDeclaration.Attributes, data); +// outputFormatter.Indent(); +// outputFormatter.PrintIdentifier(f.Name); +// if (f.Initializer != null && !f.Initializer.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(f.Initializer, data); +// } +// outputFormatter.NewLine(); +// EndVisit(fieldDeclaration); +// } +// } +// +// public override object TrackedVisitTemplateDefinition(TemplateDefinition templateDefinition, object data) +// { +// VisitAttributes(templateDefinition.Attributes, data); +// switch (templateDefinition.VarianceModifier) { +// case VarianceModifier.Invariant: +// // nothing +// break; +// case VarianceModifier.Covariant: +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Out); +// outputFormatter.Space(); +// break; +// case VarianceModifier.Contravariant: +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.In); +// outputFormatter.Space(); +// break; +// default: +// throw new Exception("Invalid value for VarianceModifier"); +// } +// outputFormatter.PrintIdentifier(templateDefinition.Name); +// if (templateDefinition.Bases.Count > 0) { +// outputFormatter.PrintText(" As "); +// VisitReturnTypeAttributes(templateDefinition.Attributes, data); +// if (templateDefinition.Bases.Count == 1) { +// TrackedVisit(templateDefinition.Bases[0], data); +// } else { +// outputFormatter.PrintToken(Tokens.OpenCurlyBrace); +// AppendCommaSeparatedList(templateDefinition.Bases); +// outputFormatter.PrintToken(Tokens.CloseCurlyBrace); +// } +// } +// return null; +// } +// +// public override object TrackedVisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) +// { +// VisitAttributes(delegateDeclaration.Attributes, data); +// +// outputFormatter.Indent(); +// OutputModifier(delegateDeclaration.Modifier, true, false); +// outputFormatter.PrintToken(Tokens.Delegate); +// outputFormatter.Space(); +// +// bool isFunction = (delegateDeclaration.ReturnType.Type != "System.Void"); +// if (isFunction) { +// outputFormatter.PrintToken(Tokens.Function); +// outputFormatter.Space(); +// } else { +// outputFormatter.PrintToken(Tokens.Sub); +// outputFormatter.Space(); +// } +// outputFormatter.PrintIdentifier(delegateDeclaration.Name); +// +// PrintTemplates(delegateDeclaration.Templates); +// +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(delegateDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// if (isFunction) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// VisitReturnTypeAttributes(delegateDeclaration.Attributes, data); +// TrackedVisit(delegateDeclaration.ReturnType, data); +// } +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitOptionDeclaration(OptionDeclaration optionDeclaration, object data) +// { +// outputFormatter.PrintToken(Tokens.Option); +// outputFormatter.Space(); +// switch (optionDeclaration.OptionType) { +// case OptionType.Strict: +// outputFormatter.PrintToken(Tokens.Strict); +// outputFormatter.Space(); +// outputFormatter.PrintToken(optionDeclaration.OptionValue ? Tokens.On : Tokens.Off); +// break; +// case OptionType.Explicit: +// outputFormatter.PrintToken(Tokens.Explicit); +// outputFormatter.Space(); +// outputFormatter.PrintToken(optionDeclaration.OptionValue ? Tokens.On : Tokens.Off); +// break; +// case OptionType.Infer: +// outputFormatter.PrintToken(Tokens.Infer); +// outputFormatter.Space(); +// outputFormatter.PrintToken(optionDeclaration.OptionValue ? Tokens.On : Tokens.Off); +// break; +// case OptionType.CompareBinary: +// outputFormatter.PrintToken(Tokens.Compare); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Binary); +// break; +// case OptionType.CompareText: +// outputFormatter.PrintToken(Tokens.Compare); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Text); +// break; +// } +// outputFormatter.NewLine(); +// return null; +// } +// #endregion +// +// #region Type level +// TypeReference currentVariableType; +// public override object TrackedVisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) +// { +// +// VisitAttributes(fieldDeclaration.Attributes, data); +// outputFormatter.Indent(); +// if (fieldDeclaration.Modifier == Modifiers.None) { +// outputFormatter.PrintToken(Tokens.Private); +// outputFormatter.Space(); +// } else { +// OutputModifier(fieldDeclaration.Modifier, false, true); +// } +// currentVariableType = fieldDeclaration.TypeReference; +// AppendCommaSeparatedList(fieldDeclaration.Fields); +// currentVariableType = null; +// +// outputFormatter.NewLine(); +// +// return null; +// } +// +// public override object TrackedVisitVariableDeclaration(VariableDeclaration variableDeclaration, object data) +// { +// outputFormatter.PrintIdentifier(variableDeclaration.Name); +// +// TypeReference varType = currentVariableType; +// if (varType != null && varType.IsNull) +// varType = null; +// if (varType == null && !variableDeclaration.TypeReference.IsNull) +// varType = variableDeclaration.TypeReference; +// +// if (varType != null) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// ObjectCreateExpression init = variableDeclaration.Initializer as ObjectCreateExpression; +// if (init != null && TypeReference.AreEqualReferences(init.CreateType, varType)) { +// TrackedVisit(variableDeclaration.Initializer, data); +// return null; +// } else { +// TrackedVisit(varType, data); +// } +// } +// +// if (!variableDeclaration.Initializer.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(variableDeclaration.Initializer, data); +// } +// return null; +// } +// +// public override object TrackedVisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) +// { +// VisitAttributes(propertyDeclaration.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(propertyDeclaration.Modifier); +// +// if ((propertyDeclaration.Modifier & (Modifiers.ReadOnly | Modifiers.WriteOnly)) == Modifiers.None) { +// if (propertyDeclaration.IsReadOnly) { +// outputFormatter.PrintToken(Tokens.ReadOnly); +// outputFormatter.Space(); +// } else if (propertyDeclaration.IsWriteOnly) { +// outputFormatter.PrintToken(Tokens.WriteOnly); +// outputFormatter.Space(); +// } +// } +// +// outputFormatter.PrintToken(Tokens.Property); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(propertyDeclaration.Name); +// +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(propertyDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// if (!propertyDeclaration.TypeReference.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// +// VisitReturnTypeAttributes(propertyDeclaration.Attributes, data); +// +// ObjectCreateExpression init = propertyDeclaration.Initializer as ObjectCreateExpression; +// if (init != null && TypeReference.AreEqualReferences(init.CreateType, propertyDeclaration.TypeReference)) { +// TrackedVisit(propertyDeclaration.Initializer, data); +// } else { +// TrackedVisit(propertyDeclaration.TypeReference, data); +// } +// } +// +// PrintInterfaceImplementations(propertyDeclaration.InterfaceImplementations); +// +// if (!propertyDeclaration.Initializer.IsNull && !(propertyDeclaration.Initializer is ObjectCreateExpression)) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(propertyDeclaration.Initializer, data); +// } +// +// outputFormatter.NewLine(); +// +// if (!IsAbstract(propertyDeclaration) && (propertyDeclaration.GetRegion.Block != NullBlockStatement.Instance || propertyDeclaration.SetRegion.Block != NullBlockStatement.Instance)) { +// outputFormatter.IsInMemberBody = true; +// ++outputFormatter.IndentationLevel; +// exitTokenStack.Push(Tokens.Property); +// TrackedVisit(propertyDeclaration.GetRegion, data); +// TrackedVisit(propertyDeclaration.SetRegion, data); +// exitTokenStack.Pop(); +// --outputFormatter.IndentationLevel; +// outputFormatter.IsInMemberBody = false; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Property); +// outputFormatter.NewLine(); +// } +// +// return null; +// } +// +// public override object TrackedVisitPropertyGetRegion(PropertyGetRegion propertyGetRegion, object data) +// { +// VisitAttributes(propertyGetRegion.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(propertyGetRegion.Modifier); +// outputFormatter.PrintToken(Tokens.Get); +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// TrackedVisit(propertyGetRegion.Block, data); +// --outputFormatter.IndentationLevel; +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Get); +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitPropertySetRegion(PropertySetRegion propertySetRegion, object data) +// { +// VisitAttributes(propertySetRegion.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(propertySetRegion.Modifier); +// outputFormatter.PrintToken(Tokens.Set); +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// TrackedVisit(propertySetRegion.Block, data); +// --outputFormatter.IndentationLevel; +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Set); +// outputFormatter.NewLine(); +// return null; +// } +// +// TypeReference currentEventType = null; +// public override object TrackedVisitEventDeclaration(EventDeclaration eventDeclaration, object data) +// { +// bool customEvent = eventDeclaration.HasAddRegion || eventDeclaration.HasRemoveRegion; +// +// VisitAttributes(eventDeclaration.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(eventDeclaration.Modifier); +// if (customEvent) { +// outputFormatter.PrintText("Custom"); +// outputFormatter.Space(); +// } +// +// outputFormatter.PrintToken(Tokens.Event); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(eventDeclaration.Name); +// +// if (eventDeclaration.Parameters.Count > 0) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// this.AppendCommaSeparatedList(eventDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// if (!eventDeclaration.TypeReference.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// VisitReturnTypeAttributes(eventDeclaration.Attributes, data); +// TrackedVisit(eventDeclaration.TypeReference, data); +// } +// +// PrintInterfaceImplementations(eventDeclaration.InterfaceImplementations); +// +// if (!eventDeclaration.Initializer.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(eventDeclaration.Initializer, data); +// } +// +// outputFormatter.NewLine(); +// +// if (customEvent) { +// ++outputFormatter.IndentationLevel; +// currentEventType = eventDeclaration.TypeReference; +// exitTokenStack.Push(Tokens.Sub); +// TrackedVisit(eventDeclaration.AddRegion, data); +// TrackedVisit(eventDeclaration.RemoveRegion, data); +// exitTokenStack.Pop(); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Event); +// outputFormatter.NewLine(); +// } +// return null; +// } +// +// void PrintInterfaceImplementations(IList list) +// { +// if (list == null || list.Count == 0) +// return; +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Implements); +// for (int i = 0; i < list.Count; i++) { +// if (i > 0) +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(list[i].InterfaceType, null); +// outputFormatter.PrintToken(Tokens.Dot); +// outputFormatter.PrintIdentifier(list[i].MemberName); +// } +// } +// +// public override object TrackedVisitEventAddRegion(EventAddRegion eventAddRegion, object data) +// { +// VisitAttributes(eventAddRegion.Attributes, data); +// outputFormatter.Indent(); +// outputFormatter.PrintText("AddHandler("); +// if (eventAddRegion.Parameters.Count == 0) { +// outputFormatter.PrintToken(Tokens.ByVal); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier("value"); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// TrackedVisit(currentEventType, data); +// } else { +// this.AppendCommaSeparatedList(eventAddRegion.Parameters); +// } +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// TrackedVisit(eventAddRegion.Block, data); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintText("AddHandler"); +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitEventRemoveRegion(EventRemoveRegion eventRemoveRegion, object data) +// { +// VisitAttributes(eventRemoveRegion.Attributes, data); +// outputFormatter.Indent(); +// outputFormatter.PrintText("RemoveHandler"); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// if (eventRemoveRegion.Parameters.Count == 0) { +// outputFormatter.PrintToken(Tokens.ByVal); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier("value"); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// TrackedVisit(currentEventType, data); +// } else { +// this.AppendCommaSeparatedList(eventRemoveRegion.Parameters); +// } +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// TrackedVisit(eventRemoveRegion.Block, data); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintText("RemoveHandler"); +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitEventRaiseRegion(EventRaiseRegion eventRaiseRegion, object data) +// { +// VisitAttributes(eventRaiseRegion.Attributes, data); +// outputFormatter.Indent(); +// outputFormatter.PrintText("RaiseEvent"); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// if (eventRaiseRegion.Parameters.Count == 0) { +// outputFormatter.PrintToken(Tokens.ByVal); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier("value"); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// TrackedVisit(currentEventType, data); +// } else { +// this.AppendCommaSeparatedList(eventRaiseRegion.Parameters); +// } +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// TrackedVisit(eventRaiseRegion.Block, data); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintText("RaiseEvent"); +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitParameterDeclarationExpression(ParameterDeclarationExpression parameterDeclarationExpression, object data) +// { +// printAttributeSectionInline = true; +// VisitAttributes(parameterDeclarationExpression.Attributes, data); +// printAttributeSectionInline = false; +// OutputModifier(parameterDeclarationExpression.ParamModifier); +// outputFormatter.PrintIdentifier(parameterDeclarationExpression.ParameterName); +// if (!parameterDeclarationExpression.TypeReference.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// VisitReturnTypeAttributes(parameterDeclarationExpression.Attributes, data); +// TrackedVisit(parameterDeclarationExpression.TypeReference, data); +// } +// if (!parameterDeclarationExpression.DefaultValue.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(parameterDeclarationExpression.DefaultValue, data); +// } +// return null; +// } +// +// public override object TrackedVisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) +// { +// VisitAttributes(methodDeclaration.Attributes, data); +// if (methodDeclaration.IsExtensionMethod) { +// outputFormatter.Indent(); +// outputFormatter.PrintText(" _"); +// outputFormatter.NewLine(); +// } +// outputFormatter.Indent(); +// OutputModifier(methodDeclaration.Modifier); +// +// bool isSub = methodDeclaration.TypeReference.IsNull || +// methodDeclaration.TypeReference.Type == "System.Void"; +// +// if (isSub) { +// outputFormatter.PrintToken(Tokens.Sub); +// } else { +// outputFormatter.PrintToken(Tokens.Function); +// } +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(methodDeclaration.Name); +// +// PrintTemplates(methodDeclaration.Templates); +// +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(methodDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// if (!isSub) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// VisitReturnTypeAttributes(methodDeclaration.Attributes, data); +// TrackedVisit(methodDeclaration.TypeReference, data); +// } +// +// PrintInterfaceImplementations(methodDeclaration.InterfaceImplementations); +// +// if (methodDeclaration.HandlesClause.Count > 0) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Handles); +// for (int i = 0; i < methodDeclaration.HandlesClause.Count; i++) { +// if (i > 0) +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// outputFormatter.PrintText(methodDeclaration.HandlesClause[i]); +// } +// } +// +// outputFormatter.NewLine(); +// +// if (!IsAbstract(methodDeclaration)) { +// outputFormatter.IsInMemberBody = true; +// BeginVisit(methodDeclaration.Body); +// ++outputFormatter.IndentationLevel; +// exitTokenStack.Push(isSub ? Tokens.Sub : Tokens.Function); +// // we're doing the tracking manually using BeginVisit/EndVisit, so call Tracked... directly +// this.TrackedVisitBlockStatement(methodDeclaration.Body, data); +// exitTokenStack.Pop(); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// if (isSub) { +// outputFormatter.PrintToken(Tokens.Sub); +// } else { +// outputFormatter.PrintToken(Tokens.Function); +// } +// outputFormatter.NewLine(); +// EndVisit(methodDeclaration.Body); +// outputFormatter.IsInMemberBody = false; +// } +// return null; +// } +// +// public override object TrackedVisitInterfaceImplementation(InterfaceImplementation interfaceImplementation, object data) +// { +// throw new InvalidOperationException(); +// } +// +// bool IsAbstract(AttributedNode node) +// { +// if ((node.Modifier & Modifiers.Abstract) == Modifiers.Abstract) +// return true; +// return currentType != null && currentType.Type == ClassType.Interface; +// } +// +// public override object TrackedVisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) +// { +// VisitAttributes(constructorDeclaration.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(constructorDeclaration.Modifier); +// outputFormatter.PrintToken(Tokens.Sub); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.New); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(constructorDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// outputFormatter.NewLine(); +// +// outputFormatter.IsInMemberBody = true; +// ++outputFormatter.IndentationLevel; +// exitTokenStack.Push(Tokens.Sub); +// +// TrackedVisit(constructorDeclaration.ConstructorInitializer, data); +// +// TrackedVisit(constructorDeclaration.Body, data); +// exitTokenStack.Pop(); +// --outputFormatter.IndentationLevel; +// outputFormatter.IsInMemberBody = false; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Sub); +// outputFormatter.NewLine(); +// +// return null; +// } +// +// public override object TrackedVisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) +// { +// outputFormatter.Indent(); +// if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) { +// outputFormatter.PrintToken(Tokens.Me); +// } else { +// outputFormatter.PrintToken(Tokens.MyBase); +// } +// outputFormatter.PrintToken(Tokens.Dot); +// outputFormatter.PrintToken(Tokens.New); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(constructorInitializer.Arguments); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// outputFormatter.NewLine(); +// return null; +// } +// +// public override object TrackedVisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) +// { +// VisitAttributes(operatorDeclaration.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(operatorDeclaration.Modifier); +// +// if (operatorDeclaration.IsConversionOperator) { +// if (operatorDeclaration.ConversionType == ConversionType.Implicit) { +// outputFormatter.PrintToken(Tokens.Widening); +// } else { +// outputFormatter.PrintToken(Tokens.Narrowing); +// } +// outputFormatter.Space(); +// } +// +// outputFormatter.PrintToken(Tokens.Operator); +// outputFormatter.Space(); +// +// int op = -1; +// +// switch(operatorDeclaration.OverloadableOperator) +// { +// case OverloadableOperatorType.Add: +// case OverloadableOperatorType.UnaryPlus: +// op = Tokens.Plus; +// break; +// case OverloadableOperatorType.UnaryMinus: +// case OverloadableOperatorType.Subtract: +// op = Tokens.Minus; +// break; +// case OverloadableOperatorType.Multiply: +// op = Tokens.Times; +// break; +// case OverloadableOperatorType.Divide: +// op = Tokens.Div; +// break; +// case OverloadableOperatorType.Modulus: +// op = Tokens.Mod; +// break; +// case OverloadableOperatorType.Concat: +// op = Tokens.ConcatString; +// break; +// case OverloadableOperatorType.Not: +// op = Tokens.Not; +// break; +// case OverloadableOperatorType.BitNot: +// op = Tokens.Not; +// break; +// case OverloadableOperatorType.BitwiseAnd: +// op = Tokens.And; +// break; +// case OverloadableOperatorType.BitwiseOr: +// op = Tokens.Or; +// break; +// case OverloadableOperatorType.ExclusiveOr: +// op = Tokens.Xor; +// break; +// case OverloadableOperatorType.ShiftLeft: +// op = Tokens.ShiftLeft; +// break; +// case OverloadableOperatorType.ShiftRight: +// op = Tokens.ShiftRight; +// break; +// case OverloadableOperatorType.GreaterThan: +// op = Tokens.GreaterThan; +// break; +// case OverloadableOperatorType.GreaterThanOrEqual: +// op = Tokens.GreaterEqual; +// break; +// case OverloadableOperatorType.Equality: +// op = Tokens.Assign; +// break; +// case OverloadableOperatorType.InEquality: +// op = Tokens.NotEqual; +// break; +// case OverloadableOperatorType.LessThan: +// op = Tokens.LessThan; +// break; +// case OverloadableOperatorType.LessThanOrEqual: +// op = Tokens.LessEqual; +// break; +// case OverloadableOperatorType.Increment: +// Error("Increment operator is not supported in Visual Basic", operatorDeclaration.StartLocation); +// break; +// case OverloadableOperatorType.Decrement: +// Error("Decrement operator is not supported in Visual Basic", operatorDeclaration.StartLocation); +// break; +// case OverloadableOperatorType.IsTrue: +// outputFormatter.PrintText("IsTrue"); +// break; +// case OverloadableOperatorType.IsFalse: +// outputFormatter.PrintText("IsFalse"); +// break; +// case OverloadableOperatorType.Like: +// op = Tokens.Like; +// break; +// case OverloadableOperatorType.Power: +// op = Tokens.Power; +// break; +// case OverloadableOperatorType.CType: +// op = Tokens.CType; +// break; +// case OverloadableOperatorType.DivideInteger: +// op = Tokens.DivInteger; +// break; +// } +// +// +// +// if (operatorDeclaration.IsConversionOperator) { +// outputFormatter.PrintToken(Tokens.CType); +// } else { +// if(op != -1) outputFormatter.PrintToken(op); +// } +// +// PrintTemplates(operatorDeclaration.Templates); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(operatorDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// if (!operatorDeclaration.TypeReference.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// VisitReturnTypeAttributes(operatorDeclaration.Attributes, data); +// TrackedVisit(operatorDeclaration.TypeReference, data); +// } +// +// outputFormatter.NewLine(); +// +// ++outputFormatter.IndentationLevel; +// TrackedVisit(operatorDeclaration.Body, data); +// --outputFormatter.IndentationLevel; +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Operator); +// outputFormatter.NewLine(); +// +// return null; +// } +// +// public override object TrackedVisitDeclareDeclaration(DeclareDeclaration declareDeclaration, object data) +// { +// VisitAttributes(declareDeclaration.Attributes, data); +// outputFormatter.Indent(); +// OutputModifier(declareDeclaration.Modifier); +// outputFormatter.PrintToken(Tokens.Declare); +// outputFormatter.Space(); +// +// switch (declareDeclaration.Charset) { +// case CharsetModifier.Auto: +// outputFormatter.PrintToken(Tokens.Auto); +// outputFormatter.Space(); +// break; +// case CharsetModifier.Unicode: +// outputFormatter.PrintToken(Tokens.Unicode); +// outputFormatter.Space(); +// break; +// case CharsetModifier.Ansi: +// outputFormatter.PrintToken(Tokens.Ansi); +// outputFormatter.Space(); +// break; +// } +// +// bool isVoid = declareDeclaration.TypeReference.IsNull || declareDeclaration.TypeReference.Type == "System.Void"; +// if (isVoid) { +// outputFormatter.PrintToken(Tokens.Sub); +// } else { +// outputFormatter.PrintToken(Tokens.Function); +// } +// outputFormatter.Space(); +// +// outputFormatter.PrintIdentifier(declareDeclaration.Name); +// +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Lib); +// outputFormatter.Space(); +// outputFormatter.PrintText(ConvertString(declareDeclaration.Library)); +// outputFormatter.Space(); +// +// if (declareDeclaration.Alias.Length > 0) { +// outputFormatter.PrintToken(Tokens.Alias); +// outputFormatter.Space(); +// outputFormatter.PrintText(ConvertString(declareDeclaration.Alias)); +// outputFormatter.Space(); +// } +// +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(declareDeclaration.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// if (!isVoid) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// VisitReturnTypeAttributes(declareDeclaration.Attributes, data); +// TrackedVisit(declareDeclaration.TypeReference, data); +// } +// +// outputFormatter.NewLine(); +// +// return null; +// } +// #endregion +// +// #region Statements +// public override object TrackedVisitBlockStatement(BlockStatement blockStatement, object data) +// { +// if (blockStatement.Parent is BlockStatement) { +// outputFormatter.Indent(); +// outputFormatter.PrintText("If True Then"); +// outputFormatter.NewLine(); +// outputFormatter.IndentationLevel += 1; +// } +// VisitStatementList(blockStatement.Children); +// if (blockStatement.Parent is BlockStatement) { +// outputFormatter.IndentationLevel -= 1; +// outputFormatter.Indent(); +// outputFormatter.PrintText("End If"); +// outputFormatter.NewLine(); +// } +// return null; +// } +// +// void PrintIndentedBlock(Statement stmt) +// { +// outputFormatter.IndentationLevel += 1; +// if (stmt is BlockStatement) { +// TrackedVisit(stmt, null); +// } else { +// outputFormatter.Indent(); +// TrackedVisit(stmt, null); +// outputFormatter.NewLine(); +// } +// outputFormatter.IndentationLevel -= 1; +// } +// +// void PrintIndentedBlock(IEnumerable statements) +// { +// outputFormatter.IndentationLevel += 1; +// VisitStatementList(statements); +// outputFormatter.IndentationLevel -= 1; +// } +// +// void VisitStatementList(IEnumerable statements) +// { +// foreach (Statement stmt in statements) { +// if (stmt is BlockStatement) { +// TrackedVisit(stmt, null); +// } else { +// outputFormatter.Indent(); +// TrackedVisit(stmt, null); +// outputFormatter.NewLine(); +// } +// } +// } +// +// public override object TrackedVisitAddHandlerStatement(AddHandlerStatement addHandlerStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.AddHandler); +// outputFormatter.Space(); +// TrackedVisit(addHandlerStatement.EventExpression, data); +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(addHandlerStatement.HandlerExpression, data); +// return null; +// } +// +// public override object TrackedVisitRemoveHandlerStatement(RemoveHandlerStatement removeHandlerStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.RemoveHandler); +// outputFormatter.Space(); +// TrackedVisit(removeHandlerStatement.EventExpression, data); +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(removeHandlerStatement.HandlerExpression, data); +// return null; +// } +// +// public override object TrackedVisitRaiseEventStatement(RaiseEventStatement raiseEventStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.RaiseEvent); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(raiseEventStatement.EventName); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(raiseEventStatement.Arguments); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// public override object TrackedVisitEraseStatement(EraseStatement eraseStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Erase); +// outputFormatter.Space(); +// AppendCommaSeparatedList(eraseStatement.Expressions); +// return null; +// } +// +// public override object TrackedVisitErrorStatement(ErrorStatement errorStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Error); +// outputFormatter.Space(); +// TrackedVisit(errorStatement.Expression, data); +// return null; +// } +// +// public override object TrackedVisitOnErrorStatement(OnErrorStatement onErrorStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.On); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Error); +// outputFormatter.Space(); +// TrackedVisit(onErrorStatement.EmbeddedStatement, data); +// return null; +// } +// +// public override object TrackedVisitReDimStatement(ReDimStatement reDimStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.ReDim); +// outputFormatter.Space(); +// if (reDimStatement.IsPreserve) { +// outputFormatter.PrintToken(Tokens.Preserve); +// outputFormatter.Space(); +// } +// +// AppendCommaSeparatedList(reDimStatement.ReDimClauses); +// return null; +// } +// +// public override object TrackedVisitExpressionStatement(ExpressionStatement expressionStatement, object data) +// { +// TrackedVisit(expressionStatement.Expression, data); +// return null; +// } +// +// public override object TrackedVisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data) +// { +// if (localVariableDeclaration.Modifier != Modifiers.None) { +// OutputModifier(localVariableDeclaration.Modifier & ~Modifiers.Dim); +// } +// if (!isUsingResourceAcquisition) { +// if ((localVariableDeclaration.Modifier & Modifiers.Const) == 0) { +// outputFormatter.PrintToken(Tokens.Dim); +// } +// outputFormatter.Space(); +// } +// currentVariableType = localVariableDeclaration.TypeReference; +// +// AppendCommaSeparatedList(localVariableDeclaration.Variables); +// currentVariableType = null; +// +// return null; +// } +// +// public override object TrackedVisitReturnStatement(ReturnStatement returnStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Return); +// if (!returnStatement.Expression.IsNull) { +// outputFormatter.Space(); +// TrackedVisit(returnStatement.Expression, data); +// } +// return null; +// } +// +// public override object TrackedVisitIfElseStatement(IfElseStatement ifElseStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.If); +// outputFormatter.Space(); +// TrackedVisit(ifElseStatement.Condition, data); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Then); +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(ifElseStatement.TrueStatement); +// +// foreach (ElseIfSection elseIfSection in ifElseStatement.ElseIfSections) { +// TrackedVisit(elseIfSection, data); +// } +// +// if (ifElseStatement.HasElseStatements) { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Else); +// outputFormatter.NewLine(); +// PrintIndentedBlock(ifElseStatement.FalseStatement); +// } +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.If); +// return null; +// } +// +// public override object TrackedVisitElseIfSection(ElseIfSection elseIfSection, object data) +// { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.ElseIf); +// outputFormatter.Space(); +// TrackedVisit(elseIfSection.Condition, data); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Then); +// outputFormatter.NewLine(); +// PrintIndentedBlock(elseIfSection.EmbeddedStatement); +// return null; +// } +// +// public override object TrackedVisitLabelStatement(LabelStatement labelStatement, object data) +// { +// outputFormatter.PrintIdentifier(labelStatement.Label); +// outputFormatter.PrintToken(Tokens.Colon); +// return null; +// } +// +// public override object TrackedVisitGotoStatement(GotoStatement gotoStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.GoTo); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(gotoStatement.Label); +// return null; +// } +// +// public override object TrackedVisitSwitchStatement(SwitchStatement switchStatement, object data) +// { +// exitTokenStack.Push(Tokens.Select); +// outputFormatter.PrintToken(Tokens.Select); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Case); +// outputFormatter.Space(); +// TrackedVisit(switchStatement.SwitchExpression, data); +// outputFormatter.NewLine(); +// ++outputFormatter.IndentationLevel; +// foreach (SwitchSection section in switchStatement.SwitchSections) { +// TrackedVisit(section, data); +// } +// --outputFormatter.IndentationLevel; +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Select); +// exitTokenStack.Pop(); +// return null; +// } +// +// public override object TrackedVisitSwitchSection(SwitchSection switchSection, object data) +// { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Case); +// outputFormatter.Space(); +// this.AppendCommaSeparatedList(switchSection.SwitchLabels); +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(switchSection.Children); +// +// return null; +// } +// +// public override object TrackedVisitCaseLabel(CaseLabel caseLabel, object data) +// { +// if (caseLabel.IsDefault) { +// outputFormatter.PrintToken(Tokens.Else); +// } else { +// if (caseLabel.BinaryOperatorType != BinaryOperatorType.None) { +// switch (caseLabel.BinaryOperatorType) { +// case BinaryOperatorType.Equality: +// outputFormatter.PrintToken(Tokens.Assign); +// break; +// case BinaryOperatorType.InEquality: +// outputFormatter.PrintToken(Tokens.LessThan); +// outputFormatter.PrintToken(Tokens.GreaterThan); +// break; +// +// case BinaryOperatorType.GreaterThan: +// outputFormatter.PrintToken(Tokens.GreaterThan); +// break; +// case BinaryOperatorType.GreaterThanOrEqual: +// outputFormatter.PrintToken(Tokens.GreaterEqual); +// break; +// case BinaryOperatorType.LessThan: +// outputFormatter.PrintToken(Tokens.LessThan); +// break; +// case BinaryOperatorType.LessThanOrEqual: +// outputFormatter.PrintToken(Tokens.LessEqual); +// break; +// } +// outputFormatter.Space(); +// } +// +// TrackedVisit(caseLabel.Label, data); +// if (!caseLabel.ToExpression.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.To); +// outputFormatter.Space(); +// TrackedVisit(caseLabel.ToExpression, data); +// } +// } +// +// return null; +// } +// +// public override object TrackedVisitStopStatement(StopStatement stopStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Stop); +// return null; +// } +// +// public override object TrackedVisitResumeStatement(ResumeStatement resumeStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Resume); +// outputFormatter.Space(); +// if (resumeStatement.IsResumeNext) { +// outputFormatter.PrintToken(Tokens.Next); +// } else { +// outputFormatter.PrintIdentifier(resumeStatement.LabelName); +// } +// return null; +// } +// +// public override object TrackedVisitEndStatement(EndStatement endStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.End); +// return null; +// } +// +// public override object TrackedVisitContinueStatement(ContinueStatement continueStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Continue); +// outputFormatter.Space(); +// switch (continueStatement.ContinueType) { +// case ContinueType.Do: +// outputFormatter.PrintToken(Tokens.Do); +// break; +// case ContinueType.For: +// outputFormatter.PrintToken(Tokens.For); +// break; +// case ContinueType.While: +// outputFormatter.PrintToken(Tokens.While); +// break; +// default: +// outputFormatter.PrintToken(exitTokenStack.Peek()); +// break; +// } +// return null; +// } +// +// public override object TrackedVisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) +// { +// if (doLoopStatement.ConditionPosition == ConditionPosition.None) { +// Error(String.Format("Unknown condition position for loop : {0}.", doLoopStatement), doLoopStatement.StartLocation); +// } +// +// if (doLoopStatement.ConditionPosition == ConditionPosition.Start) { +// switch (doLoopStatement.ConditionType) { +// case ConditionType.DoWhile: +// exitTokenStack.Push(Tokens.Do); +// outputFormatter.PrintToken(Tokens.Do); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.While); +// break; +// case ConditionType.While: +// exitTokenStack.Push(Tokens.While); +// outputFormatter.PrintToken(Tokens.While); +// break; +// case ConditionType.Until: +// exitTokenStack.Push(Tokens.Do); +// outputFormatter.PrintToken(Tokens.Do); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.While); +// break; +// default: +// throw new InvalidOperationException(); +// } +// outputFormatter.Space(); +// TrackedVisit(doLoopStatement.Condition, null); +// } else { +// exitTokenStack.Push(Tokens.Do); +// outputFormatter.PrintToken(Tokens.Do); +// } +// +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(doLoopStatement.EmbeddedStatement); +// +// outputFormatter.Indent(); +// if (doLoopStatement.ConditionPosition == ConditionPosition.Start && doLoopStatement.ConditionType == ConditionType.While) { +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.While); +// } else { +// outputFormatter.PrintToken(Tokens.Loop); +// } +// +// if (doLoopStatement.ConditionPosition == ConditionPosition.End && !doLoopStatement.Condition.IsNull) { +// outputFormatter.Space(); +// switch (doLoopStatement.ConditionType) { +// case ConditionType.While: +// case ConditionType.DoWhile: +// outputFormatter.PrintToken(Tokens.While); +// break; +// case ConditionType.Until: +// outputFormatter.PrintToken(Tokens.Until); +// break; +// } +// outputFormatter.Space(); +// TrackedVisit(doLoopStatement.Condition, null); +// } +// exitTokenStack.Pop(); +// return null; +// } +// +// public override object TrackedVisitForeachStatement(ForeachStatement foreachStatement, object data) +// { +// exitTokenStack.Push(Tokens.For); +// outputFormatter.PrintToken(Tokens.For); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Each); +// outputFormatter.Space(); +// +// // loop control variable +// outputFormatter.PrintIdentifier(foreachStatement.VariableName); +// if (!foreachStatement.TypeReference.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// TrackedVisit(foreachStatement.TypeReference, data); +// } +// +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.In); +// outputFormatter.Space(); +// +// TrackedVisit(foreachStatement.Expression, data); +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(foreachStatement.EmbeddedStatement); +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Next); +// if (!foreachStatement.NextExpression.IsNull) { +// outputFormatter.Space(); +// TrackedVisit(foreachStatement.NextExpression, data); +// } +// exitTokenStack.Pop(); +// return null; +// } +// +// public override object TrackedVisitLockStatement(LockStatement lockStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.SyncLock); +// outputFormatter.Space(); +// TrackedVisit(lockStatement.LockExpression, data); +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(lockStatement.EmbeddedStatement); +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.SyncLock); +// return null; +// } +// +// bool isUsingResourceAcquisition; +// +// public override object TrackedVisitUsingStatement(UsingStatement usingStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Using); +// outputFormatter.Space(); +// +// isUsingResourceAcquisition = true; +// TrackedVisit(usingStatement.ResourceAcquisition, data); +// isUsingResourceAcquisition = false; +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(usingStatement.EmbeddedStatement); +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Using); +// +// return null; +// } +// +// public override object TrackedVisitWithStatement(WithStatement withStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.With); +// outputFormatter.Space(); +// TrackedVisit(withStatement.Expression, data); +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(withStatement.Body); +// +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.With); +// return null; +// } +// +// public override object TrackedVisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) +// { +// exitTokenStack.Push(Tokens.Try); +// outputFormatter.PrintToken(Tokens.Try); +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(tryCatchStatement.StatementBlock); +// +// foreach (CatchClause catchClause in tryCatchStatement.CatchClauses) { +// TrackedVisit(catchClause, data); +// } +// +// if (!tryCatchStatement.FinallyBlock.IsNull) { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Finally); +// outputFormatter.NewLine(); +// PrintIndentedBlock(tryCatchStatement.FinallyBlock); +// } +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Try); +// exitTokenStack.Pop(); +// return null; +// } +// +// public override object TrackedVisitCatchClause(CatchClause catchClause, object data) +// { +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Catch); +// +// if (!catchClause.TypeReference.IsNull) { +// outputFormatter.Space(); +// if (catchClause.VariableName.Length > 0) { +// outputFormatter.PrintIdentifier(catchClause.VariableName); +// } else { +// outputFormatter.PrintIdentifier("generatedExceptionName"); +// } +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(catchClause.TypeReference.Type); +// } +// +// if (!catchClause.Condition.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.When); +// outputFormatter.Space(); +// TrackedVisit(catchClause.Condition, data); +// } +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(catchClause.StatementBlock); +// +// return null; +// } +// +// public override object TrackedVisitThrowStatement(ThrowStatement throwStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Throw); +// if (!throwStatement.Expression.IsNull) { +// outputFormatter.Space(); +// TrackedVisit(throwStatement.Expression, data); +// } +// return null; +// } +// +// public override object TrackedVisitExitStatement(ExitStatement exitStatement, object data) +// { +// outputFormatter.PrintToken(Tokens.Exit); +// if (exitStatement.ExitType != ExitType.None) { +// outputFormatter.Space(); +// switch (exitStatement.ExitType) { +// case ExitType.Sub: +// outputFormatter.PrintToken(Tokens.Sub); +// break; +// case ExitType.Function: +// outputFormatter.PrintToken(Tokens.Function); +// break; +// case ExitType.Property: +// outputFormatter.PrintToken(Tokens.Property); +// break; +// case ExitType.Do: +// outputFormatter.PrintToken(Tokens.Do); +// break; +// case ExitType.For: +// outputFormatter.PrintToken(Tokens.For); +// break; +// case ExitType.Try: +// outputFormatter.PrintToken(Tokens.Try); +// break; +// case ExitType.While: +// outputFormatter.PrintToken(Tokens.While); +// break; +// case ExitType.Select: +// outputFormatter.PrintToken(Tokens.Select); +// break; +// default: +// Error(String.Format("Unsupported exit type : {0}", exitStatement.ExitType), exitStatement.StartLocation); +// break; +// } +// } +// +// return null; +// } +// +// public override object TrackedVisitForNextStatement(ForNextStatement forNextStatement, object data) +// { +// exitTokenStack.Push(Tokens.For); +// outputFormatter.PrintToken(Tokens.For); +// outputFormatter.Space(); +// +// if (!forNextStatement.LoopVariableExpression.IsNull) { +// TrackedVisit(forNextStatement.LoopVariableExpression, data); +// } else { +// outputFormatter.PrintIdentifier(forNextStatement.VariableName); +// +// if (!forNextStatement.TypeReference.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// TrackedVisit(forNextStatement.TypeReference, data); +// } +// } +// +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// +// TrackedVisit(forNextStatement.Start, data); +// +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.To); +// outputFormatter.Space(); +// +// TrackedVisit(forNextStatement.End, data); +// +// if (!forNextStatement.Step.IsNull) { +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Step); +// outputFormatter.Space(); +// TrackedVisit(forNextStatement.Step, data); +// } +// outputFormatter.NewLine(); +// +// PrintIndentedBlock(forNextStatement.EmbeddedStatement); +// +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.Next); +// +// if (forNextStatement.NextExpressions.Count > 0) { +// outputFormatter.Space(); +// AppendCommaSeparatedList(forNextStatement.NextExpressions); +// } +// exitTokenStack.Pop(); +// return null; +// } +// #endregion +// +// #region Expressions +// +// public override object TrackedVisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.MyClass); +// return null; +// } +// +// +// static string ConvertCharLiteral(char ch) +// { +// if (Char.IsControl(ch)) { +// string charName = GetCharName(ch); +// if (charName != null) +// return "ControlChars." + charName; +// else +// return "ChrW(" + ((int)ch).ToString() + ")"; +// } else if (ch == '"') { +// return "\"\"\"\"C"; +// } else { +// return "\"" + ch.ToString() + "\"C"; +// } +// } +// +// static string GetCharName(char ch) +// { +// switch (ch) { +// case '\b': +// return "Back"; +// case '\r': +// return "Cr"; +// case '\f': +// return "FormFeed"; +// case '\n': +// return "Lf"; +// case '\0': +// return "NullChar"; +// case '\t': +// return "Tab"; +// case '\v': +// return "VerticalTab"; +// default: +// return null; +// } +// } +// +// static string ConvertString(string str) +// { +// StringBuilder sb = new StringBuilder(); +// bool inString = false; +// foreach (char ch in str) { +// if (char.IsControl(ch)) { +// if (inString) { +// sb.Append('"'); +// inString = false; +// } +// if (sb.Length > 0) +// sb.Append(" & "); +// string charName = GetCharName(ch); +// if (charName != null) +// sb.Append("vb" + charName); +// else +// sb.Append("ChrW(" + ((int)ch) + ")"); +// } else { +// if (!inString) { +// if (sb.Length > 0) +// sb.Append(" & "); +// sb.Append('"'); +// inString = true; +// } +// if (ch == '"') { +// sb.Append("\"\""); +// } else { +// sb.Append(ch); +// } +// } +// } +// if (inString) +// sb.Append('"'); +// if (sb.Length == 0) +// return "\"\""; +// return sb.ToString(); +// } +// +// public override object TrackedVisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) +// { +// outputFormatter.PrintText(ToVBNetString(primitiveExpression)); +// return null; +// } +// +// internal static string ToVBNetString(PrimitiveExpression primitiveExpression) +// { +// object val = primitiveExpression.Value; +// if (val == null) { +// return "Nothing"; +// } +// if (val is bool) { +// if ((bool)primitiveExpression.Value) { +// return "True"; +// } else { +// return "False"; +// } +// } +// +// if (val is string) { +// return ConvertString((string)val); +// } +// +// if (val is char) { +// return ConvertCharLiteral((char)primitiveExpression.Value); +// } +// +// if (val is decimal) { +// return ((decimal)primitiveExpression.Value).ToString(NumberFormatInfo.InvariantInfo) + "D"; +// } +// +// if (val is float) { +// return ((float)primitiveExpression.Value).ToString(NumberFormatInfo.InvariantInfo) + "F"; +// } +// +// if (val is double) { +// string text = ((double)val).ToString(NumberFormatInfo.InvariantInfo); +// if (text.IndexOf('.') < 0 && text.IndexOf('E') < 0) +// return text + ".0"; +// else +// return text; +// } +// +// if (val is IFormattable) { +// StringBuilder b = new StringBuilder(); +// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) { +// b.Append("&H"); +// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo)); +// } else { +// b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo)); +// } +// if (val is ushort || val is uint || val is ulong) { +// b.Append('U'); +// if (val is uint) +// b.Append('I'); +// } +// if (val is long || val is ulong) +// b.Append('L'); +// if (val is short || val is ushort) +// b.Append('S'); +// return b.ToString(); +// } else { +// return val.ToString(); +// } +// } +// +// public override object TrackedVisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) +// { +// int op = 0; +// switch (binaryOperatorExpression.Op) { +// case BinaryOperatorType.Concat: +// op = Tokens.ConcatString; +// break; +// +// case BinaryOperatorType.Add: +// op = Tokens.Plus; +// break; +// +// case BinaryOperatorType.Subtract: +// op = Tokens.Minus; +// break; +// +// case BinaryOperatorType.Multiply: +// op = Tokens.Times; +// break; +// +// case BinaryOperatorType.Divide: +// op = Tokens.Div; +// break; +// +// case BinaryOperatorType.DivideInteger: +// op = Tokens.DivInteger; +// break; +// +// case BinaryOperatorType.Modulus: +// op = Tokens.Mod; +// break; +// +// case BinaryOperatorType.ShiftLeft: +// op = Tokens.ShiftLeft; +// break; +// +// case BinaryOperatorType.ShiftRight: +// op = Tokens.ShiftRight; +// break; +// +// case BinaryOperatorType.BitwiseAnd: +// op = Tokens.And; +// break; +// case BinaryOperatorType.BitwiseOr: +// op = Tokens.Or; +// break; +// case BinaryOperatorType.ExclusiveOr: +// op = Tokens.Xor; +// break; +// +// case BinaryOperatorType.LogicalAnd: +// op = Tokens.AndAlso; +// break; +// case BinaryOperatorType.LogicalOr: +// op = Tokens.OrElse; +// break; +// case BinaryOperatorType.ReferenceEquality: +// op = Tokens.Is; +// break; +// case BinaryOperatorType.ReferenceInequality: +// op = Tokens.IsNot; +// break; +// +// case BinaryOperatorType.Equality: +// op = Tokens.Assign; +// break; +// case BinaryOperatorType.GreaterThan: +// op = Tokens.GreaterThan; +// break; +// case BinaryOperatorType.GreaterThanOrEqual: +// op = Tokens.GreaterEqual; +// break; +// case BinaryOperatorType.InEquality: +// op = Tokens.NotEqual; +// break; +// case BinaryOperatorType.NullCoalescing: +// outputFormatter.PrintText("If("); +// TrackedVisit(binaryOperatorExpression.Left, data); +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(binaryOperatorExpression.Right, data); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// case BinaryOperatorType.DictionaryAccess: +// { +// PrimitiveExpression pright = binaryOperatorExpression.Right as PrimitiveExpression; +// TrackedVisit(binaryOperatorExpression.Left, data); +// if (pright != null && pright.Value is string) { +// outputFormatter.PrintText("!" + (string)pright.Value); +// } else { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(binaryOperatorExpression.Right, data); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// return null; +// } +// case BinaryOperatorType.LessThan: +// op = Tokens.LessThan; +// break; +// case BinaryOperatorType.LessThanOrEqual: +// op = Tokens.LessEqual; +// break; +// } +// +// +// BinaryOperatorExpression childBoe = binaryOperatorExpression.Left as BinaryOperatorExpression; +// bool requireParenthesis = childBoe != null && OperatorPrecedence.ComparePrecedenceVB(binaryOperatorExpression.Op, childBoe.Op) > 0; +// if (requireParenthesis) +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(binaryOperatorExpression.Left, data); +// if (requireParenthesis) +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// outputFormatter.Space(); +// outputFormatter.PrintToken(op); +// outputFormatter.Space(); +// +// childBoe = binaryOperatorExpression.Right as BinaryOperatorExpression; +// requireParenthesis = childBoe != null && OperatorPrecedence.ComparePrecedenceVB(binaryOperatorExpression.Op, childBoe.Op) >= 0; +// if (requireParenthesis) +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(binaryOperatorExpression.Right, data); +// if (requireParenthesis) +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// return null; +// } +// +// public override object TrackedVisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(parenthesizedExpression.Expression, data); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// public override object TrackedVisitInvocationExpression(InvocationExpression invocationExpression, object data) +// { +// TrackedVisit(invocationExpression.TargetObject, data); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(invocationExpression.Arguments); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// void PrintTypeArguments(List typeArguments) +// { +// if (typeArguments != null && typeArguments.Count > 0) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// outputFormatter.PrintToken(Tokens.Of); +// outputFormatter.Space(); +// AppendCommaSeparatedList(typeArguments); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// } +// +// public override object TrackedVisitIdentifierExpression(SimpleNameExpression identifierExpression, object data) +// { +// outputFormatter.PrintIdentifier(identifierExpression.Identifier); +// PrintTypeArguments(identifierExpression.TypeArguments); +// return null; +// } +// +// public override object TrackedVisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) +// { +// TrackedVisit(typeReferenceExpression.TypeReference, data); +// return null; +// } +// +// public override object TrackedVisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) +// { +// switch (unaryOperatorExpression.Op) { +// case UnaryOperatorType.Not: +// case UnaryOperatorType.BitNot: +// outputFormatter.PrintToken(Tokens.Not); +// outputFormatter.Space(); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// return null; +// +// case UnaryOperatorType.Decrement: +// outputFormatter.PrintText("System.Threading.Interlocked.Decrement("); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText(")"); +// return null; +// +// case UnaryOperatorType.Increment: +// outputFormatter.PrintText("System.Threading.Interlocked.Increment("); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText(")"); +// return null; +// +// case UnaryOperatorType.Minus: +// outputFormatter.PrintToken(Tokens.Minus); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// return null; +// +// case UnaryOperatorType.Plus: +// outputFormatter.PrintToken(Tokens.Plus); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// return null; +// +// case UnaryOperatorType.PostDecrement: +// outputFormatter.PrintText("System.Math.Max(System.Threading.Interlocked.Decrement("); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText("),"); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText(" + 1)"); +// return null; +// +// case UnaryOperatorType.PostIncrement: +// outputFormatter.PrintText("System.Math.Max(System.Threading.Interlocked.Increment("); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText("),"); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText(" - 1)"); +// return null; +// +// case UnaryOperatorType.Dereference: +// outputFormatter.PrintToken(Tokens.Times); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// return null; +// case UnaryOperatorType.AddressOf: +// outputFormatter.PrintToken(Tokens.AddressOf); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// return null; +// default: +// Error("unknown unary operator: " + unaryOperatorExpression.Op.ToString(), unaryOperatorExpression.StartLocation); +// outputFormatter.PrintText(unaryOperatorExpression.Op.ToString()); +// outputFormatter.PrintText("("); +// TrackedVisit(unaryOperatorExpression.Expression, data); +// outputFormatter.PrintText(")"); +// return null; +// } +// } +// +// public override object TrackedVisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) +// { +// int op = 0; +// bool unsupportedOpAssignment = false; +// switch (assignmentExpression.Op) { +// case AssignmentOperatorType.Assign: +// op = Tokens.Assign; +// break; +// case AssignmentOperatorType.Add: +// op = Tokens.PlusAssign; +// break; +// case AssignmentOperatorType.Subtract: +// op = Tokens.MinusAssign; +// break; +// case AssignmentOperatorType.Multiply: +// op = Tokens.TimesAssign; +// break; +// case AssignmentOperatorType.Divide: +// op = Tokens.DivAssign; +// break; +// case AssignmentOperatorType.ShiftLeft: +// op = Tokens.ShiftLeftAssign; +// break; +// case AssignmentOperatorType.ShiftRight: +// op = Tokens.ShiftRightAssign; +// break; +// +// case AssignmentOperatorType.ExclusiveOr: +// op = Tokens.Xor; +// unsupportedOpAssignment = true; +// break; +// case AssignmentOperatorType.Modulus: +// op = Tokens.Mod; +// unsupportedOpAssignment = true; +// break; +// case AssignmentOperatorType.BitwiseAnd: +// op = Tokens.And; +// unsupportedOpAssignment = true; +// break; +// case AssignmentOperatorType.BitwiseOr: +// op = Tokens.Or; +// unsupportedOpAssignment = true; +// break; +// } +// +// TrackedVisit(assignmentExpression.Left, data); +// outputFormatter.Space(); +// +// if (unsupportedOpAssignment) { // left = left OP right +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(assignmentExpression.Left, data); +// outputFormatter.Space(); +// } +// +// outputFormatter.PrintToken(op); +// outputFormatter.Space(); +// TrackedVisit(assignmentExpression.Right, data); +// +// return null; +// } +// +// public override object TrackedVisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.GetType); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(typeOfExpression.TypeReference, data); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// public override object TrackedVisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) +// { +// // assigning nothing to a generic type in VB compiles to a DefaultValueExpression +// outputFormatter.PrintToken(Tokens.Nothing); +// return null; +// } +// +// public override object TrackedVisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.TypeOf); +// outputFormatter.Space(); +// TrackedVisit(typeOfIsExpression.Expression, data); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Is); +// outputFormatter.Space(); +// TrackedVisit(typeOfIsExpression.TypeReference, data); +// return null; +// } +// +// public override object TrackedVisitAddressOfExpression(AddressOfExpression addressOfExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.AddressOf); +// outputFormatter.Space(); +// TrackedVisit(addressOfExpression.Expression, data); +// return null; +// } +// +// public override object TrackedVisitCastExpression(CastExpression castExpression, object data) +// { +// if (castExpression.CastType == CastType.TryCast) { +// return PrintCast(Tokens.TryCast, castExpression); +// } +// if (castExpression.CastType == CastType.Cast || castExpression.CastTo.IsArrayType) { +// return PrintCast(Tokens.DirectCast, castExpression); +// } +// switch (castExpression.CastTo.Type) { +// case "System.Boolean": +// outputFormatter.PrintToken(Tokens.CBool); +// break; +// case "System.Byte": +// outputFormatter.PrintToken(Tokens.CByte); +// break; +// case "System.SByte": +// outputFormatter.PrintToken(Tokens.CSByte); +// break; +// case "System.Char": +// outputFormatter.PrintToken(Tokens.CChar); +// break; +// case "System.DateTime": +// outputFormatter.PrintToken(Tokens.CDate); +// break; +// case "System.Decimal": +// outputFormatter.PrintToken(Tokens.CDec); +// break; +// case "System.Double": +// outputFormatter.PrintToken(Tokens.CDbl); +// break; +// case "System.Int16": +// outputFormatter.PrintToken(Tokens.CShort); +// break; +// case "System.Int32": +// outputFormatter.PrintToken(Tokens.CInt); +// break; +// case "System.Int64": +// outputFormatter.PrintToken(Tokens.CLng); +// break; +// case "System.UInt16": +// outputFormatter.PrintToken(Tokens.CUShort); +// break; +// case "System.UInt32": +// outputFormatter.PrintToken(Tokens.CUInt); +// break; +// case "System.UInt64": +// outputFormatter.PrintToken(Tokens.CULng); +// break; +// case "System.Object": +// outputFormatter.PrintToken(Tokens.CObj); +// break; +// case "System.Single": +// outputFormatter.PrintToken(Tokens.CSng); +// break; +// case "System.String": +// outputFormatter.PrintToken(Tokens.CStr); +// break; +// default: +// return PrintCast(Tokens.CType, castExpression); +// } +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(castExpression.Expression, data); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// object PrintCast(int castToken, CastExpression castExpression) +// { +// outputFormatter.PrintToken(castToken); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(castExpression.Expression, null); +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(castExpression.CastTo, null); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// public override object TrackedVisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.Me); +// return null; +// } +// +// public override object TrackedVisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.MyBase); +// return null; +// } +// +// public override object TrackedVisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.New); +// if (!objectCreateExpression.IsAnonymousType) { +// outputFormatter.Space(); +// TrackedVisit(objectCreateExpression.CreateType, data); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(objectCreateExpression.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// } +// CollectionInitializerExpression initializer = objectCreateExpression.ObjectInitializer; +// if (!initializer.IsNull) { +// outputFormatter.Space(); +// if (initializer.CreateExpressions.Any(ce => ce is MemberInitializerExpression)) +// outputFormatter.PrintToken(Tokens.With); +// else +// outputFormatter.PrintToken(Tokens.From); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.OpenCurlyBrace); +// outputFormatter.IndentationLevel++; +// for (int i = 0; i < initializer.CreateExpressions.Count; i++) { +// Expression expr = initializer.CreateExpressions[i]; +// if (i > 0) +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.PrintLineContinuation(); +// outputFormatter.Indent(); +// TrackedVisit(expr, data); +// } +// outputFormatter.IndentationLevel--; +// outputFormatter.PrintLineContinuation(); +// outputFormatter.Indent(); +// outputFormatter.PrintToken(Tokens.CloseCurlyBrace); +// } +// return null; +// } +// +// public override object TrackedVisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.New); +// outputFormatter.Space(); +// PrintTypeReferenceWithoutArray(arrayCreateExpression.CreateType); +// +// if (arrayCreateExpression.Arguments.Count > 0) { +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(arrayCreateExpression.Arguments); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// PrintArrayRank(arrayCreateExpression.CreateType.RankSpecifier, 1); +// } else { +// PrintArrayRank(arrayCreateExpression.CreateType.RankSpecifier, 0); +// } +// +// outputFormatter.Space(); +// +// if (arrayCreateExpression.ArrayInitializer.IsNull) { +// outputFormatter.PrintToken(Tokens.OpenCurlyBrace); +// outputFormatter.PrintToken(Tokens.CloseCurlyBrace); +// } else { +// TrackedVisit(arrayCreateExpression.ArrayInitializer, data); +// } +// return null; +// } +// +// public override object TrackedVisitCollectionInitializerExpression(CollectionInitializerExpression arrayInitializerExpression, object data) +// { +// outputFormatter.PrintToken(Tokens.OpenCurlyBrace); +// this.AppendCommaSeparatedList(arrayInitializerExpression.CreateExpressions); +// outputFormatter.PrintToken(Tokens.CloseCurlyBrace); +// return null; +// } +// +// public override object TrackedVisitMemberInitializerExpression(MemberInitializerExpression memberInitializerExpression, object data) +// { +// if (memberInitializerExpression.IsKey) { +// outputFormatter.PrintToken(Tokens.Key); +// outputFormatter.Space(); +// } +// outputFormatter.PrintToken(Tokens.Dot); +// outputFormatter.PrintIdentifier(memberInitializerExpression.Name); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// TrackedVisit(memberInitializerExpression.Expression, data); +// return null; +// } +// +// public override object TrackedVisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) +// { +// TrackedVisit(memberReferenceExpression.TargetObject, data); +// outputFormatter.PrintToken(Tokens.Dot); +// if (string.Equals(memberReferenceExpression.MemberName, "New", StringComparison.OrdinalIgnoreCase) +// && (memberReferenceExpression.TargetObject is BaseReferenceExpression || memberReferenceExpression.TargetObject is ThisReferenceExpression || memberReferenceExpression.TargetObject is ClassReferenceExpression)) +// { +// outputFormatter.PrintToken(Tokens.New); +// } else { +// outputFormatter.PrintIdentifier(memberReferenceExpression.MemberName); +// } +// PrintTypeArguments(memberReferenceExpression.TypeArguments); +// return null; +// } +// +// public override object TrackedVisitDirectionExpression(DirectionExpression directionExpression, object data) +// { +// // VB does not need to specify the direction in method calls +// TrackedVisit(directionExpression.Expression, data); +// return null; +// } +// +// +// public override object TrackedVisitConditionalExpression(ConditionalExpression conditionalExpression, object data) +// { +// outputFormatter.PrintText("If"); +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// TrackedVisit(conditionalExpression.Condition, data); +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(conditionalExpression.TrueExpression, data); +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// TrackedVisit(conditionalExpression.FalseExpression, data); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// return null; +// } +// +// #endregion +// #endregion +// +// +// void OutputModifier(ParameterModifiers modifier) +// { +// if ((modifier & ParameterModifiers.Optional) == ParameterModifiers.Optional) { +// outputFormatter.PrintToken(Tokens.Optional); +// outputFormatter.Space(); +// } +// if ((modifier & ParameterModifiers.Ref) == ParameterModifiers.Ref +// || (modifier & ParameterModifiers.Out) == ParameterModifiers.Out) { +// outputFormatter.PrintToken(Tokens.ByRef); +// outputFormatter.Space(); +// } +// if ((modifier & ParameterModifiers.Params) == ParameterModifiers.Params) { +// outputFormatter.PrintToken(Tokens.ParamArray); +// outputFormatter.Space(); +// } +// if (prettyPrintOptions.OutputByValModifier && +// (modifier & (ParameterModifiers.Params | ParameterModifiers.Ref)) == ParameterModifiers.None) +// { +// outputFormatter.PrintToken(Tokens.ByVal); +// outputFormatter.Space(); +// } +// } +// +// void OutputModifier(Modifiers modifier) +// { +// OutputModifier(modifier, false, false); +// } +// +// void OutputModifier(Modifiers modifier, bool forTypeDecl, bool forFieldDecl) +// { +// if ((modifier & Modifiers.Public) == Modifiers.Public) { +// outputFormatter.PrintToken(Tokens.Public); +// outputFormatter.Space(); +// } else if ((modifier & Modifiers.Private) == Modifiers.Private) { +// outputFormatter.PrintToken(Tokens.Private); +// outputFormatter.Space(); +// } else if ((modifier & (Modifiers.Protected | Modifiers.Internal)) == (Modifiers.Protected | Modifiers.Internal)) { +// outputFormatter.PrintToken(Tokens.Protected); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Friend); +// outputFormatter.Space(); +// } else if ((modifier & Modifiers.Internal) == Modifiers.Internal) { +// outputFormatter.PrintToken(Tokens.Friend); +// outputFormatter.Space(); +// } else if ((modifier & Modifiers.Protected) == Modifiers.Protected) { +// outputFormatter.PrintToken(Tokens.Protected); +// outputFormatter.Space(); +// } +// +// if ((modifier & Modifiers.Static) == Modifiers.Static) { +// outputFormatter.PrintToken(Tokens.Shared); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Virtual) == Modifiers.Virtual) { +// outputFormatter.PrintToken(Tokens.Overridable); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Abstract) == Modifiers.Abstract) { +// if (forFieldDecl) +// outputFormatter.PrintToken(Tokens.Dim); +// else if (forTypeDecl) +// outputFormatter.PrintToken(Tokens.MustInherit); +// else +// outputFormatter.PrintToken(Tokens.MustOverride); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Dim) == Modifiers.Dim) { +// outputFormatter.PrintToken(Tokens.Dim); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Overloads) == Modifiers.Overloads) { +// outputFormatter.PrintToken(Tokens.Overloads); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Override) == Modifiers.Override) { +// outputFormatter.PrintToken(Tokens.Overrides); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.New) == Modifiers.New) { +// outputFormatter.PrintToken(Tokens.Shadows); +// outputFormatter.Space(); +// } +// +// if ((modifier & Modifiers.Sealed) == Modifiers.Sealed) { +// outputFormatter.PrintToken(forTypeDecl ? Tokens.NotInheritable : Tokens.NotOverridable); +// outputFormatter.Space(); +// } +// +// if ((modifier & Modifiers.ReadOnly) == Modifiers.ReadOnly) { +// outputFormatter.PrintToken(Tokens.ReadOnly); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.WriteOnly) == Modifiers.WriteOnly) { +// outputFormatter.PrintToken(Tokens.WriteOnly); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Const) == Modifiers.Const) { +// outputFormatter.PrintToken(Tokens.Const); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.WithEvents) == Modifiers.WithEvents) { +// outputFormatter.PrintToken(Tokens.WithEvents); +// outputFormatter.Space(); +// } +// if ((modifier & Modifiers.Partial) == Modifiers.Partial) { +// outputFormatter.PrintToken(Tokens.Partial); +// outputFormatter.Space(); +// } +// +// if ((modifier & Modifiers.Extern) == Modifiers.Extern) { +// // not required in VB +// } +// +// if ((modifier & Modifiers.Default) == Modifiers.Default) { +// outputFormatter.PrintToken(Tokens.Default); +// outputFormatter.Space(); +// } +// +// if ((modifier & Modifiers.Volatile) == Modifiers.Volatile) { +// Error("'Volatile' modifier not convertable", Location.Empty); +// } +// +// if ((modifier & Modifiers.Unsafe) == Modifiers.Unsafe) { +// Error("'Unsafe' modifier not convertable", Location.Empty); +// } +// } +// +// public void AppendCommaSeparatedList(ICollection list) where T : class, INode +// { +// if (list != null) { +// int i = 0; +// foreach (T node in list) { +// TrackedVisit(node, null); +// if (i + 1 < list.Count) { +// outputFormatter.PrintToken(Tokens.Comma); +// outputFormatter.Space(); +// if ((i + 1) % 6 == 0) { +// outputFormatter.PrintLineContinuation(); +// outputFormatter.Indent(); +// outputFormatter.PrintText("\t"); +// } +// } +// i++; +// } +// } +// } +// +// void VisitAttributes(ICollection attributes, object data) +// { +// if (attributes == null) { +// return; +// } +// foreach (AttributeSection section in attributes) { +// if (string.Equals(section.AttributeTarget, "return", StringComparison.OrdinalIgnoreCase)) +// continue; +// TrackedVisit(section, data); +// } +// } +// +// void VisitReturnTypeAttributes(ICollection attributes, object data) +// { +// if (attributes == null) { +// return; +// } +// printAttributeSectionInline = true; +// foreach (AttributeSection section in attributes) { +// if (string.Equals(section.AttributeTarget, "return", StringComparison.OrdinalIgnoreCase)) { +// TrackedVisit(section, data); +// } +// } +// printAttributeSectionInline = false; +// } +// +// public override object TrackedVisitLambdaExpression(LambdaExpression lambdaExpression, object data) +// { +// bool isSub = !lambdaExpression.ReturnType.IsNull && +// lambdaExpression.ReturnType.Type == "System.Void" && lambdaExpression.ReturnType.IsKeyword; +// +// if (isSub) +// outputFormatter.PrintToken(Tokens.Sub); +// else +// outputFormatter.PrintToken(Tokens.Function); +// +// outputFormatter.PrintToken(Tokens.OpenParenthesis); +// AppendCommaSeparatedList(lambdaExpression.Parameters); +// outputFormatter.PrintToken(Tokens.CloseParenthesis); +// +// outputFormatter.Space(); +// +// if (!lambdaExpression.ExpressionBody.IsNull) { +// return lambdaExpression.ExpressionBody.AcceptVisitor(this, data); +// } else { +// if (!isSub && !lambdaExpression.ReturnType.IsNull) { +// outputFormatter.PrintToken(Tokens.As); +// outputFormatter.Space(); +// TrackedVisit(lambdaExpression.ReturnType, data); +// } +// +// if (lambdaExpression.StatementBody is BlockStatement) +// outputFormatter.NewLine(); +// +// TrackedVisit(lambdaExpression.StatementBody, data); +// +// if (lambdaExpression.StatementBody is BlockStatement) { +// outputFormatter.NewLine(); +// outputFormatter.PrintToken(Tokens.End); +// outputFormatter.Space(); +// if (isSub) +// outputFormatter.PrintToken(Tokens.Sub); +// else +// outputFormatter.PrintToken(Tokens.Function); +// } +// +// return null; +// } +// } +// +// public override object TrackedVisitQueryExpression(QueryExpression queryExpression, object data) +// { +// outputFormatter.IndentationLevel++; +// for (int i = 0; i < queryExpression.Clauses.Count; i++) { +// QueryExpressionClause clause = queryExpression.Clauses[i]; +// if (!clause.IsNull) { +// if (i != 0) { +// outputFormatter.PrintLineContinuation(); +// outputFormatter.Indent(); +// } +// clause.AcceptVisitor(this, null); +// } +// } +// outputFormatter.IndentationLevel--; +// return null; +// } +// +// void PrintClause(QueryExpressionClause clause) +// { +// +// } +// +// public override object TrackedVisitQueryExpressionFromClause(QueryExpressionFromClause fromClause, object data) +// { +// outputFormatter.PrintText("From"); +// outputFormatter.Space(); +// for (int i = 0; i < fromClause.Sources.Count; i++) { +// CollectionRangeVariable clause = fromClause.Sources[i]; +// outputFormatter.PrintIdentifier(clause.Identifier); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.In); +// outputFormatter.Space(); +// clause.Expression.AcceptVisitor(this, data); +// if (i < fromClause.Sources.Count - 1) +// outputFormatter.PrintToken(Tokens.Comma); +// } +// return null; +// } +// +// public override object TrackedVisitQueryExpressionJoinClause(QueryExpressionJoinClause joinClause, object data) +// { +// outputFormatter.PrintText("Join"); +// outputFormatter.Space(); +// CollectionRangeVariable clause = joinClause.Source; +// outputFormatter.PrintIdentifier(clause.Identifier); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.In); +// outputFormatter.Space(); +// clause.Expression.AcceptVisitor(this, data); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.On); +// outputFormatter.Space(); +// joinClause.OnExpression.AcceptVisitor(this, data); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// joinClause.EqualsExpression.AcceptVisitor(this, data); +// if (!string.IsNullOrEmpty(joinClause.IntoIdentifier)) { +// outputFormatter.Space(); +// outputFormatter.PrintText("Into"); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(joinClause.IntoIdentifier); +// } +// return null; +// } +// +//// void VisitQueryExpressionFromOrJoinClause(QueryExpressionFromOrJoinClause clause, object data) +//// { +//// outputFormatter.PrintIdentifier(clause.Identifier); +//// outputFormatter.Space(); +//// outputFormatter.PrintToken(Tokens.In); +//// outputFormatter.Space(); +//// clause.InExpression.AcceptVisitor(this, data); +//// } +// +// public override object TrackedVisitQueryExpressionLetClause(QueryExpressionLetClause letClause, object data) +// { +// outputFormatter.PrintToken(Tokens.Let); +// outputFormatter.Space(); +// outputFormatter.PrintIdentifier(letClause.Identifier); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.Assign); +// outputFormatter.Space(); +// return letClause.Expression.AcceptVisitor(this, data); +// } +// +// public override object TrackedVisitQueryExpressionGroupClause(QueryExpressionGroupClause groupClause, object data) +// { +// outputFormatter.PrintText("Group"); +// outputFormatter.Space(); +// groupClause.Projection.AcceptVisitor(this, data); +// outputFormatter.Space(); +// outputFormatter.PrintText("By"); +// outputFormatter.Space(); +// return groupClause.GroupBy.AcceptVisitor(this, data); +// } +// +// public override object TrackedVisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) +// { +// outputFormatter.PrintText("Order By"); +// outputFormatter.Space(); +// AppendCommaSeparatedList(queryExpressionOrderClause.Orderings); +// return null; +// } +// +// public override object TrackedVisitQueryExpressionOrdering(QueryExpressionOrdering ordering, object data) +// { +// ordering.Criteria.AcceptVisitor(this, data); +// if (ordering.Direction == QueryExpressionOrderingDirection.Ascending) { +// outputFormatter.Space(); +// outputFormatter.PrintText("Ascending"); +// } else if (ordering.Direction == QueryExpressionOrderingDirection.Descending) { +// outputFormatter.Space(); +// outputFormatter.PrintText("Descending"); +// } +// return null; +// } +// +// public override object TrackedVisitQueryExpressionSelectVBClause(QueryExpressionSelectVBClause selectClause, object data) +// { +// outputFormatter.PrintToken(Tokens.Select); +// outputFormatter.Space(); +// foreach (ExpressionRangeVariable var in selectClause.Variables) { +// var.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public override object TrackedVisitQueryExpressionWhereClause(QueryExpressionWhereClause whereClause, object data) +// { +// outputFormatter.Space(); +// outputFormatter.PrintText("Where"); +// outputFormatter.Space(); +// return whereClause.Condition.AcceptVisitor(this, data); +// } +// +// public override object TrackedVisitExternAliasDirective(ExternAliasDirective externAliasDirective, object data) +// { +// UnsupportedNode(externAliasDirective); +// return null; +// } +// +// public override object TrackedVisitXmlContentExpression(XmlContentExpression xmlContentExpression, object data) +// { +// switch (xmlContentExpression.Type) { +// case XmlContentType.Comment: +// outputFormatter.PrintText(""); +// break; +// case XmlContentType.Text: +// outputFormatter.PrintText(xmlContentExpression.Content); +// break; +// case XmlContentType.CData: +// outputFormatter.PrintText(""); +// break; +// case XmlContentType.ProcessingInstruction: +// outputFormatter.PrintText(""); +// break; +// default: +// throw new Exception("Invalid value for XmlContentType"); +// } +// return null; +// } +// +// public override object TrackedVisitXmlEmbeddedExpression(XmlEmbeddedExpression xmlEmbeddedExpression, object data) +// { +// outputFormatter.PrintText("<%="); +// outputFormatter.Space(); +// xmlEmbeddedExpression.InlineVBExpression.AcceptVisitor(this, data); +// outputFormatter.Space(); +// outputFormatter.PrintText("%>"); +// return null; +// } +// +// public override object TrackedVisitXmlAttributeExpression(XmlAttributeExpression xmlAttributeExpression, object data) +// { +// outputFormatter.PrintText(xmlAttributeExpression.Name); +// outputFormatter.PrintToken(Tokens.Assign); +// if (xmlAttributeExpression.IsLiteralValue) { +// if (xmlAttributeExpression.UseDoubleQuotes) +// outputFormatter.PrintText("\""); +// else +// outputFormatter.PrintText("'"); +// outputFormatter.PrintText(xmlAttributeExpression.LiteralValue); +// if (xmlAttributeExpression.UseDoubleQuotes) +// outputFormatter.PrintText("\""); +// else +// outputFormatter.PrintText("'"); +// } else +// xmlAttributeExpression.ExpressionValue.AcceptVisitor(this, data); +// return null; +// } +// +// public override object TrackedVisitXmlElementExpression(XmlElementExpression xmlElementExpression, object data) +// { +// outputFormatter.PrintText("<"); +// if (xmlElementExpression.NameIsExpression) { +// outputFormatter.PrintToken(Tokens.XmlStartInlineVB); +// outputFormatter.Space(); +// xmlElementExpression.NameExpression.AcceptVisitor(this, data); +// outputFormatter.Space(); +// outputFormatter.PrintToken(Tokens.XmlEndInlineVB); +// } else { +// outputFormatter.PrintText(xmlElementExpression.XmlName); +// } +// foreach (XmlExpression attribute in xmlElementExpression.Attributes) { +// outputFormatter.Space(); +// attribute.AcceptVisitor(this, data); +// } +// if (xmlElementExpression.Children.Any()) { +// outputFormatter.PrintText(">"); +// foreach (INode node in xmlElementExpression.Children) { +// node.AcceptVisitor(this, data); +// } +// outputFormatter.PrintText(""); +// } else { +// outputFormatter.Space(); +// outputFormatter.PrintText("/>"); +// } +// return null; +// } +// +// public override object TrackedVisitXmlMemberAccessExpression(XmlMemberAccessExpression xmlMemberAccessExpression, object data) +// { +// xmlMemberAccessExpression.TargetObject.AcceptVisitor(this, data); +// switch (xmlMemberAccessExpression.AxisType) { +// case XmlAxisType.Element: +// outputFormatter.PrintToken(Tokens.Dot); +// break; +// case XmlAxisType.Attribute: +// outputFormatter.PrintToken(Tokens.DotAt); +// break; +// case XmlAxisType.Descendents: +// outputFormatter.PrintToken(Tokens.TripleDot); +// break; +// default: +// throw new Exception("Invalid value for XmlAxisType"); +// } +// if (xmlMemberAccessExpression.IsXmlIdentifier) +// outputFormatter.PrintText("<" + xmlMemberAccessExpression.Identifier + ">"); +// else +// outputFormatter.PrintIdentifier(xmlMemberAccessExpression.Identifier); +// return null; +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs new file mode 100644 index 0000000000..0b6170a07d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs @@ -0,0 +1,18 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.PrettyPrinter +{ + /// + /// Description of VBNetPrettyPrintOptions. + /// + public class VBNetPrettyPrintOptions : AbstractPrettyPrintOptions + { + /// + /// Gets/Sets if the optional "ByVal" modifier should be written. + /// + public bool OutputByValModifier { get; set; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Properties/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..3f604f3e86 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ICSharpCode.NRefactory.VB")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ICSharpCode.NRefactory.VB")] +[assembly: AssemblyCopyright("Copyright 2010")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +//[assembly: CLSCompliant(true)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// 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.*")] diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/VBParser.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/VBParser.cs new file mode 100644 index 0000000000..27d244be1b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/VBParser.cs @@ -0,0 +1,55 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; + +using ICSharpCode.NRefactory.VB.Ast; +using ICSharpCode.NRefactory.VB.Parser; + +namespace ICSharpCode.NRefactory.VB +{ + public enum SnippetType + { + None, + CompilationUnit, + Expression, + Statements, + TypeMembers + } + + public class VBParser + { + bool hasErrors; + Errors errors; + + public CompilationUnit Parse(string content) + { + return Parse(new StringReader(content)); + } + + public CompilationUnit Parse(TextReader reader) + { + var parser = new ICSharpCode.NRefactory.VB.Parser.VBParser(new VBLexer(reader)); + parser.Parse(); + hasErrors = parser.Errors.Count > 0; + errors = parser.Errors; + return parser.CompilationUnit; + } + + public AstNode ParseSnippet(TextReader reader) + { + throw new NotImplementedException(); + } + + public bool HasErrors { + get { return hasErrors; } + } + + public Errors Errors { + get { return errors; } + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/AbstractAstTransformer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/AbstractAstTransformer.cs new file mode 100644 index 0000000000..5441575067 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/AbstractAstTransformer.cs @@ -0,0 +1,2078 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ICSharpCode.NRefactory.VB.Visitors { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using ICSharpCode.NRefactory.VB.Ast; + + + /// + /// The AbstractAstTransformer will iterate through the whole Ast, + /// just like the AbstractAstVisitor. However, the AbstractAstTransformer allows + /// you to modify the Ast at the same time: It does not use 'foreach' internally, + /// so you can add members to collections of parents of the current node (but + /// you cannot insert or delete items as that will make the index used invalid). + /// You can use the methods ReplaceCurrentNode and RemoveCurrentNode to replace + /// or remove the current node, totally independent from the type of the parent node. + /// +// public abstract class AbstractAstTransformer : IAstVisitor { +// +// private Stack nodeStack = new Stack(); +// +// public void ReplaceCurrentNode(INode newNode) { +// nodeStack.Pop(); +// nodeStack.Push(newNode); +// } +// +// public void RemoveCurrentNode() { +// nodeStack.Pop(); +// nodeStack.Push(null); +// } +// +// public virtual object VisitAddHandlerStatement(AddHandlerStatement addHandlerStatement, object data) { +// Debug.Assert((addHandlerStatement != null)); +// Debug.Assert((addHandlerStatement.EventExpression != null)); +// Debug.Assert((addHandlerStatement.HandlerExpression != null)); +// nodeStack.Push(addHandlerStatement.EventExpression); +// addHandlerStatement.EventExpression.AcceptVisitor(this, data); +// addHandlerStatement.EventExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(addHandlerStatement.HandlerExpression); +// addHandlerStatement.HandlerExpression.AcceptVisitor(this, data); +// addHandlerStatement.HandlerExpression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitAddressOfExpression(AddressOfExpression addressOfExpression, object data) { +// Debug.Assert((addressOfExpression != null)); +// Debug.Assert((addressOfExpression.Expression != null)); +// nodeStack.Push(addressOfExpression.Expression); +// addressOfExpression.Expression.AcceptVisitor(this, data); +// addressOfExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) { +// Debug.Assert((arrayCreateExpression != null)); +// Debug.Assert((arrayCreateExpression.CreateType != null)); +// Debug.Assert((arrayCreateExpression.Arguments != null)); +// Debug.Assert((arrayCreateExpression.ArrayInitializer != null)); +// nodeStack.Push(arrayCreateExpression.CreateType); +// arrayCreateExpression.CreateType.AcceptVisitor(this, data); +// arrayCreateExpression.CreateType = ((TypeReference)(nodeStack.Pop())); +// for (int i = 0; i < arrayCreateExpression.Arguments.Count; i++) { +// Expression o = arrayCreateExpression.Arguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// arrayCreateExpression.Arguments.RemoveAt(i--); +// else +// arrayCreateExpression.Arguments[i] = o; +// } +// nodeStack.Push(arrayCreateExpression.ArrayInitializer); +// arrayCreateExpression.ArrayInitializer.AcceptVisitor(this, data); +// arrayCreateExpression.ArrayInitializer = ((CollectionInitializerExpression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) { +// Debug.Assert((assignmentExpression != null)); +// Debug.Assert((assignmentExpression.Left != null)); +// Debug.Assert((assignmentExpression.Right != null)); +// nodeStack.Push(assignmentExpression.Left); +// assignmentExpression.Left.AcceptVisitor(this, data); +// assignmentExpression.Left = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(assignmentExpression.Right); +// assignmentExpression.Right.AcceptVisitor(this, data); +// assignmentExpression.Right = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) { +// Debug.Assert((attribute != null)); +// Debug.Assert((attribute.PositionalArguments != null)); +// Debug.Assert((attribute.NamedArguments != null)); +// for (int i = 0; i < attribute.PositionalArguments.Count; i++) { +// Expression o = attribute.PositionalArguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// attribute.PositionalArguments.RemoveAt(i--); +// else +// attribute.PositionalArguments[i] = o; +// } +// for (int i = 0; i < attribute.NamedArguments.Count; i++) { +// NamedArgumentExpression o = attribute.NamedArguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (NamedArgumentExpression)nodeStack.Pop(); +// if (o == null) +// attribute.NamedArguments.RemoveAt(i--); +// else +// attribute.NamedArguments[i] = o; +// } +// return null; +// } +// +// public virtual object VisitAttributeSection(AttributeSection attributeSection, object data) { +// Debug.Assert((attributeSection != null)); +// Debug.Assert((attributeSection.Attributes != null)); +// for (int i = 0; i < attributeSection.Attributes.Count; i++) { +// ICSharpCode.NRefactory.VB.Ast.Attribute o = attributeSection.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ICSharpCode.NRefactory.VB.Ast.Attribute)nodeStack.Pop(); +// if (o == null) +// attributeSection.Attributes.RemoveAt(i--); +// else +// attributeSection.Attributes[i] = o; +// } +// return null; +// } +// +// public virtual object VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) { +// Debug.Assert((baseReferenceExpression != null)); +// return null; +// } +// +// public virtual object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { +// Debug.Assert((binaryOperatorExpression != null)); +// Debug.Assert((binaryOperatorExpression.Left != null)); +// Debug.Assert((binaryOperatorExpression.Right != null)); +// nodeStack.Push(binaryOperatorExpression.Left); +// binaryOperatorExpression.Left.AcceptVisitor(this, data); +// binaryOperatorExpression.Left = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(binaryOperatorExpression.Right); +// binaryOperatorExpression.Right.AcceptVisitor(this, data); +// binaryOperatorExpression.Right = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitBlockStatement(BlockStatement blockStatement, object data) { +// Debug.Assert((blockStatement != null)); +// for (int i = 0; i < blockStatement.Children.Count; i++) { +// INode o = blockStatement.Children[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = nodeStack.Pop(); +// if (o == null) +// blockStatement.Children.RemoveAt(i--); +// else +// blockStatement.Children[i] = o; +// } +// return null; +// } +// +// public virtual object VisitCaseLabel(CaseLabel caseLabel, object data) { +// Debug.Assert((caseLabel != null)); +// Debug.Assert((caseLabel.Label != null)); +// Debug.Assert((caseLabel.ToExpression != null)); +// nodeStack.Push(caseLabel.Label); +// caseLabel.Label.AcceptVisitor(this, data); +// caseLabel.Label = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(caseLabel.ToExpression); +// caseLabel.ToExpression.AcceptVisitor(this, data); +// caseLabel.ToExpression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitCastExpression(CastExpression castExpression, object data) { +// Debug.Assert((castExpression != null)); +// Debug.Assert((castExpression.CastTo != null)); +// Debug.Assert((castExpression.Expression != null)); +// nodeStack.Push(castExpression.CastTo); +// castExpression.CastTo.AcceptVisitor(this, data); +// castExpression.CastTo = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(castExpression.Expression); +// castExpression.Expression.AcceptVisitor(this, data); +// castExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitCatchClause(CatchClause catchClause, object data) { +// Debug.Assert((catchClause != null)); +// Debug.Assert((catchClause.TypeReference != null)); +// Debug.Assert((catchClause.StatementBlock != null)); +// Debug.Assert((catchClause.Condition != null)); +// nodeStack.Push(catchClause.TypeReference); +// catchClause.TypeReference.AcceptVisitor(this, data); +// catchClause.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(catchClause.StatementBlock); +// catchClause.StatementBlock.AcceptVisitor(this, data); +// catchClause.StatementBlock = ((Statement)(nodeStack.Pop())); +// nodeStack.Push(catchClause.Condition); +// catchClause.Condition.AcceptVisitor(this, data); +// catchClause.Condition = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data) { +// Debug.Assert((classReferenceExpression != null)); +// return null; +// } +// +// public virtual object VisitCollectionInitializerExpression(CollectionInitializerExpression collectionInitializerExpression, object data) { +// Debug.Assert((collectionInitializerExpression != null)); +// Debug.Assert((collectionInitializerExpression.CreateExpressions != null)); +// for (int i = 0; i < collectionInitializerExpression.CreateExpressions.Count; i++) { +// Expression o = collectionInitializerExpression.CreateExpressions[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// collectionInitializerExpression.CreateExpressions.RemoveAt(i--); +// else +// collectionInitializerExpression.CreateExpressions[i] = o; +// } +// return null; +// } +// +// public virtual object VisitCollectionRangeVariable(CollectionRangeVariable collectionRangeVariable, object data) { +// Debug.Assert((collectionRangeVariable != null)); +// Debug.Assert((collectionRangeVariable.Expression != null)); +// Debug.Assert((collectionRangeVariable.Type != null)); +// nodeStack.Push(collectionRangeVariable.Expression); +// collectionRangeVariable.Expression.AcceptVisitor(this, data); +// collectionRangeVariable.Expression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(collectionRangeVariable.Type); +// collectionRangeVariable.Type.AcceptVisitor(this, data); +// collectionRangeVariable.Type = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitCompilationUnit(CompilationUnit compilationUnit, object data) { +// Debug.Assert((compilationUnit != null)); +// for (int i = 0; i < compilationUnit.Children.Count; i++) { +// INode o = compilationUnit.Children[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = nodeStack.Pop(); +// if (o == null) +// compilationUnit.Children.RemoveAt(i--); +// else +// compilationUnit.Children[i] = o; +// } +// return null; +// } +// +// public virtual object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) { +// Debug.Assert((conditionalExpression != null)); +// Debug.Assert((conditionalExpression.Condition != null)); +// Debug.Assert((conditionalExpression.TrueExpression != null)); +// Debug.Assert((conditionalExpression.FalseExpression != null)); +// nodeStack.Push(conditionalExpression.Condition); +// conditionalExpression.Condition.AcceptVisitor(this, data); +// conditionalExpression.Condition = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(conditionalExpression.TrueExpression); +// conditionalExpression.TrueExpression.AcceptVisitor(this, data); +// conditionalExpression.TrueExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(conditionalExpression.FalseExpression); +// conditionalExpression.FalseExpression.AcceptVisitor(this, data); +// conditionalExpression.FalseExpression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) { +// Debug.Assert((constructorDeclaration != null)); +// Debug.Assert((constructorDeclaration.Attributes != null)); +// Debug.Assert((constructorDeclaration.Parameters != null)); +// Debug.Assert((constructorDeclaration.ConstructorInitializer != null)); +// Debug.Assert((constructorDeclaration.Body != null)); +// for (int i = 0; i < constructorDeclaration.Attributes.Count; i++) { +// AttributeSection o = constructorDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// constructorDeclaration.Attributes.RemoveAt(i--); +// else +// constructorDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < constructorDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = constructorDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// constructorDeclaration.Parameters.RemoveAt(i--); +// else +// constructorDeclaration.Parameters[i] = o; +// } +// nodeStack.Push(constructorDeclaration.ConstructorInitializer); +// constructorDeclaration.ConstructorInitializer.AcceptVisitor(this, data); +// constructorDeclaration.ConstructorInitializer = ((ConstructorInitializer)(nodeStack.Pop())); +// nodeStack.Push(constructorDeclaration.Body); +// constructorDeclaration.Body.AcceptVisitor(this, data); +// constructorDeclaration.Body = ((BlockStatement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) { +// Debug.Assert((constructorInitializer != null)); +// Debug.Assert((constructorInitializer.Arguments != null)); +// for (int i = 0; i < constructorInitializer.Arguments.Count; i++) { +// Expression o = constructorInitializer.Arguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// constructorInitializer.Arguments.RemoveAt(i--); +// else +// constructorInitializer.Arguments[i] = o; +// } +// return null; +// } +// +// public virtual object VisitContinueStatement(ContinueStatement continueStatement, object data) { +// Debug.Assert((continueStatement != null)); +// return null; +// } +// +// public virtual object VisitDeclareDeclaration(DeclareDeclaration declareDeclaration, object data) { +// Debug.Assert((declareDeclaration != null)); +// Debug.Assert((declareDeclaration.Attributes != null)); +// Debug.Assert((declareDeclaration.Parameters != null)); +// Debug.Assert((declareDeclaration.TypeReference != null)); +// for (int i = 0; i < declareDeclaration.Attributes.Count; i++) { +// AttributeSection o = declareDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// declareDeclaration.Attributes.RemoveAt(i--); +// else +// declareDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < declareDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = declareDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// declareDeclaration.Parameters.RemoveAt(i--); +// else +// declareDeclaration.Parameters[i] = o; +// } +// nodeStack.Push(declareDeclaration.TypeReference); +// declareDeclaration.TypeReference.AcceptVisitor(this, data); +// declareDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) { +// Debug.Assert((defaultValueExpression != null)); +// Debug.Assert((defaultValueExpression.TypeReference != null)); +// nodeStack.Push(defaultValueExpression.TypeReference); +// defaultValueExpression.TypeReference.AcceptVisitor(this, data); +// defaultValueExpression.TypeReference = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { +// Debug.Assert((delegateDeclaration != null)); +// Debug.Assert((delegateDeclaration.Attributes != null)); +// Debug.Assert((delegateDeclaration.ReturnType != null)); +// Debug.Assert((delegateDeclaration.Parameters != null)); +// Debug.Assert((delegateDeclaration.Templates != null)); +// for (int i = 0; i < delegateDeclaration.Attributes.Count; i++) { +// AttributeSection o = delegateDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// delegateDeclaration.Attributes.RemoveAt(i--); +// else +// delegateDeclaration.Attributes[i] = o; +// } +// nodeStack.Push(delegateDeclaration.ReturnType); +// delegateDeclaration.ReturnType.AcceptVisitor(this, data); +// delegateDeclaration.ReturnType = ((TypeReference)(nodeStack.Pop())); +// for (int i = 0; i < delegateDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = delegateDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// delegateDeclaration.Parameters.RemoveAt(i--); +// else +// delegateDeclaration.Parameters[i] = o; +// } +// for (int i = 0; i < delegateDeclaration.Templates.Count; i++) { +// TemplateDefinition o = delegateDeclaration.Templates[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TemplateDefinition)nodeStack.Pop(); +// if (o == null) +// delegateDeclaration.Templates.RemoveAt(i--); +// else +// delegateDeclaration.Templates[i] = o; +// } +// return null; +// } +// +// public virtual object VisitDirectionExpression(DirectionExpression directionExpression, object data) { +// Debug.Assert((directionExpression != null)); +// Debug.Assert((directionExpression.Expression != null)); +// nodeStack.Push(directionExpression.Expression); +// directionExpression.Expression.AcceptVisitor(this, data); +// directionExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) { +// Debug.Assert((doLoopStatement != null)); +// Debug.Assert((doLoopStatement.Condition != null)); +// Debug.Assert((doLoopStatement.EmbeddedStatement != null)); +// nodeStack.Push(doLoopStatement.Condition); +// doLoopStatement.Condition.AcceptVisitor(this, data); +// doLoopStatement.Condition = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(doLoopStatement.EmbeddedStatement); +// doLoopStatement.EmbeddedStatement.AcceptVisitor(this, data); +// doLoopStatement.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitElseIfSection(ElseIfSection elseIfSection, object data) { +// Debug.Assert((elseIfSection != null)); +// Debug.Assert((elseIfSection.Condition != null)); +// Debug.Assert((elseIfSection.EmbeddedStatement != null)); +// nodeStack.Push(elseIfSection.Condition); +// elseIfSection.Condition.AcceptVisitor(this, data); +// elseIfSection.Condition = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(elseIfSection.EmbeddedStatement); +// elseIfSection.EmbeddedStatement.AcceptVisitor(this, data); +// elseIfSection.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitEndStatement(EndStatement endStatement, object data) { +// Debug.Assert((endStatement != null)); +// return null; +// } +// +// public virtual object VisitEraseStatement(EraseStatement eraseStatement, object data) { +// Debug.Assert((eraseStatement != null)); +// Debug.Assert((eraseStatement.Expressions != null)); +// for (int i = 0; i < eraseStatement.Expressions.Count; i++) { +// Expression o = eraseStatement.Expressions[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// eraseStatement.Expressions.RemoveAt(i--); +// else +// eraseStatement.Expressions[i] = o; +// } +// return null; +// } +// +// public virtual object VisitErrorStatement(ErrorStatement errorStatement, object data) { +// Debug.Assert((errorStatement != null)); +// Debug.Assert((errorStatement.Expression != null)); +// nodeStack.Push(errorStatement.Expression); +// errorStatement.Expression.AcceptVisitor(this, data); +// errorStatement.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitEventAddRegion(EventAddRegion eventAddRegion, object data) { +// Debug.Assert((eventAddRegion != null)); +// Debug.Assert((eventAddRegion.Attributes != null)); +// Debug.Assert((eventAddRegion.Block != null)); +// Debug.Assert((eventAddRegion.Parameters != null)); +// for (int i = 0; i < eventAddRegion.Attributes.Count; i++) { +// AttributeSection o = eventAddRegion.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// eventAddRegion.Attributes.RemoveAt(i--); +// else +// eventAddRegion.Attributes[i] = o; +// } +// nodeStack.Push(eventAddRegion.Block); +// eventAddRegion.Block.AcceptVisitor(this, data); +// eventAddRegion.Block = ((BlockStatement)(nodeStack.Pop())); +// for (int i = 0; i < eventAddRegion.Parameters.Count; i++) { +// ParameterDeclarationExpression o = eventAddRegion.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// eventAddRegion.Parameters.RemoveAt(i--); +// else +// eventAddRegion.Parameters[i] = o; +// } +// return null; +// } +// +// public virtual object VisitEventDeclaration(EventDeclaration eventDeclaration, object data) { +// Debug.Assert((eventDeclaration != null)); +// Debug.Assert((eventDeclaration.Attributes != null)); +// Debug.Assert((eventDeclaration.Parameters != null)); +// Debug.Assert((eventDeclaration.InterfaceImplementations != null)); +// Debug.Assert((eventDeclaration.TypeReference != null)); +// Debug.Assert((eventDeclaration.AddRegion != null)); +// Debug.Assert((eventDeclaration.RemoveRegion != null)); +// Debug.Assert((eventDeclaration.RaiseRegion != null)); +// Debug.Assert((eventDeclaration.Initializer != null)); +// for (int i = 0; i < eventDeclaration.Attributes.Count; i++) { +// AttributeSection o = eventDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// eventDeclaration.Attributes.RemoveAt(i--); +// else +// eventDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < eventDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = eventDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// eventDeclaration.Parameters.RemoveAt(i--); +// else +// eventDeclaration.Parameters[i] = o; +// } +// for (int i = 0; i < eventDeclaration.InterfaceImplementations.Count; i++) { +// InterfaceImplementation o = eventDeclaration.InterfaceImplementations[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (InterfaceImplementation)nodeStack.Pop(); +// if (o == null) +// eventDeclaration.InterfaceImplementations.RemoveAt(i--); +// else +// eventDeclaration.InterfaceImplementations[i] = o; +// } +// nodeStack.Push(eventDeclaration.TypeReference); +// eventDeclaration.TypeReference.AcceptVisitor(this, data); +// eventDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(eventDeclaration.AddRegion); +// eventDeclaration.AddRegion.AcceptVisitor(this, data); +// eventDeclaration.AddRegion = ((EventAddRegion)(nodeStack.Pop())); +// nodeStack.Push(eventDeclaration.RemoveRegion); +// eventDeclaration.RemoveRegion.AcceptVisitor(this, data); +// eventDeclaration.RemoveRegion = ((EventRemoveRegion)(nodeStack.Pop())); +// nodeStack.Push(eventDeclaration.RaiseRegion); +// eventDeclaration.RaiseRegion.AcceptVisitor(this, data); +// eventDeclaration.RaiseRegion = ((EventRaiseRegion)(nodeStack.Pop())); +// nodeStack.Push(eventDeclaration.Initializer); +// eventDeclaration.Initializer.AcceptVisitor(this, data); +// eventDeclaration.Initializer = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitEventRaiseRegion(EventRaiseRegion eventRaiseRegion, object data) { +// Debug.Assert((eventRaiseRegion != null)); +// Debug.Assert((eventRaiseRegion.Attributes != null)); +// Debug.Assert((eventRaiseRegion.Block != null)); +// Debug.Assert((eventRaiseRegion.Parameters != null)); +// for (int i = 0; i < eventRaiseRegion.Attributes.Count; i++) { +// AttributeSection o = eventRaiseRegion.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// eventRaiseRegion.Attributes.RemoveAt(i--); +// else +// eventRaiseRegion.Attributes[i] = o; +// } +// nodeStack.Push(eventRaiseRegion.Block); +// eventRaiseRegion.Block.AcceptVisitor(this, data); +// eventRaiseRegion.Block = ((BlockStatement)(nodeStack.Pop())); +// for (int i = 0; i < eventRaiseRegion.Parameters.Count; i++) { +// ParameterDeclarationExpression o = eventRaiseRegion.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// eventRaiseRegion.Parameters.RemoveAt(i--); +// else +// eventRaiseRegion.Parameters[i] = o; +// } +// return null; +// } +// +// public virtual object VisitEventRemoveRegion(EventRemoveRegion eventRemoveRegion, object data) { +// Debug.Assert((eventRemoveRegion != null)); +// Debug.Assert((eventRemoveRegion.Attributes != null)); +// Debug.Assert((eventRemoveRegion.Block != null)); +// Debug.Assert((eventRemoveRegion.Parameters != null)); +// for (int i = 0; i < eventRemoveRegion.Attributes.Count; i++) { +// AttributeSection o = eventRemoveRegion.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// eventRemoveRegion.Attributes.RemoveAt(i--); +// else +// eventRemoveRegion.Attributes[i] = o; +// } +// nodeStack.Push(eventRemoveRegion.Block); +// eventRemoveRegion.Block.AcceptVisitor(this, data); +// eventRemoveRegion.Block = ((BlockStatement)(nodeStack.Pop())); +// for (int i = 0; i < eventRemoveRegion.Parameters.Count; i++) { +// ParameterDeclarationExpression o = eventRemoveRegion.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// eventRemoveRegion.Parameters.RemoveAt(i--); +// else +// eventRemoveRegion.Parameters[i] = o; +// } +// return null; +// } +// +// public virtual object VisitExitStatement(ExitStatement exitStatement, object data) { +// Debug.Assert((exitStatement != null)); +// return null; +// } +// +// public virtual object VisitExpressionRangeVariable(ExpressionRangeVariable expressionRangeVariable, object data) { +// Debug.Assert((expressionRangeVariable != null)); +// Debug.Assert((expressionRangeVariable.Expression != null)); +// Debug.Assert((expressionRangeVariable.Type != null)); +// nodeStack.Push(expressionRangeVariable.Expression); +// expressionRangeVariable.Expression.AcceptVisitor(this, data); +// expressionRangeVariable.Expression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(expressionRangeVariable.Type); +// expressionRangeVariable.Type.AcceptVisitor(this, data); +// expressionRangeVariable.Type = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) { +// Debug.Assert((expressionStatement != null)); +// Debug.Assert((expressionStatement.Expression != null)); +// nodeStack.Push(expressionStatement.Expression); +// expressionStatement.Expression.AcceptVisitor(this, data); +// expressionStatement.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitExternAliasDirective(ExternAliasDirective externAliasDirective, object data) { +// Debug.Assert((externAliasDirective != null)); +// return null; +// } +// +// public virtual object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { +// Debug.Assert((fieldDeclaration != null)); +// Debug.Assert((fieldDeclaration.Attributes != null)); +// Debug.Assert((fieldDeclaration.TypeReference != null)); +// Debug.Assert((fieldDeclaration.Fields != null)); +// for (int i = 0; i < fieldDeclaration.Attributes.Count; i++) { +// AttributeSection o = fieldDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// fieldDeclaration.Attributes.RemoveAt(i--); +// else +// fieldDeclaration.Attributes[i] = o; +// } +// nodeStack.Push(fieldDeclaration.TypeReference); +// fieldDeclaration.TypeReference.AcceptVisitor(this, data); +// fieldDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// for (int i = 0; i < fieldDeclaration.Fields.Count; i++) { +// VariableDeclaration o = fieldDeclaration.Fields[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (VariableDeclaration)nodeStack.Pop(); +// if (o == null) +// fieldDeclaration.Fields.RemoveAt(i--); +// else +// fieldDeclaration.Fields[i] = o; +// } +// return null; +// } +// +// public virtual object VisitForeachStatement(ForeachStatement foreachStatement, object data) { +// Debug.Assert((foreachStatement != null)); +// Debug.Assert((foreachStatement.TypeReference != null)); +// Debug.Assert((foreachStatement.Expression != null)); +// Debug.Assert((foreachStatement.NextExpression != null)); +// Debug.Assert((foreachStatement.EmbeddedStatement != null)); +// nodeStack.Push(foreachStatement.TypeReference); +// foreachStatement.TypeReference.AcceptVisitor(this, data); +// foreachStatement.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(foreachStatement.Expression); +// foreachStatement.Expression.AcceptVisitor(this, data); +// foreachStatement.Expression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(foreachStatement.NextExpression); +// foreachStatement.NextExpression.AcceptVisitor(this, data); +// foreachStatement.NextExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(foreachStatement.EmbeddedStatement); +// foreachStatement.EmbeddedStatement.AcceptVisitor(this, data); +// foreachStatement.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitForNextStatement(ForNextStatement forNextStatement, object data) { +// Debug.Assert((forNextStatement != null)); +// Debug.Assert((forNextStatement.Start != null)); +// Debug.Assert((forNextStatement.End != null)); +// Debug.Assert((forNextStatement.Step != null)); +// Debug.Assert((forNextStatement.NextExpressions != null)); +// Debug.Assert((forNextStatement.TypeReference != null)); +// Debug.Assert((forNextStatement.LoopVariableExpression != null)); +// Debug.Assert((forNextStatement.EmbeddedStatement != null)); +// nodeStack.Push(forNextStatement.Start); +// forNextStatement.Start.AcceptVisitor(this, data); +// forNextStatement.Start = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(forNextStatement.End); +// forNextStatement.End.AcceptVisitor(this, data); +// forNextStatement.End = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(forNextStatement.Step); +// forNextStatement.Step.AcceptVisitor(this, data); +// forNextStatement.Step = ((Expression)(nodeStack.Pop())); +// for (int i = 0; i < forNextStatement.NextExpressions.Count; i++) { +// Expression o = forNextStatement.NextExpressions[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// forNextStatement.NextExpressions.RemoveAt(i--); +// else +// forNextStatement.NextExpressions[i] = o; +// } +// nodeStack.Push(forNextStatement.TypeReference); +// forNextStatement.TypeReference.AcceptVisitor(this, data); +// forNextStatement.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(forNextStatement.LoopVariableExpression); +// forNextStatement.LoopVariableExpression.AcceptVisitor(this, data); +// forNextStatement.LoopVariableExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(forNextStatement.EmbeddedStatement); +// forNextStatement.EmbeddedStatement.AcceptVisitor(this, data); +// forNextStatement.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitGotoStatement(GotoStatement gotoStatement, object data) { +// Debug.Assert((gotoStatement != null)); +// return null; +// } +// +// public virtual object VisitIdentifierExpression(SimpleNameExpression identifierExpression, object data) { +// Debug.Assert((identifierExpression != null)); +// Debug.Assert((identifierExpression.TypeArguments != null)); +// for (int i = 0; i < identifierExpression.TypeArguments.Count; i++) { +// TypeReference o = identifierExpression.TypeArguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TypeReference)nodeStack.Pop(); +// if (o == null) +// identifierExpression.TypeArguments.RemoveAt(i--); +// else +// identifierExpression.TypeArguments[i] = o; +// } +// return null; +// } +// +// public virtual object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) { +// Debug.Assert((ifElseStatement != null)); +// Debug.Assert((ifElseStatement.Condition != null)); +// Debug.Assert((ifElseStatement.TrueStatement != null)); +// Debug.Assert((ifElseStatement.FalseStatement != null)); +// Debug.Assert((ifElseStatement.ElseIfSections != null)); +// nodeStack.Push(ifElseStatement.Condition); +// ifElseStatement.Condition.AcceptVisitor(this, data); +// ifElseStatement.Condition = ((Expression)(nodeStack.Pop())); +// for (int i = 0; i < ifElseStatement.TrueStatement.Count; i++) { +// Statement o = ifElseStatement.TrueStatement[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Statement)nodeStack.Pop(); +// if (o == null) +// ifElseStatement.TrueStatement.RemoveAt(i--); +// else +// ifElseStatement.TrueStatement[i] = o; +// } +// for (int i = 0; i < ifElseStatement.FalseStatement.Count; i++) { +// Statement o = ifElseStatement.FalseStatement[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Statement)nodeStack.Pop(); +// if (o == null) +// ifElseStatement.FalseStatement.RemoveAt(i--); +// else +// ifElseStatement.FalseStatement[i] = o; +// } +// for (int i = 0; i < ifElseStatement.ElseIfSections.Count; i++) { +// ElseIfSection o = ifElseStatement.ElseIfSections[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ElseIfSection)nodeStack.Pop(); +// if (o == null) +// ifElseStatement.ElseIfSections.RemoveAt(i--); +// else +// ifElseStatement.ElseIfSections[i] = o; +// } +// return null; +// } +// +// public virtual object VisitInnerClassTypeReference(InnerClassTypeReference innerClassTypeReference, object data) { +// Debug.Assert((innerClassTypeReference != null)); +// Debug.Assert((innerClassTypeReference.GenericTypes != null)); +// Debug.Assert((innerClassTypeReference.BaseType != null)); +// for (int i = 0; i < innerClassTypeReference.GenericTypes.Count; i++) { +// TypeReference o = innerClassTypeReference.GenericTypes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TypeReference)nodeStack.Pop(); +// if (o == null) +// innerClassTypeReference.GenericTypes.RemoveAt(i--); +// else +// innerClassTypeReference.GenericTypes[i] = o; +// } +// nodeStack.Push(innerClassTypeReference.BaseType); +// innerClassTypeReference.BaseType.AcceptVisitor(this, data); +// innerClassTypeReference.BaseType = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitInterfaceImplementation(InterfaceImplementation interfaceImplementation, object data) { +// Debug.Assert((interfaceImplementation != null)); +// Debug.Assert((interfaceImplementation.InterfaceType != null)); +// nodeStack.Push(interfaceImplementation.InterfaceType); +// interfaceImplementation.InterfaceType.AcceptVisitor(this, data); +// interfaceImplementation.InterfaceType = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitInvocationExpression(InvocationExpression invocationExpression, object data) { +// Debug.Assert((invocationExpression != null)); +// Debug.Assert((invocationExpression.TargetObject != null)); +// Debug.Assert((invocationExpression.Arguments != null)); +// nodeStack.Push(invocationExpression.TargetObject); +// invocationExpression.TargetObject.AcceptVisitor(this, data); +// invocationExpression.TargetObject = ((Expression)(nodeStack.Pop())); +// for (int i = 0; i < invocationExpression.Arguments.Count; i++) { +// Expression o = invocationExpression.Arguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// invocationExpression.Arguments.RemoveAt(i--); +// else +// invocationExpression.Arguments[i] = o; +// } +// return null; +// } +// +// public virtual object VisitLabelStatement(LabelStatement labelStatement, object data) { +// Debug.Assert((labelStatement != null)); +// return null; +// } +// +// public virtual object VisitLambdaExpression(LambdaExpression lambdaExpression, object data) { +// Debug.Assert((lambdaExpression != null)); +// Debug.Assert((lambdaExpression.Parameters != null)); +// Debug.Assert((lambdaExpression.StatementBody != null)); +// Debug.Assert((lambdaExpression.ExpressionBody != null)); +// Debug.Assert((lambdaExpression.ReturnType != null)); +// for (int i = 0; i < lambdaExpression.Parameters.Count; i++) { +// ParameterDeclarationExpression o = lambdaExpression.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// lambdaExpression.Parameters.RemoveAt(i--); +// else +// lambdaExpression.Parameters[i] = o; +// } +// nodeStack.Push(lambdaExpression.StatementBody); +// lambdaExpression.StatementBody.AcceptVisitor(this, data); +// lambdaExpression.StatementBody = ((Statement)(nodeStack.Pop())); +// nodeStack.Push(lambdaExpression.ExpressionBody); +// lambdaExpression.ExpressionBody.AcceptVisitor(this, data); +// lambdaExpression.ExpressionBody = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(lambdaExpression.ReturnType); +// lambdaExpression.ReturnType.AcceptVisitor(this, data); +// lambdaExpression.ReturnType = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data) { +// Debug.Assert((localVariableDeclaration != null)); +// Debug.Assert((localVariableDeclaration.TypeReference != null)); +// Debug.Assert((localVariableDeclaration.Variables != null)); +// nodeStack.Push(localVariableDeclaration.TypeReference); +// localVariableDeclaration.TypeReference.AcceptVisitor(this, data); +// localVariableDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// for (int i = 0; i < localVariableDeclaration.Variables.Count; i++) { +// VariableDeclaration o = localVariableDeclaration.Variables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (VariableDeclaration)nodeStack.Pop(); +// if (o == null) +// localVariableDeclaration.Variables.RemoveAt(i--); +// else +// localVariableDeclaration.Variables[i] = o; +// } +// return null; +// } +// +// public virtual object VisitLockStatement(LockStatement lockStatement, object data) { +// Debug.Assert((lockStatement != null)); +// Debug.Assert((lockStatement.LockExpression != null)); +// Debug.Assert((lockStatement.EmbeddedStatement != null)); +// nodeStack.Push(lockStatement.LockExpression); +// lockStatement.LockExpression.AcceptVisitor(this, data); +// lockStatement.LockExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(lockStatement.EmbeddedStatement); +// lockStatement.EmbeddedStatement.AcceptVisitor(this, data); +// lockStatement.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitMemberInitializerExpression(MemberInitializerExpression memberInitializerExpression, object data) { +// Debug.Assert((memberInitializerExpression != null)); +// Debug.Assert((memberInitializerExpression.Expression != null)); +// nodeStack.Push(memberInitializerExpression.Expression); +// memberInitializerExpression.Expression.AcceptVisitor(this, data); +// memberInitializerExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) { +// Debug.Assert((memberReferenceExpression != null)); +// Debug.Assert((memberReferenceExpression.TargetObject != null)); +// Debug.Assert((memberReferenceExpression.TypeArguments != null)); +// nodeStack.Push(memberReferenceExpression.TargetObject); +// memberReferenceExpression.TargetObject.AcceptVisitor(this, data); +// memberReferenceExpression.TargetObject = ((Expression)(nodeStack.Pop())); +// for (int i = 0; i < memberReferenceExpression.TypeArguments.Count; i++) { +// TypeReference o = memberReferenceExpression.TypeArguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TypeReference)nodeStack.Pop(); +// if (o == null) +// memberReferenceExpression.TypeArguments.RemoveAt(i--); +// else +// memberReferenceExpression.TypeArguments[i] = o; +// } +// return null; +// } +// +// public virtual object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) { +// Debug.Assert((methodDeclaration != null)); +// Debug.Assert((methodDeclaration.Attributes != null)); +// Debug.Assert((methodDeclaration.Parameters != null)); +// Debug.Assert((methodDeclaration.InterfaceImplementations != null)); +// Debug.Assert((methodDeclaration.TypeReference != null)); +// Debug.Assert((methodDeclaration.Body != null)); +// Debug.Assert((methodDeclaration.Templates != null)); +// for (int i = 0; i < methodDeclaration.Attributes.Count; i++) { +// AttributeSection o = methodDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// methodDeclaration.Attributes.RemoveAt(i--); +// else +// methodDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < methodDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = methodDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// methodDeclaration.Parameters.RemoveAt(i--); +// else +// methodDeclaration.Parameters[i] = o; +// } +// for (int i = 0; i < methodDeclaration.InterfaceImplementations.Count; i++) { +// InterfaceImplementation o = methodDeclaration.InterfaceImplementations[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (InterfaceImplementation)nodeStack.Pop(); +// if (o == null) +// methodDeclaration.InterfaceImplementations.RemoveAt(i--); +// else +// methodDeclaration.InterfaceImplementations[i] = o; +// } +// nodeStack.Push(methodDeclaration.TypeReference); +// methodDeclaration.TypeReference.AcceptVisitor(this, data); +// methodDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(methodDeclaration.Body); +// methodDeclaration.Body.AcceptVisitor(this, data); +// methodDeclaration.Body = ((BlockStatement)(nodeStack.Pop())); +// for (int i = 0; i < methodDeclaration.Templates.Count; i++) { +// TemplateDefinition o = methodDeclaration.Templates[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TemplateDefinition)nodeStack.Pop(); +// if (o == null) +// methodDeclaration.Templates.RemoveAt(i--); +// else +// methodDeclaration.Templates[i] = o; +// } +// return null; +// } +// +// public virtual object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { +// Debug.Assert((namedArgumentExpression != null)); +// Debug.Assert((namedArgumentExpression.Expression != null)); +// nodeStack.Push(namedArgumentExpression.Expression); +// namedArgumentExpression.Expression.AcceptVisitor(this, data); +// namedArgumentExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { +// Debug.Assert((namespaceDeclaration != null)); +// for (int i = 0; i < namespaceDeclaration.Children.Count; i++) { +// INode o = namespaceDeclaration.Children[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = nodeStack.Pop(); +// if (o == null) +// namespaceDeclaration.Children.RemoveAt(i--); +// else +// namespaceDeclaration.Children[i] = o; +// } +// return null; +// } +// +// public virtual object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { +// Debug.Assert((objectCreateExpression != null)); +// Debug.Assert((objectCreateExpression.CreateType != null)); +// Debug.Assert((objectCreateExpression.Parameters != null)); +// Debug.Assert((objectCreateExpression.ObjectInitializer != null)); +// nodeStack.Push(objectCreateExpression.CreateType); +// objectCreateExpression.CreateType.AcceptVisitor(this, data); +// objectCreateExpression.CreateType = ((TypeReference)(nodeStack.Pop())); +// for (int i = 0; i < objectCreateExpression.Parameters.Count; i++) { +// Expression o = objectCreateExpression.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// objectCreateExpression.Parameters.RemoveAt(i--); +// else +// objectCreateExpression.Parameters[i] = o; +// } +// nodeStack.Push(objectCreateExpression.ObjectInitializer); +// objectCreateExpression.ObjectInitializer.AcceptVisitor(this, data); +// objectCreateExpression.ObjectInitializer = ((CollectionInitializerExpression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitOnErrorStatement(OnErrorStatement onErrorStatement, object data) { +// Debug.Assert((onErrorStatement != null)); +// Debug.Assert((onErrorStatement.EmbeddedStatement != null)); +// nodeStack.Push(onErrorStatement.EmbeddedStatement); +// onErrorStatement.EmbeddedStatement.AcceptVisitor(this, data); +// onErrorStatement.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) { +// Debug.Assert((operatorDeclaration != null)); +// Debug.Assert((operatorDeclaration.Attributes != null)); +// Debug.Assert((operatorDeclaration.Parameters != null)); +// Debug.Assert((operatorDeclaration.InterfaceImplementations != null)); +// Debug.Assert((operatorDeclaration.TypeReference != null)); +// Debug.Assert((operatorDeclaration.Body != null)); +// Debug.Assert((operatorDeclaration.Templates != null)); +// for (int i = 0; i < operatorDeclaration.Attributes.Count; i++) { +// AttributeSection o = operatorDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// operatorDeclaration.Attributes.RemoveAt(i--); +// else +// operatorDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < operatorDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = operatorDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// operatorDeclaration.Parameters.RemoveAt(i--); +// else +// operatorDeclaration.Parameters[i] = o; +// } +// for (int i = 0; i < operatorDeclaration.InterfaceImplementations.Count; i++) { +// InterfaceImplementation o = operatorDeclaration.InterfaceImplementations[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (InterfaceImplementation)nodeStack.Pop(); +// if (o == null) +// operatorDeclaration.InterfaceImplementations.RemoveAt(i--); +// else +// operatorDeclaration.InterfaceImplementations[i] = o; +// } +// nodeStack.Push(operatorDeclaration.TypeReference); +// operatorDeclaration.TypeReference.AcceptVisitor(this, data); +// operatorDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(operatorDeclaration.Body); +// operatorDeclaration.Body.AcceptVisitor(this, data); +// operatorDeclaration.Body = ((BlockStatement)(nodeStack.Pop())); +// for (int i = 0; i < operatorDeclaration.Templates.Count; i++) { +// TemplateDefinition o = operatorDeclaration.Templates[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TemplateDefinition)nodeStack.Pop(); +// if (o == null) +// operatorDeclaration.Templates.RemoveAt(i--); +// else +// operatorDeclaration.Templates[i] = o; +// } +// return null; +// } +// +// public virtual object VisitOptionDeclaration(OptionDeclaration optionDeclaration, object data) { +// Debug.Assert((optionDeclaration != null)); +// return null; +// } +// +// public virtual object VisitParameterDeclarationExpression(ParameterDeclarationExpression parameterDeclarationExpression, object data) { +// Debug.Assert((parameterDeclarationExpression != null)); +// Debug.Assert((parameterDeclarationExpression.Attributes != null)); +// Debug.Assert((parameterDeclarationExpression.TypeReference != null)); +// Debug.Assert((parameterDeclarationExpression.DefaultValue != null)); +// for (int i = 0; i < parameterDeclarationExpression.Attributes.Count; i++) { +// AttributeSection o = parameterDeclarationExpression.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// parameterDeclarationExpression.Attributes.RemoveAt(i--); +// else +// parameterDeclarationExpression.Attributes[i] = o; +// } +// nodeStack.Push(parameterDeclarationExpression.TypeReference); +// parameterDeclarationExpression.TypeReference.AcceptVisitor(this, data); +// parameterDeclarationExpression.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(parameterDeclarationExpression.DefaultValue); +// parameterDeclarationExpression.DefaultValue.AcceptVisitor(this, data); +// parameterDeclarationExpression.DefaultValue = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) { +// Debug.Assert((parenthesizedExpression != null)); +// Debug.Assert((parenthesizedExpression.Expression != null)); +// nodeStack.Push(parenthesizedExpression.Expression); +// parenthesizedExpression.Expression.AcceptVisitor(this, data); +// parenthesizedExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { +// Debug.Assert((primitiveExpression != null)); +// return null; +// } +// +// public virtual object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) { +// Debug.Assert((propertyDeclaration != null)); +// Debug.Assert((propertyDeclaration.Attributes != null)); +// Debug.Assert((propertyDeclaration.Parameters != null)); +// Debug.Assert((propertyDeclaration.InterfaceImplementations != null)); +// Debug.Assert((propertyDeclaration.TypeReference != null)); +// Debug.Assert((propertyDeclaration.GetRegion != null)); +// Debug.Assert((propertyDeclaration.SetRegion != null)); +// Debug.Assert((propertyDeclaration.Initializer != null)); +// for (int i = 0; i < propertyDeclaration.Attributes.Count; i++) { +// AttributeSection o = propertyDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// propertyDeclaration.Attributes.RemoveAt(i--); +// else +// propertyDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < propertyDeclaration.Parameters.Count; i++) { +// ParameterDeclarationExpression o = propertyDeclaration.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// propertyDeclaration.Parameters.RemoveAt(i--); +// else +// propertyDeclaration.Parameters[i] = o; +// } +// for (int i = 0; i < propertyDeclaration.InterfaceImplementations.Count; i++) { +// InterfaceImplementation o = propertyDeclaration.InterfaceImplementations[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (InterfaceImplementation)nodeStack.Pop(); +// if (o == null) +// propertyDeclaration.InterfaceImplementations.RemoveAt(i--); +// else +// propertyDeclaration.InterfaceImplementations[i] = o; +// } +// nodeStack.Push(propertyDeclaration.TypeReference); +// propertyDeclaration.TypeReference.AcceptVisitor(this, data); +// propertyDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(propertyDeclaration.GetRegion); +// propertyDeclaration.GetRegion.AcceptVisitor(this, data); +// propertyDeclaration.GetRegion = ((PropertyGetRegion)(nodeStack.Pop())); +// nodeStack.Push(propertyDeclaration.SetRegion); +// propertyDeclaration.SetRegion.AcceptVisitor(this, data); +// propertyDeclaration.SetRegion = ((PropertySetRegion)(nodeStack.Pop())); +// nodeStack.Push(propertyDeclaration.Initializer); +// propertyDeclaration.Initializer.AcceptVisitor(this, data); +// propertyDeclaration.Initializer = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitPropertyGetRegion(PropertyGetRegion propertyGetRegion, object data) { +// Debug.Assert((propertyGetRegion != null)); +// Debug.Assert((propertyGetRegion.Attributes != null)); +// Debug.Assert((propertyGetRegion.Block != null)); +// for (int i = 0; i < propertyGetRegion.Attributes.Count; i++) { +// AttributeSection o = propertyGetRegion.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// propertyGetRegion.Attributes.RemoveAt(i--); +// else +// propertyGetRegion.Attributes[i] = o; +// } +// nodeStack.Push(propertyGetRegion.Block); +// propertyGetRegion.Block.AcceptVisitor(this, data); +// propertyGetRegion.Block = ((BlockStatement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitPropertySetRegion(PropertySetRegion propertySetRegion, object data) { +// Debug.Assert((propertySetRegion != null)); +// Debug.Assert((propertySetRegion.Attributes != null)); +// Debug.Assert((propertySetRegion.Block != null)); +// Debug.Assert((propertySetRegion.Parameters != null)); +// for (int i = 0; i < propertySetRegion.Attributes.Count; i++) { +// AttributeSection o = propertySetRegion.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// propertySetRegion.Attributes.RemoveAt(i--); +// else +// propertySetRegion.Attributes[i] = o; +// } +// nodeStack.Push(propertySetRegion.Block); +// propertySetRegion.Block.AcceptVisitor(this, data); +// propertySetRegion.Block = ((BlockStatement)(nodeStack.Pop())); +// for (int i = 0; i < propertySetRegion.Parameters.Count; i++) { +// ParameterDeclarationExpression o = propertySetRegion.Parameters[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ParameterDeclarationExpression)nodeStack.Pop(); +// if (o == null) +// propertySetRegion.Parameters.RemoveAt(i--); +// else +// propertySetRegion.Parameters[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpression(QueryExpression queryExpression, object data) { +// Debug.Assert((queryExpression != null)); +// Debug.Assert((queryExpression.Clauses != null)); +// for (int i = 0; i < queryExpression.Clauses.Count; i++) { +// QueryExpressionClause o = queryExpression.Clauses[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (QueryExpressionClause)nodeStack.Pop(); +// if (o == null) +// queryExpression.Clauses.RemoveAt(i--); +// else +// queryExpression.Clauses[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionAggregateClause(QueryExpressionAggregateClause queryExpressionAggregateClause, object data) { +// Debug.Assert((queryExpressionAggregateClause != null)); +// Debug.Assert((queryExpressionAggregateClause.Source != null)); +// Debug.Assert((queryExpressionAggregateClause.MiddleClauses != null)); +// Debug.Assert((queryExpressionAggregateClause.IntoVariables != null)); +// nodeStack.Push(queryExpressionAggregateClause.Source); +// queryExpressionAggregateClause.Source.AcceptVisitor(this, data); +// queryExpressionAggregateClause.Source = ((CollectionRangeVariable)(nodeStack.Pop())); +// for (int i = 0; i < queryExpressionAggregateClause.MiddleClauses.Count; i++) { +// QueryExpressionClause o = queryExpressionAggregateClause.MiddleClauses[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (QueryExpressionClause)nodeStack.Pop(); +// if (o == null) +// queryExpressionAggregateClause.MiddleClauses.RemoveAt(i--); +// else +// queryExpressionAggregateClause.MiddleClauses[i] = o; +// } +// for (int i = 0; i < queryExpressionAggregateClause.IntoVariables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionAggregateClause.IntoVariables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionAggregateClause.IntoVariables.RemoveAt(i--); +// else +// queryExpressionAggregateClause.IntoVariables[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionDistinctClause(QueryExpressionDistinctClause queryExpressionDistinctClause, object data) { +// Debug.Assert((queryExpressionDistinctClause != null)); +// return null; +// } +// +// public virtual object VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) { +// Debug.Assert((queryExpressionFromClause != null)); +// Debug.Assert((queryExpressionFromClause.Sources != null)); +// for (int i = 0; i < queryExpressionFromClause.Sources.Count; i++) { +// CollectionRangeVariable o = queryExpressionFromClause.Sources[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (CollectionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionFromClause.Sources.RemoveAt(i--); +// else +// queryExpressionFromClause.Sources[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) { +// Debug.Assert((queryExpressionGroupClause != null)); +// Debug.Assert((queryExpressionGroupClause.Projection != null)); +// Debug.Assert((queryExpressionGroupClause.GroupBy != null)); +// nodeStack.Push(queryExpressionGroupClause.Projection); +// queryExpressionGroupClause.Projection.AcceptVisitor(this, data); +// queryExpressionGroupClause.Projection = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(queryExpressionGroupClause.GroupBy); +// queryExpressionGroupClause.GroupBy.AcceptVisitor(this, data); +// queryExpressionGroupClause.GroupBy = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitQueryExpressionGroupJoinVBClause(QueryExpressionGroupJoinVBClause queryExpressionGroupJoinVBClause, object data) { +// Debug.Assert((queryExpressionGroupJoinVBClause != null)); +// Debug.Assert((queryExpressionGroupJoinVBClause.JoinClause != null)); +// Debug.Assert((queryExpressionGroupJoinVBClause.IntoVariables != null)); +// nodeStack.Push(queryExpressionGroupJoinVBClause.JoinClause); +// queryExpressionGroupJoinVBClause.JoinClause.AcceptVisitor(this, data); +// queryExpressionGroupJoinVBClause.JoinClause = ((QueryExpressionJoinVBClause)(nodeStack.Pop())); +// for (int i = 0; i < queryExpressionGroupJoinVBClause.IntoVariables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionGroupJoinVBClause.IntoVariables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionGroupJoinVBClause.IntoVariables.RemoveAt(i--); +// else +// queryExpressionGroupJoinVBClause.IntoVariables[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionGroupVBClause(QueryExpressionGroupVBClause queryExpressionGroupVBClause, object data) { +// Debug.Assert((queryExpressionGroupVBClause != null)); +// Debug.Assert((queryExpressionGroupVBClause.GroupVariables != null)); +// Debug.Assert((queryExpressionGroupVBClause.ByVariables != null)); +// Debug.Assert((queryExpressionGroupVBClause.IntoVariables != null)); +// for (int i = 0; i < queryExpressionGroupVBClause.GroupVariables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionGroupVBClause.GroupVariables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionGroupVBClause.GroupVariables.RemoveAt(i--); +// else +// queryExpressionGroupVBClause.GroupVariables[i] = o; +// } +// for (int i = 0; i < queryExpressionGroupVBClause.ByVariables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionGroupVBClause.ByVariables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionGroupVBClause.ByVariables.RemoveAt(i--); +// else +// queryExpressionGroupVBClause.ByVariables[i] = o; +// } +// for (int i = 0; i < queryExpressionGroupVBClause.IntoVariables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionGroupVBClause.IntoVariables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionGroupVBClause.IntoVariables.RemoveAt(i--); +// else +// queryExpressionGroupVBClause.IntoVariables[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) { +// Debug.Assert((queryExpressionJoinClause != null)); +// Debug.Assert((queryExpressionJoinClause.OnExpression != null)); +// Debug.Assert((queryExpressionJoinClause.EqualsExpression != null)); +// Debug.Assert((queryExpressionJoinClause.Source != null)); +// nodeStack.Push(queryExpressionJoinClause.OnExpression); +// queryExpressionJoinClause.OnExpression.AcceptVisitor(this, data); +// queryExpressionJoinClause.OnExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(queryExpressionJoinClause.EqualsExpression); +// queryExpressionJoinClause.EqualsExpression.AcceptVisitor(this, data); +// queryExpressionJoinClause.EqualsExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(queryExpressionJoinClause.Source); +// queryExpressionJoinClause.Source.AcceptVisitor(this, data); +// queryExpressionJoinClause.Source = ((CollectionRangeVariable)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitQueryExpressionJoinConditionVB(QueryExpressionJoinConditionVB queryExpressionJoinConditionVB, object data) { +// Debug.Assert((queryExpressionJoinConditionVB != null)); +// Debug.Assert((queryExpressionJoinConditionVB.LeftSide != null)); +// Debug.Assert((queryExpressionJoinConditionVB.RightSide != null)); +// nodeStack.Push(queryExpressionJoinConditionVB.LeftSide); +// queryExpressionJoinConditionVB.LeftSide.AcceptVisitor(this, data); +// queryExpressionJoinConditionVB.LeftSide = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(queryExpressionJoinConditionVB.RightSide); +// queryExpressionJoinConditionVB.RightSide.AcceptVisitor(this, data); +// queryExpressionJoinConditionVB.RightSide = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitQueryExpressionJoinVBClause(QueryExpressionJoinVBClause queryExpressionJoinVBClause, object data) { +// Debug.Assert((queryExpressionJoinVBClause != null)); +// Debug.Assert((queryExpressionJoinVBClause.JoinVariable != null)); +// Debug.Assert((queryExpressionJoinVBClause.SubJoin != null)); +// Debug.Assert((queryExpressionJoinVBClause.Conditions != null)); +// nodeStack.Push(queryExpressionJoinVBClause.JoinVariable); +// queryExpressionJoinVBClause.JoinVariable.AcceptVisitor(this, data); +// queryExpressionJoinVBClause.JoinVariable = ((CollectionRangeVariable)(nodeStack.Pop())); +// nodeStack.Push(queryExpressionJoinVBClause.SubJoin); +// queryExpressionJoinVBClause.SubJoin.AcceptVisitor(this, data); +// queryExpressionJoinVBClause.SubJoin = ((QueryExpressionJoinVBClause)(nodeStack.Pop())); +// for (int i = 0; i < queryExpressionJoinVBClause.Conditions.Count; i++) { +// QueryExpressionJoinConditionVB o = queryExpressionJoinVBClause.Conditions[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (QueryExpressionJoinConditionVB)nodeStack.Pop(); +// if (o == null) +// queryExpressionJoinVBClause.Conditions.RemoveAt(i--); +// else +// queryExpressionJoinVBClause.Conditions[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetVBClause, object data) { +// Debug.Assert((queryExpressionLetVBClause != null)); +// Debug.Assert((queryExpressionLetVBClause.Variables != null)); +// for (int i = 0; i < queryExpressionLetVBClause.Variables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionLetVBClause.Variables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionLetVBClause.Variables.RemoveAt(i--); +// else +// queryExpressionLetVBClause.Variables[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { +// Debug.Assert((queryExpressionOrderClause != null)); +// Debug.Assert((queryExpressionOrderClause.Orderings != null)); +// for (int i = 0; i < queryExpressionOrderClause.Orderings.Count; i++) { +// QueryExpressionOrdering o = queryExpressionOrderClause.Orderings[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (QueryExpressionOrdering)nodeStack.Pop(); +// if (o == null) +// queryExpressionOrderClause.Orderings.RemoveAt(i--); +// else +// queryExpressionOrderClause.Orderings[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { +// Debug.Assert((queryExpressionOrdering != null)); +// Debug.Assert((queryExpressionOrdering.Criteria != null)); +// nodeStack.Push(queryExpressionOrdering.Criteria); +// queryExpressionOrdering.Criteria.AcceptVisitor(this, data); +// queryExpressionOrdering.Criteria = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitQueryExpressionPartitionVBClause(QueryExpressionPartitionVBClause queryExpressionPartitionVBClause, object data) { +// Debug.Assert((queryExpressionPartitionVBClause != null)); +// Debug.Assert((queryExpressionPartitionVBClause.Expression != null)); +// nodeStack.Push(queryExpressionPartitionVBClause.Expression); +// queryExpressionPartitionVBClause.Expression.AcceptVisitor(this, data); +// queryExpressionPartitionVBClause.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data) { +// Debug.Assert((queryExpressionSelectClause != null)); +// Debug.Assert((queryExpressionSelectClause.Projection != null)); +// nodeStack.Push(queryExpressionSelectClause.Projection); +// queryExpressionSelectClause.Projection.AcceptVisitor(this, data); +// queryExpressionSelectClause.Projection = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitQueryExpressionSelectVBClause(QueryExpressionSelectVBClause queryExpressionSelectVBClause, object data) { +// Debug.Assert((queryExpressionSelectVBClause != null)); +// Debug.Assert((queryExpressionSelectVBClause.Variables != null)); +// for (int i = 0; i < queryExpressionSelectVBClause.Variables.Count; i++) { +// ExpressionRangeVariable o = queryExpressionSelectVBClause.Variables[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ExpressionRangeVariable)nodeStack.Pop(); +// if (o == null) +// queryExpressionSelectVBClause.Variables.RemoveAt(i--); +// else +// queryExpressionSelectVBClause.Variables[i] = o; +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionWhereClause(QueryExpressionWhereClause queryExpressionWhereClause, object data) { +// Debug.Assert((queryExpressionWhereClause != null)); +// Debug.Assert((queryExpressionWhereClause.Condition != null)); +// nodeStack.Push(queryExpressionWhereClause.Condition); +// queryExpressionWhereClause.Condition.AcceptVisitor(this, data); +// queryExpressionWhereClause.Condition = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitRaiseEventStatement(RaiseEventStatement raiseEventStatement, object data) { +// Debug.Assert((raiseEventStatement != null)); +// Debug.Assert((raiseEventStatement.Arguments != null)); +// for (int i = 0; i < raiseEventStatement.Arguments.Count; i++) { +// Expression o = raiseEventStatement.Arguments[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (Expression)nodeStack.Pop(); +// if (o == null) +// raiseEventStatement.Arguments.RemoveAt(i--); +// else +// raiseEventStatement.Arguments[i] = o; +// } +// return null; +// } +// +// public virtual object VisitReDimStatement(ReDimStatement reDimStatement, object data) { +// Debug.Assert((reDimStatement != null)); +// Debug.Assert((reDimStatement.ReDimClauses != null)); +// for (int i = 0; i < reDimStatement.ReDimClauses.Count; i++) { +// InvocationExpression o = reDimStatement.ReDimClauses[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (InvocationExpression)nodeStack.Pop(); +// if (o == null) +// reDimStatement.ReDimClauses.RemoveAt(i--); +// else +// reDimStatement.ReDimClauses[i] = o; +// } +// return null; +// } +// +// public virtual object VisitRemoveHandlerStatement(RemoveHandlerStatement removeHandlerStatement, object data) { +// Debug.Assert((removeHandlerStatement != null)); +// Debug.Assert((removeHandlerStatement.EventExpression != null)); +// Debug.Assert((removeHandlerStatement.HandlerExpression != null)); +// nodeStack.Push(removeHandlerStatement.EventExpression); +// removeHandlerStatement.EventExpression.AcceptVisitor(this, data); +// removeHandlerStatement.EventExpression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(removeHandlerStatement.HandlerExpression); +// removeHandlerStatement.HandlerExpression.AcceptVisitor(this, data); +// removeHandlerStatement.HandlerExpression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitResumeStatement(ResumeStatement resumeStatement, object data) { +// Debug.Assert((resumeStatement != null)); +// return null; +// } +// +// public virtual object VisitReturnStatement(ReturnStatement returnStatement, object data) { +// Debug.Assert((returnStatement != null)); +// Debug.Assert((returnStatement.Expression != null)); +// nodeStack.Push(returnStatement.Expression); +// returnStatement.Expression.AcceptVisitor(this, data); +// returnStatement.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitStopStatement(StopStatement stopStatement, object data) { +// Debug.Assert((stopStatement != null)); +// return null; +// } +// +// public virtual object VisitSwitchSection(SwitchSection switchSection, object data) { +// Debug.Assert((switchSection != null)); +// Debug.Assert((switchSection.SwitchLabels != null)); +// for (int i = 0; i < switchSection.SwitchLabels.Count; i++) { +// CaseLabel o = switchSection.SwitchLabels[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (CaseLabel)nodeStack.Pop(); +// if (o == null) +// switchSection.SwitchLabels.RemoveAt(i--); +// else +// switchSection.SwitchLabels[i] = o; +// } +// for (int i = 0; i < switchSection.Children.Count; i++) { +// INode o = switchSection.Children[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = nodeStack.Pop(); +// if (o == null) +// switchSection.Children.RemoveAt(i--); +// else +// switchSection.Children[i] = o; +// } +// return null; +// } +// +// public virtual object VisitSwitchStatement(SwitchStatement switchStatement, object data) { +// Debug.Assert((switchStatement != null)); +// Debug.Assert((switchStatement.SwitchExpression != null)); +// Debug.Assert((switchStatement.SwitchSections != null)); +// nodeStack.Push(switchStatement.SwitchExpression); +// switchStatement.SwitchExpression.AcceptVisitor(this, data); +// switchStatement.SwitchExpression = ((Expression)(nodeStack.Pop())); +// for (int i = 0; i < switchStatement.SwitchSections.Count; i++) { +// SwitchSection o = switchStatement.SwitchSections[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (SwitchSection)nodeStack.Pop(); +// if (o == null) +// switchStatement.SwitchSections.RemoveAt(i--); +// else +// switchStatement.SwitchSections[i] = o; +// } +// return null; +// } +// +// public virtual object VisitTemplateDefinition(TemplateDefinition templateDefinition, object data) { +// Debug.Assert((templateDefinition != null)); +// Debug.Assert((templateDefinition.Attributes != null)); +// Debug.Assert((templateDefinition.Bases != null)); +// for (int i = 0; i < templateDefinition.Attributes.Count; i++) { +// AttributeSection o = templateDefinition.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// templateDefinition.Attributes.RemoveAt(i--); +// else +// templateDefinition.Attributes[i] = o; +// } +// for (int i = 0; i < templateDefinition.Bases.Count; i++) { +// TypeReference o = templateDefinition.Bases[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TypeReference)nodeStack.Pop(); +// if (o == null) +// templateDefinition.Bases.RemoveAt(i--); +// else +// templateDefinition.Bases[i] = o; +// } +// return null; +// } +// +// public virtual object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) { +// Debug.Assert((thisReferenceExpression != null)); +// return null; +// } +// +// public virtual object VisitThrowStatement(ThrowStatement throwStatement, object data) { +// Debug.Assert((throwStatement != null)); +// Debug.Assert((throwStatement.Expression != null)); +// nodeStack.Push(throwStatement.Expression); +// throwStatement.Expression.AcceptVisitor(this, data); +// throwStatement.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) { +// Debug.Assert((tryCatchStatement != null)); +// Debug.Assert((tryCatchStatement.StatementBlock != null)); +// Debug.Assert((tryCatchStatement.CatchClauses != null)); +// Debug.Assert((tryCatchStatement.FinallyBlock != null)); +// nodeStack.Push(tryCatchStatement.StatementBlock); +// tryCatchStatement.StatementBlock.AcceptVisitor(this, data); +// tryCatchStatement.StatementBlock = ((Statement)(nodeStack.Pop())); +// for (int i = 0; i < tryCatchStatement.CatchClauses.Count; i++) { +// CatchClause o = tryCatchStatement.CatchClauses[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (CatchClause)nodeStack.Pop(); +// if (o == null) +// tryCatchStatement.CatchClauses.RemoveAt(i--); +// else +// tryCatchStatement.CatchClauses[i] = o; +// } +// nodeStack.Push(tryCatchStatement.FinallyBlock); +// tryCatchStatement.FinallyBlock.AcceptVisitor(this, data); +// tryCatchStatement.FinallyBlock = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { +// Debug.Assert((typeDeclaration != null)); +// Debug.Assert((typeDeclaration.Attributes != null)); +// Debug.Assert((typeDeclaration.BaseTypes != null)); +// Debug.Assert((typeDeclaration.Templates != null)); +// for (int i = 0; i < typeDeclaration.Attributes.Count; i++) { +// AttributeSection o = typeDeclaration.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (AttributeSection)nodeStack.Pop(); +// if (o == null) +// typeDeclaration.Attributes.RemoveAt(i--); +// else +// typeDeclaration.Attributes[i] = o; +// } +// for (int i = 0; i < typeDeclaration.BaseTypes.Count; i++) { +// TypeReference o = typeDeclaration.BaseTypes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TypeReference)nodeStack.Pop(); +// if (o == null) +// typeDeclaration.BaseTypes.RemoveAt(i--); +// else +// typeDeclaration.BaseTypes[i] = o; +// } +// for (int i = 0; i < typeDeclaration.Templates.Count; i++) { +// TemplateDefinition o = typeDeclaration.Templates[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TemplateDefinition)nodeStack.Pop(); +// if (o == null) +// typeDeclaration.Templates.RemoveAt(i--); +// else +// typeDeclaration.Templates[i] = o; +// } +// for (int i = 0; i < typeDeclaration.Children.Count; i++) { +// INode o = typeDeclaration.Children[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = nodeStack.Pop(); +// if (o == null) +// typeDeclaration.Children.RemoveAt(i--); +// else +// typeDeclaration.Children[i] = o; +// } +// return null; +// } +// +// public virtual object VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) { +// Debug.Assert((typeOfExpression != null)); +// Debug.Assert((typeOfExpression.TypeReference != null)); +// nodeStack.Push(typeOfExpression.TypeReference); +// typeOfExpression.TypeReference.AcceptVisitor(this, data); +// typeOfExpression.TypeReference = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) { +// Debug.Assert((typeOfIsExpression != null)); +// Debug.Assert((typeOfIsExpression.Expression != null)); +// Debug.Assert((typeOfIsExpression.TypeReference != null)); +// nodeStack.Push(typeOfIsExpression.Expression); +// typeOfIsExpression.Expression.AcceptVisitor(this, data); +// typeOfIsExpression.Expression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(typeOfIsExpression.TypeReference); +// typeOfIsExpression.TypeReference.AcceptVisitor(this, data); +// typeOfIsExpression.TypeReference = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitTypeReference(TypeReference typeReference, object data) { +// Debug.Assert((typeReference != null)); +// Debug.Assert((typeReference.GenericTypes != null)); +// for (int i = 0; i < typeReference.GenericTypes.Count; i++) { +// TypeReference o = typeReference.GenericTypes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (TypeReference)nodeStack.Pop(); +// if (o == null) +// typeReference.GenericTypes.RemoveAt(i--); +// else +// typeReference.GenericTypes[i] = o; +// } +// return null; +// } +// +// public virtual object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) { +// Debug.Assert((typeReferenceExpression != null)); +// Debug.Assert((typeReferenceExpression.TypeReference != null)); +// nodeStack.Push(typeReferenceExpression.TypeReference); +// typeReferenceExpression.TypeReference.AcceptVisitor(this, data); +// typeReferenceExpression.TypeReference = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { +// Debug.Assert((unaryOperatorExpression != null)); +// Debug.Assert((unaryOperatorExpression.Expression != null)); +// nodeStack.Push(unaryOperatorExpression.Expression); +// unaryOperatorExpression.Expression.AcceptVisitor(this, data); +// unaryOperatorExpression.Expression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitUsing(ImportsClause @using, object data) { +// Debug.Assert((@using != null)); +// Debug.Assert((@using.Alias != null)); +// nodeStack.Push(@using.Alias); +// @using.Alias.AcceptVisitor(this, data); +// @using.Alias = ((TypeReference)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitUsingDeclaration(ImportsStatement usingDeclaration, object data) { +// Debug.Assert((usingDeclaration != null)); +// Debug.Assert((usingDeclaration.ImportsClauses != null)); +// for (int i = 0; i < usingDeclaration.ImportsClauses.Count; i++) { +// ImportsClause o = usingDeclaration.ImportsClauses[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (ImportsClause)nodeStack.Pop(); +// if (o == null) +// usingDeclaration.ImportsClauses.RemoveAt(i--); +// else +// usingDeclaration.ImportsClauses[i] = o; +// } +// return null; +// } +// +// public virtual object VisitUsingStatement(UsingStatement usingStatement, object data) { +// Debug.Assert((usingStatement != null)); +// Debug.Assert((usingStatement.ResourceAcquisition != null)); +// Debug.Assert((usingStatement.EmbeddedStatement != null)); +// nodeStack.Push(usingStatement.ResourceAcquisition); +// usingStatement.ResourceAcquisition.AcceptVisitor(this, data); +// usingStatement.ResourceAcquisition = ((Statement)(nodeStack.Pop())); +// nodeStack.Push(usingStatement.EmbeddedStatement); +// usingStatement.EmbeddedStatement.AcceptVisitor(this, data); +// usingStatement.EmbeddedStatement = ((Statement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data) { +// Debug.Assert((variableDeclaration != null)); +// Debug.Assert((variableDeclaration.Initializer != null)); +// Debug.Assert((variableDeclaration.TypeReference != null)); +// Debug.Assert((variableDeclaration.FixedArrayInitialization != null)); +// nodeStack.Push(variableDeclaration.Initializer); +// variableDeclaration.Initializer.AcceptVisitor(this, data); +// variableDeclaration.Initializer = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(variableDeclaration.TypeReference); +// variableDeclaration.TypeReference.AcceptVisitor(this, data); +// variableDeclaration.TypeReference = ((TypeReference)(nodeStack.Pop())); +// nodeStack.Push(variableDeclaration.FixedArrayInitialization); +// variableDeclaration.FixedArrayInitialization.AcceptVisitor(this, data); +// variableDeclaration.FixedArrayInitialization = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitWithStatement(WithStatement withStatement, object data) { +// Debug.Assert((withStatement != null)); +// Debug.Assert((withStatement.Expression != null)); +// Debug.Assert((withStatement.Body != null)); +// nodeStack.Push(withStatement.Expression); +// withStatement.Expression.AcceptVisitor(this, data); +// withStatement.Expression = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(withStatement.Body); +// withStatement.Body.AcceptVisitor(this, data); +// withStatement.Body = ((BlockStatement)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitXmlAttributeExpression(XmlAttributeExpression xmlAttributeExpression, object data) { +// Debug.Assert((xmlAttributeExpression != null)); +// Debug.Assert((xmlAttributeExpression.ExpressionValue != null)); +// nodeStack.Push(xmlAttributeExpression.ExpressionValue); +// xmlAttributeExpression.ExpressionValue.AcceptVisitor(this, data); +// xmlAttributeExpression.ExpressionValue = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitXmlContentExpression(XmlContentExpression xmlContentExpression, object data) { +// Debug.Assert((xmlContentExpression != null)); +// return null; +// } +// +// public virtual object VisitXmlDocumentExpression(XmlDocumentExpression xmlDocumentExpression, object data) { +// Debug.Assert((xmlDocumentExpression != null)); +// Debug.Assert((xmlDocumentExpression.Expressions != null)); +// for (int i = 0; i < xmlDocumentExpression.Expressions.Count; i++) { +// XmlExpression o = xmlDocumentExpression.Expressions[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (XmlExpression)nodeStack.Pop(); +// if (o == null) +// xmlDocumentExpression.Expressions.RemoveAt(i--); +// else +// xmlDocumentExpression.Expressions[i] = o; +// } +// return null; +// } +// +// public virtual object VisitXmlElementExpression(XmlElementExpression xmlElementExpression, object data) { +// Debug.Assert((xmlElementExpression != null)); +// Debug.Assert((xmlElementExpression.Content != null)); +// Debug.Assert((xmlElementExpression.NameExpression != null)); +// Debug.Assert((xmlElementExpression.Attributes != null)); +// nodeStack.Push(xmlElementExpression.Content); +// xmlElementExpression.Content.AcceptVisitor(this, data); +// xmlElementExpression.Content = ((Expression)(nodeStack.Pop())); +// nodeStack.Push(xmlElementExpression.NameExpression); +// xmlElementExpression.NameExpression.AcceptVisitor(this, data); +// xmlElementExpression.NameExpression = ((Expression)(nodeStack.Pop())); +// for (int i = 0; i < xmlElementExpression.Attributes.Count; i++) { +// XmlExpression o = xmlElementExpression.Attributes[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = (XmlExpression)nodeStack.Pop(); +// if (o == null) +// xmlElementExpression.Attributes.RemoveAt(i--); +// else +// xmlElementExpression.Attributes[i] = o; +// } +// for (int i = 0; i < xmlElementExpression.Children.Count; i++) { +// INode o = xmlElementExpression.Children[i]; +// Debug.Assert(o != null); +// nodeStack.Push(o); +// o.AcceptVisitor(this, data); +// o = nodeStack.Pop(); +// if (o == null) +// xmlElementExpression.Children.RemoveAt(i--); +// else +// xmlElementExpression.Children[i] = o; +// } +// return null; +// } +// +// public virtual object VisitXmlEmbeddedExpression(XmlEmbeddedExpression xmlEmbeddedExpression, object data) { +// Debug.Assert((xmlEmbeddedExpression != null)); +// Debug.Assert((xmlEmbeddedExpression.InlineVBExpression != null)); +// nodeStack.Push(xmlEmbeddedExpression.InlineVBExpression); +// xmlEmbeddedExpression.InlineVBExpression.AcceptVisitor(this, data); +// xmlEmbeddedExpression.InlineVBExpression = ((Expression)(nodeStack.Pop())); +// return null; +// } +// +// public virtual object VisitXmlMemberAccessExpression(XmlMemberAccessExpression xmlMemberAccessExpression, object data) { +// Debug.Assert((xmlMemberAccessExpression != null)); +// Debug.Assert((xmlMemberAccessExpression.TargetObject != null)); +// nodeStack.Push(xmlMemberAccessExpression.TargetObject); +// xmlMemberAccessExpression.TargetObject.AcceptVisitor(this, data); +// xmlMemberAccessExpression.TargetObject = ((Expression)(nodeStack.Pop())); +// return null; +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/AbstractAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/AbstractAstVisitor.cs new file mode 100644 index 0000000000..6f44974418 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/AbstractAstVisitor.cs @@ -0,0 +1,1156 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ICSharpCode.NRefactory.VB.Visitors { + using System; + using System.Collections.Generic; + using System.Diagnostics; + using ICSharpCode.NRefactory.VB.Ast; + + +// public abstract class AbstractAstVisitor : IAstVisitor { +// +// public virtual object VisitAddHandlerStatement(AddHandlerStatement addHandlerStatement, object data) { +// Debug.Assert((addHandlerStatement != null)); +// Debug.Assert((addHandlerStatement.EventExpression != null)); +// Debug.Assert((addHandlerStatement.HandlerExpression != null)); +// addHandlerStatement.EventExpression.AcceptVisitor(this, data); +// return addHandlerStatement.HandlerExpression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitAddressOfExpression(AddressOfExpression addressOfExpression, object data) { +// Debug.Assert((addressOfExpression != null)); +// Debug.Assert((addressOfExpression.Expression != null)); +// return addressOfExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) { +// Debug.Assert((arrayCreateExpression != null)); +// Debug.Assert((arrayCreateExpression.CreateType != null)); +// Debug.Assert((arrayCreateExpression.Arguments != null)); +// Debug.Assert((arrayCreateExpression.ArrayInitializer != null)); +// arrayCreateExpression.CreateType.AcceptVisitor(this, data); +// foreach (Expression o in arrayCreateExpression.Arguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return arrayCreateExpression.ArrayInitializer.AcceptVisitor(this, data); +// } +// +// public virtual object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) { +// Debug.Assert((assignmentExpression != null)); +// Debug.Assert((assignmentExpression.Left != null)); +// Debug.Assert((assignmentExpression.Right != null)); +// assignmentExpression.Left.AcceptVisitor(this, data); +// return assignmentExpression.Right.AcceptVisitor(this, data); +// } +// +// public virtual object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) { +// Debug.Assert((attribute != null)); +// Debug.Assert((attribute.PositionalArguments != null)); +// Debug.Assert((attribute.NamedArguments != null)); +// foreach (Expression o in attribute.PositionalArguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (NamedArgumentExpression o in attribute.NamedArguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitAttributeSection(AttributeSection attributeSection, object data) { +// Debug.Assert((attributeSection != null)); +// Debug.Assert((attributeSection.Attributes != null)); +// foreach (ICSharpCode.NRefactory.VB.Ast.Attribute o in attributeSection.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) { +// Debug.Assert((baseReferenceExpression != null)); +// return null; +// } +// +// public virtual object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { +// Debug.Assert((binaryOperatorExpression != null)); +// Debug.Assert((binaryOperatorExpression.Left != null)); +// Debug.Assert((binaryOperatorExpression.Right != null)); +// binaryOperatorExpression.Left.AcceptVisitor(this, data); +// return binaryOperatorExpression.Right.AcceptVisitor(this, data); +// } +// +// public virtual object VisitBlockStatement(BlockStatement blockStatement, object data) { +// Debug.Assert((blockStatement != null)); +// return blockStatement.AcceptChildren(this, data); +// } +// +// public virtual object VisitCaseLabel(CaseLabel caseLabel, object data) { +// Debug.Assert((caseLabel != null)); +// Debug.Assert((caseLabel.Label != null)); +// Debug.Assert((caseLabel.ToExpression != null)); +// caseLabel.Label.AcceptVisitor(this, data); +// return caseLabel.ToExpression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitCastExpression(CastExpression castExpression, object data) { +// Debug.Assert((castExpression != null)); +// Debug.Assert((castExpression.CastTo != null)); +// Debug.Assert((castExpression.Expression != null)); +// castExpression.CastTo.AcceptVisitor(this, data); +// return castExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitCatchClause(CatchClause catchClause, object data) { +// Debug.Assert((catchClause != null)); +// Debug.Assert((catchClause.TypeReference != null)); +// Debug.Assert((catchClause.StatementBlock != null)); +// Debug.Assert((catchClause.Condition != null)); +// catchClause.TypeReference.AcceptVisitor(this, data); +// catchClause.StatementBlock.AcceptVisitor(this, data); +// return catchClause.Condition.AcceptVisitor(this, data); +// } +// +// public virtual object VisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data) { +// Debug.Assert((classReferenceExpression != null)); +// return null; +// } +// +// public virtual object VisitCollectionInitializerExpression(CollectionInitializerExpression collectionInitializerExpression, object data) { +// Debug.Assert((collectionInitializerExpression != null)); +// Debug.Assert((collectionInitializerExpression.CreateExpressions != null)); +// foreach (Expression o in collectionInitializerExpression.CreateExpressions) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitCollectionRangeVariable(CollectionRangeVariable collectionRangeVariable, object data) { +// Debug.Assert((collectionRangeVariable != null)); +// Debug.Assert((collectionRangeVariable.Expression != null)); +// Debug.Assert((collectionRangeVariable.Type != null)); +// collectionRangeVariable.Expression.AcceptVisitor(this, data); +// return collectionRangeVariable.Type.AcceptVisitor(this, data); +// } +// +// public virtual object VisitCompilationUnit(CompilationUnit compilationUnit, object data) { +// Debug.Assert((compilationUnit != null)); +// return compilationUnit.AcceptChildren(this, data); +// } +// +// public virtual object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) { +// Debug.Assert((conditionalExpression != null)); +// Debug.Assert((conditionalExpression.Condition != null)); +// Debug.Assert((conditionalExpression.TrueExpression != null)); +// Debug.Assert((conditionalExpression.FalseExpression != null)); +// conditionalExpression.Condition.AcceptVisitor(this, data); +// conditionalExpression.TrueExpression.AcceptVisitor(this, data); +// return conditionalExpression.FalseExpression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) { +// Debug.Assert((constructorDeclaration != null)); +// Debug.Assert((constructorDeclaration.Attributes != null)); +// Debug.Assert((constructorDeclaration.Parameters != null)); +// Debug.Assert((constructorDeclaration.ConstructorInitializer != null)); +// Debug.Assert((constructorDeclaration.Body != null)); +// foreach (AttributeSection o in constructorDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ParameterDeclarationExpression o in constructorDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// constructorDeclaration.ConstructorInitializer.AcceptVisitor(this, data); +// return constructorDeclaration.Body.AcceptVisitor(this, data); +// } +// +// public virtual object VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) { +// Debug.Assert((constructorInitializer != null)); +// Debug.Assert((constructorInitializer.Arguments != null)); +// foreach (Expression o in constructorInitializer.Arguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitContinueStatement(ContinueStatement continueStatement, object data) { +// Debug.Assert((continueStatement != null)); +// return null; +// } +// +// public virtual object VisitDeclareDeclaration(DeclareDeclaration declareDeclaration, object data) { +// Debug.Assert((declareDeclaration != null)); +// Debug.Assert((declareDeclaration.Attributes != null)); +// Debug.Assert((declareDeclaration.Parameters != null)); +// Debug.Assert((declareDeclaration.TypeReference != null)); +// foreach (AttributeSection o in declareDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ParameterDeclarationExpression o in declareDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return declareDeclaration.TypeReference.AcceptVisitor(this, data); +// } +// +// public virtual object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) { +// Debug.Assert((defaultValueExpression != null)); +// Debug.Assert((defaultValueExpression.TypeReference != null)); +// return defaultValueExpression.TypeReference.AcceptVisitor(this, data); +// } +// +// public virtual object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { +// Debug.Assert((delegateDeclaration != null)); +// Debug.Assert((delegateDeclaration.Attributes != null)); +// Debug.Assert((delegateDeclaration.ReturnType != null)); +// Debug.Assert((delegateDeclaration.Parameters != null)); +// Debug.Assert((delegateDeclaration.Templates != null)); +// foreach (AttributeSection o in delegateDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// delegateDeclaration.ReturnType.AcceptVisitor(this, data); +// foreach (ParameterDeclarationExpression o in delegateDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (TemplateDefinition o in delegateDeclaration.Templates) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitDirectionExpression(DirectionExpression directionExpression, object data) { +// Debug.Assert((directionExpression != null)); +// Debug.Assert((directionExpression.Expression != null)); +// return directionExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) { +// Debug.Assert((doLoopStatement != null)); +// Debug.Assert((doLoopStatement.Condition != null)); +// Debug.Assert((doLoopStatement.EmbeddedStatement != null)); +// doLoopStatement.Condition.AcceptVisitor(this, data); +// return doLoopStatement.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitElseIfSection(ElseIfSection elseIfSection, object data) { +// Debug.Assert((elseIfSection != null)); +// Debug.Assert((elseIfSection.Condition != null)); +// Debug.Assert((elseIfSection.EmbeddedStatement != null)); +// elseIfSection.Condition.AcceptVisitor(this, data); +// return elseIfSection.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitEndStatement(EndStatement endStatement, object data) { +// Debug.Assert((endStatement != null)); +// return null; +// } +// +// public virtual object VisitEraseStatement(EraseStatement eraseStatement, object data) { +// Debug.Assert((eraseStatement != null)); +// Debug.Assert((eraseStatement.Expressions != null)); +// foreach (Expression o in eraseStatement.Expressions) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitErrorStatement(ErrorStatement errorStatement, object data) { +// Debug.Assert((errorStatement != null)); +// Debug.Assert((errorStatement.Expression != null)); +// return errorStatement.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitEventAddRegion(EventAddRegion eventAddRegion, object data) { +// Debug.Assert((eventAddRegion != null)); +// Debug.Assert((eventAddRegion.Attributes != null)); +// Debug.Assert((eventAddRegion.Block != null)); +// Debug.Assert((eventAddRegion.Parameters != null)); +// foreach (AttributeSection o in eventAddRegion.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// eventAddRegion.Block.AcceptVisitor(this, data); +// foreach (ParameterDeclarationExpression o in eventAddRegion.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitEventDeclaration(EventDeclaration eventDeclaration, object data) { +// Debug.Assert((eventDeclaration != null)); +// Debug.Assert((eventDeclaration.Attributes != null)); +// Debug.Assert((eventDeclaration.Parameters != null)); +// Debug.Assert((eventDeclaration.InterfaceImplementations != null)); +// Debug.Assert((eventDeclaration.TypeReference != null)); +// Debug.Assert((eventDeclaration.AddRegion != null)); +// Debug.Assert((eventDeclaration.RemoveRegion != null)); +// Debug.Assert((eventDeclaration.RaiseRegion != null)); +// Debug.Assert((eventDeclaration.Initializer != null)); +// foreach (AttributeSection o in eventDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ParameterDeclarationExpression o in eventDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (InterfaceImplementation o in eventDeclaration.InterfaceImplementations) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// eventDeclaration.TypeReference.AcceptVisitor(this, data); +// eventDeclaration.AddRegion.AcceptVisitor(this, data); +// eventDeclaration.RemoveRegion.AcceptVisitor(this, data); +// eventDeclaration.RaiseRegion.AcceptVisitor(this, data); +// return eventDeclaration.Initializer.AcceptVisitor(this, data); +// } +// +// public virtual object VisitEventRaiseRegion(EventRaiseRegion eventRaiseRegion, object data) { +// Debug.Assert((eventRaiseRegion != null)); +// Debug.Assert((eventRaiseRegion.Attributes != null)); +// Debug.Assert((eventRaiseRegion.Block != null)); +// Debug.Assert((eventRaiseRegion.Parameters != null)); +// foreach (AttributeSection o in eventRaiseRegion.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// eventRaiseRegion.Block.AcceptVisitor(this, data); +// foreach (ParameterDeclarationExpression o in eventRaiseRegion.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitEventRemoveRegion(EventRemoveRegion eventRemoveRegion, object data) { +// Debug.Assert((eventRemoveRegion != null)); +// Debug.Assert((eventRemoveRegion.Attributes != null)); +// Debug.Assert((eventRemoveRegion.Block != null)); +// Debug.Assert((eventRemoveRegion.Parameters != null)); +// foreach (AttributeSection o in eventRemoveRegion.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// eventRemoveRegion.Block.AcceptVisitor(this, data); +// foreach (ParameterDeclarationExpression o in eventRemoveRegion.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitExitStatement(ExitStatement exitStatement, object data) { +// Debug.Assert((exitStatement != null)); +// return null; +// } +// +// public virtual object VisitExpressionRangeVariable(ExpressionRangeVariable expressionRangeVariable, object data) { +// Debug.Assert((expressionRangeVariable != null)); +// Debug.Assert((expressionRangeVariable.Expression != null)); +// Debug.Assert((expressionRangeVariable.Type != null)); +// expressionRangeVariable.Expression.AcceptVisitor(this, data); +// return expressionRangeVariable.Type.AcceptVisitor(this, data); +// } +// +// public virtual object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) { +// Debug.Assert((expressionStatement != null)); +// Debug.Assert((expressionStatement.Expression != null)); +// return expressionStatement.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitExternAliasDirective(ExternAliasDirective externAliasDirective, object data) { +// Debug.Assert((externAliasDirective != null)); +// return null; +// } +// +// public virtual object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { +// Debug.Assert((fieldDeclaration != null)); +// Debug.Assert((fieldDeclaration.Attributes != null)); +// Debug.Assert((fieldDeclaration.TypeReference != null)); +// Debug.Assert((fieldDeclaration.Fields != null)); +// foreach (AttributeSection o in fieldDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// fieldDeclaration.TypeReference.AcceptVisitor(this, data); +// foreach (VariableDeclaration o in fieldDeclaration.Fields) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitForeachStatement(ForeachStatement foreachStatement, object data) { +// Debug.Assert((foreachStatement != null)); +// Debug.Assert((foreachStatement.TypeReference != null)); +// Debug.Assert((foreachStatement.Expression != null)); +// Debug.Assert((foreachStatement.NextExpression != null)); +// Debug.Assert((foreachStatement.EmbeddedStatement != null)); +// foreachStatement.TypeReference.AcceptVisitor(this, data); +// foreachStatement.Expression.AcceptVisitor(this, data); +// foreachStatement.NextExpression.AcceptVisitor(this, data); +// return foreachStatement.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitForNextStatement(ForNextStatement forNextStatement, object data) { +// Debug.Assert((forNextStatement != null)); +// Debug.Assert((forNextStatement.Start != null)); +// Debug.Assert((forNextStatement.End != null)); +// Debug.Assert((forNextStatement.Step != null)); +// Debug.Assert((forNextStatement.NextExpressions != null)); +// Debug.Assert((forNextStatement.TypeReference != null)); +// Debug.Assert((forNextStatement.LoopVariableExpression != null)); +// Debug.Assert((forNextStatement.EmbeddedStatement != null)); +// forNextStatement.Start.AcceptVisitor(this, data); +// forNextStatement.End.AcceptVisitor(this, data); +// forNextStatement.Step.AcceptVisitor(this, data); +// foreach (Expression o in forNextStatement.NextExpressions) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// forNextStatement.TypeReference.AcceptVisitor(this, data); +// forNextStatement.LoopVariableExpression.AcceptVisitor(this, data); +// return forNextStatement.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitGotoStatement(GotoStatement gotoStatement, object data) { +// Debug.Assert((gotoStatement != null)); +// return null; +// } +// +// public virtual object VisitIdentifierExpression(SimpleNameExpression identifierExpression, object data) { +// Debug.Assert((identifierExpression != null)); +// Debug.Assert((identifierExpression.TypeArguments != null)); +// foreach (TypeReference o in identifierExpression.TypeArguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) { +// Debug.Assert((ifElseStatement != null)); +// Debug.Assert((ifElseStatement.Condition != null)); +// Debug.Assert((ifElseStatement.TrueStatement != null)); +// Debug.Assert((ifElseStatement.FalseStatement != null)); +// Debug.Assert((ifElseStatement.ElseIfSections != null)); +// ifElseStatement.Condition.AcceptVisitor(this, data); +// foreach (Statement o in ifElseStatement.TrueStatement) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (Statement o in ifElseStatement.FalseStatement) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ElseIfSection o in ifElseStatement.ElseIfSections) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitInnerClassTypeReference(InnerClassTypeReference innerClassTypeReference, object data) { +// Debug.Assert((innerClassTypeReference != null)); +// Debug.Assert((innerClassTypeReference.GenericTypes != null)); +// Debug.Assert((innerClassTypeReference.BaseType != null)); +// foreach (TypeReference o in innerClassTypeReference.GenericTypes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return innerClassTypeReference.BaseType.AcceptVisitor(this, data); +// } +// +// public virtual object VisitInterfaceImplementation(InterfaceImplementation interfaceImplementation, object data) { +// Debug.Assert((interfaceImplementation != null)); +// Debug.Assert((interfaceImplementation.InterfaceType != null)); +// return interfaceImplementation.InterfaceType.AcceptVisitor(this, data); +// } +// +// public virtual object VisitInvocationExpression(InvocationExpression invocationExpression, object data) { +// Debug.Assert((invocationExpression != null)); +// Debug.Assert((invocationExpression.TargetObject != null)); +// Debug.Assert((invocationExpression.Arguments != null)); +// invocationExpression.TargetObject.AcceptVisitor(this, data); +// foreach (Expression o in invocationExpression.Arguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitLabelStatement(LabelStatement labelStatement, object data) { +// Debug.Assert((labelStatement != null)); +// return null; +// } +// +// public virtual object VisitLambdaExpression(LambdaExpression lambdaExpression, object data) { +// Debug.Assert((lambdaExpression != null)); +// Debug.Assert((lambdaExpression.Parameters != null)); +// Debug.Assert((lambdaExpression.StatementBody != null)); +// Debug.Assert((lambdaExpression.ExpressionBody != null)); +// Debug.Assert((lambdaExpression.ReturnType != null)); +// foreach (ParameterDeclarationExpression o in lambdaExpression.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// lambdaExpression.StatementBody.AcceptVisitor(this, data); +// lambdaExpression.ExpressionBody.AcceptVisitor(this, data); +// return lambdaExpression.ReturnType.AcceptVisitor(this, data); +// } +// +// public virtual object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data) { +// Debug.Assert((localVariableDeclaration != null)); +// Debug.Assert((localVariableDeclaration.TypeReference != null)); +// Debug.Assert((localVariableDeclaration.Variables != null)); +// localVariableDeclaration.TypeReference.AcceptVisitor(this, data); +// foreach (VariableDeclaration o in localVariableDeclaration.Variables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitLockStatement(LockStatement lockStatement, object data) { +// Debug.Assert((lockStatement != null)); +// Debug.Assert((lockStatement.LockExpression != null)); +// Debug.Assert((lockStatement.EmbeddedStatement != null)); +// lockStatement.LockExpression.AcceptVisitor(this, data); +// return lockStatement.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitMemberInitializerExpression(MemberInitializerExpression memberInitializerExpression, object data) { +// Debug.Assert((memberInitializerExpression != null)); +// Debug.Assert((memberInitializerExpression.Expression != null)); +// return memberInitializerExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) { +// Debug.Assert((memberReferenceExpression != null)); +// Debug.Assert((memberReferenceExpression.TargetObject != null)); +// Debug.Assert((memberReferenceExpression.TypeArguments != null)); +// memberReferenceExpression.TargetObject.AcceptVisitor(this, data); +// foreach (TypeReference o in memberReferenceExpression.TypeArguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) { +// Debug.Assert((methodDeclaration != null)); +// Debug.Assert((methodDeclaration.Attributes != null)); +// Debug.Assert((methodDeclaration.Parameters != null)); +// Debug.Assert((methodDeclaration.InterfaceImplementations != null)); +// Debug.Assert((methodDeclaration.TypeReference != null)); +// Debug.Assert((methodDeclaration.Body != null)); +// Debug.Assert((methodDeclaration.Templates != null)); +// foreach (AttributeSection o in methodDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ParameterDeclarationExpression o in methodDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (InterfaceImplementation o in methodDeclaration.InterfaceImplementations) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// methodDeclaration.TypeReference.AcceptVisitor(this, data); +// methodDeclaration.Body.AcceptVisitor(this, data); +// foreach (TemplateDefinition o in methodDeclaration.Templates) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { +// Debug.Assert((namedArgumentExpression != null)); +// Debug.Assert((namedArgumentExpression.Expression != null)); +// return namedArgumentExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { +// Debug.Assert((namespaceDeclaration != null)); +// return namespaceDeclaration.AcceptChildren(this, data); +// } +// +// public virtual object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { +// Debug.Assert((objectCreateExpression != null)); +// Debug.Assert((objectCreateExpression.CreateType != null)); +// Debug.Assert((objectCreateExpression.Parameters != null)); +// Debug.Assert((objectCreateExpression.ObjectInitializer != null)); +// objectCreateExpression.CreateType.AcceptVisitor(this, data); +// foreach (Expression o in objectCreateExpression.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return objectCreateExpression.ObjectInitializer.AcceptVisitor(this, data); +// } +// +// public virtual object VisitOnErrorStatement(OnErrorStatement onErrorStatement, object data) { +// Debug.Assert((onErrorStatement != null)); +// Debug.Assert((onErrorStatement.EmbeddedStatement != null)); +// return onErrorStatement.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) { +// Debug.Assert((operatorDeclaration != null)); +// Debug.Assert((operatorDeclaration.Attributes != null)); +// Debug.Assert((operatorDeclaration.Parameters != null)); +// Debug.Assert((operatorDeclaration.InterfaceImplementations != null)); +// Debug.Assert((operatorDeclaration.TypeReference != null)); +// Debug.Assert((operatorDeclaration.Body != null)); +// Debug.Assert((operatorDeclaration.Templates != null)); +// foreach (AttributeSection o in operatorDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ParameterDeclarationExpression o in operatorDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (InterfaceImplementation o in operatorDeclaration.InterfaceImplementations) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// operatorDeclaration.TypeReference.AcceptVisitor(this, data); +// operatorDeclaration.Body.AcceptVisitor(this, data); +// foreach (TemplateDefinition o in operatorDeclaration.Templates) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitOptionDeclaration(OptionDeclaration optionDeclaration, object data) { +// Debug.Assert((optionDeclaration != null)); +// return null; +// } +// +// public virtual object VisitParameterDeclarationExpression(ParameterDeclarationExpression parameterDeclarationExpression, object data) { +// Debug.Assert((parameterDeclarationExpression != null)); +// Debug.Assert((parameterDeclarationExpression.Attributes != null)); +// Debug.Assert((parameterDeclarationExpression.TypeReference != null)); +// Debug.Assert((parameterDeclarationExpression.DefaultValue != null)); +// foreach (AttributeSection o in parameterDeclarationExpression.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// parameterDeclarationExpression.TypeReference.AcceptVisitor(this, data); +// return parameterDeclarationExpression.DefaultValue.AcceptVisitor(this, data); +// } +// +// public virtual object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) { +// Debug.Assert((parenthesizedExpression != null)); +// Debug.Assert((parenthesizedExpression.Expression != null)); +// return parenthesizedExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { +// Debug.Assert((primitiveExpression != null)); +// return null; +// } +// +// public virtual object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) { +// Debug.Assert((propertyDeclaration != null)); +// Debug.Assert((propertyDeclaration.Attributes != null)); +// Debug.Assert((propertyDeclaration.Parameters != null)); +// Debug.Assert((propertyDeclaration.InterfaceImplementations != null)); +// Debug.Assert((propertyDeclaration.TypeReference != null)); +// Debug.Assert((propertyDeclaration.GetRegion != null)); +// Debug.Assert((propertyDeclaration.SetRegion != null)); +// Debug.Assert((propertyDeclaration.Initializer != null)); +// foreach (AttributeSection o in propertyDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ParameterDeclarationExpression o in propertyDeclaration.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (InterfaceImplementation o in propertyDeclaration.InterfaceImplementations) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// propertyDeclaration.TypeReference.AcceptVisitor(this, data); +// propertyDeclaration.GetRegion.AcceptVisitor(this, data); +// propertyDeclaration.SetRegion.AcceptVisitor(this, data); +// return propertyDeclaration.Initializer.AcceptVisitor(this, data); +// } +// +// public virtual object VisitPropertyGetRegion(PropertyGetRegion propertyGetRegion, object data) { +// Debug.Assert((propertyGetRegion != null)); +// Debug.Assert((propertyGetRegion.Attributes != null)); +// Debug.Assert((propertyGetRegion.Block != null)); +// foreach (AttributeSection o in propertyGetRegion.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return propertyGetRegion.Block.AcceptVisitor(this, data); +// } +// +// public virtual object VisitPropertySetRegion(PropertySetRegion propertySetRegion, object data) { +// Debug.Assert((propertySetRegion != null)); +// Debug.Assert((propertySetRegion.Attributes != null)); +// Debug.Assert((propertySetRegion.Block != null)); +// Debug.Assert((propertySetRegion.Parameters != null)); +// foreach (AttributeSection o in propertySetRegion.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// propertySetRegion.Block.AcceptVisitor(this, data); +// foreach (ParameterDeclarationExpression o in propertySetRegion.Parameters) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpression(QueryExpression queryExpression, object data) { +// Debug.Assert((queryExpression != null)); +// Debug.Assert((queryExpression.Clauses != null)); +// foreach (QueryExpressionClause o in queryExpression.Clauses) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionAggregateClause(QueryExpressionAggregateClause queryExpressionAggregateClause, object data) { +// Debug.Assert((queryExpressionAggregateClause != null)); +// Debug.Assert((queryExpressionAggregateClause.Source != null)); +// Debug.Assert((queryExpressionAggregateClause.MiddleClauses != null)); +// Debug.Assert((queryExpressionAggregateClause.IntoVariables != null)); +// queryExpressionAggregateClause.Source.AcceptVisitor(this, data); +// foreach (QueryExpressionClause o in queryExpressionAggregateClause.MiddleClauses) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ExpressionRangeVariable o in queryExpressionAggregateClause.IntoVariables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionDistinctClause(QueryExpressionDistinctClause queryExpressionDistinctClause, object data) { +// Debug.Assert((queryExpressionDistinctClause != null)); +// return null; +// } +// +// public virtual object VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) { +// Debug.Assert((queryExpressionFromClause != null)); +// Debug.Assert((queryExpressionFromClause.Sources != null)); +// foreach (CollectionRangeVariable o in queryExpressionFromClause.Sources) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) { +// Debug.Assert((queryExpressionGroupClause != null)); +// Debug.Assert((queryExpressionGroupClause.Projection != null)); +// Debug.Assert((queryExpressionGroupClause.GroupBy != null)); +// queryExpressionGroupClause.Projection.AcceptVisitor(this, data); +// return queryExpressionGroupClause.GroupBy.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionGroupJoinVBClause(QueryExpressionGroupJoinVBClause queryExpressionGroupJoinVBClause, object data) { +// Debug.Assert((queryExpressionGroupJoinVBClause != null)); +// Debug.Assert((queryExpressionGroupJoinVBClause.JoinClause != null)); +// Debug.Assert((queryExpressionGroupJoinVBClause.IntoVariables != null)); +// queryExpressionGroupJoinVBClause.JoinClause.AcceptVisitor(this, data); +// foreach (ExpressionRangeVariable o in queryExpressionGroupJoinVBClause.IntoVariables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionGroupVBClause(QueryExpressionGroupVBClause queryExpressionGroupVBClause, object data) { +// Debug.Assert((queryExpressionGroupVBClause != null)); +// Debug.Assert((queryExpressionGroupVBClause.GroupVariables != null)); +// Debug.Assert((queryExpressionGroupVBClause.ByVariables != null)); +// Debug.Assert((queryExpressionGroupVBClause.IntoVariables != null)); +// foreach (ExpressionRangeVariable o in queryExpressionGroupVBClause.GroupVariables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ExpressionRangeVariable o in queryExpressionGroupVBClause.ByVariables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (ExpressionRangeVariable o in queryExpressionGroupVBClause.IntoVariables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) { +// Debug.Assert((queryExpressionJoinClause != null)); +// Debug.Assert((queryExpressionJoinClause.OnExpression != null)); +// Debug.Assert((queryExpressionJoinClause.EqualsExpression != null)); +// Debug.Assert((queryExpressionJoinClause.Source != null)); +// queryExpressionJoinClause.OnExpression.AcceptVisitor(this, data); +// queryExpressionJoinClause.EqualsExpression.AcceptVisitor(this, data); +// return queryExpressionJoinClause.Source.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionJoinConditionVB(QueryExpressionJoinConditionVB queryExpressionJoinConditionVB, object data) { +// Debug.Assert((queryExpressionJoinConditionVB != null)); +// Debug.Assert((queryExpressionJoinConditionVB.LeftSide != null)); +// Debug.Assert((queryExpressionJoinConditionVB.RightSide != null)); +// queryExpressionJoinConditionVB.LeftSide.AcceptVisitor(this, data); +// return queryExpressionJoinConditionVB.RightSide.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionJoinVBClause(QueryExpressionJoinVBClause queryExpressionJoinVBClause, object data) { +// Debug.Assert((queryExpressionJoinVBClause != null)); +// Debug.Assert((queryExpressionJoinVBClause.JoinVariable != null)); +// Debug.Assert((queryExpressionJoinVBClause.SubJoin != null)); +// Debug.Assert((queryExpressionJoinVBClause.Conditions != null)); +// queryExpressionJoinVBClause.JoinVariable.AcceptVisitor(this, data); +// queryExpressionJoinVBClause.SubJoin.AcceptVisitor(this, data); +// foreach (QueryExpressionJoinConditionVB o in queryExpressionJoinVBClause.Conditions) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) { +// Debug.Assert((queryExpressionLetClause != null)); +// Debug.Assert((queryExpressionLetClause.Expression != null)); +// return queryExpressionLetClause.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionLetVBClause(QueryExpressionLetClause queryExpressionLetVBClause, object data) { +// Debug.Assert((queryExpressionLetVBClause != null)); +// Debug.Assert((queryExpressionLetVBClause.Variables != null)); +// foreach (ExpressionRangeVariable o in queryExpressionLetVBClause.Variables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { +// Debug.Assert((queryExpressionOrderClause != null)); +// Debug.Assert((queryExpressionOrderClause.Orderings != null)); +// foreach (QueryExpressionOrdering o in queryExpressionOrderClause.Orderings) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { +// Debug.Assert((queryExpressionOrdering != null)); +// Debug.Assert((queryExpressionOrdering.Criteria != null)); +// return queryExpressionOrdering.Criteria.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionPartitionVBClause(QueryExpressionPartitionVBClause queryExpressionPartitionVBClause, object data) { +// Debug.Assert((queryExpressionPartitionVBClause != null)); +// Debug.Assert((queryExpressionPartitionVBClause.Expression != null)); +// return queryExpressionPartitionVBClause.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data) { +// Debug.Assert((queryExpressionSelectClause != null)); +// Debug.Assert((queryExpressionSelectClause.Projection != null)); +// return queryExpressionSelectClause.Projection.AcceptVisitor(this, data); +// } +// +// public virtual object VisitQueryExpressionSelectVBClause(QueryExpressionSelectVBClause queryExpressionSelectVBClause, object data) { +// Debug.Assert((queryExpressionSelectVBClause != null)); +// Debug.Assert((queryExpressionSelectVBClause.Variables != null)); +// foreach (ExpressionRangeVariable o in queryExpressionSelectVBClause.Variables) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitQueryExpressionWhereClause(QueryExpressionWhereClause queryExpressionWhereClause, object data) { +// Debug.Assert((queryExpressionWhereClause != null)); +// Debug.Assert((queryExpressionWhereClause.Condition != null)); +// return queryExpressionWhereClause.Condition.AcceptVisitor(this, data); +// } +// +// public virtual object VisitRaiseEventStatement(RaiseEventStatement raiseEventStatement, object data) { +// Debug.Assert((raiseEventStatement != null)); +// Debug.Assert((raiseEventStatement.Arguments != null)); +// foreach (Expression o in raiseEventStatement.Arguments) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitReDimStatement(ReDimStatement reDimStatement, object data) { +// Debug.Assert((reDimStatement != null)); +// Debug.Assert((reDimStatement.ReDimClauses != null)); +// foreach (InvocationExpression o in reDimStatement.ReDimClauses) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitRemoveHandlerStatement(RemoveHandlerStatement removeHandlerStatement, object data) { +// Debug.Assert((removeHandlerStatement != null)); +// Debug.Assert((removeHandlerStatement.EventExpression != null)); +// Debug.Assert((removeHandlerStatement.HandlerExpression != null)); +// removeHandlerStatement.EventExpression.AcceptVisitor(this, data); +// return removeHandlerStatement.HandlerExpression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitResumeStatement(ResumeStatement resumeStatement, object data) { +// Debug.Assert((resumeStatement != null)); +// return null; +// } +// +// public virtual object VisitReturnStatement(ReturnStatement returnStatement, object data) { +// Debug.Assert((returnStatement != null)); +// Debug.Assert((returnStatement.Expression != null)); +// return returnStatement.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitStopStatement(StopStatement stopStatement, object data) { +// Debug.Assert((stopStatement != null)); +// return null; +// } +// +// public virtual object VisitSwitchSection(SwitchSection switchSection, object data) { +// Debug.Assert((switchSection != null)); +// Debug.Assert((switchSection.SwitchLabels != null)); +// foreach (CaseLabel o in switchSection.SwitchLabels) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return switchSection.AcceptChildren(this, data); +// } +// +// public virtual object VisitSwitchStatement(SwitchStatement switchStatement, object data) { +// Debug.Assert((switchStatement != null)); +// Debug.Assert((switchStatement.SwitchExpression != null)); +// Debug.Assert((switchStatement.SwitchSections != null)); +// switchStatement.SwitchExpression.AcceptVisitor(this, data); +// foreach (SwitchSection o in switchStatement.SwitchSections) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitTemplateDefinition(TemplateDefinition templateDefinition, object data) { +// Debug.Assert((templateDefinition != null)); +// Debug.Assert((templateDefinition.Attributes != null)); +// Debug.Assert((templateDefinition.Bases != null)); +// foreach (AttributeSection o in templateDefinition.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (TypeReference o in templateDefinition.Bases) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) { +// Debug.Assert((thisReferenceExpression != null)); +// return null; +// } +// +// public virtual object VisitThrowStatement(ThrowStatement throwStatement, object data) { +// Debug.Assert((throwStatement != null)); +// Debug.Assert((throwStatement.Expression != null)); +// return throwStatement.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) { +// Debug.Assert((tryCatchStatement != null)); +// Debug.Assert((tryCatchStatement.StatementBlock != null)); +// Debug.Assert((tryCatchStatement.CatchClauses != null)); +// Debug.Assert((tryCatchStatement.FinallyBlock != null)); +// tryCatchStatement.StatementBlock.AcceptVisitor(this, data); +// foreach (CatchClause o in tryCatchStatement.CatchClauses) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return tryCatchStatement.FinallyBlock.AcceptVisitor(this, data); +// } +// +// public virtual object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { +// Debug.Assert((typeDeclaration != null)); +// Debug.Assert((typeDeclaration.Attributes != null)); +// Debug.Assert((typeDeclaration.BaseTypes != null)); +// Debug.Assert((typeDeclaration.Templates != null)); +// foreach (AttributeSection o in typeDeclaration.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (TypeReference o in typeDeclaration.BaseTypes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// foreach (TemplateDefinition o in typeDeclaration.Templates) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return typeDeclaration.AcceptChildren(this, data); +// } +// +// public virtual object VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) { +// Debug.Assert((typeOfExpression != null)); +// Debug.Assert((typeOfExpression.TypeReference != null)); +// return typeOfExpression.TypeReference.AcceptVisitor(this, data); +// } +// +// public virtual object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) { +// Debug.Assert((typeOfIsExpression != null)); +// Debug.Assert((typeOfIsExpression.Expression != null)); +// Debug.Assert((typeOfIsExpression.TypeReference != null)); +// typeOfIsExpression.Expression.AcceptVisitor(this, data); +// return typeOfIsExpression.TypeReference.AcceptVisitor(this, data); +// } +// +// public virtual object VisitTypeReference(TypeReference typeReference, object data) { +// Debug.Assert((typeReference != null)); +// Debug.Assert((typeReference.GenericTypes != null)); +// foreach (TypeReference o in typeReference.GenericTypes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) { +// Debug.Assert((typeReferenceExpression != null)); +// Debug.Assert((typeReferenceExpression.TypeReference != null)); +// return typeReferenceExpression.TypeReference.AcceptVisitor(this, data); +// } +// +// public virtual object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { +// Debug.Assert((unaryOperatorExpression != null)); +// Debug.Assert((unaryOperatorExpression.Expression != null)); +// return unaryOperatorExpression.Expression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitUsing(ImportsClause @using, object data) { +// Debug.Assert((@using != null)); +// Debug.Assert((@using.Alias != null)); +// return @using.Alias.AcceptVisitor(this, data); +// } +// +// public virtual object VisitUsingDeclaration(ImportsStatement usingDeclaration, object data) { +// Debug.Assert((usingDeclaration != null)); +// Debug.Assert((usingDeclaration.ImportsClauses != null)); +// foreach (ImportsClause o in usingDeclaration.ImportsClauses) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitUsingStatement(UsingStatement usingStatement, object data) { +// Debug.Assert((usingStatement != null)); +// Debug.Assert((usingStatement.ResourceAcquisition != null)); +// Debug.Assert((usingStatement.EmbeddedStatement != null)); +// usingStatement.ResourceAcquisition.AcceptVisitor(this, data); +// return usingStatement.EmbeddedStatement.AcceptVisitor(this, data); +// } +// +// public virtual object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data) { +// Debug.Assert((variableDeclaration != null)); +// Debug.Assert((variableDeclaration.Initializer != null)); +// Debug.Assert((variableDeclaration.TypeReference != null)); +// Debug.Assert((variableDeclaration.FixedArrayInitialization != null)); +// variableDeclaration.Initializer.AcceptVisitor(this, data); +// variableDeclaration.TypeReference.AcceptVisitor(this, data); +// return variableDeclaration.FixedArrayInitialization.AcceptVisitor(this, data); +// } +// +// public virtual object VisitWithStatement(WithStatement withStatement, object data) { +// Debug.Assert((withStatement != null)); +// Debug.Assert((withStatement.Expression != null)); +// Debug.Assert((withStatement.Body != null)); +// withStatement.Expression.AcceptVisitor(this, data); +// return withStatement.Body.AcceptVisitor(this, data); +// } +// +// public virtual object VisitXmlAttributeExpression(XmlAttributeExpression xmlAttributeExpression, object data) { +// Debug.Assert((xmlAttributeExpression != null)); +// Debug.Assert((xmlAttributeExpression.ExpressionValue != null)); +// return xmlAttributeExpression.ExpressionValue.AcceptVisitor(this, data); +// } +// +// public virtual object VisitXmlContentExpression(XmlContentExpression xmlContentExpression, object data) { +// Debug.Assert((xmlContentExpression != null)); +// return null; +// } +// +// public virtual object VisitXmlDocumentExpression(XmlDocumentExpression xmlDocumentExpression, object data) { +// Debug.Assert((xmlDocumentExpression != null)); +// Debug.Assert((xmlDocumentExpression.Expressions != null)); +// foreach (XmlExpression o in xmlDocumentExpression.Expressions) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return null; +// } +// +// public virtual object VisitXmlElementExpression(XmlElementExpression xmlElementExpression, object data) { +// Debug.Assert((xmlElementExpression != null)); +// Debug.Assert((xmlElementExpression.Content != null)); +// Debug.Assert((xmlElementExpression.NameExpression != null)); +// Debug.Assert((xmlElementExpression.Attributes != null)); +// xmlElementExpression.Content.AcceptVisitor(this, data); +// xmlElementExpression.NameExpression.AcceptVisitor(this, data); +// foreach (XmlExpression o in xmlElementExpression.Attributes) { +// Debug.Assert(o != null); +// o.AcceptVisitor(this, data); +// } +// return xmlElementExpression.AcceptChildren(this, data); +// } +// +// public virtual object VisitXmlEmbeddedExpression(XmlEmbeddedExpression xmlEmbeddedExpression, object data) { +// Debug.Assert((xmlEmbeddedExpression != null)); +// Debug.Assert((xmlEmbeddedExpression.InlineVBExpression != null)); +// return xmlEmbeddedExpression.InlineVBExpression.AcceptVisitor(this, data); +// } +// +// public virtual object VisitXmlMemberAccessExpression(XmlMemberAccessExpression xmlMemberAccessExpression, object data) { +// Debug.Assert((xmlMemberAccessExpression != null)); +// Debug.Assert((xmlMemberAccessExpression.TargetObject != null)); +// return xmlMemberAccessExpression.TargetObject.AcceptVisitor(this, data); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/NodeTrackingAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/NodeTrackingAstVisitor.cs new file mode 100644 index 0000000000..a94cb0333e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory.VB/Visitors/NodeTrackingAstVisitor.cs @@ -0,0 +1,1266 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.1 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ICSharpCode.NRefactory.VB.Visitors { + using System; + using ICSharpCode.NRefactory.VB.Ast; + + + /// + /// The NodeTrackingAstVisitor will iterate through the whole Ast, + /// just like the AbstractAstVisitor, and calls the virtual methods + /// BeginVisit and EndVisit for each node being visited. + /// + /// + /// base.Visit(node, data) calls this.TrackedVisit(node, data), so if + /// you want to visit child nodes using the default visiting behaviour, + /// use base.TrackedVisit(parentNode, data). + /// +// public abstract class NodeTrackingAstVisitor : AbstractAstVisitor { +// +// protected virtual void BeginVisit(INode node) { +// } +// +// protected virtual void EndVisit(INode node) { +// } +// +// public sealed override object VisitAddHandlerStatement(AddHandlerStatement addHandlerStatement, object data) { +// this.BeginVisit(addHandlerStatement); +// object result = this.TrackedVisitAddHandlerStatement(addHandlerStatement, data); +// this.EndVisit(addHandlerStatement); +// return result; +// } +// +// public sealed override object VisitAddressOfExpression(AddressOfExpression addressOfExpression, object data) { +// this.BeginVisit(addressOfExpression); +// object result = this.TrackedVisitAddressOfExpression(addressOfExpression, data); +// this.EndVisit(addressOfExpression); +// return result; +// } +// +// public sealed override object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) { +// this.BeginVisit(arrayCreateExpression); +// object result = this.TrackedVisitArrayCreateExpression(arrayCreateExpression, data); +// this.EndVisit(arrayCreateExpression); +// return result; +// } +// +// public sealed override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) { +// this.BeginVisit(assignmentExpression); +// object result = this.TrackedVisitAssignmentExpression(assignmentExpression, data); +// this.EndVisit(assignmentExpression); +// return result; +// } +// +// public sealed override object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) { +// this.BeginVisit(attribute); +// object result = this.TrackedVisitAttribute(attribute, data); +// this.EndVisit(attribute); +// return result; +// } +// +// public sealed override object VisitAttributeSection(AttributeSection attributeSection, object data) { +// this.BeginVisit(attributeSection); +// object result = this.TrackedVisitAttributeSection(attributeSection, data); +// this.EndVisit(attributeSection); +// return result; +// } +// +// public sealed override object VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) { +// this.BeginVisit(baseReferenceExpression); +// object result = this.TrackedVisitBaseReferenceExpression(baseReferenceExpression, data); +// this.EndVisit(baseReferenceExpression); +// return result; +// } +// +// public sealed override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { +// this.BeginVisit(binaryOperatorExpression); +// object result = this.TrackedVisitBinaryOperatorExpression(binaryOperatorExpression, data); +// this.EndVisit(binaryOperatorExpression); +// return result; +// } +// +// public sealed override object VisitBlockStatement(BlockStatement blockStatement, object data) { +// this.BeginVisit(blockStatement); +// object result = this.TrackedVisitBlockStatement(blockStatement, data); +// this.EndVisit(blockStatement); +// return result; +// } +// +// public sealed override object VisitCaseLabel(CaseLabel caseLabel, object data) { +// this.BeginVisit(caseLabel); +// object result = this.TrackedVisitCaseLabel(caseLabel, data); +// this.EndVisit(caseLabel); +// return result; +// } +// +// public sealed override object VisitCastExpression(CastExpression castExpression, object data) { +// this.BeginVisit(castExpression); +// object result = this.TrackedVisitCastExpression(castExpression, data); +// this.EndVisit(castExpression); +// return result; +// } +// +// public sealed override object VisitCatchClause(CatchClause catchClause, object data) { +// this.BeginVisit(catchClause); +// object result = this.TrackedVisitCatchClause(catchClause, data); +// this.EndVisit(catchClause); +// return result; +// } +// +// public sealed override object VisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data) { +// this.BeginVisit(classReferenceExpression); +// object result = this.TrackedVisitClassReferenceExpression(classReferenceExpression, data); +// this.EndVisit(classReferenceExpression); +// return result; +// } +// +// public sealed override object VisitCollectionInitializerExpression(CollectionInitializerExpression collectionInitializerExpression, object data) { +// this.BeginVisit(collectionInitializerExpression); +// object result = this.TrackedVisitCollectionInitializerExpression(collectionInitializerExpression, data); +// this.EndVisit(collectionInitializerExpression); +// return result; +// } +// +// public sealed override object VisitCollectionRangeVariable(CollectionRangeVariable collectionRangeVariable, object data) { +// this.BeginVisit(collectionRangeVariable); +// object result = this.TrackedVisitCollectionRangeVariable(collectionRangeVariable, data); +// this.EndVisit(collectionRangeVariable); +// return result; +// } +// +// public sealed override object VisitCompilationUnit(CompilationUnit compilationUnit, object data) { +// this.BeginVisit(compilationUnit); +// object result = this.TrackedVisitCompilationUnit(compilationUnit, data); +// this.EndVisit(compilationUnit); +// return result; +// } +// +// public sealed override object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) { +// this.BeginVisit(conditionalExpression); +// object result = this.TrackedVisitConditionalExpression(conditionalExpression, data); +// this.EndVisit(conditionalExpression); +// return result; +// } +// +// public sealed override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) { +// this.BeginVisit(constructorDeclaration); +// object result = this.TrackedVisitConstructorDeclaration(constructorDeclaration, data); +// this.EndVisit(constructorDeclaration); +// return result; +// } +// +// public sealed override object VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) { +// this.BeginVisit(constructorInitializer); +// object result = this.TrackedVisitConstructorInitializer(constructorInitializer, data); +// this.EndVisit(constructorInitializer); +// return result; +// } +// +// public sealed override object VisitContinueStatement(ContinueStatement continueStatement, object data) { +// this.BeginVisit(continueStatement); +// object result = this.TrackedVisitContinueStatement(continueStatement, data); +// this.EndVisit(continueStatement); +// return result; +// } +// +// public sealed override object VisitDeclareDeclaration(DeclareDeclaration declareDeclaration, object data) { +// this.BeginVisit(declareDeclaration); +// object result = this.TrackedVisitDeclareDeclaration(declareDeclaration, data); +// this.EndVisit(declareDeclaration); +// return result; +// } +// +// public sealed override object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) { +// this.BeginVisit(defaultValueExpression); +// object result = this.TrackedVisitDefaultValueExpression(defaultValueExpression, data); +// this.EndVisit(defaultValueExpression); +// return result; +// } +// +// public sealed override object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { +// this.BeginVisit(delegateDeclaration); +// object result = this.TrackedVisitDelegateDeclaration(delegateDeclaration, data); +// this.EndVisit(delegateDeclaration); +// return result; +// } +// +// public sealed override object VisitDirectionExpression(DirectionExpression directionExpression, object data) { +// this.BeginVisit(directionExpression); +// object result = this.TrackedVisitDirectionExpression(directionExpression, data); +// this.EndVisit(directionExpression); +// return result; +// } +// +// public sealed override object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) { +// this.BeginVisit(doLoopStatement); +// object result = this.TrackedVisitDoLoopStatement(doLoopStatement, data); +// this.EndVisit(doLoopStatement); +// return result; +// } +// +// public sealed override object VisitElseIfSection(ElseIfSection elseIfSection, object data) { +// this.BeginVisit(elseIfSection); +// object result = this.TrackedVisitElseIfSection(elseIfSection, data); +// this.EndVisit(elseIfSection); +// return result; +// } +// +// public sealed override object VisitEndStatement(EndStatement endStatement, object data) { +// this.BeginVisit(endStatement); +// object result = this.TrackedVisitEndStatement(endStatement, data); +// this.EndVisit(endStatement); +// return result; +// } +// +// public sealed override object VisitEraseStatement(EraseStatement eraseStatement, object data) { +// this.BeginVisit(eraseStatement); +// object result = this.TrackedVisitEraseStatement(eraseStatement, data); +// this.EndVisit(eraseStatement); +// return result; +// } +// +// public sealed override object VisitErrorStatement(ErrorStatement errorStatement, object data) { +// this.BeginVisit(errorStatement); +// object result = this.TrackedVisitErrorStatement(errorStatement, data); +// this.EndVisit(errorStatement); +// return result; +// } +// +// public sealed override object VisitEventAddRegion(EventAddRegion eventAddRegion, object data) { +// this.BeginVisit(eventAddRegion); +// object result = this.TrackedVisitEventAddRegion(eventAddRegion, data); +// this.EndVisit(eventAddRegion); +// return result; +// } +// +// public sealed override object VisitEventDeclaration(EventDeclaration eventDeclaration, object data) { +// this.BeginVisit(eventDeclaration); +// object result = this.TrackedVisitEventDeclaration(eventDeclaration, data); +// this.EndVisit(eventDeclaration); +// return result; +// } +// +// public sealed override object VisitEventRaiseRegion(EventRaiseRegion eventRaiseRegion, object data) { +// this.BeginVisit(eventRaiseRegion); +// object result = this.TrackedVisitEventRaiseRegion(eventRaiseRegion, data); +// this.EndVisit(eventRaiseRegion); +// return result; +// } +// +// public sealed override object VisitEventRemoveRegion(EventRemoveRegion eventRemoveRegion, object data) { +// this.BeginVisit(eventRemoveRegion); +// object result = this.TrackedVisitEventRemoveRegion(eventRemoveRegion, data); +// this.EndVisit(eventRemoveRegion); +// return result; +// } +// +// public sealed override object VisitExitStatement(ExitStatement exitStatement, object data) { +// this.BeginVisit(exitStatement); +// object result = this.TrackedVisitExitStatement(exitStatement, data); +// this.EndVisit(exitStatement); +// return result; +// } +// +// public sealed override object VisitExpressionRangeVariable(ExpressionRangeVariable expressionRangeVariable, object data) { +// this.BeginVisit(expressionRangeVariable); +// object result = this.TrackedVisitExpressionRangeVariable(expressionRangeVariable, data); +// this.EndVisit(expressionRangeVariable); +// return result; +// } +// +// public sealed override object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) { +// this.BeginVisit(expressionStatement); +// object result = this.TrackedVisitExpressionStatement(expressionStatement, data); +// this.EndVisit(expressionStatement); +// return result; +// } +// +// public sealed override object VisitExternAliasDirective(ExternAliasDirective externAliasDirective, object data) { +// this.BeginVisit(externAliasDirective); +// object result = this.TrackedVisitExternAliasDirective(externAliasDirective, data); +// this.EndVisit(externAliasDirective); +// return result; +// } +// +// public sealed override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { +// this.BeginVisit(fieldDeclaration); +// object result = this.TrackedVisitFieldDeclaration(fieldDeclaration, data); +// this.EndVisit(fieldDeclaration); +// return result; +// } +// +// public sealed override object VisitForeachStatement(ForeachStatement foreachStatement, object data) { +// this.BeginVisit(foreachStatement); +// object result = this.TrackedVisitForeachStatement(foreachStatement, data); +// this.EndVisit(foreachStatement); +// return result; +// } +// +// public sealed override object VisitForNextStatement(ForNextStatement forNextStatement, object data) { +// this.BeginVisit(forNextStatement); +// object result = this.TrackedVisitForNextStatement(forNextStatement, data); +// this.EndVisit(forNextStatement); +// return result; +// } +// +// public sealed override object VisitGotoStatement(GotoStatement gotoStatement, object data) { +// this.BeginVisit(gotoStatement); +// object result = this.TrackedVisitGotoStatement(gotoStatement, data); +// this.EndVisit(gotoStatement); +// return result; +// } +// +// public sealed override object VisitIdentifierExpression(SimpleNameExpression identifierExpression, object data) { +// this.BeginVisit(identifierExpression); +// object result = this.TrackedVisitIdentifierExpression(identifierExpression, data); +// this.EndVisit(identifierExpression); +// return result; +// } +// +// public sealed override object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) { +// this.BeginVisit(ifElseStatement); +// object result = this.TrackedVisitIfElseStatement(ifElseStatement, data); +// this.EndVisit(ifElseStatement); +// return result; +// } +// +// public sealed override object VisitInnerClassTypeReference(InnerClassTypeReference innerClassTypeReference, object data) { +// this.BeginVisit(innerClassTypeReference); +// object result = this.TrackedVisitInnerClassTypeReference(innerClassTypeReference, data); +// this.EndVisit(innerClassTypeReference); +// return result; +// } +// +// public sealed override object VisitInterfaceImplementation(InterfaceImplementation interfaceImplementation, object data) { +// this.BeginVisit(interfaceImplementation); +// object result = this.TrackedVisitInterfaceImplementation(interfaceImplementation, data); +// this.EndVisit(interfaceImplementation); +// return result; +// } +// +// public sealed override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) { +// this.BeginVisit(invocationExpression); +// object result = this.TrackedVisitInvocationExpression(invocationExpression, data); +// this.EndVisit(invocationExpression); +// return result; +// } +// +// public sealed override object VisitLabelStatement(LabelStatement labelStatement, object data) { +// this.BeginVisit(labelStatement); +// object result = this.TrackedVisitLabelStatement(labelStatement, data); +// this.EndVisit(labelStatement); +// return result; +// } +// +// public sealed override object VisitLambdaExpression(LambdaExpression lambdaExpression, object data) { +// this.BeginVisit(lambdaExpression); +// object result = this.TrackedVisitLambdaExpression(lambdaExpression, data); +// this.EndVisit(lambdaExpression); +// return result; +// } +// +// public sealed override object VisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data) { +// this.BeginVisit(localVariableDeclaration); +// object result = this.TrackedVisitLocalVariableDeclaration(localVariableDeclaration, data); +// this.EndVisit(localVariableDeclaration); +// return result; +// } +// +// public sealed override object VisitLockStatement(LockStatement lockStatement, object data) { +// this.BeginVisit(lockStatement); +// object result = this.TrackedVisitLockStatement(lockStatement, data); +// this.EndVisit(lockStatement); +// return result; +// } +// +// public sealed override object VisitMemberInitializerExpression(MemberInitializerExpression memberInitializerExpression, object data) { +// this.BeginVisit(memberInitializerExpression); +// object result = this.TrackedVisitMemberInitializerExpression(memberInitializerExpression, data); +// this.EndVisit(memberInitializerExpression); +// return result; +// } +// +// public sealed override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) { +// this.BeginVisit(memberReferenceExpression); +// object result = this.TrackedVisitMemberReferenceExpression(memberReferenceExpression, data); +// this.EndVisit(memberReferenceExpression); +// return result; +// } +// +// public sealed override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) { +// this.BeginVisit(methodDeclaration); +// object result = this.TrackedVisitMethodDeclaration(methodDeclaration, data); +// this.EndVisit(methodDeclaration); +// return result; +// } +// +// public sealed override object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { +// this.BeginVisit(namedArgumentExpression); +// object result = this.TrackedVisitNamedArgumentExpression(namedArgumentExpression, data); +// this.EndVisit(namedArgumentExpression); +// return result; +// } +// +// public sealed override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { +// this.BeginVisit(namespaceDeclaration); +// object result = this.TrackedVisitNamespaceDeclaration(namespaceDeclaration, data); +// this.EndVisit(namespaceDeclaration); +// return result; +// } +// +// public sealed override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { +// this.BeginVisit(objectCreateExpression); +// object result = this.TrackedVisitObjectCreateExpression(objectCreateExpression, data); +// this.EndVisit(objectCreateExpression); +// return result; +// } +// +// public sealed override object VisitOnErrorStatement(OnErrorStatement onErrorStatement, object data) { +// this.BeginVisit(onErrorStatement); +// object result = this.TrackedVisitOnErrorStatement(onErrorStatement, data); +// this.EndVisit(onErrorStatement); +// return result; +// } +// +// public sealed override object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) { +// this.BeginVisit(operatorDeclaration); +// object result = this.TrackedVisitOperatorDeclaration(operatorDeclaration, data); +// this.EndVisit(operatorDeclaration); +// return result; +// } +// +// public sealed override object VisitOptionDeclaration(OptionDeclaration optionDeclaration, object data) { +// this.BeginVisit(optionDeclaration); +// object result = this.TrackedVisitOptionDeclaration(optionDeclaration, data); +// this.EndVisit(optionDeclaration); +// return result; +// } +// +// public sealed override object VisitParameterDeclarationExpression(ParameterDeclarationExpression parameterDeclarationExpression, object data) { +// this.BeginVisit(parameterDeclarationExpression); +// object result = this.TrackedVisitParameterDeclarationExpression(parameterDeclarationExpression, data); +// this.EndVisit(parameterDeclarationExpression); +// return result; +// } +// +// public sealed override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) { +// this.BeginVisit(parenthesizedExpression); +// object result = this.TrackedVisitParenthesizedExpression(parenthesizedExpression, data); +// this.EndVisit(parenthesizedExpression); +// return result; +// } +// +// public sealed override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { +// this.BeginVisit(primitiveExpression); +// object result = this.TrackedVisitPrimitiveExpression(primitiveExpression, data); +// this.EndVisit(primitiveExpression); +// return result; +// } +// +// public sealed override object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) { +// this.BeginVisit(propertyDeclaration); +// object result = this.TrackedVisitPropertyDeclaration(propertyDeclaration, data); +// this.EndVisit(propertyDeclaration); +// return result; +// } +// +// public sealed override object VisitPropertyGetRegion(PropertyGetRegion propertyGetRegion, object data) { +// this.BeginVisit(propertyGetRegion); +// object result = this.TrackedVisitPropertyGetRegion(propertyGetRegion, data); +// this.EndVisit(propertyGetRegion); +// return result; +// } +// +// public sealed override object VisitPropertySetRegion(PropertySetRegion propertySetRegion, object data) { +// this.BeginVisit(propertySetRegion); +// object result = this.TrackedVisitPropertySetRegion(propertySetRegion, data); +// this.EndVisit(propertySetRegion); +// return result; +// } +// +// public sealed override object VisitQueryExpression(QueryExpression queryExpression, object data) { +// this.BeginVisit(queryExpression); +// object result = this.TrackedVisitQueryExpression(queryExpression, data); +// this.EndVisit(queryExpression); +// return result; +// } +// +// public sealed override object VisitQueryExpressionAggregateClause(QueryExpressionAggregateClause queryExpressionAggregateClause, object data) { +// this.BeginVisit(queryExpressionAggregateClause); +// object result = this.TrackedVisitQueryExpressionAggregateClause(queryExpressionAggregateClause, data); +// this.EndVisit(queryExpressionAggregateClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionDistinctClause(QueryExpressionDistinctClause queryExpressionDistinctClause, object data) { +// this.BeginVisit(queryExpressionDistinctClause); +// object result = this.TrackedVisitQueryExpressionDistinctClause(queryExpressionDistinctClause, data); +// this.EndVisit(queryExpressionDistinctClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) { +// this.BeginVisit(queryExpressionFromClause); +// object result = this.TrackedVisitQueryExpressionFromClause(queryExpressionFromClause, data); +// this.EndVisit(queryExpressionFromClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) { +// this.BeginVisit(queryExpressionGroupClause); +// object result = this.TrackedVisitQueryExpressionGroupClause(queryExpressionGroupClause, data); +// this.EndVisit(queryExpressionGroupClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionGroupJoinVBClause(QueryExpressionGroupJoinVBClause queryExpressionGroupJoinVBClause, object data) { +// this.BeginVisit(queryExpressionGroupJoinVBClause); +// object result = this.TrackedVisitQueryExpressionGroupJoinVBClause(queryExpressionGroupJoinVBClause, data); +// this.EndVisit(queryExpressionGroupJoinVBClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionGroupVBClause(QueryExpressionGroupVBClause queryExpressionGroupVBClause, object data) { +// this.BeginVisit(queryExpressionGroupVBClause); +// object result = this.TrackedVisitQueryExpressionGroupVBClause(queryExpressionGroupVBClause, data); +// this.EndVisit(queryExpressionGroupVBClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) { +// this.BeginVisit(queryExpressionJoinClause); +// object result = this.TrackedVisitQueryExpressionJoinClause(queryExpressionJoinClause, data); +// this.EndVisit(queryExpressionJoinClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionJoinConditionVB(QueryExpressionJoinConditionVB queryExpressionJoinConditionVB, object data) { +// this.BeginVisit(queryExpressionJoinConditionVB); +// object result = this.TrackedVisitQueryExpressionJoinConditionVB(queryExpressionJoinConditionVB, data); +// this.EndVisit(queryExpressionJoinConditionVB); +// return result; +// } +// +// public sealed override object VisitQueryExpressionJoinVBClause(QueryExpressionJoinVBClause queryExpressionJoinVBClause, object data) { +// this.BeginVisit(queryExpressionJoinVBClause); +// object result = this.TrackedVisitQueryExpressionJoinVBClause(queryExpressionJoinVBClause, data); +// this.EndVisit(queryExpressionJoinVBClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) { +// this.BeginVisit(queryExpressionLetClause); +// object result = this.TrackedVisitQueryExpressionLetClause(queryExpressionLetClause, data); +// this.EndVisit(queryExpressionLetClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionLetVBClause(QueryExpressionLetClause queryExpressionLetVBClause, object data) { +// this.BeginVisit(queryExpressionLetVBClause); +// object result = this.TrackedVisitQueryExpressionLetVBClause(queryExpressionLetVBClause, data); +// this.EndVisit(queryExpressionLetVBClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { +// this.BeginVisit(queryExpressionOrderClause); +// object result = this.TrackedVisitQueryExpressionOrderClause(queryExpressionOrderClause, data); +// this.EndVisit(queryExpressionOrderClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { +// this.BeginVisit(queryExpressionOrdering); +// object result = this.TrackedVisitQueryExpressionOrdering(queryExpressionOrdering, data); +// this.EndVisit(queryExpressionOrdering); +// return result; +// } +// +// public sealed override object VisitQueryExpressionPartitionVBClause(QueryExpressionPartitionVBClause queryExpressionPartitionVBClause, object data) { +// this.BeginVisit(queryExpressionPartitionVBClause); +// object result = this.TrackedVisitQueryExpressionPartitionVBClause(queryExpressionPartitionVBClause, data); +// this.EndVisit(queryExpressionPartitionVBClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data) { +// this.BeginVisit(queryExpressionSelectClause); +// object result = this.TrackedVisitQueryExpressionSelectClause(queryExpressionSelectClause, data); +// this.EndVisit(queryExpressionSelectClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionSelectVBClause(QueryExpressionSelectVBClause queryExpressionSelectVBClause, object data) { +// this.BeginVisit(queryExpressionSelectVBClause); +// object result = this.TrackedVisitQueryExpressionSelectVBClause(queryExpressionSelectVBClause, data); +// this.EndVisit(queryExpressionSelectVBClause); +// return result; +// } +// +// public sealed override object VisitQueryExpressionWhereClause(QueryExpressionWhereClause queryExpressionWhereClause, object data) { +// this.BeginVisit(queryExpressionWhereClause); +// object result = this.TrackedVisitQueryExpressionWhereClause(queryExpressionWhereClause, data); +// this.EndVisit(queryExpressionWhereClause); +// return result; +// } +// +// public sealed override object VisitRaiseEventStatement(RaiseEventStatement raiseEventStatement, object data) { +// this.BeginVisit(raiseEventStatement); +// object result = this.TrackedVisitRaiseEventStatement(raiseEventStatement, data); +// this.EndVisit(raiseEventStatement); +// return result; +// } +// +// public sealed override object VisitReDimStatement(ReDimStatement reDimStatement, object data) { +// this.BeginVisit(reDimStatement); +// object result = this.TrackedVisitReDimStatement(reDimStatement, data); +// this.EndVisit(reDimStatement); +// return result; +// } +// +// public sealed override object VisitRemoveHandlerStatement(RemoveHandlerStatement removeHandlerStatement, object data) { +// this.BeginVisit(removeHandlerStatement); +// object result = this.TrackedVisitRemoveHandlerStatement(removeHandlerStatement, data); +// this.EndVisit(removeHandlerStatement); +// return result; +// } +// +// public sealed override object VisitResumeStatement(ResumeStatement resumeStatement, object data) { +// this.BeginVisit(resumeStatement); +// object result = this.TrackedVisitResumeStatement(resumeStatement, data); +// this.EndVisit(resumeStatement); +// return result; +// } +// +// public sealed override object VisitReturnStatement(ReturnStatement returnStatement, object data) { +// this.BeginVisit(returnStatement); +// object result = this.TrackedVisitReturnStatement(returnStatement, data); +// this.EndVisit(returnStatement); +// return result; +// } +// +// public sealed override object VisitStopStatement(StopStatement stopStatement, object data) { +// this.BeginVisit(stopStatement); +// object result = this.TrackedVisitStopStatement(stopStatement, data); +// this.EndVisit(stopStatement); +// return result; +// } +// +// public sealed override object VisitSwitchSection(SwitchSection switchSection, object data) { +// this.BeginVisit(switchSection); +// object result = this.TrackedVisitSwitchSection(switchSection, data); +// this.EndVisit(switchSection); +// return result; +// } +// +// public sealed override object VisitSwitchStatement(SwitchStatement switchStatement, object data) { +// this.BeginVisit(switchStatement); +// object result = this.TrackedVisitSwitchStatement(switchStatement, data); +// this.EndVisit(switchStatement); +// return result; +// } +// +// public sealed override object VisitTemplateDefinition(TemplateDefinition templateDefinition, object data) { +// this.BeginVisit(templateDefinition); +// object result = this.TrackedVisitTemplateDefinition(templateDefinition, data); +// this.EndVisit(templateDefinition); +// return result; +// } +// +// public sealed override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) { +// this.BeginVisit(thisReferenceExpression); +// object result = this.TrackedVisitThisReferenceExpression(thisReferenceExpression, data); +// this.EndVisit(thisReferenceExpression); +// return result; +// } +// +// public sealed override object VisitThrowStatement(ThrowStatement throwStatement, object data) { +// this.BeginVisit(throwStatement); +// object result = this.TrackedVisitThrowStatement(throwStatement, data); +// this.EndVisit(throwStatement); +// return result; +// } +// +// public sealed override object VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) { +// this.BeginVisit(tryCatchStatement); +// object result = this.TrackedVisitTryCatchStatement(tryCatchStatement, data); +// this.EndVisit(tryCatchStatement); +// return result; +// } +// +// public sealed override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { +// this.BeginVisit(typeDeclaration); +// object result = this.TrackedVisitTypeDeclaration(typeDeclaration, data); +// this.EndVisit(typeDeclaration); +// return result; +// } +// +// public sealed override object VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) { +// this.BeginVisit(typeOfExpression); +// object result = this.TrackedVisitTypeOfExpression(typeOfExpression, data); +// this.EndVisit(typeOfExpression); +// return result; +// } +// +// public sealed override object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) { +// this.BeginVisit(typeOfIsExpression); +// object result = this.TrackedVisitTypeOfIsExpression(typeOfIsExpression, data); +// this.EndVisit(typeOfIsExpression); +// return result; +// } +// +// public sealed override object VisitTypeReference(TypeReference typeReference, object data) { +// this.BeginVisit(typeReference); +// object result = this.TrackedVisitTypeReference(typeReference, data); +// this.EndVisit(typeReference); +// return result; +// } +// +// public sealed override object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) { +// this.BeginVisit(typeReferenceExpression); +// object result = this.TrackedVisitTypeReferenceExpression(typeReferenceExpression, data); +// this.EndVisit(typeReferenceExpression); +// return result; +// } +// +// public sealed override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { +// this.BeginVisit(unaryOperatorExpression); +// object result = this.TrackedVisitUnaryOperatorExpression(unaryOperatorExpression, data); +// this.EndVisit(unaryOperatorExpression); +// return result; +// } +// +// public sealed override object VisitUsing(ImportsClause @using, object data) { +// this.BeginVisit(@using); +// object result = this.TrackedVisitUsing(@using, data); +// this.EndVisit(@using); +// return result; +// } +// +// public sealed override object VisitUsingDeclaration(ImportsStatement usingDeclaration, object data) { +// this.BeginVisit(usingDeclaration); +// object result = this.TrackedVisitUsingDeclaration(usingDeclaration, data); +// this.EndVisit(usingDeclaration); +// return result; +// } +// +// public sealed override object VisitUsingStatement(UsingStatement usingStatement, object data) { +// this.BeginVisit(usingStatement); +// object result = this.TrackedVisitUsingStatement(usingStatement, data); +// this.EndVisit(usingStatement); +// return result; +// } +// +// public sealed override object VisitVariableDeclaration(VariableDeclaration variableDeclaration, object data) { +// this.BeginVisit(variableDeclaration); +// object result = this.TrackedVisitVariableDeclaration(variableDeclaration, data); +// this.EndVisit(variableDeclaration); +// return result; +// } +// +// public sealed override object VisitWithStatement(WithStatement withStatement, object data) { +// this.BeginVisit(withStatement); +// object result = this.TrackedVisitWithStatement(withStatement, data); +// this.EndVisit(withStatement); +// return result; +// } +// +// public sealed override object VisitXmlAttributeExpression(XmlAttributeExpression xmlAttributeExpression, object data) { +// this.BeginVisit(xmlAttributeExpression); +// object result = this.TrackedVisitXmlAttributeExpression(xmlAttributeExpression, data); +// this.EndVisit(xmlAttributeExpression); +// return result; +// } +// +// public sealed override object VisitXmlContentExpression(XmlContentExpression xmlContentExpression, object data) { +// this.BeginVisit(xmlContentExpression); +// object result = this.TrackedVisitXmlContentExpression(xmlContentExpression, data); +// this.EndVisit(xmlContentExpression); +// return result; +// } +// +// public sealed override object VisitXmlDocumentExpression(XmlDocumentExpression xmlDocumentExpression, object data) { +// this.BeginVisit(xmlDocumentExpression); +// object result = this.TrackedVisitXmlDocumentExpression(xmlDocumentExpression, data); +// this.EndVisit(xmlDocumentExpression); +// return result; +// } +// +// public sealed override object VisitXmlElementExpression(XmlElementExpression xmlElementExpression, object data) { +// this.BeginVisit(xmlElementExpression); +// object result = this.TrackedVisitXmlElementExpression(xmlElementExpression, data); +// this.EndVisit(xmlElementExpression); +// return result; +// } +// +// public sealed override object VisitXmlEmbeddedExpression(XmlEmbeddedExpression xmlEmbeddedExpression, object data) { +// this.BeginVisit(xmlEmbeddedExpression); +// object result = this.TrackedVisitXmlEmbeddedExpression(xmlEmbeddedExpression, data); +// this.EndVisit(xmlEmbeddedExpression); +// return result; +// } +// +// public sealed override object VisitXmlMemberAccessExpression(XmlMemberAccessExpression xmlMemberAccessExpression, object data) { +// this.BeginVisit(xmlMemberAccessExpression); +// object result = this.TrackedVisitXmlMemberAccessExpression(xmlMemberAccessExpression, data); +// this.EndVisit(xmlMemberAccessExpression); +// return result; +// } +// +// public virtual object TrackedVisitAddHandlerStatement(AddHandlerStatement addHandlerStatement, object data) { +// return base.VisitAddHandlerStatement(addHandlerStatement, data); +// } +// +// public virtual object TrackedVisitAddressOfExpression(AddressOfExpression addressOfExpression, object data) { +// return base.VisitAddressOfExpression(addressOfExpression, data); +// } +// +// public virtual object TrackedVisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) { +// return base.VisitArrayCreateExpression(arrayCreateExpression, data); +// } +// +// public virtual object TrackedVisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) { +// return base.VisitAssignmentExpression(assignmentExpression, data); +// } +// +// public virtual object TrackedVisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) { +// return base.VisitAttribute(attribute, data); +// } +// +// public virtual object TrackedVisitAttributeSection(AttributeSection attributeSection, object data) { +// return base.VisitAttributeSection(attributeSection, data); +// } +// +// public virtual object TrackedVisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) { +// return base.VisitBaseReferenceExpression(baseReferenceExpression, data); +// } +// +// public virtual object TrackedVisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) { +// return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); +// } +// +// public virtual object TrackedVisitBlockStatement(BlockStatement blockStatement, object data) { +// return base.VisitBlockStatement(blockStatement, data); +// } +// +// public virtual object TrackedVisitCaseLabel(CaseLabel caseLabel, object data) { +// return base.VisitCaseLabel(caseLabel, data); +// } +// +// public virtual object TrackedVisitCastExpression(CastExpression castExpression, object data) { +// return base.VisitCastExpression(castExpression, data); +// } +// +// public virtual object TrackedVisitCatchClause(CatchClause catchClause, object data) { +// return base.VisitCatchClause(catchClause, data); +// } +// +// public virtual object TrackedVisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data) { +// return base.VisitClassReferenceExpression(classReferenceExpression, data); +// } +// +// public virtual object TrackedVisitCollectionInitializerExpression(CollectionInitializerExpression collectionInitializerExpression, object data) { +// return base.VisitCollectionInitializerExpression(collectionInitializerExpression, data); +// } +// +// public virtual object TrackedVisitCollectionRangeVariable(CollectionRangeVariable collectionRangeVariable, object data) { +// return base.VisitCollectionRangeVariable(collectionRangeVariable, data); +// } +// +// public virtual object TrackedVisitCompilationUnit(CompilationUnit compilationUnit, object data) { +// return base.VisitCompilationUnit(compilationUnit, data); +// } +// +// public virtual object TrackedVisitConditionalExpression(ConditionalExpression conditionalExpression, object data) { +// return base.VisitConditionalExpression(conditionalExpression, data); +// } +// +// public virtual object TrackedVisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) { +// return base.VisitConstructorDeclaration(constructorDeclaration, data); +// } +// +// public virtual object TrackedVisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) { +// return base.VisitConstructorInitializer(constructorInitializer, data); +// } +// +// public virtual object TrackedVisitContinueStatement(ContinueStatement continueStatement, object data) { +// return base.VisitContinueStatement(continueStatement, data); +// } +// +// public virtual object TrackedVisitDeclareDeclaration(DeclareDeclaration declareDeclaration, object data) { +// return base.VisitDeclareDeclaration(declareDeclaration, data); +// } +// +// public virtual object TrackedVisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) { +// return base.VisitDefaultValueExpression(defaultValueExpression, data); +// } +// +// public virtual object TrackedVisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { +// return base.VisitDelegateDeclaration(delegateDeclaration, data); +// } +// +// public virtual object TrackedVisitDirectionExpression(DirectionExpression directionExpression, object data) { +// return base.VisitDirectionExpression(directionExpression, data); +// } +// +// public virtual object TrackedVisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) { +// return base.VisitDoLoopStatement(doLoopStatement, data); +// } +// +// public virtual object TrackedVisitElseIfSection(ElseIfSection elseIfSection, object data) { +// return base.VisitElseIfSection(elseIfSection, data); +// } +// +// public virtual object TrackedVisitEndStatement(EndStatement endStatement, object data) { +// return base.VisitEndStatement(endStatement, data); +// } +// +// public virtual object TrackedVisitEraseStatement(EraseStatement eraseStatement, object data) { +// return base.VisitEraseStatement(eraseStatement, data); +// } +// +// public virtual object TrackedVisitErrorStatement(ErrorStatement errorStatement, object data) { +// return base.VisitErrorStatement(errorStatement, data); +// } +// +// public virtual object TrackedVisitEventAddRegion(EventAddRegion eventAddRegion, object data) { +// return base.VisitEventAddRegion(eventAddRegion, data); +// } +// +// public virtual object TrackedVisitEventDeclaration(EventDeclaration eventDeclaration, object data) { +// return base.VisitEventDeclaration(eventDeclaration, data); +// } +// +// public virtual object TrackedVisitEventRaiseRegion(EventRaiseRegion eventRaiseRegion, object data) { +// return base.VisitEventRaiseRegion(eventRaiseRegion, data); +// } +// +// public virtual object TrackedVisitEventRemoveRegion(EventRemoveRegion eventRemoveRegion, object data) { +// return base.VisitEventRemoveRegion(eventRemoveRegion, data); +// } +// +// public virtual object TrackedVisitExitStatement(ExitStatement exitStatement, object data) { +// return base.VisitExitStatement(exitStatement, data); +// } +// +// public virtual object TrackedVisitExpressionRangeVariable(ExpressionRangeVariable expressionRangeVariable, object data) { +// return base.VisitExpressionRangeVariable(expressionRangeVariable, data); +// } +// +// public virtual object TrackedVisitExpressionStatement(ExpressionStatement expressionStatement, object data) { +// return base.VisitExpressionStatement(expressionStatement, data); +// } +// +// public virtual object TrackedVisitExternAliasDirective(ExternAliasDirective externAliasDirective, object data) { +// return base.VisitExternAliasDirective(externAliasDirective, data); +// } +// +// public virtual object TrackedVisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) { +// return base.VisitFieldDeclaration(fieldDeclaration, data); +// } +// +// public virtual object TrackedVisitForeachStatement(ForeachStatement foreachStatement, object data) { +// return base.VisitForeachStatement(foreachStatement, data); +// } +// +// public virtual object TrackedVisitForNextStatement(ForNextStatement forNextStatement, object data) { +// return base.VisitForNextStatement(forNextStatement, data); +// } +// +// public virtual object TrackedVisitGotoStatement(GotoStatement gotoStatement, object data) { +// return base.VisitGotoStatement(gotoStatement, data); +// } +// +// public virtual object TrackedVisitIdentifierExpression(SimpleNameExpression identifierExpression, object data) { +// return base.VisitIdentifierExpression(identifierExpression, data); +// } +// +// public virtual object TrackedVisitIfElseStatement(IfElseStatement ifElseStatement, object data) { +// return base.VisitIfElseStatement(ifElseStatement, data); +// } +// +// public virtual object TrackedVisitInnerClassTypeReference(InnerClassTypeReference innerClassTypeReference, object data) { +// return base.VisitInnerClassTypeReference(innerClassTypeReference, data); +// } +// +// public virtual object TrackedVisitInterfaceImplementation(InterfaceImplementation interfaceImplementation, object data) { +// return base.VisitInterfaceImplementation(interfaceImplementation, data); +// } +// +// public virtual object TrackedVisitInvocationExpression(InvocationExpression invocationExpression, object data) { +// return base.VisitInvocationExpression(invocationExpression, data); +// } +// +// public virtual object TrackedVisitLabelStatement(LabelStatement labelStatement, object data) { +// return base.VisitLabelStatement(labelStatement, data); +// } +// +// public virtual object TrackedVisitLambdaExpression(LambdaExpression lambdaExpression, object data) { +// return base.VisitLambdaExpression(lambdaExpression, data); +// } +// +// public virtual object TrackedVisitLocalVariableDeclaration(LocalVariableDeclaration localVariableDeclaration, object data) { +// return base.VisitLocalVariableDeclaration(localVariableDeclaration, data); +// } +// +// public virtual object TrackedVisitLockStatement(LockStatement lockStatement, object data) { +// return base.VisitLockStatement(lockStatement, data); +// } +// +// public virtual object TrackedVisitMemberInitializerExpression(MemberInitializerExpression memberInitializerExpression, object data) { +// return base.VisitMemberInitializerExpression(memberInitializerExpression, data); +// } +// +// public virtual object TrackedVisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) { +// return base.VisitMemberReferenceExpression(memberReferenceExpression, data); +// } +// +// public virtual object TrackedVisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) { +// return base.VisitMethodDeclaration(methodDeclaration, data); +// } +// +// public virtual object TrackedVisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { +// return base.VisitNamedArgumentExpression(namedArgumentExpression, data); +// } +// +// public virtual object TrackedVisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { +// return base.VisitNamespaceDeclaration(namespaceDeclaration, data); +// } +// +// public virtual object TrackedVisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { +// return base.VisitObjectCreateExpression(objectCreateExpression, data); +// } +// +// public virtual object TrackedVisitOnErrorStatement(OnErrorStatement onErrorStatement, object data) { +// return base.VisitOnErrorStatement(onErrorStatement, data); +// } +// +// public virtual object TrackedVisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) { +// return base.VisitOperatorDeclaration(operatorDeclaration, data); +// } +// +// public virtual object TrackedVisitOptionDeclaration(OptionDeclaration optionDeclaration, object data) { +// return base.VisitOptionDeclaration(optionDeclaration, data); +// } +// +// public virtual object TrackedVisitParameterDeclarationExpression(ParameterDeclarationExpression parameterDeclarationExpression, object data) { +// return base.VisitParameterDeclarationExpression(parameterDeclarationExpression, data); +// } +// +// public virtual object TrackedVisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) { +// return base.VisitParenthesizedExpression(parenthesizedExpression, data); +// } +// +// public virtual object TrackedVisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { +// return base.VisitPrimitiveExpression(primitiveExpression, data); +// } +// +// public virtual object TrackedVisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) { +// return base.VisitPropertyDeclaration(propertyDeclaration, data); +// } +// +// public virtual object TrackedVisitPropertyGetRegion(PropertyGetRegion propertyGetRegion, object data) { +// return base.VisitPropertyGetRegion(propertyGetRegion, data); +// } +// +// public virtual object TrackedVisitPropertySetRegion(PropertySetRegion propertySetRegion, object data) { +// return base.VisitPropertySetRegion(propertySetRegion, data); +// } +// +// public virtual object TrackedVisitQueryExpression(QueryExpression queryExpression, object data) { +// return base.VisitQueryExpression(queryExpression, data); +// } +// +// public virtual object TrackedVisitQueryExpressionAggregateClause(QueryExpressionAggregateClause queryExpressionAggregateClause, object data) { +// return base.VisitQueryExpressionAggregateClause(queryExpressionAggregateClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionDistinctClause(QueryExpressionDistinctClause queryExpressionDistinctClause, object data) { +// return base.VisitQueryExpressionDistinctClause(queryExpressionDistinctClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionFromClause(QueryExpressionFromClause queryExpressionFromClause, object data) { +// return base.VisitQueryExpressionFromClause(queryExpressionFromClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionGroupClause(QueryExpressionGroupClause queryExpressionGroupClause, object data) { +// return base.VisitQueryExpressionGroupClause(queryExpressionGroupClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionGroupJoinVBClause(QueryExpressionGroupJoinVBClause queryExpressionGroupJoinVBClause, object data) { +// return base.VisitQueryExpressionGroupJoinVBClause(queryExpressionGroupJoinVBClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionGroupVBClause(QueryExpressionGroupVBClause queryExpressionGroupVBClause, object data) { +// return base.VisitQueryExpressionGroupVBClause(queryExpressionGroupVBClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionJoinClause(QueryExpressionJoinClause queryExpressionJoinClause, object data) { +// return base.VisitQueryExpressionJoinClause(queryExpressionJoinClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionJoinConditionVB(QueryExpressionJoinConditionVB queryExpressionJoinConditionVB, object data) { +// return base.VisitQueryExpressionJoinConditionVB(queryExpressionJoinConditionVB, data); +// } +// +// public virtual object TrackedVisitQueryExpressionJoinVBClause(QueryExpressionJoinVBClause queryExpressionJoinVBClause, object data) { +// return base.VisitQueryExpressionJoinVBClause(queryExpressionJoinVBClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionLetClause(QueryExpressionLetClause queryExpressionLetClause, object data) { +// return base.VisitQueryExpressionLetClause(queryExpressionLetClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionLetVBClause(QueryExpressionLetClause queryExpressionLetVBClause, object data) { +// return base.VisitQueryExpressionLetVBClause(queryExpressionLetVBClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionOrderClause(QueryExpressionOrderClause queryExpressionOrderClause, object data) { +// return base.VisitQueryExpressionOrderClause(queryExpressionOrderClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionOrdering(QueryExpressionOrdering queryExpressionOrdering, object data) { +// return base.VisitQueryExpressionOrdering(queryExpressionOrdering, data); +// } +// +// public virtual object TrackedVisitQueryExpressionPartitionVBClause(QueryExpressionPartitionVBClause queryExpressionPartitionVBClause, object data) { +// return base.VisitQueryExpressionPartitionVBClause(queryExpressionPartitionVBClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionSelectClause(QueryExpressionSelectClause queryExpressionSelectClause, object data) { +// return base.VisitQueryExpressionSelectClause(queryExpressionSelectClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionSelectVBClause(QueryExpressionSelectVBClause queryExpressionSelectVBClause, object data) { +// return base.VisitQueryExpressionSelectVBClause(queryExpressionSelectVBClause, data); +// } +// +// public virtual object TrackedVisitQueryExpressionWhereClause(QueryExpressionWhereClause queryExpressionWhereClause, object data) { +// return base.VisitQueryExpressionWhereClause(queryExpressionWhereClause, data); +// } +// +// public virtual object TrackedVisitRaiseEventStatement(RaiseEventStatement raiseEventStatement, object data) { +// return base.VisitRaiseEventStatement(raiseEventStatement, data); +// } +// +// public virtual object TrackedVisitReDimStatement(ReDimStatement reDimStatement, object data) { +// return base.VisitReDimStatement(reDimStatement, data); +// } +// +// public virtual object TrackedVisitRemoveHandlerStatement(RemoveHandlerStatement removeHandlerStatement, object data) { +// return base.VisitRemoveHandlerStatement(removeHandlerStatement, data); +// } +// +// public virtual object TrackedVisitResumeStatement(ResumeStatement resumeStatement, object data) { +// return base.VisitResumeStatement(resumeStatement, data); +// } +// +// public virtual object TrackedVisitReturnStatement(ReturnStatement returnStatement, object data) { +// return base.VisitReturnStatement(returnStatement, data); +// } +// +// public virtual object TrackedVisitStopStatement(StopStatement stopStatement, object data) { +// return base.VisitStopStatement(stopStatement, data); +// } +// +// public virtual object TrackedVisitSwitchSection(SwitchSection switchSection, object data) { +// return base.VisitSwitchSection(switchSection, data); +// } +// +// public virtual object TrackedVisitSwitchStatement(SwitchStatement switchStatement, object data) { +// return base.VisitSwitchStatement(switchStatement, data); +// } +// +// public virtual object TrackedVisitTemplateDefinition(TemplateDefinition templateDefinition, object data) { +// return base.VisitTemplateDefinition(templateDefinition, data); +// } +// +// public virtual object TrackedVisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) { +// return base.VisitThisReferenceExpression(thisReferenceExpression, data); +// } +// +// public virtual object TrackedVisitThrowStatement(ThrowStatement throwStatement, object data) { +// return base.VisitThrowStatement(throwStatement, data); +// } +// +// public virtual object TrackedVisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) { +// return base.VisitTryCatchStatement(tryCatchStatement, data); +// } +// +// public virtual object TrackedVisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { +// return base.VisitTypeDeclaration(typeDeclaration, data); +// } +// +// public virtual object TrackedVisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) { +// return base.VisitTypeOfExpression(typeOfExpression, data); +// } +// +// public virtual object TrackedVisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) { +// return base.VisitTypeOfIsExpression(typeOfIsExpression, data); +// } +// +// public virtual object TrackedVisitTypeReference(TypeReference typeReference, object data) { +// return base.VisitTypeReference(typeReference, data); +// } +// +// public virtual object TrackedVisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) { +// return base.VisitTypeReferenceExpression(typeReferenceExpression, data); +// } +// +// public virtual object TrackedVisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { +// return base.VisitUnaryOperatorExpression(unaryOperatorExpression, data); +// } +// +// public virtual object TrackedVisitUsing(ImportsClause @using, object data) { +// return base.VisitUsing(@using, data); +// } +// +// public virtual object TrackedVisitUsingDeclaration(ImportsStatement usingDeclaration, object data) { +// return base.VisitUsingDeclaration(usingDeclaration, data); +// } +// +// public virtual object TrackedVisitUsingStatement(UsingStatement usingStatement, object data) { +// return base.VisitUsingStatement(usingStatement, data); +// } +// +// public virtual object TrackedVisitVariableDeclaration(VariableDeclaration variableDeclaration, object data) { +// return base.VisitVariableDeclaration(variableDeclaration, data); +// } +// +// public virtual object TrackedVisitWithStatement(WithStatement withStatement, object data) { +// return base.VisitWithStatement(withStatement, data); +// } +// +// public virtual object TrackedVisitXmlAttributeExpression(XmlAttributeExpression xmlAttributeExpression, object data) { +// return base.VisitXmlAttributeExpression(xmlAttributeExpression, data); +// } +// +// public virtual object TrackedVisitXmlContentExpression(XmlContentExpression xmlContentExpression, object data) { +// return base.VisitXmlContentExpression(xmlContentExpression, data); +// } +// +// public virtual object TrackedVisitXmlDocumentExpression(XmlDocumentExpression xmlDocumentExpression, object data) { +// return base.VisitXmlDocumentExpression(xmlDocumentExpression, data); +// } +// +// public virtual object TrackedVisitXmlElementExpression(XmlElementExpression xmlElementExpression, object data) { +// return base.VisitXmlElementExpression(xmlElementExpression, data); +// } +// +// public virtual object TrackedVisitXmlEmbeddedExpression(XmlEmbeddedExpression xmlEmbeddedExpression, object data) { +// return base.VisitXmlEmbeddedExpression(xmlEmbeddedExpression, data); +// } +// +// public virtual object TrackedVisitXmlMemberAccessExpression(XmlMemberAccessExpression xmlMemberAccessExpression, object data) { +// return base.VisitXmlMemberAccessExpression(xmlMemberAccessExpression, data); +// } +// } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/.gitignore b/src/Libraries/NRefactory/ICSharpCode.NRefactory/.gitignore new file mode 100644 index 0000000000..9ce745d95d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs new file mode 100644 index 0000000000..bfaaf11f52 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs @@ -0,0 +1,683 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; + +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Analysis +{ + /// + /// Represents a node in the control flow graph of a C# method. + /// + public class ControlFlowNode + { + public readonly Statement PreviousStatement; + public readonly Statement NextStatement; + + public readonly ControlFlowNodeType Type; + + public readonly List Outgoing = new List(); + public readonly List Incoming = new List(); + + public ControlFlowNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) + { + if (previousStatement == null && nextStatement == null) + throw new ArgumentException("previousStatement and nextStatement must not be both null"); + this.PreviousStatement = previousStatement; + this.NextStatement = nextStatement; + this.Type = type; + } + } + + public enum ControlFlowNodeType + { + /// + /// Unknown node type + /// + None, + /// + /// Node in front of a statement + /// + StartNode, + /// + /// Node between two statements + /// + BetweenStatements, + /// + /// Node at the end of a statement list + /// + EndNode, + /// + /// Node representing the position before evaluating the condition of a loop. + /// + LoopCondition + } + + public class ControlFlowEdge + { + public readonly ControlFlowNode From; + public readonly ControlFlowNode To; + public readonly ControlFlowEdgeType Type; + + List jumpOutOfTryFinally; + + public ControlFlowEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type) + { + if (from == null) + throw new ArgumentNullException("from"); + if (to == null) + throw new ArgumentNullException("to"); + this.From = from; + this.To = to; + this.Type = type; + } + + internal void AddJumpOutOfTryFinally(TryCatchStatement tryFinally) + { + if (jumpOutOfTryFinally == null) + jumpOutOfTryFinally = new List(); + jumpOutOfTryFinally.Add(tryFinally); + } + + /// + /// Gets whether this control flow edge is leaving any try-finally statements. + /// + public bool IsLeavingTryFinally { + get { return jumpOutOfTryFinally != null; } + } + + /// + /// Gets the try-finally statements that this control flow edge is leaving. + /// + public IEnumerable TryFinallyStatements { + get { return jumpOutOfTryFinally ?? Enumerable.Empty(); } + } + } + + public enum ControlFlowEdgeType + { + /// + /// Regular control flow. + /// + Normal, + /// + /// Conditional control flow (edge taken if condition is true) + /// + ConditionTrue, + /// + /// Conditional control flow (edge taken if condition is false) + /// + ConditionFalse, + /// + /// A jump statement (goto, goto case, break or continue) + /// + Jump + } + + /// + /// Constructs the control flow graph for C# statements. + /// + public class ControlFlowGraphBuilder + { + // Written according to the reachability rules in the C# spec (§8.1 End points and reachability) + + protected virtual ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) + { + return new ControlFlowNode(previousStatement, nextStatement, type); + } + + protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type) + { + return new ControlFlowEdge(from, to, type); + } + + Statement rootStatement; + ResolveVisitor resolveVisitor; + List nodes; + Dictionary labels; + List gotoStatements; + + public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context) + { + return BuildControlFlowGraph(statement, context, CancellationToken.None); + } + + public IList BuildControlFlowGraph(Statement statement, ITypeResolveContext context, CancellationToken cancellationToken) + { + return BuildControlFlowGraph(statement, new ResolveVisitor( + new CSharpResolver(context, cancellationToken), + null, ConstantModeResolveVisitorNavigator.Skip)); + } + + public IList BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor) + { + if (statement == null) + throw new ArgumentNullException("statement"); + if (resolveVisitor == null) + throw new ArgumentNullException("resolveVisitor"); + + NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor(); + nodeCreationVisitor.builder = this; + try { + this.nodes = new List(); + this.labels = new Dictionary(); + this.gotoStatements = new List(); + this.rootStatement = statement; + this.resolveVisitor = resolveVisitor; + ControlFlowNode entryPoint = CreateStartNode(statement); + statement.AcceptVisitor(nodeCreationVisitor, entryPoint); + + // Resolve goto statements: + foreach (ControlFlowNode gotoStmt in gotoStatements) { + string label = ((GotoStatement)gotoStmt.NextStatement).Label; + ControlFlowNode labelNode; + if (labels.TryGetValue(label, out labelNode)) + nodeCreationVisitor.Connect(gotoStmt, labelNode, ControlFlowEdgeType.Jump); + } + + AnnotateLeaveEdgesWithTryFinallyBlocks(); + + return nodes; + } finally { + this.nodes = null; + this.labels = null; + this.gotoStatements = null; + this.rootStatement = null; + this.resolveVisitor = null; + } + } + + void AnnotateLeaveEdgesWithTryFinallyBlocks() + { + foreach (ControlFlowEdge edge in nodes.SelectMany(n => n.Outgoing)) { + if (edge.Type != ControlFlowEdgeType.Jump) { + // Only jumps are potential candidates for leaving try-finally blocks. + // Note that the regular edges leaving try or catch blocks are already annotated by the visitor. + continue; + } + Statement gotoStatement = edge.From.NextStatement; + Debug.Assert(gotoStatement is GotoStatement || gotoStatement is GotoDefaultStatement || gotoStatement is GotoCaseStatement || gotoStatement is BreakStatement || gotoStatement is ContinueStatement); + Statement targetStatement = edge.To.PreviousStatement ?? edge.To.NextStatement; + if (gotoStatement.Parent == targetStatement.Parent) + continue; + HashSet targetParentTryCatch = new HashSet(targetStatement.Ancestors.OfType()); + for (AstNode node = gotoStatement.Parent; node != null; node = node.Parent) { + TryCatchStatement leftTryCatch = node as TryCatchStatement; + if (leftTryCatch != null) { + if (targetParentTryCatch.Contains(leftTryCatch)) + break; + if (!leftTryCatch.FinallyBlock.IsNull) + edge.AddJumpOutOfTryFinally(leftTryCatch); + } + } + } + } + + #region Create*Node + ControlFlowNode CreateStartNode(Statement statement) + { + ControlFlowNode node = CreateNode(null, statement, ControlFlowNodeType.StartNode); + nodes.Add(node); + return node; + } + + ControlFlowNode CreateSpecialNode(Statement statement, ControlFlowNodeType type, bool addToNodeList = true) + { + ControlFlowNode node = CreateNode(null, statement, type); + if (addToNodeList) + nodes.Add(node); + return node; + } + + ControlFlowNode CreateEndNode(Statement statement, bool addToNodeList = true) + { + Statement nextStatement; + if (statement == rootStatement) { + nextStatement = null; + } else { + // Find the next statement in the same role: + AstNode next = statement; + do { + next = next.NextSibling; + } while (next != null && next.Role != statement.Role); + nextStatement = next as Statement; + } + ControlFlowNodeType type = nextStatement != null ? ControlFlowNodeType.BetweenStatements : ControlFlowNodeType.EndNode; + ControlFlowNode node = CreateNode(statement, nextStatement, type); + if (addToNodeList) + nodes.Add(node); + return node; + } + #endregion + + #region Constant evaluation + /// + /// Gets/Sets whether to handle only primitive expressions as constants (no complex expressions like "a + b"). + /// + public bool EvaluateOnlyPrimitiveConstants { get; set; } + + /// + /// Evaluates an expression. + /// + /// The constant value of the expression; or null if the expression is not a constant. + ConstantResolveResult EvaluateConstant(Expression expr) + { + if (EvaluateOnlyPrimitiveConstants) { + if (!(expr is PrimitiveExpression || expr is NullReferenceExpression)) + return null; + } + return resolveVisitor.Resolve(expr) as ConstantResolveResult; + } + + /// + /// Evaluates an expression. + /// + /// The value of the constant boolean expression; or null if the value is not a constant boolean expression. + bool? EvaluateCondition(Expression expr) + { + ConstantResolveResult rr = EvaluateConstant(expr); + if (rr != null) + return rr.ConstantValue as bool?; + else + return null; + } + + bool AreEqualConstants(ConstantResolveResult c1, ConstantResolveResult c2) + { + if (c1 == null || c2 == null) + return false; + CSharpResolver r = new CSharpResolver(resolveVisitor.TypeResolveContext, resolveVisitor.CancellationToken); + ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2); + return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true; + } + #endregion + + sealed class NodeCreationVisitor : DepthFirstAstVisitor + { + // 'data' parameter: input control flow node (start of statement being visited) + // Return value: result control flow node (end of statement being visited) + + internal ControlFlowGraphBuilder builder; + Stack breakTargets = new Stack(); + Stack continueTargets = new Stack(); + List gotoCaseOrDefault = new List(); + + internal ControlFlowEdge Connect(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type = ControlFlowEdgeType.Normal) + { + ControlFlowEdge edge = builder.CreateEdge(from, to, type); + from.Outgoing.Add(edge); + to.Incoming.Add(edge); + return edge; + } + + /// + /// Creates an end node for stmt and connects from with the new node. + /// + ControlFlowNode CreateConnectedEndNode(Statement stmt, ControlFlowNode from) + { + ControlFlowNode newNode = builder.CreateEndNode(stmt); + Connect(from, newNode); + return newNode; + } + + protected override ControlFlowNode VisitChildren(AstNode node, ControlFlowNode data) + { + // We have overrides for all possible expressions and should visit expressions only. + throw new NotImplementedException(); + } + + public override ControlFlowNode VisitBlockStatement(BlockStatement blockStatement, ControlFlowNode data) + { + // C# 4.0 spec: §8.2 Blocks + ControlFlowNode childNode = HandleStatementList(blockStatement.Statements, data); + return CreateConnectedEndNode(blockStatement, childNode); + } + + ControlFlowNode HandleStatementList(AstNodeCollection statements, ControlFlowNode source) + { + ControlFlowNode childNode = null; + foreach (Statement stmt in statements) { + if (childNode == null) { + childNode = builder.CreateStartNode(stmt); + if (source != null) + Connect(source, childNode); + } + Debug.Assert(childNode.NextStatement == stmt); + childNode = stmt.AcceptVisitor(this, childNode); + Debug.Assert(childNode.PreviousStatement == stmt); + } + return childNode ?? source; + } + + public override ControlFlowNode VisitEmptyStatement(EmptyStatement emptyStatement, ControlFlowNode data) + { + return CreateConnectedEndNode(emptyStatement, data); + } + + public override ControlFlowNode VisitLabelStatement(LabelStatement labelStatement, ControlFlowNode data) + { + ControlFlowNode end = CreateConnectedEndNode(labelStatement, data); + builder.labels[labelStatement.Label] = end; + return end; + } + + public override ControlFlowNode VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, ControlFlowNode data) + { + return CreateConnectedEndNode(variableDeclarationStatement, data); + } + + public override ControlFlowNode VisitExpressionStatement(ExpressionStatement expressionStatement, ControlFlowNode data) + { + return CreateConnectedEndNode(expressionStatement, data); + } + + public override ControlFlowNode VisitIfElseStatement(IfElseStatement ifElseStatement, ControlFlowNode data) + { + bool? cond = builder.EvaluateCondition(ifElseStatement.Condition); + ControlFlowNode trueBegin = builder.CreateStartNode(ifElseStatement.TrueStatement); + if (cond != false) + Connect(data, trueBegin, ControlFlowEdgeType.ConditionTrue); + ControlFlowNode trueEnd = ifElseStatement.TrueStatement.AcceptVisitor(this, trueBegin); + ControlFlowNode falseEnd; + if (ifElseStatement.FalseStatement.IsNull) { + falseEnd = null; + } else { + ControlFlowNode falseBegin = builder.CreateStartNode(ifElseStatement.FalseStatement); + if (cond != true) + Connect(data, falseBegin, ControlFlowEdgeType.ConditionFalse); + falseEnd = ifElseStatement.FalseStatement.AcceptVisitor(this, falseBegin); + } + ControlFlowNode end = builder.CreateEndNode(ifElseStatement); + Connect(trueEnd, end); + if (falseEnd != null) { + Connect(falseEnd, end); + } else if (cond != true) { + Connect(data, end, ControlFlowEdgeType.ConditionFalse); + } + return end; + } + + 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); + 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); + if (builder.AreEqualConstants(constant, labelConstant)) + sectionMatchedByConstant = section; + } + } + } + if (constant != null && sectionMatchedByConstant == null) + sectionMatchedByConstant = defaultSection; + + int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count; + + ControlFlowNode end = builder.CreateEndNode(switchStatement, addToNodeList: false); + breakTargets.Push(end); + foreach (SwitchSection section in switchStatement.SwitchSections) { + if (constant == null || 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. + } + breakTargets.Pop(); + if (defaultSection == null && sectionMatchedByConstant == null) { + Connect(data, end); + } + + if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope) { + // Resolve 'goto case' statements: + throw new NotImplementedException(); + } + + builder.nodes.Add(end); + return end; + } + + public override ControlFlowNode VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, ControlFlowNode data) + { + gotoCaseOrDefault.Add(data); + return builder.CreateEndNode(gotoCaseStatement); + } + + public override ControlFlowNode VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, ControlFlowNode data) + { + gotoCaseOrDefault.Add(data); + return builder.CreateEndNode(gotoDefaultStatement); + } + + public override ControlFlowNode VisitWhileStatement(WhileStatement whileStatement, ControlFlowNode data) + { + // while (cond) { embeddedStmt; } + ControlFlowNode end = builder.CreateEndNode(whileStatement, addToNodeList: false); + ControlFlowNode conditionNode = builder.CreateSpecialNode(whileStatement, ControlFlowNodeType.LoopCondition); + breakTargets.Push(end); + continueTargets.Push(conditionNode); + + Connect(data, conditionNode); + + bool? cond = builder.EvaluateCondition(whileStatement.Condition); + ControlFlowNode bodyStart = builder.CreateStartNode(whileStatement.EmbeddedStatement); + if (cond != false) + Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue); + ControlFlowNode bodyEnd = whileStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart); + Connect(bodyEnd, conditionNode); + if (cond != true) + Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse); + + breakTargets.Pop(); + continueTargets.Pop(); + builder.nodes.Add(end); + return end; + } + + public override ControlFlowNode VisitDoWhileStatement(DoWhileStatement doWhileStatement, ControlFlowNode data) + { + // do { embeddedStmt; } while(cond); + ControlFlowNode end = builder.CreateEndNode(doWhileStatement, addToNodeList: false); + ControlFlowNode conditionNode = builder.CreateSpecialNode(doWhileStatement, ControlFlowNodeType.LoopCondition, addToNodeList: false); + breakTargets.Push(end); + continueTargets.Push(conditionNode); + + ControlFlowNode bodyStart = builder.CreateStartNode(doWhileStatement.EmbeddedStatement); + Connect(data, bodyStart); + ControlFlowNode bodyEnd = doWhileStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart); + Connect(bodyEnd, conditionNode); + + bool? cond = builder.EvaluateCondition(doWhileStatement.Condition); + if (cond != false) + Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue); + if (cond != true) + Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse); + + breakTargets.Pop(); + continueTargets.Pop(); + builder.nodes.Add(conditionNode); + builder.nodes.Add(end); + return end; + } + + public override ControlFlowNode VisitForStatement(ForStatement forStatement, ControlFlowNode data) + { + data = HandleStatementList(forStatement.Initializers, data); + // for (initializers ; cond; iterators) { embeddedStmt; } + ControlFlowNode end = builder.CreateEndNode(forStatement, addToNodeList: false); + ControlFlowNode conditionNode = builder.CreateSpecialNode(forStatement, ControlFlowNodeType.LoopCondition); + Connect(data, conditionNode); + + int iteratorStartNodeID = builder.nodes.Count; + ControlFlowNode iteratorEnd = HandleStatementList(forStatement.Iterators, null); + ControlFlowNode iteratorStart; + if (iteratorEnd != null) { + iteratorStart = builder.nodes[iteratorStartNodeID]; + Connect(iteratorEnd, conditionNode); + } else { + iteratorStart = conditionNode; + } + + breakTargets.Push(end); + continueTargets.Push(iteratorStart); + + ControlFlowNode bodyStart = builder.CreateStartNode(forStatement.EmbeddedStatement); + ControlFlowNode bodyEnd = forStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart); + Connect(bodyEnd, iteratorStart); + + breakTargets.Pop(); + continueTargets.Pop(); + + bool? cond = forStatement.Condition.IsNull ? true : builder.EvaluateCondition(forStatement.Condition); + if (cond != false) + Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue); + if (cond != true) + Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse); + + builder.nodes.Add(end); + return end; + } + + ControlFlowNode HandleEmbeddedStatement(Statement embeddedStatement, ControlFlowNode source) + { + if (embeddedStatement == null || embeddedStatement.IsNull) + return source; + ControlFlowNode bodyStart = builder.CreateStartNode(embeddedStatement); + if (source != null) + Connect(source, bodyStart); + return embeddedStatement.AcceptVisitor(this, bodyStart); + } + + public override ControlFlowNode VisitForeachStatement(ForeachStatement foreachStatement, ControlFlowNode data) + { + // foreach (...) { embeddedStmt } + ControlFlowNode end = builder.CreateEndNode(foreachStatement, addToNodeList: false); + ControlFlowNode conditionNode = builder.CreateSpecialNode(foreachStatement, ControlFlowNodeType.LoopCondition); + Connect(data, conditionNode); + + breakTargets.Push(end); + continueTargets.Push(conditionNode); + + ControlFlowNode bodyEnd = HandleEmbeddedStatement(foreachStatement.EmbeddedStatement, conditionNode); + Connect(bodyEnd, conditionNode); + + breakTargets.Pop(); + continueTargets.Pop(); + + Connect(conditionNode, end); + builder.nodes.Add(end); + return end; + } + + public override ControlFlowNode VisitBreakStatement(BreakStatement breakStatement, ControlFlowNode data) + { + if (breakTargets.Count > 0) + Connect(data, breakTargets.Peek(), ControlFlowEdgeType.Jump); + return builder.CreateEndNode(breakStatement); + } + + public override ControlFlowNode VisitContinueStatement(ContinueStatement continueStatement, ControlFlowNode data) + { + if (continueTargets.Count > 0) + Connect(data, continueTargets.Peek(), ControlFlowEdgeType.Jump); + return builder.CreateEndNode(continueStatement); + } + + public override ControlFlowNode VisitGotoStatement(GotoStatement gotoStatement, ControlFlowNode data) + { + builder.gotoStatements.Add(data); + return builder.CreateEndNode(gotoStatement); + } + + public override ControlFlowNode VisitReturnStatement(ReturnStatement returnStatement, ControlFlowNode data) + { + return builder.CreateEndNode(returnStatement); // end not connected with data + } + + public override ControlFlowNode VisitThrowStatement(ThrowStatement throwStatement, ControlFlowNode data) + { + return builder.CreateEndNode(throwStatement); // end not connected with data + } + + public override ControlFlowNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement, ControlFlowNode data) + { + ControlFlowNode end = builder.CreateEndNode(tryCatchStatement, addToNodeList: false); + var edge = Connect(HandleEmbeddedStatement(tryCatchStatement.TryBlock, data), end); + if (!tryCatchStatement.FinallyBlock.IsNull) + edge.AddJumpOutOfTryFinally(tryCatchStatement); + foreach (CatchClause cc in tryCatchStatement.CatchClauses) { + edge = Connect(HandleEmbeddedStatement(cc.Body, data), end); + if (!tryCatchStatement.FinallyBlock.IsNull) + edge.AddJumpOutOfTryFinally(tryCatchStatement); + } + if (!tryCatchStatement.FinallyBlock.IsNull) { + // Don't connect the end of the try-finally block to anything. + // Consumers of the CFG will have to special-case try-finally. + HandleEmbeddedStatement(tryCatchStatement.FinallyBlock, data); + } + builder.nodes.Add(end); + return end; + } + + public override ControlFlowNode VisitCheckedStatement(CheckedStatement checkedStatement, ControlFlowNode data) + { + ControlFlowNode bodyEnd = HandleEmbeddedStatement(checkedStatement.Body, data); + return CreateConnectedEndNode(checkedStatement, bodyEnd); + } + + public override ControlFlowNode VisitUncheckedStatement(UncheckedStatement uncheckedStatement, ControlFlowNode data) + { + ControlFlowNode bodyEnd = HandleEmbeddedStatement(uncheckedStatement.Body, data); + return CreateConnectedEndNode(uncheckedStatement, bodyEnd); + } + + public override ControlFlowNode VisitLockStatement(LockStatement lockStatement, ControlFlowNode data) + { + ControlFlowNode bodyEnd = HandleEmbeddedStatement(lockStatement.EmbeddedStatement, data); + return CreateConnectedEndNode(lockStatement, bodyEnd); + } + + public override ControlFlowNode VisitUsingStatement(UsingStatement usingStatement, ControlFlowNode data) + { + data = HandleEmbeddedStatement(usingStatement.ResourceAcquisition as Statement, data); + ControlFlowNode bodyEnd = HandleEmbeddedStatement(usingStatement.EmbeddedStatement, data); + return CreateConnectedEndNode(usingStatement, bodyEnd); + } + + public override ControlFlowNode VisitYieldStatement(YieldStatement yieldStatement, ControlFlowNode data) + { + return CreateConnectedEndNode(yieldStatement, data); + } + + public override ControlFlowNode VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, ControlFlowNode data) + { + return builder.CreateEndNode(yieldBreakStatement); // end not connected with data + } + + public override ControlFlowNode VisitUnsafeStatement(UnsafeStatement unsafeStatement, ControlFlowNode data) + { + ControlFlowNode bodyEnd = HandleEmbeddedStatement(unsafeStatement.Body, data); + return CreateConnectedEndNode(unsafeStatement, bodyEnd); + } + + public override ControlFlowNode VisitFixedStatement(FixedStatement fixedStatement, ControlFlowNode data) + { + ControlFlowNode bodyEnd = HandleEmbeddedStatement(fixedStatement.EmbeddedStatement, data); + return CreateConnectedEndNode(fixedStatement, bodyEnd); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs new file mode 100644 index 0000000000..edef14f633 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs @@ -0,0 +1,750 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Analysis +{ + /// + /// Represents the definite assignment status of a variable at a specific location. + /// + public enum DefiniteAssignmentStatus + { + /// + /// The variable might be assigned or unassigned. + /// + PotentiallyAssigned, + /// + /// The variable is definitely assigned. + /// + DefinitelyAssigned, + /// + /// The variable is definitely assigned iff the expression results in the value 'true'. + /// + AssignedAfterTrueExpression, + /// + /// The variable is definitely assigned iff the expression results in the value 'false'. + /// + AssignedAfterFalseExpression, + /// + /// The code is unreachable. + /// + CodeUnreachable + } + + /// + /// Implements the C# definite assignment analysis (C# 4.0 Spec: §5.3 Definite assignment) + /// + public class DefiniteAssignmentAnalysis + { + sealed class DefiniteAssignmentNode : ControlFlowNode + { + public int Index; + public DefiniteAssignmentStatus NodeStatus; + + public DefiniteAssignmentNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) + : base(previousStatement, nextStatement, type) + { + } + } + + sealed class DerivedControlFlowGraphBuilder : ControlFlowGraphBuilder + { + protected override ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) + { + return new DefiniteAssignmentNode(previousStatement, nextStatement, type); + } + } + + readonly DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder(); + readonly DefiniteAssignmentVisitor visitor = new DefiniteAssignmentVisitor(); + readonly List allNodes = new List(); + readonly Dictionary beginNodeDict = new Dictionary(); + readonly Dictionary endNodeDict = new Dictionary(); + readonly Dictionary conditionNodeDict = new Dictionary(); + readonly ResolveVisitor resolveVisitor; + readonly CancellationToken cancellationToken; + Dictionary edgeStatus = new Dictionary(); + + string variableName; + List unassignedVariableUses = new List(); + int analyzedRangeStart, analyzedRangeEnd; + + Queue nodesWithModifiedInput = new Queue(); + + 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) + { + } + + public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken) + : this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken), + null, ConstantModeResolveVisitorNavigator.Skip)) + { + } + + public DefiniteAssignmentAnalysis(Statement rootStatement, ResolveVisitor resolveVisitor) + { + if (rootStatement == null) + throw new ArgumentNullException("rootStatement"); + if (resolveVisitor == null) + throw new ArgumentNullException("resolveVisitor"); + this.resolveVisitor = resolveVisitor; + this.cancellationToken = resolveVisitor.CancellationToken; + visitor.analysis = this; + if (resolveVisitor.TypeResolveContext is MinimalResolveContext) { + cfgBuilder.EvaluateOnlyPrimitiveConstants = true; + } + allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolveVisitor).Cast()); + for (int i = 0; i < allNodes.Count; i++) { + DefiniteAssignmentNode node = allNodes[i]; + node.Index = i; // assign numbers to the nodes + if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements) { + // 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); + } + } + // Now register the node in the dictionaries: + if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements) + beginNodeDict.Add(node.NextStatement, node); + if (node.Type == ControlFlowNodeType.BetweenStatements || node.Type == ControlFlowNodeType.EndNode) + endNodeDict.Add(node.PreviousStatement, node); + if (node.Type == ControlFlowNodeType.LoopCondition) + conditionNodeDict.Add(node.NextStatement, node); + } + // Verify that we created nodes for all statements: + Debug.Assert(!rootStatement.DescendantsAndSelf.OfType().Except(allNodes.Select(n => n.NextStatement)).Any()); + // Verify that we put all nodes into the dictionaries: + Debug.Assert(rootStatement.DescendantsAndSelf.OfType().All(stmt => beginNodeDict.ContainsKey(stmt))); + Debug.Assert(rootStatement.DescendantsAndSelf.OfType().All(stmt => endNodeDict.ContainsKey(stmt))); + + this.analyzedRangeStart = 0; + this.analyzedRangeEnd = allNodes.Count - 1; + } + + void InsertAnonymousMethods(int insertPos, AstNode node) + { + // 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()); + return; + } + LambdaExpression lambda = node as LambdaExpression; + if (lambda != null && lambda.Body is Statement) { + allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph((Statement)lambda.Body, resolveVisitor).Cast()); + 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); + } + } + + /// + /// Gets the unassigned usages of the previously analyzed variable. + /// + public IList UnassignedVariableUses { + get { + return unassignedVariableUses.AsReadOnly(); + } + } + + /// + /// Sets the range of statements to be analyzed. + /// This method can be used to restrict the analysis to only a part of the method. + /// Only the control flow paths that are fully contained within the selected part will be analyzed. + /// + /// By default, both 'start' and 'end' are inclusive. + public void SetAnalyzedRange(Statement start, Statement end, bool startInclusive = true, bool endInclusive = true) + { + var dictForStart = startInclusive ? beginNodeDict : endNodeDict; + var dictForEnd = endInclusive ? endNodeDict : beginNodeDict; + Debug.Assert(dictForStart.ContainsKey(start) && dictForEnd.ContainsKey(end)); + int startIndex = dictForStart[start].Index; + int endIndex = dictForEnd[end].Index; + if (startIndex > endIndex) + throw new ArgumentException("The start statement must be lexically preceding the end statement"); + this.analyzedRangeStart = startIndex; + this.analyzedRangeEnd = endIndex; + } + + public void Analyze(string variable, DefiniteAssignmentStatus initialStatus = DefiniteAssignmentStatus.PotentiallyAssigned) + { + 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]); + } + ChangeNodeStatus(node, inputStatus); + } + } + + public DefiniteAssignmentStatus GetStatusBefore(Statement statement) + { + return beginNodeDict[statement].NodeStatus; + } + + public DefiniteAssignmentStatus GetStatusAfter(Statement statement) + { + return endNodeDict[statement].NodeStatus; + } + + public DefiniteAssignmentStatus GetStatusBeforeLoopCondition(Statement statement) + { + return conditionNodeDict[statement].NodeStatus; + } + + /// + /// Exports the CFG. This method is intended to help debugging issues related to definite assignment. + /// + public GraphVizGraph ExportGraph() + { + GraphVizGraph g = new GraphVizGraph(); + g.Title = "DefiniteAssignment - " + variableName; + for (int i = 0; i < allNodes.Count; i++) { + string name = "#" + i + " = " + allNodes[i].NodeStatus.ToString() + Environment.NewLine; + switch (allNodes[i].Type) { + case ControlFlowNodeType.StartNode: + case ControlFlowNodeType.BetweenStatements: + name += allNodes[i].NextStatement.ToString(); + break; + case ControlFlowNodeType.EndNode: + name += "End of " + allNodes[i].PreviousStatement.ToString(); + break; + case ControlFlowNodeType.LoopCondition: + name += "Condition in " + allNodes[i].NextStatement.ToString(); + break; + default: + name += allNodes[i].Type.ToString(); + break; + } + g.AddNode(new GraphVizNode(i) { label = name }); + foreach (ControlFlowEdge edge in allNodes[i].Outgoing) { + GraphVizEdge ge = new GraphVizEdge(i, ((DefiniteAssignmentNode)edge.To).Index); + if (edgeStatus.Count > 0) + ge.label = edgeStatus[edge].ToString(); + if (edge.IsLeavingTryFinally) + ge.style = "dashed"; + switch (edge.Type) { + case ControlFlowEdgeType.ConditionTrue: + ge.color = "green"; + break; + case ControlFlowEdgeType.ConditionFalse: + ge.color = "red"; + break; + case ControlFlowEdgeType.Jump: + ge.color = "blue"; + break; + } + g.AddEdge(ge); + } + } + return g; + } + + static DefiniteAssignmentStatus MergeStatus(DefiniteAssignmentStatus a, DefiniteAssignmentStatus b) + { + // The result will be DefinitelyAssigned if at least one incoming edge is DefinitelyAssigned and all others are unreachable. + // The result will be DefinitelyUnassigned if at least one incoming edge is DefinitelyUnassigned and all others are unreachable. + // The result will be Unreachable if all incoming edges are unreachable. + // Otherwise, the result will be PotentiallyAssigned. + + if (a == b) + return a; + else if (a == DefiniteAssignmentStatus.CodeUnreachable) + return b; + else if (b == DefiniteAssignmentStatus.CodeUnreachable) + return a; + else + return DefiniteAssignmentStatus.PotentiallyAssigned; + } + + void ChangeNodeStatus(DefiniteAssignmentNode node, DefiniteAssignmentStatus inputStatus) + { + if (node.NodeStatus == inputStatus) + return; + node.NodeStatus = inputStatus; + DefiniteAssignmentStatus outputStatus; + switch (node.Type) { + case ControlFlowNodeType.StartNode: + case ControlFlowNodeType.BetweenStatements: + if (node.NextStatement is IfElseStatement) { + // Handle if-else as a condition node + goto case ControlFlowNodeType.LoopCondition; + } + if (inputStatus == DefiniteAssignmentStatus.DefinitelyAssigned) { + // There isn't any way to un-assign variables, so we don't have to check the expression + // if the status already is definitely assigned. + outputStatus = DefiniteAssignmentStatus.DefinitelyAssigned; + } else { + outputStatus = CleanSpecialValues(node.NextStatement.AcceptVisitor(visitor, inputStatus)); + } + break; + case ControlFlowNodeType.EndNode: + outputStatus = inputStatus; + if (node.PreviousStatement.Role == TryCatchStatement.FinallyBlockRole + && (outputStatus == DefiniteAssignmentStatus.DefinitelyAssigned || outputStatus == DefiniteAssignmentStatus.PotentiallyAssigned)) + { + TryCatchStatement tryFinally = (TryCatchStatement)node.PreviousStatement.Parent; + // Changing the status on a finally block potentially changes the status of all edges leaving that finally block: + foreach (ControlFlowEdge edge in allNodes.SelectMany(n => n.Outgoing)) { + if (edge.IsLeavingTryFinally && edge.TryFinallyStatements.Contains(tryFinally)) { + DefiniteAssignmentStatus s = edgeStatus[edge]; + if (s == DefiniteAssignmentStatus.PotentiallyAssigned) { + ChangeEdgeStatus(edge, outputStatus); + } + } + } + } + break; + case ControlFlowNodeType.LoopCondition: + ForeachStatement foreachStmt = node.NextStatement as ForeachStatement; + if (foreachStmt != null) { + outputStatus = CleanSpecialValues(foreachStmt.InExpression.AcceptVisitor(visitor, inputStatus)); + if (foreachStmt.VariableName == this.variableName) + outputStatus = DefiniteAssignmentStatus.DefinitelyAssigned; + break; + } else { + Debug.Assert(node.NextStatement is IfElseStatement || node.NextStatement is WhileStatement || node.NextStatement is ForStatement || node.NextStatement is DoWhileStatement); + Expression condition = node.NextStatement.GetChildByRole(AstNode.Roles.Condition); + if (condition.IsNull) + outputStatus = inputStatus; + else + outputStatus = condition.AcceptVisitor(visitor, inputStatus); + foreach (ControlFlowEdge edge in node.Outgoing) { + if (edge.Type == ControlFlowEdgeType.ConditionTrue && outputStatus == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { + ChangeEdgeStatus(edge, DefiniteAssignmentStatus.DefinitelyAssigned); + } else if (edge.Type == ControlFlowEdgeType.ConditionFalse && outputStatus == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { + ChangeEdgeStatus(edge, DefiniteAssignmentStatus.DefinitelyAssigned); + } else { + ChangeEdgeStatus(edge, CleanSpecialValues(outputStatus)); + } + } + return; + } + default: + throw new InvalidOperationException(); + } + foreach (ControlFlowEdge edge in node.Outgoing) { + ChangeEdgeStatus(edge, outputStatus); + } + } + + void ChangeEdgeStatus(ControlFlowEdge edge, DefiniteAssignmentStatus newStatus) + { + DefiniteAssignmentStatus oldStatus = edgeStatus[edge]; + if (oldStatus == newStatus) + return; + // Ensure that status can cannot change back to CodeUnreachable after it once was reachable. + // Also, don't ever use AssignedAfter... for statements. + if (newStatus == DefiniteAssignmentStatus.CodeUnreachable + || newStatus == DefiniteAssignmentStatus.AssignedAfterFalseExpression + || newStatus == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + { + throw new InvalidOperationException(); + } + // Note that the status can change from DefinitelyAssigned + // back to PotentiallyAssigned as unreachable input edges are + // discovered to be reachable. + + edgeStatus[edge] = newStatus; + DefiniteAssignmentNode targetNode = (DefiniteAssignmentNode)edge.To; + if (analyzedRangeStart <= targetNode.Index && targetNode.Index <= analyzedRangeEnd) { + // TODO: potential optimization: visit previously unreachable nodes with higher priority + // (e.g. use Deque and enqueue previously unreachable nodes at the front, but + // other nodes at the end) + nodesWithModifiedInput.Enqueue(targetNode); + } + } + + /// + /// Evaluates an expression. + /// + /// The constant value of the expression; or null if the expression is not a constant. + ConstantResolveResult EvaluateConstant(Expression expr) + { + if (resolveVisitor.TypeResolveContext is MinimalResolveContext) { + if (!(expr is PrimitiveExpression || expr is NullReferenceExpression)) + return null; + } + return resolveVisitor.Resolve(expr) as ConstantResolveResult; + } + + /// + /// Evaluates an expression. + /// + /// The value of the constant boolean expression; or null if the value is not a constant boolean expression. + bool? EvaluateCondition(Expression expr) + { + ConstantResolveResult rr = EvaluateConstant(expr); + if (rr != null) + return rr.ConstantValue as bool?; + else + return null; + } + + static DefiniteAssignmentStatus CleanSpecialValues(DefiniteAssignmentStatus status) + { + if (status == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + return DefiniteAssignmentStatus.PotentiallyAssigned; + else if (status == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + return DefiniteAssignmentStatus.PotentiallyAssigned; + else + return status; + } + + sealed class DefiniteAssignmentVisitor : DepthFirstAstVisitor + { + internal DefiniteAssignmentAnalysis analysis; + + // The general approach for unknown nodes is to pass the status through all child nodes in order + protected override DefiniteAssignmentStatus VisitChildren(AstNode node, DefiniteAssignmentStatus data) + { + // the special values are valid as output only, not as input + Debug.Assert(data == CleanSpecialValues(data)); + DefiniteAssignmentStatus status = data; + foreach (AstNode child in node.Children) { + Debug.Assert(!(child is Statement)); // statements are visited with the CFG, not with the visitor pattern + status = child.AcceptVisitor(this, status); + status = CleanSpecialValues(status); + } + return status; + } + + #region Statements + // For statements, the visitor only describes the effect of the statement itself; + // we do not consider the effect of any nested statements. + // This is done because the nested statements will be reached using the control flow graph. + + // In fact, these methods are present so that the default logic in VisitChildren does not try to visit the nested statements. + + public override DefiniteAssignmentStatus VisitBlockStatement(BlockStatement blockStatement, DefiniteAssignmentStatus data) + { + return data; + } + + public override DefiniteAssignmentStatus VisitCheckedStatement(CheckedStatement checkedStatement, DefiniteAssignmentStatus data) + { + return data; + } + + public override DefiniteAssignmentStatus VisitUncheckedStatement(UncheckedStatement uncheckedStatement, DefiniteAssignmentStatus data) + { + return data; + } + + // ExpressionStatement handled by default logic + // VariableDeclarationStatement handled by default logic + + public override DefiniteAssignmentStatus VisitVariableInitializer(VariableInitializer variableInitializer, DefiniteAssignmentStatus data) + { + if (variableInitializer.Initializer.IsNull) { + return data; + } else { + DefiniteAssignmentStatus status = variableInitializer.Initializer.AcceptVisitor(this, data); + if (variableInitializer.Name == analysis.variableName) + return DefiniteAssignmentStatus.DefinitelyAssigned; + else + return status; + } + } + + // IfStatement not handled by visitor, but special-cased in the code consuming the control flow graph + + public override DefiniteAssignmentStatus VisitSwitchStatement(SwitchStatement switchStatement, DefiniteAssignmentStatus data) + { + return switchStatement.Expression.AcceptVisitor(this, data); + } + + public override DefiniteAssignmentStatus VisitWhileStatement(WhileStatement whileStatement, DefiniteAssignmentStatus data) + { + return data; // condition is handled by special condition CFG node + } + + public override DefiniteAssignmentStatus VisitDoWhileStatement(DoWhileStatement doWhileStatement, DefiniteAssignmentStatus data) + { + return data; // condition is handled by special condition CFG node + } + + public override DefiniteAssignmentStatus VisitForStatement(ForStatement forStatement, DefiniteAssignmentStatus data) + { + return data; // condition is handled by special condition CFG node; initializer and iterator statements are handled by CFG + } + + // Break/Continue/Goto: handled by default logic + + // ThrowStatement: handled by default logic (just visit the expression) + // ReturnStatement: handled by default logic (just visit the expression) + + public override DefiniteAssignmentStatus VisitTryCatchStatement(TryCatchStatement tryCatchStatement, DefiniteAssignmentStatus data) + { + return data; // no special logic when entering the try-catch-finally statement + // TODO: where to put the special logic when exiting the try-finally statement? + } + + public override DefiniteAssignmentStatus VisitForeachStatement(ForeachStatement foreachStatement, DefiniteAssignmentStatus data) + { + return data; // assignment of the foreach loop variable is done when handling the condition node + } + + public override DefiniteAssignmentStatus VisitUsingStatement(UsingStatement usingStatement, DefiniteAssignmentStatus data) + { + if (usingStatement.ResourceAcquisition is Expression) + return usingStatement.ResourceAcquisition.AcceptVisitor(this, data); + else + return data; // don't handle resource acquisition statements, as those are connected in the control flow graph + } + + public override DefiniteAssignmentStatus VisitLockStatement(LockStatement lockStatement, DefiniteAssignmentStatus data) + { + return lockStatement.Expression.AcceptVisitor(this, data); + } + + // Yield statements use the default logic + + public override DefiniteAssignmentStatus VisitUnsafeStatement(UnsafeStatement unsafeStatement, DefiniteAssignmentStatus data) + { + return data; + } + + public override DefiniteAssignmentStatus VisitFixedStatement(FixedStatement fixedStatement, DefiniteAssignmentStatus data) + { + DefiniteAssignmentStatus status = data; + foreach (var variable in fixedStatement.Variables) + status = variable.AcceptVisitor(this, status); + return status; + } + #endregion + + public override DefiniteAssignmentStatus VisitDirectionExpression(DirectionExpression directionExpression, DefiniteAssignmentStatus data) + { + if (directionExpression.FieldDirection == FieldDirection.Out) { + return HandleAssignment(directionExpression.Expression, null, data); + } else { + // use default logic for 'ref' + return VisitChildren(directionExpression, data); + } + } + + public override DefiniteAssignmentStatus VisitAssignmentExpression(AssignmentExpression assignmentExpression, DefiniteAssignmentStatus data) + { + if (assignmentExpression.Operator == AssignmentOperatorType.Assign) { + return HandleAssignment(assignmentExpression.Left, assignmentExpression.Right, data); + } else { + // use default logic for compound assignment operators + return VisitChildren(assignmentExpression, data); + } + } + + DefiniteAssignmentStatus HandleAssignment(Expression left, Expression right, DefiniteAssignmentStatus initialStatus) + { + IdentifierExpression ident = left as IdentifierExpression; + if (ident != null && ident.Identifier == analysis.variableName) { + // right==null is special case when handling 'out' expressions + if (right != null) + right.AcceptVisitor(this, initialStatus); + return DefiniteAssignmentStatus.DefinitelyAssigned; + } else { + DefiniteAssignmentStatus status = left.AcceptVisitor(this, initialStatus); + if (right != null) + status = right.AcceptVisitor(this, CleanSpecialValues(status)); + return CleanSpecialValues(status); + } + } + + public override DefiniteAssignmentStatus VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, DefiniteAssignmentStatus data) + { + // Don't use the default logic here because we don't want to clean up the special values. + return parenthesizedExpression.Expression.AcceptVisitor(this, data); + } + + public override DefiniteAssignmentStatus VisitCheckedExpression(CheckedExpression checkedExpression, DefiniteAssignmentStatus data) + { + return checkedExpression.Expression.AcceptVisitor(this, data); + } + + public override DefiniteAssignmentStatus VisitUncheckedExpression(UncheckedExpression uncheckedExpression, DefiniteAssignmentStatus data) + { + return uncheckedExpression.Expression.AcceptVisitor(this, data); + } + + public override DefiniteAssignmentStatus VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, DefiniteAssignmentStatus data) + { + if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd) { + // Handle constant left side of && expressions (not in the C# spec, but done by the MS compiler) + bool? cond = analysis.EvaluateCondition(binaryOperatorExpression.Left); + if (cond == true) + return binaryOperatorExpression.Right.AcceptVisitor(this, data); // right operand gets evaluated unconditionally + else if (cond == false) + return data; // right operand never gets evaluated + // C# 4.0 spec: §5.3.3.24 Definite Assignment for && expressions + DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data); + DefiniteAssignmentStatus beforeRight; + if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned; + else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned; + else + beforeRight = afterLeft; + DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight); + if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned) + return DefiniteAssignmentStatus.DefinitelyAssigned; + else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + return DefiniteAssignmentStatus.DefinitelyAssigned; + else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + return DefiniteAssignmentStatus.AssignedAfterTrueExpression; + else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + return DefiniteAssignmentStatus.AssignedAfterFalseExpression; + else + return DefiniteAssignmentStatus.PotentiallyAssigned; + } else if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr) { + // C# 4.0 spec: §5.3.3.25 Definite Assignment for || expressions + bool? cond = analysis.EvaluateCondition(binaryOperatorExpression.Left); + if (cond == false) + return binaryOperatorExpression.Right.AcceptVisitor(this, data); // right operand gets evaluated unconditionally + else if (cond == true) + return data; // right operand never gets evaluated + DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data); + DefiniteAssignmentStatus beforeRight; + if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned; + else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned; + else + beforeRight = afterLeft; + DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight); + if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned) + return DefiniteAssignmentStatus.DefinitelyAssigned; + else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + return DefiniteAssignmentStatus.DefinitelyAssigned; + else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + return DefiniteAssignmentStatus.AssignedAfterFalseExpression; + else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + return DefiniteAssignmentStatus.AssignedAfterTrueExpression; + else + 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) + return binaryOperatorExpression.Right.AcceptVisitor(this, data); + DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data)); + binaryOperatorExpression.Right.AcceptVisitor(this, status); + return status; + } else { + // use default logic for other operators + return VisitChildren(binaryOperatorExpression, data); + } + } + + public override DefiniteAssignmentStatus VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, DefiniteAssignmentStatus data) + { + if (unaryOperatorExpression.Operator == UnaryOperatorType.Not) { + // C# 4.0 spec: §5.3.3.26 Definite assignment for ! expressions + DefiniteAssignmentStatus status = unaryOperatorExpression.Expression.AcceptVisitor(this, data); + if (status == DefiniteAssignmentStatus.AssignedAfterFalseExpression) + return DefiniteAssignmentStatus.AssignedAfterTrueExpression; + else if (status == DefiniteAssignmentStatus.AssignedAfterTrueExpression) + return DefiniteAssignmentStatus.AssignedAfterFalseExpression; + else + return status; + } else { + // use default logic for other operators + return VisitChildren(unaryOperatorExpression, data); + } + } + + public override DefiniteAssignmentStatus VisitConditionalExpression(ConditionalExpression conditionalExpression, DefiniteAssignmentStatus data) + { + // C# 4.0 spec: §5.3.3.28 Definite assignment for ?: expressions + bool? cond = analysis.EvaluateCondition(conditionalExpression.Condition); + if (cond == true) { + return conditionalExpression.TrueExpression.AcceptVisitor(this, data); + } else if (cond == false) { + return conditionalExpression.FalseExpression.AcceptVisitor(this, data); + } else { + DefiniteAssignmentStatus afterCondition = conditionalExpression.Condition.AcceptVisitor(this, data); + + DefiniteAssignmentStatus beforeTrue, beforeFalse; + if (afterCondition == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { + beforeTrue = DefiniteAssignmentStatus.DefinitelyAssigned; + beforeFalse = DefiniteAssignmentStatus.PotentiallyAssigned; + } else if (afterCondition == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { + beforeTrue = DefiniteAssignmentStatus.PotentiallyAssigned; + beforeFalse = DefiniteAssignmentStatus.DefinitelyAssigned; + } else { + beforeTrue = afterCondition; + beforeFalse = afterCondition; + } + + DefiniteAssignmentStatus afterTrue = conditionalExpression.TrueExpression.AcceptVisitor(this, beforeTrue); + DefiniteAssignmentStatus afterFalse = conditionalExpression.TrueExpression.AcceptVisitor(this, beforeFalse); + return MergeStatus(CleanSpecialValues(afterTrue), CleanSpecialValues(afterFalse)); + } + } + + public override DefiniteAssignmentStatus VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, DefiniteAssignmentStatus data) + { + BlockStatement body = anonymousMethodExpression.Body; + analysis.ChangeNodeStatus(analysis.beginNodeDict[body], data); + return data; + } + + public override DefiniteAssignmentStatus VisitLambdaExpression(LambdaExpression lambdaExpression, DefiniteAssignmentStatus data) + { + Statement body = lambdaExpression.Body as Statement; + if (body != null) { + analysis.ChangeNodeStatus(analysis.beginNodeDict[body], data); + } else { + lambdaExpression.Body.AcceptVisitor(this, data); + } + return data; + } + + public override DefiniteAssignmentStatus VisitIdentifierExpression(IdentifierExpression identifierExpression, DefiniteAssignmentStatus data) + { + if (data != DefiniteAssignmentStatus.DefinitelyAssigned + && identifierExpression.Identifier == analysis.variableName && identifierExpression.TypeArguments.Count == 0) + { + analysis.unassignedVariableUses.Add(identifierExpression); + } + return data; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs new file mode 100644 index 0000000000..64fc134935 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs @@ -0,0 +1,127 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Analysis +{ + /// + /// Resolve context represents the minimal mscorlib required for evaluating constants. + /// + sealed class MinimalResolveContext : AbstractAnnotatable, IProjectContent, ISynchronizedTypeResolveContext + { + static readonly Lazy instance = new Lazy(() => new MinimalResolveContext()); + + public static MinimalResolveContext Instance { + get { return instance.Value; } + } + + readonly ReadOnlyCollection namespaces = Array.AsReadOnly(new string[] { "System" }); + readonly IAttribute[] assemblyAttributes = new IAttribute[0]; + readonly ITypeDefinition systemObject, systemValueType; + readonly ReadOnlyCollection types; + + private MinimalResolveContext() + { + List types = new List(); + types.Add(systemObject = new DefaultTypeDefinition(this, "System", "Object")); + types.Add(systemValueType = new DefaultTypeDefinition(this, "System", "ValueType") { BaseTypes = { systemObject } }); + types.Add(CreateStruct("System", "Boolean")); + types.Add(CreateStruct("System", "SByte")); + types.Add(CreateStruct("System", "Byte")); + types.Add(CreateStruct("System", "Int16")); + types.Add(CreateStruct("System", "UInt16")); + types.Add(CreateStruct("System", "Int32")); + types.Add(CreateStruct("System", "UInt32")); + types.Add(CreateStruct("System", "Int64")); + types.Add(CreateStruct("System", "UInt64")); + types.Add(CreateStruct("System", "Single")); + types.Add(CreateStruct("System", "Double")); + types.Add(CreateStruct("System", "Decimal")); + types.Add(new DefaultTypeDefinition(this, "System", "String") { BaseTypes = { systemObject } }); + foreach (ITypeDefinition type in types) + type.Freeze(); + this.types = types.AsReadOnly(); + } + + ITypeDefinition CreateStruct(string nameSpace, string name) + { + return new DefaultTypeDefinition(this, nameSpace, name) { + ClassType = ClassType.Struct, + BaseTypes = { systemValueType } + }; + } + + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + { + foreach (ITypeDefinition type in types) { + if (nameComparer.Equals(type.Name, name) && nameComparer.Equals(type.Namespace, nameSpace) && type.TypeParameterCount == typeParameterCount) + return type; + } + return null; + } + + public IEnumerable GetTypes() + { + return types; + } + + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) + { + return types.Where(t => nameComparer.Equals(t.Namespace, nameSpace)); + } + + public IEnumerable GetNamespaces() + { + return namespaces; + } + + public string GetNamespace(string nameSpace, StringComparer nameComparer) + { + foreach (string ns in namespaces) { + if (nameComparer.Equals(ns, nameSpace)) + return ns; + } + return null; + } + + public IList AssemblyAttributes { + get { return assemblyAttributes; } + } + + ICSharpCode.NRefactory.Utils.CacheManager ITypeResolveContext.CacheManager { + get { + // We don't support caching + return null; + } + } + + ISynchronizedTypeResolveContext ITypeResolveContext.Synchronize() + { + // This class is immutable + return this; + } + + void IDisposable.Dispose() + { + // exit from Synchronize() block + } + + IParsedFile IProjectContent.GetFile(string fileName) + { + return null; + } + + IEnumerable IProjectContent.Files { + get { + return EmptyList.Instance; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs new file mode 100644 index 0000000000..2d0a5a7962 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs @@ -0,0 +1,137 @@ +// +// DomLocation.cs +// +// Author: +// Mike Krüger +// +// Copyright (C) 2008 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + [Serializable] + public struct AstLocation : IComparable, IEquatable + { + public static readonly AstLocation Empty = new AstLocation(0, 0); + + readonly int line, column; + + public AstLocation (int line, int column) + { + this.line = line; + this.column = column; + } + + public bool IsEmpty { + get { + return line <= 0; + } + } + + public int Line { + get { return line; } + } + + public int Column { + get { return column; } + } + + public override bool Equals (object obj) + { + if (!(obj is AstLocation)) + return false; + return (AstLocation)obj == this; + } + + public override int GetHashCode () + { + unchecked { + return line + column * 5000; + } + } + + public bool Equals (AstLocation other) + { + return other == this; + } + + public int CompareTo (AstLocation other) + { + if (this == other) + return 0; + if (this < other) + return -1; + return 1; + } + + public override string ToString () + { + return String.Format ("(Line {0}, Column {1})", Line, Column); + } + + public static AstLocation FromInvariantString (string invariantString) + { + if (string.Equals(invariantString, "EMPTY", StringComparison.OrdinalIgnoreCase)) + return AstLocation.Empty; + string[] splits = invariantString.Split (',', '/'); + if (splits.Length == 2) + return new AstLocation (Int32.Parse (splits[0]), Int32.Parse (splits[1])); + return AstLocation.Empty; + } + + public string ToInvariantString () + { + if (IsEmpty) + return "Empty"; + return String.Format ("{0}/{1}", line, column); + } + + public static bool operator==(AstLocation left, AstLocation right) + { + return left.line == right.line && left.column == right.column; + } + + public static bool operator!=(AstLocation left, AstLocation right) + { + return left.line != right.line || left.column != right.column; + } + + public static bool operator<(AstLocation left, AstLocation right) + { + return left.line < right.line || left.line == right.line && left.column < right.column; + } + public static bool operator>(AstLocation left, AstLocation right) + { + return left.line > right.line || left.line == right.line && left.column > right.column; + } + public static bool operator<=(AstLocation left, AstLocation right) + { + return !(left > right); + } + public static bool operator>=(AstLocation left, AstLocation right) + { + return !(left < right); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs new file mode 100644 index 0000000000..9e27348b33 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs @@ -0,0 +1,712 @@ +// +// AstNode.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; + +namespace ICSharpCode.NRefactory.CSharp +{ + public abstract class AstNode : AbstractAnnotatable, PatternMatching.INode + { + #region Null + public static readonly AstNode Null = new NullAstNode (); + + sealed class NullAstNode : AstNode + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator AstNode (PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder (pattern) : null; + } + + sealed class PatternPlaceholder : AstNode, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder (PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder (this, child, data); + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + return child.DoMatch (other, match); + } + + bool PatternMatching.INode.DoMatchCollection (Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection (role, pos, match, backtrackingInfo); + } + } + #endregion + + AstNode parent; + AstNode prevSibling; + AstNode nextSibling; + AstNode firstChild; + AstNode lastChild; + Role role = RootRole; + + public abstract NodeType NodeType { + get; + } + + public virtual bool IsNull { + get { + return false; + } + } + + public virtual AstLocation StartLocation { + get { + var child = firstChild; + if (child == null) + return AstLocation.Empty; + return child.StartLocation; + } + } + + public virtual AstLocation EndLocation { + get { + var child = lastChild; + if (child == null) + return AstLocation.Empty; + return child.EndLocation; + } + } + + public AstNode Parent { + get { return parent; } + } + + public Role Role { + get { return role; } + } + + public AstNode NextSibling { + get { return nextSibling; } + } + + public AstNode PrevSibling { + get { return prevSibling; } + } + + public AstNode FirstChild { + get { return firstChild; } + } + + public AstNode LastChild { + get { return lastChild; } + } + + public IEnumerable Children { + get { + AstNode next; + for (AstNode cur = firstChild; cur != null; cur = next) { + Debug.Assert (cur.parent == this); + // Remember next before yielding cur. + // This allows removing/replacing nodes while iterating through the list. + next = cur.nextSibling; + yield return cur; + } + } + } + + /// + /// Gets the ancestors of this node (excluding this node itself) + /// + public IEnumerable Ancestors { + get { + for (AstNode cur = parent; cur != null; cur = cur.parent) { + yield return cur; + } + } + } + + /// + /// Gets all descendants of this node (excluding this node itself). + /// + public IEnumerable Descendants { + get { + return Utils.TreeTraversal.PreOrder (this.Children, n => n.Children); + } + } + + /// + /// Gets all descendants of this node (including this node itself). + /// + public IEnumerable DescendantsAndSelf { + get { + return Utils.TreeTraversal.PreOrder (this, n => n.Children); + } + } + + /// + /// Gets the first child with the specified role. + /// Returns the role's null object if the child is not found. + /// + public T GetChildByRole (Role role) where T : AstNode + { + if (role == null) + throw new ArgumentNullException ("role"); + for (var cur = firstChild; cur != null; cur = cur.nextSibling) { + if (cur.role == role) + return (T)cur; + } + return role.NullObject; + } + + public AstNodeCollection GetChildrenByRole (Role role) where T : AstNode + { + return new AstNodeCollection (this, role); + } + + protected void SetChildByRole (Role role, T newChild) where T : AstNode + { + AstNode oldChild = GetChildByRole (role); + if (oldChild.IsNull) + AddChild (newChild, role); + else + oldChild.ReplaceWith (newChild); + } + + public void AddChild (T child, Role role) where T : AstNode + { + if (role == null) + throw new ArgumentNullException ("role"); + if (child == null || child.IsNull) + return; + if (this.IsNull) + throw new InvalidOperationException ("Cannot add children to null nodes"); + if (child.parent != null) + throw new ArgumentException ("Node is already used in another tree.", "child"); + AddChildUnsafe (child, role); + } + + /// + /// Adds a child without performing any safety checks. + /// + void AddChildUnsafe (AstNode child, Role role) + { + child.parent = this; + child.role = role; + if (firstChild == null) { + lastChild = firstChild = child; + } else { + lastChild.nextSibling = child; + child.prevSibling = lastChild; + lastChild = child; + } + } + + public void InsertChildBefore (AstNode nextSibling, T child, Role role) where T : AstNode + { + if (role == null) + throw new ArgumentNullException ("role"); + if (nextSibling == null || nextSibling.IsNull) { + AddChild (child, role); + return; + } + + if (child == null || child.IsNull) + return; + if (child.parent != null) + throw new ArgumentException ("Node is already used in another tree.", "child"); + if (nextSibling.parent != this) + throw new ArgumentException ("NextSibling is not a child of this node.", "nextSibling"); + // No need to test for "Cannot add children to null nodes", + // as there isn't any valid nextSibling in null nodes. + InsertChildBeforeUnsafe (nextSibling, child, role); + } + + void InsertChildBeforeUnsafe (AstNode nextSibling, AstNode child, Role role) + { + child.parent = this; + child.role = role; + child.nextSibling = nextSibling; + child.prevSibling = nextSibling.prevSibling; + + if (nextSibling.prevSibling != null) { + Debug.Assert (nextSibling.prevSibling.nextSibling == nextSibling); + nextSibling.prevSibling.nextSibling = child; + } else { + Debug.Assert (firstChild == nextSibling); + firstChild = child; + } + nextSibling.prevSibling = child; + } + + public void InsertChildAfter (AstNode prevSibling, T child, Role role) where T : AstNode + { + InsertChildBefore ((prevSibling == null || prevSibling.IsNull) ? firstChild : prevSibling.nextSibling, child, role); + } + + /// + /// Removes this node from its parent. + /// + public void Remove () + { + if (parent != null) { + if (prevSibling != null) { + Debug.Assert (prevSibling.nextSibling == this); + prevSibling.nextSibling = nextSibling; + } else { + Debug.Assert (parent.firstChild == this); + parent.firstChild = nextSibling; + } + if (nextSibling != null) { + Debug.Assert (nextSibling.prevSibling == this); + nextSibling.prevSibling = prevSibling; + } else { + Debug.Assert (parent.lastChild == this); + parent.lastChild = prevSibling; + } + parent = null; + role = Roles.Root; + prevSibling = null; + nextSibling = null; + } + } + + /// + /// Replaces this node with the new node. + /// + public void ReplaceWith (AstNode newNode) + { + if (newNode == null || newNode.IsNull) { + Remove (); + return; + } + if (newNode == this) + return; // nothing to do... + if (parent == null) { + throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); + } + // Because this method doesn't statically check the new node's type with the role, + // we perform a runtime test: + if (!role.IsValid (newNode)) { + throw new ArgumentException (string.Format ("The new node '{0}' is not valid in the role {1}", newNode.GetType ().Name, role.ToString ()), "newNode"); + } + if (newNode.parent != null) { + // newNode is used within this tree? + if (newNode.Ancestors.Contains (this)) { + // e.g. "parenthesizedExpr.ReplaceWith(parenthesizedExpr.Expression);" + // enable automatic removal + newNode.Remove (); + } else { + throw new ArgumentException ("Node is already used in another tree.", "newNode"); + } + } + + newNode.parent = parent; + newNode.role = role; + newNode.prevSibling = prevSibling; + newNode.nextSibling = nextSibling; + if (parent != null) { + if (prevSibling != null) { + Debug.Assert (prevSibling.nextSibling == this); + prevSibling.nextSibling = newNode; + } else { + Debug.Assert (parent.firstChild == this); + parent.firstChild = newNode; + } + if (nextSibling != null) { + Debug.Assert (nextSibling.prevSibling == this); + nextSibling.prevSibling = newNode; + } else { + Debug.Assert (parent.lastChild == this); + parent.lastChild = newNode; + } + parent = null; + prevSibling = null; + nextSibling = null; + role = Roles.Root; + } + } + + public AstNode ReplaceWith (Func replaceFunction) + { + if (replaceFunction == null) + throw new ArgumentNullException ("replaceFunction"); + if (parent == null) { + throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node"); + } + AstNode oldParent = parent; + AstNode oldSuccessor = nextSibling; + Role oldRole = role; + Remove (); + AstNode replacement = replaceFunction (this); + if (oldSuccessor != null && oldSuccessor.parent != oldParent) + throw new InvalidOperationException ("replace function changed nextSibling of node being replaced?"); + if (!(replacement == null || replacement.IsNull)) { + if (replacement.parent != null) + throw new InvalidOperationException ("replace function must return the root of a tree"); + if (!oldRole.IsValid (replacement)) { + throw new InvalidOperationException (string.Format ("The new node '{0}' is not valid in the role {1}", replacement.GetType ().Name, oldRole.ToString ())); + } + + if (oldSuccessor != null) + oldParent.InsertChildBeforeUnsafe (oldSuccessor, replacement, oldRole); + else + oldParent.AddChildUnsafe (replacement, oldRole); + } + return replacement; + } + + /// + /// Clones the whole subtree starting at this AST node. + /// + /// Annotations are copied over to the new nodes; and any annotations implementing ICloneable will be cloned. + public AstNode Clone () + { + AstNode copy = (AstNode)MemberwiseClone (); + // First, reset the shallow pointer copies + copy.parent = null; + copy.role = Roles.Root; + copy.firstChild = null; + copy.lastChild = null; + copy.prevSibling = null; + copy.nextSibling = null; + + // Then perform a deep copy: + for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) { + copy.AddChildUnsafe (cur.Clone (), cur.role); + } + + // Finally, clone the annotation, if necessary + ICloneable copiedAnnotations = copy.annotations as ICloneable; // read from copy (for thread-safety) + if (copiedAnnotations != null) + copy.annotations = copiedAnnotations.Clone(); + + return copy; + } + + public abstract S AcceptVisitor (IAstVisitor visitor, T data); + + #region Pattern Matching + protected static bool MatchString (string name1, string name2) + { + return string.IsNullOrEmpty (name1) || name1 == name2; + } + + protected internal abstract bool DoMatch (AstNode other, PatternMatching.Match match); + + bool PatternMatching.INode.DoMatch (PatternMatching.INode other, PatternMatching.Match match) + { + AstNode o = other as AstNode; + // try matching if other is null, or if other is an AstNode + return (other == null || o != null) && DoMatch (o, match); + } + + bool PatternMatching.INode.DoMatchCollection (Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + AstNode o = pos as AstNode; + return (pos == null || o != null) && DoMatch (o, match); + } + + PatternMatching.INode PatternMatching.INode.NextSibling { + get { return nextSibling; } + } + + PatternMatching.INode PatternMatching.INode.FirstChild { + get { return firstChild; } + } + + #endregion + + public AstNode GetNextNode () + { + if (NextSibling != null) + return NextSibling; + if (Parent != null) + return Parent.GetNextNode (); + return null; + } + + public AstNode GetPrevNode () + { + if (PrevSibling != null) + return PrevSibling; + if (Parent != null) + return Parent.GetPrevNode (); + return null; + } + + // filters all non c# nodes (comments, white spaces or pre processor directives) + public AstNode GetCSharpNodeBefore (AstNode node) + { + var n = node.PrevSibling; + while (n != null) { + if (n.Role != Roles.Comment) + return n; + n = n.GetPrevNode (); + } + return null; + } + + public AstNode GetNodeAt (int line, int column, Predicate pred = null) + { + return GetNodeAt (new AstLocation (line, column), pred); + } + + public AstNode GetNodeAt (AstLocation location, Predicate pred = null) + { + AstNode result = null; + AstNode node = this; + while (node.FirstChild != null) { + var child = node.FirstChild; + while (child != null) { + if (child.StartLocation <= location && location < child.EndLocation) { + if (pred == null || pred (child)) + result = child; + node = child; + break; + } + child = child.NextSibling; + } + // found no better child node - therefore the parent is the right one. + if (child == null) + break; + } + return result; + } + + public T GetNodeAt (int line, int column) where T : AstNode + { + return GetNodeAt (new AstLocation (line, column)); + } + + /// + /// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching + /// the current method declaration. + /// + public T GetNodeAt (AstLocation location) where T : AstNode + { + T result = null; + AstNode node = this; + while (node.FirstChild != null) { + var child = node.FirstChild; + while (child != null) { + if (child.StartLocation <= location && location < child.EndLocation) { + if (child is T) + result = (T)child; + node = child; + break; + } + child = child.NextSibling; + } + // found no better child node - therefore the parent is the right one. + if (child == null) + break; + } + return result; + } + + public AstNode GetResolveableNodeAt (int line, int column) + { + return GetResolveableNodeAt (new AstLocation (line, column)); + } + + /// + /// Gets a node that can be resolved at location. + /// + public AstNode GetResolveableNodeAt (AstLocation location) + { + return GetNodeAt (location, delegate (AstNode n) { + + if (n is TypeDeclaration) { + var decl = (TypeDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is DelegateDeclaration) { + var decl = (DelegateDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is MemberDeclaration) { + var decl = (MemberDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is ConstructorDeclaration) { + var decl = (ConstructorDeclaration)n; + return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation; + } + + if (n is DestructorDeclaration) { + var decl = (DestructorDeclaration)n; + return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation; + } + + if (n is VariableInitializer) { + var decl = (VariableInitializer)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is ParameterDeclaration) { + var decl = (ParameterDeclaration)n; + return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; + } + + if (n is MemberReferenceExpression) { + var decl = (MemberReferenceExpression)n; + return decl.MemberNameToken.StartLocation <= location && location <= decl.MemberNameToken.EndLocation; + } + + return n is IdentifierExpression || n is AstType; + }); + } + + public IEnumerable GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn) + { + return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn)); + } + + public IEnumerable GetNodesBetween (AstLocation start, AstLocation end) + { + AstNode node = this; + while (node != null) { + AstNode next; + if (start <= node.StartLocation && node.EndLocation <= end) { + // Remember next before yielding node. + // This allows iteration to continue when the caller removes/replaces the node. + next = node.NextSibling; + yield return node; + } else { + if (node.EndLocation <= start) { + next = node.NextSibling; + } else { + next = node.FirstChild; + } + } + + if (next != null && next.StartLocation > end) + yield break; + node = next; + } + } + + public bool Contains (int line, int column) + { + return Contains (new AstLocation (line, column)); + } + + public bool Contains (AstLocation location) + { + return this.StartLocation <= location && location < this.EndLocation; + } + + public override void AddAnnotation (object annotation) + { + if (this.IsNull) + throw new InvalidOperationException ("Cannot add annotations to the null node"); + base.AddAnnotation (annotation); + } + + // the Root role must be available when creating the null nodes, so we can't put it in the Roles class + static readonly Role RootRole = new Role ("Root"); + + public static class Roles + { + /// + /// Root of an abstract syntax tree. + /// + public static readonly Role Root = RootRole; + + // some pre defined constants for common roles + public static readonly Role Identifier = new Role ("Identifier", CSharp.Identifier.Null); + public static readonly Role Body = new Role ("Body", CSharp.BlockStatement.Null); + public static readonly Role Parameter = new Role ("Parameter"); + public static readonly Role Argument = new Role ("Argument", CSharp.Expression.Null); + public static readonly Role Type = new Role ("Type", CSharp.AstType.Null); + public static readonly Role Expression = new Role ("Expression", CSharp.Expression.Null); + public static readonly Role TargetExpression = new Role ("Target", CSharp.Expression.Null); + public readonly static Role Condition = new Role ("Condition", CSharp.Expression.Null); + public static readonly Role TypeParameter = new Role ("TypeParameter"); + public static readonly Role TypeArgument = new Role ("TypeArgument", CSharp.AstType.Null); + public readonly static Role Constraint = new Role ("Constraint"); + public static readonly Role Variable = new Role ("Variable"); + public static readonly Role EmbeddedStatement = new Role ("EmbeddedStatement", CSharp.Statement.Null); + public static readonly Role Keyword = new Role ("Keyword", CSharpTokenNode.Null); + public static readonly Role InKeyword = new Role ("InKeyword", CSharpTokenNode.Null); + + // some pre defined constants for most used punctuation + public static readonly Role LPar = new Role ("LPar", CSharpTokenNode.Null); + public static readonly Role RPar = new Role ("RPar", CSharpTokenNode.Null); + public static readonly Role LBracket = new Role ("LBracket", CSharpTokenNode.Null); + public static readonly Role RBracket = new Role ("RBracket", CSharpTokenNode.Null); + public static readonly Role LBrace = new Role ("LBrace", CSharpTokenNode.Null); + public static readonly Role RBrace = new Role ("RBrace", CSharpTokenNode.Null); + public static readonly Role LChevron = new Role ("LChevron", CSharpTokenNode.Null); + public static readonly Role RChevron = new Role ("RChevron", CSharpTokenNode.Null); + public static readonly Role Comma = new Role ("Comma", CSharpTokenNode.Null); + public static readonly Role Dot = new Role ("Dot", CSharpTokenNode.Null); + public static readonly Role Semicolon = new Role ("Semicolon", CSharpTokenNode.Null); + public static readonly Role Assign = new Role ("Assign", CSharpTokenNode.Null); + public static readonly Role Colon = new Role ("Colon", CSharpTokenNode.Null); + public static readonly Role Comment = new Role ("Comment"); + public static readonly Role Error = new Role ("Error"); + + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs new file mode 100644 index 0000000000..adc6e5e41e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs @@ -0,0 +1,175 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents the children of an AstNode that have a specific role. + /// + public class AstNodeCollection : ICollection where T : AstNode + { + readonly AstNode node; + readonly Role role; + + public AstNodeCollection(AstNode node, Role role) + { + if (node == null) + throw new ArgumentNullException("node"); + if (role == null) + throw new ArgumentNullException("role"); + this.node = node; + this.role = role; + } + + public int Count { + get { + int count = 0; + for (AstNode cur = node.FirstChild; cur != null; cur = cur.NextSibling) { + if (cur.Role == role) + count++; + } + return count; + } + } + + public void Add(T element) + { + node.AddChild(element, role); + } + + public void AddRange(IEnumerable nodes) + { + // Evaluate 'nodes' first, since it might change when we add the new children + // Example: collection.AddRange(collection); + if (nodes != null) { + foreach (T node in nodes.ToList()) + Add(node); + } + } + + public void AddRange(T[] nodes) + { + // Fast overload for arrays - we don't need to create a copy + if (nodes != null) { + foreach (T node in nodes) + Add(node); + } + } + + public void ReplaceWith(IEnumerable nodes) + { + // Evaluate 'nodes' first, since it might change when we call Clear() + // Example: collection.ReplaceWith(collection); + if (nodes != null) + nodes = nodes.ToList(); + Clear(); + foreach (T node in nodes) + Add(node); + } + + public void MoveTo(ICollection targetCollection) + { + foreach (T node in this) { + node.Remove(); + targetCollection.Add(node); + } + } + + public bool Contains(T element) + { + return element != null && element.Parent == node && element.Role == role; + } + + public bool Remove(T element) + { + if (Contains(element)) { + element.Remove(); + return true; + } else { + return false; + } + } + + public void CopyTo(T[] array, int arrayIndex) + { + foreach (T item in this) + array[arrayIndex++] = item; + } + + public void Clear() + { + foreach (T item in this) + item.Remove(); + } + + bool ICollection.IsReadOnly { + get { return false; } + } + + public IEnumerator GetEnumerator() + { + AstNode next; + for (AstNode cur = node.FirstChild; cur != null; cur = next) { + Debug.Assert(cur.Parent == node); + // Remember next before yielding cur. + // This allows removing/replacing nodes while iterating through the list. + next = cur.NextSibling; + if (cur.Role == role) + yield return (T)cur; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #region Equals and GetHashCode implementation + public override bool Equals(object obj) + { + if (obj is AstNodeCollection) { + return ((AstNodeCollection)obj) == this; + } else { + return false; + } + } + + public override int GetHashCode() + { + return node.GetHashCode() ^ role.GetHashCode(); + } + + public static bool operator ==(AstNodeCollection left, AstNodeCollection right) + { + return left.role == right.role && left.node == right.node; + } + + public static bool operator !=(AstNodeCollection left, AstNodeCollection right) + { + return !(left.role == right.role && left.node == right.node); + } + #endregion + + internal bool DoMatch(AstNodeCollection other, Match match) + { + return Pattern.DoMatchCollection(role, node.FirstChild, other.node.FirstChild, match); + } + + public void InsertAfter(T existingItem, T newItem) + { + node.InsertChildAfter(existingItem, newItem, role); + } + + public void InsertBefore(T existingItem, T newItem) + { + node.InsertChildBefore(existingItem, newItem, role); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs new file mode 100644 index 0000000000..4c6c0f0b00 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs @@ -0,0 +1,175 @@ +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// A type reference in the C# AST. + /// + public abstract class AstType : AstNode + { + #region Null + public new static readonly AstType Null = new NullAstType (); + + sealed class NullAstType : AstType + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator AstType(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : AstType, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public override NodeType NodeType { + get { return NodeType.TypeReference; } + } + + public new AstType Clone() + { + return (AstType)base.Clone(); + } + + /// + /// Creates a pointer type from this type by nesting it in a . + /// If this type already is a pointer type, this method just increases the PointerRank of the existing pointer type. + /// + public virtual AstType MakePointerType() + { + return new ComposedType { BaseType = this }.MakePointerType(); + } + + /// + /// Creates an array type from this type by nesting it in a . + /// If this type already is an array type, the additional rank is prepended to the existing array specifier list. + /// Thus, new SimpleType("T").MakeArrayType(1).MakeArrayType(2) will result in "T[,][]". + /// + public virtual AstType MakeArrayType(int rank = 1) + { + return new ComposedType { BaseType = this }.MakeArrayType(rank); + } + + /// + /// Creates a nullable type from this type by nesting it in a . + /// + public AstType MakeNullableType() + { + return new ComposedType { BaseType = this, HasNullableSpecifier = true }; + } + + /// + /// Builds an expression that can be used to access a static member on this type. + /// + public MemberReferenceExpression Member(string memberName) + { + return new TypeReferenceExpression { Type = this }.Member(memberName); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, params Expression[] arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, typeArguments, arguments); + } + + public static AstType Create(Type type) + { + switch (Type.GetTypeCode(type)) { + case TypeCode.Object: + return new PrimitiveType("object"); + case TypeCode.Boolean: + return new PrimitiveType("bool"); + case TypeCode.Char: + return new PrimitiveType("char"); + case TypeCode.SByte: + return new PrimitiveType("sbyte"); + case TypeCode.Byte: + return new PrimitiveType("byte"); + case TypeCode.Int16: + return new PrimitiveType("short"); + case TypeCode.UInt16: + return new PrimitiveType("ushort"); + case TypeCode.Int32: + return new PrimitiveType("int"); + case TypeCode.UInt32: + return new PrimitiveType("uint"); + case TypeCode.Int64: + return new PrimitiveType("long"); + case TypeCode.UInt64: + return new PrimitiveType("ulong"); + case TypeCode.Single: + return new PrimitiveType("float"); + case TypeCode.Double: + return new PrimitiveType("double"); + case TypeCode.Decimal: + return new PrimitiveType("decimal"); + case TypeCode.String: + return new PrimitiveType("string"); + } + return new SimpleType(type.FullName); // TODO: implement this correctly + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs new file mode 100644 index 0000000000..3fc7fa2912 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs @@ -0,0 +1,132 @@ +// +// CSharpModifierToken.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + + public class CSharpModifierToken : CSharpTokenNode + { + Modifiers modifier; + + public Modifiers Modifier { + get { return modifier; } + set { + for (int i = 0; i < lengthTable.Count; i++) { + if (lengthTable[i].Key == value) { + this.modifier = value; + this.tokenLength = lengthTable[i].Value; + return; + } + } + throw new ArgumentException ("Modifier " + value + " is invalid."); + } + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CSharpModifierToken o = other as CSharpModifierToken; + return o != null && this.modifier == o.modifier; + } + + // Not worth using a dictionary for such few elements. + // This table is sorted in the order that modifiers should be output when generating code. + static readonly List> lengthTable = new List> () { + new KeyValuePair(Modifiers.Public, "public".Length), + new KeyValuePair(Modifiers.Protected, "protected".Length), + new KeyValuePair(Modifiers.Private, "private".Length), + new KeyValuePair(Modifiers.Internal, "internal".Length), + new KeyValuePair(Modifiers.New, "new".Length), + new KeyValuePair(Modifiers.Unsafe, "unsafe".Length), + new KeyValuePair(Modifiers.Abstract, "abstract".Length), + new KeyValuePair(Modifiers.Virtual, "virtual".Length), + new KeyValuePair(Modifiers.Sealed, "sealed".Length), + new KeyValuePair(Modifiers.Static, "static".Length), + new KeyValuePair(Modifiers.Override, "override".Length), + new KeyValuePair(Modifiers.Readonly, "readonly".Length), + new KeyValuePair(Modifiers.Volatile, "volatile".Length), + new KeyValuePair(Modifiers.Extern, "extern".Length), + new KeyValuePair(Modifiers.Partial, "partial".Length), + new KeyValuePair(Modifiers.Const, "const".Length), + + // even though it's used for patterns only, it needs to be in this table to be usable in the AST + new KeyValuePair(Modifiers.Any, "any".Length) + }; + + public static IEnumerable AllModifiers { + get { return lengthTable.Select(p => p.Key); } + } + + public CSharpModifierToken (AstLocation location, Modifiers modifier) : base (location, 0) + { + this.Modifier = modifier; + } + + public static string GetModifierName(Modifiers modifier) + { + switch (modifier) { + case Modifiers.Private: + return "private"; + case Modifiers.Internal: + return "internal"; + case Modifiers.Protected: + return "protected"; + case Modifiers.Public: + return "public"; + case Modifiers.Abstract: + return "abstract"; + case Modifiers.Virtual: + return "virtual"; + case Modifiers.Sealed: + return "sealed"; + case Modifiers.Static: + return "static"; + case Modifiers.Override: + return "override"; + case Modifiers.Readonly: + return "readonly"; + case Modifiers.Const: + return "const"; + case Modifiers.New: + return "new"; + case Modifiers.Partial: + return "partial"; + case Modifiers.Extern: + return "extern"; + case Modifiers.Volatile: + return "volatile"; + case Modifiers.Unsafe: + return "unsafe"; + case Modifiers.Fixed: + return "fixed"; + default: + throw new NotSupportedException("Invalid value for Modifiers"); + } + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs new file mode 100644 index 0000000000..b125413d0f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs @@ -0,0 +1,107 @@ +// +// TokenNode.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class CSharpTokenNode : AstNode, IRelocatable + { + public static new readonly CSharpTokenNode Null = new NullCSharpTokenNode (); + class NullCSharpTokenNode : CSharpTokenNode + { + public override bool IsNull { + get { + return true; + } + } + + public NullCSharpTokenNode () : base (AstLocation.Empty, 0) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + + public override NodeType NodeType { + get { + return NodeType.Token; + } + } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + } + + protected int tokenLength; + public override AstLocation EndLocation { + get { + return new AstLocation (StartLocation.Line, StartLocation.Column + tokenLength); + } + } + + public CSharpTokenNode (AstLocation location, int tokenLength) + { + this.startLocation = location; + this.tokenLength = tokenLength; + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.startLocation = startLocation; + } + #endregion + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCSharpTokenNode (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CSharpTokenNode o = other as CSharpTokenNode; + return o != null && !o.IsNull && !(o is CSharpModifierToken); + } + + public override string ToString () + { + return string.Format ("[CSharpTokenNode: StartLocation={0}, EndLocation={1}, Role={2}]", StartLocation, EndLocation, Role); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs new file mode 100644 index 0000000000..46f528d46b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs @@ -0,0 +1,95 @@ +// +// CSharpUtil.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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.CSharp; + +namespace ICSharpCode.NRefactory.CSharp +{ + public static class CSharpUtil + { + public static Expression InvertCondition (Expression condition) + { + return InvertConditionInternal (condition.Clone ()); + } + + static Expression InvertConditionInternal (Expression condition) + { + if (condition is ParenthesizedExpression) { + ((ParenthesizedExpression)condition).Expression = InvertCondition (((ParenthesizedExpression)condition).Expression); + return condition; + } + + if (condition is UnaryOperatorExpression) { + var uOp = (UnaryOperatorExpression)condition; + if (uOp.Operator == UnaryOperatorType.Not) + return uOp.Expression; + return new UnaryOperatorExpression (UnaryOperatorType.Not, uOp); + } + + if (condition is BinaryOperatorExpression) { + var bOp = (BinaryOperatorExpression)condition; + switch (bOp.Operator) { + case BinaryOperatorType.GreaterThan: + bOp.Operator = BinaryOperatorType.LessThanOrEqual; + return bOp; + case BinaryOperatorType.GreaterThanOrEqual: + bOp.Operator = BinaryOperatorType.LessThan; + return bOp; + case BinaryOperatorType.Equality: + bOp.Operator = BinaryOperatorType.InEquality; + return bOp; + case BinaryOperatorType.InEquality: + bOp.Operator = BinaryOperatorType.Equality; + return bOp; + case BinaryOperatorType.LessThan: + bOp.Operator = BinaryOperatorType.GreaterThanOrEqual; + return bOp; + case BinaryOperatorType.LessThanOrEqual: + bOp.Operator = BinaryOperatorType.GreaterThan; + return bOp; + default: + return new UnaryOperatorExpression (UnaryOperatorType.Not, new ParenthesizedExpression (condition)); + } + } + + if (condition is ConditionalExpression) { + var cEx = condition as ConditionalExpression; + cEx.Condition = InvertCondition (cEx.Condition); + return cEx; + } + if (condition is PrimitiveExpression) { + var pex = condition as PrimitiveExpression; + if (pex.Value is bool) { + pex.Value = !((bool)pex.Value); + return pex; + } + } + + return new UnaryOperatorExpression (UnaryOperatorType.Not, condition); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs new file mode 100644 index 0000000000..889e8d048b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs @@ -0,0 +1,92 @@ +// +// CompilationUnit.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class CompilationUnit : AstNode + { + public static readonly Role MemberRole = new Role("Member", AstNode.Null); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + List errors = new List (); + + public List Errors { + get { return errors; } + } + + /// + /// 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 ., <, ('. + /// + public AstNode TopExpression { + get; + internal set; + } + + public CompilationUnit () + { + } + + public IEnumerable GetTypes (bool includeInnerTypes = false) + { + Stack nodeStack = new Stack (); + nodeStack.Push (this); + while (nodeStack.Count > 0) { + var curNode = nodeStack.Pop (); + if (curNode is TypeDeclaration) + 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))) + nodeStack.Push (child); + } + } + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CompilationUnit o = other as CompilationUnit; + return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCompilationUnit (this, data); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs new file mode 100644 index 0000000000..813f472137 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs @@ -0,0 +1,179 @@ +// +// ComposedType.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class ComposedType : AstType + { + public static readonly Role NullableRole = new Role("Nullable", CSharpTokenNode.Null); + public static readonly Role PointerRole = new Role("Pointer", CSharpTokenNode.Null); + public static readonly Role ArraySpecifierRole = new Role("ArraySpecifier"); + + public AstType BaseType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public bool HasNullableSpecifier { + get { + return !GetChildByRole(NullableRole).IsNull; + } + set { + SetChildByRole(NullableRole, value ? new CSharpTokenNode(AstLocation.Empty, 1) : null); + } + } + + public int PointerRank { + get { + return GetChildrenByRole(PointerRole).Count; + } + set { + if (value < 0) + throw new ArgumentOutOfRangeException(); + int d = this.PointerRank; + while (d > value) { + GetChildByRole(PointerRole).Remove(); + d--; + } + while (d < value) { + InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(AstLocation.Empty, 1), PointerRole); + d++; + } + } + } + + public AstNodeCollection ArraySpecifiers { + get { return GetChildrenByRole (ArraySpecifierRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitComposedType (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ComposedType o = other as ComposedType; + return o != null && this.HasNullableSpecifier == o.HasNullableSpecifier && this.PointerRank == o.PointerRank && this.ArraySpecifiers.DoMatch(o.ArraySpecifiers, match); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append(this.BaseType.ToString()); + if (this.HasNullableSpecifier) + b.Append('?'); + b.Append('*', this.PointerRank); + foreach (var arraySpecifier in this.ArraySpecifiers) { + b.Append('['); + b.Append(',', arraySpecifier.Dimensions - 1); + b.Append(']'); + } + return b.ToString(); + } + + public override AstType MakePointerType() + { + if (ArraySpecifiers.Any()) { + return base.MakePointerType(); + } else { + this.PointerRank++; + return this; + } + } + + public override AstType MakeArrayType(int dimensions) + { + InsertChildBefore(this.ArraySpecifiers.FirstOrDefault(), new ArraySpecifier(dimensions), ArraySpecifierRole); + return this; + } + } + + /// + /// [,,,] + /// + public class ArraySpecifier : AstNode + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public ArraySpecifier() + { + } + + public ArraySpecifier(int dimensions) + { + this.Dimensions = dimensions; + } + + public CSharpTokenNode LBracketToken { + get { return GetChildByRole (Roles.LBracket); } + } + + public int Dimensions { + get { return 1 + GetChildrenByRole(Roles.Comma).Count; } + set { + int d = this.Dimensions; + while (d > value) { + GetChildByRole(Roles.Comma).Remove(); + d--; + } + while (d < value) { + InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(AstLocation.Empty, 1), Roles.Comma); + d++; + } + } + } + + public CSharpTokenNode RBracketToken { + get { return GetChildByRole (Roles.RBracket); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArraySpecifier(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArraySpecifier o = other as ArraySpecifier; + return o != null && this.Dimensions == o.Dimensions; + } + + public override string ToString() + { + return "[" + new string(',', this.Dimensions - 1) + "]"; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs new file mode 100644 index 0000000000..ecc5210a1b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs @@ -0,0 +1,598 @@ +// +// IAstVisitor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// AST visitor with a default implementation that visits all node depth-first. + /// + public abstract class DepthFirstAstVisitor : IAstVisitor + { + protected virtual S VisitChildren (AstNode node, T data) + { + AstNode next; + for (var child = node.FirstChild; child != null; child = next) { + // Store next to allow the loop to continue + // if the visitor removes/replaces child. + next = child.NextSibling; + child.AcceptVisitor (this, data); + } + return default (S); + } + + public virtual S VisitCompilationUnit (CompilationUnit unit, T data) + { + return VisitChildren (unit, data); + } + + public virtual S VisitComment (Comment comment, T data) + { + return VisitChildren (comment, data); + } + + public virtual S VisitIdentifier (Identifier identifier, T data) + { + return VisitChildren (identifier, data); + } + + public virtual S VisitCSharpTokenNode (CSharpTokenNode token, T data) + { + return VisitChildren (token, data); + } + + public virtual S VisitPrimitiveType (PrimitiveType primitiveType, T data) + { + return VisitChildren (primitiveType, data); + } + + public virtual S VisitComposedType (ComposedType composedType, T data) + { + return VisitChildren (composedType, data); + } + + public virtual S VisitSimpleType(SimpleType simpleType, T data) + { + return VisitChildren (simpleType, data); + } + + public virtual S VisitMemberType(MemberType memberType, T data) + { + return VisitChildren (memberType, data); + } + + public virtual S VisitAttribute (Attribute attribute, T data) + { + return VisitChildren (attribute, data); + } + + public virtual S VisitAttributeSection (AttributeSection attributeSection, T data) + { + return VisitChildren (attributeSection, data); + } + + public virtual S VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, T data) + { + return VisitChildren (delegateDeclaration, data); + } + + public virtual S VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, T data) + { + return VisitChildren (namespaceDeclaration, data); + } + + public virtual S VisitTypeDeclaration (TypeDeclaration typeDeclaration, T data) + { + return VisitChildren (typeDeclaration, data); + } + + public virtual S VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, T data) + { + return VisitChildren (typeParameterDeclaration, data); + } + + public virtual S VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, T data) + { + return VisitChildren (enumMemberDeclaration, data); + } + + public virtual S VisitUsingDeclaration (UsingDeclaration usingDeclaration, T data) + { + return VisitChildren (usingDeclaration, data); + } + + public virtual S VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, T data) + { + return VisitChildren (usingDeclaration, data); + } + + public virtual S VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, T data) + { + return VisitChildren (externAliasDeclaration, data); + } + + public virtual S VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, T data) + { + return VisitChildren (constructorDeclaration, data); + } + + public virtual S VisitConstructorInitializer (ConstructorInitializer constructorInitializer, T data) + { + return VisitChildren (constructorInitializer, data); + } + + public virtual S VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, T data) + { + return VisitChildren (destructorDeclaration, data); + } + + public virtual S VisitEventDeclaration (EventDeclaration eventDeclaration, T data) + { + return VisitChildren (eventDeclaration, data); + } + + public virtual S VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, T data) + { + return VisitChildren (eventDeclaration, data); + } + + public virtual S VisitFieldDeclaration (FieldDeclaration fieldDeclaration, T data) + { + return VisitChildren (fieldDeclaration, data); + } + + public virtual S VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, T data) + { + return VisitChildren (fixedFieldDeclaration, data); + } + + public virtual S VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, T data) + { + return VisitChildren (fixedVariableInitializer, data); + } + + public virtual S VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, T data) + { + return VisitChildren (indexerDeclaration, data); + } + + public virtual S VisitMethodDeclaration (MethodDeclaration methodDeclaration, T data) + { + return VisitChildren (methodDeclaration, data); + } + + public virtual S VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, T data) + { + return VisitChildren (operatorDeclaration, data); + } + + public virtual S VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, T data) + { + return VisitChildren (propertyDeclaration, data); + } + + public virtual S VisitAccessor (Accessor accessor, T data) + { + return VisitChildren (accessor, data); + } + + public virtual S VisitVariableInitializer (VariableInitializer variableInitializer, T data) + { + return VisitChildren (variableInitializer, data); + } + + public virtual S VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, T data) + { + return VisitChildren (parameterDeclaration, data); + } + + public virtual S VisitConstraint (Constraint constraint, T data) + { + return VisitChildren (constraint, data); + } + + public virtual S VisitBlockStatement (BlockStatement blockStatement, T data) + { + return VisitChildren (blockStatement, data); + } + + public virtual S VisitExpressionStatement (ExpressionStatement expressionStatement, T data) + { + return VisitChildren (expressionStatement, data); + } + + public virtual S VisitBreakStatement (BreakStatement breakStatement, T data) + { + return VisitChildren (breakStatement, data); + } + + public virtual S VisitCheckedStatement (CheckedStatement checkedStatement, T data) + { + return VisitChildren (checkedStatement, data); + } + + public virtual S VisitContinueStatement (ContinueStatement continueStatement, T data) + { + return VisitChildren (continueStatement, data); + } + + public virtual S VisitDoWhileStatement (DoWhileStatement doWhileStatement, T data) + { + return VisitChildren (doWhileStatement, data); + } + + public virtual S VisitEmptyStatement (EmptyStatement emptyStatement, T data) + { + return VisitChildren (emptyStatement, data); + } + + public virtual S VisitFixedStatement (FixedStatement fixedStatement, T data) + { + return VisitChildren (fixedStatement, data); + } + + public virtual S VisitForeachStatement (ForeachStatement foreachStatement, T data) + { + return VisitChildren (foreachStatement, data); + } + + public virtual S VisitForStatement (ForStatement forStatement, T data) + { + return VisitChildren (forStatement, data); + } + + public virtual S VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, T data) + { + return VisitChildren (gotoCaseStatement, data); + } + + public virtual S VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, T data) + { + return VisitChildren (gotoDefaultStatement, data); + } + + public virtual S VisitGotoStatement (GotoStatement gotoStatement, T data) + { + return VisitChildren (gotoStatement, data); + } + + public virtual S VisitIfElseStatement (IfElseStatement ifElseStatement, T data) + { + return VisitChildren (ifElseStatement, data); + } + + public virtual S VisitLabelStatement (LabelStatement labelStatement, T data) + { + return VisitChildren (labelStatement, data); + } + + public virtual S VisitLockStatement (LockStatement lockStatement, T data) + { + return VisitChildren (lockStatement, data); + } + + public virtual S VisitReturnStatement (ReturnStatement returnStatement, T data) + { + return VisitChildren (returnStatement, data); + } + + public virtual S VisitSwitchStatement (SwitchStatement switchStatement, T data) + { + return VisitChildren (switchStatement, data); + } + + public virtual S VisitSwitchSection (SwitchSection switchSection, T data) + { + return VisitChildren (switchSection, data); + } + + public virtual S VisitCaseLabel (CaseLabel caseLabel, T data) + { + return VisitChildren (caseLabel, data); + } + + public virtual S VisitThrowStatement (ThrowStatement throwStatement, T data) + { + return VisitChildren (throwStatement, data); + } + + public virtual S VisitTryCatchStatement (TryCatchStatement tryCatchStatement, T data) + { + return VisitChildren (tryCatchStatement, data); + } + + public virtual S VisitCatchClause (CatchClause catchClause, T data) + { + return VisitChildren (catchClause, data); + } + + public virtual S VisitUncheckedStatement (UncheckedStatement uncheckedStatement, T data) + { + return VisitChildren (uncheckedStatement, data); + } + + public virtual S VisitUnsafeStatement (UnsafeStatement unsafeStatement, T data) + { + return VisitChildren (unsafeStatement, data); + } + + public virtual S VisitUsingStatement (UsingStatement usingStatement, T data) + { + return VisitChildren (usingStatement, data); + } + + public virtual S VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, T data) + { + return VisitChildren (variableDeclarationStatement, data); + } + + public virtual S VisitWhileStatement (WhileStatement whileStatement, T data) + { + return VisitChildren (whileStatement, data); + } + + public virtual S VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, T data) + { + return VisitChildren (yieldBreakStatement, data); + } + + public virtual S VisitYieldStatement (YieldStatement yieldStatement, T data) + { + return VisitChildren (yieldStatement, data); + } + + public virtual S VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, T data) + { + return VisitChildren (anonymousMethodExpression, data); + } + + public virtual S VisitLambdaExpression (LambdaExpression lambdaExpression, T data) + { + return VisitChildren (lambdaExpression, data); + } + + public virtual S VisitAssignmentExpression (AssignmentExpression assignmentExpression, T data) + { + return VisitChildren (assignmentExpression, data); + } + + public virtual S VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, T data) + { + return VisitChildren (baseReferenceExpression, data); + } + + public virtual S VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, T data) + { + return VisitChildren (binaryOperatorExpression, data); + } + + public virtual S VisitCastExpression (CastExpression castExpression, T data) + { + return VisitChildren (castExpression, data); + } + + public virtual S VisitCheckedExpression (CheckedExpression checkedExpression, T data) + { + return VisitChildren (checkedExpression, data); + } + + public virtual S VisitConditionalExpression (ConditionalExpression conditionalExpression, T data) + { + return VisitChildren (conditionalExpression, data); + } + + public virtual S VisitIdentifierExpression (IdentifierExpression identifierExpression, T data) + { + return VisitChildren (identifierExpression, data); + } + + public virtual S VisitIndexerExpression (IndexerExpression indexerExpression, T data) + { + return VisitChildren (indexerExpression, data); + } + + public virtual S VisitInvocationExpression (InvocationExpression invocationExpression, T data) + { + return VisitChildren (invocationExpression, data); + } + + public virtual S VisitDirectionExpression (DirectionExpression directionExpression, T data) + { + return VisitChildren (directionExpression, data); + } + + public virtual S VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, T data) + { + return VisitChildren (memberReferenceExpression, data); + } + + public virtual S VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, T data) + { + return VisitChildren (nullReferenceExpression, data); + } + + public virtual S VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, T data) + { + return VisitChildren (objectCreateExpression, data); + } + + public virtual S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data) + { + return VisitChildren (anonymousTypeCreateExpression, data); + } + + public virtual S VisitArrayCreateExpression (ArrayCreateExpression arrayObjectCreateExpression, T data) + { + return VisitChildren (arrayObjectCreateExpression, data); + } + + public virtual S VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, T data) + { + return VisitChildren (parenthesizedExpression, data); + } + + public virtual S VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, T data) + { + return VisitChildren (pointerReferenceExpression, data); + } + + public virtual S VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, T data) + { + return VisitChildren (primitiveExpression, data); + } + + public virtual S VisitSizeOfExpression (SizeOfExpression sizeOfExpression, T data) + { + return VisitChildren (sizeOfExpression, data); + } + + public virtual S VisitStackAllocExpression (StackAllocExpression stackAllocExpression, T data) + { + return VisitChildren (stackAllocExpression, data); + } + + public virtual S VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, T data) + { + return VisitChildren (thisReferenceExpression, data); + } + + public virtual S VisitTypeOfExpression (TypeOfExpression typeOfExpression, T data) + { + return VisitChildren (typeOfExpression, data); + } + + public virtual S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data) + { + return VisitChildren (typeReferenceExpression, data); + } + + public virtual S VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, T data) + { + return VisitChildren (unaryOperatorExpression, data); + } + + public virtual S VisitUncheckedExpression (UncheckedExpression uncheckedExpression, T data) + { + return VisitChildren (uncheckedExpression, data); + } + + public virtual S VisitQueryExpression(QueryExpression queryExpression, T data) + { + return VisitChildren (queryExpression, data); + } + + public virtual S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data) + { + return VisitChildren (queryContinuationClause, data); + } + + public virtual S VisitQueryFromClause(QueryFromClause queryFromClause, T data) + { + return VisitChildren (queryFromClause, data); + } + + public virtual S VisitQueryLetClause(QueryLetClause queryLetClause, T data) + { + return VisitChildren (queryLetClause, data); + } + + public virtual S VisitQueryWhereClause(QueryWhereClause queryWhereClause, T data) + { + return VisitChildren (queryWhereClause, data); + } + + public virtual S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data) + { + return VisitChildren (queryJoinClause, data); + } + + public virtual S VisitQueryOrderClause(QueryOrderClause queryOrderClause, T data) + { + return VisitChildren (queryOrderClause, data); + } + + public virtual S VisitQueryOrdering(QueryOrdering queryOrdering, T data) + { + return VisitChildren (queryOrdering, data); + } + + public virtual S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data) + { + return VisitChildren (querySelectClause, data); + } + + public virtual S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data) + { + return VisitChildren (queryGroupClause, data); + } + + public virtual S VisitAsExpression (AsExpression asExpression, T data) + { + return VisitChildren (asExpression, data); + } + + public virtual S VisitIsExpression (IsExpression isExpression, T data) + { + return VisitChildren (isExpression, data); + } + + public virtual S VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, T data) + { + return VisitChildren (defaultValueExpression, data); + } + + public virtual S VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, T data) + { + return VisitChildren (undocumentedExpression, data); + } + + public virtual S VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, T data) + { + return VisitChildren (arrayInitializerExpression, data); + } + + public virtual S VisitArraySpecifier (ArraySpecifier arraySpecifier, T data) + { + return VisitChildren (arraySpecifier, data); + } + + public virtual S VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, T data) + { + return VisitChildren (namedArgumentExpression, data); + } + + public virtual S VisitEmptyExpression (EmptyExpression emptyExpression, T data) + { + return VisitChildren (emptyExpression, data); + } + + public virtual S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data) + { + return VisitChildren (placeholder, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs new file mode 100644 index 0000000000..af2fed7506 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs @@ -0,0 +1,79 @@ +// +// ErrorNode.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin (http://www.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a parsing error in the ast. At the moment it only represents missing closing bracket. + /// This closing bracket is replaced by a node at the highest possible position. + /// (To make GetAstNodeAt (line, col) working). + /// + public class ErrorNode : AstNode + { + static AstLocation maxLoc = new AstLocation (int.MaxValue, int.MaxValue); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public override AstLocation StartLocation { + get { + return maxLoc; + } + } + + public override AstLocation EndLocation { + get { + return maxLoc; + } + } + + public ErrorNode () + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + // nothing + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as ErrorNode; + return o != null; + } + + public override string ToString () + { + return "[ErrorNode]"; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousMethodExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousMethodExpression.cs new file mode 100644 index 0000000000..f8c8cefac9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousMethodExpression.cs @@ -0,0 +1,92 @@ +// +// AnonymousMethodExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// delegate(Parameters) {Body} + /// + public class AnonymousMethodExpression : Expression + { + // used to make a difference between delegate {} and delegate () {} + public bool HasParameterList { + get; set; + } + + public CSharpTokenNode DelegateToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public AnonymousMethodExpression () + { + } + + public AnonymousMethodExpression (BlockStatement body, IEnumerable parameters = null) + { + if (parameters != null) { + foreach (var parameter in parameters) { + AddChild (parameter, Roles.Parameter); + } + } + AddChild (body, Roles.Body); + } + + public AnonymousMethodExpression (BlockStatement body, params ParameterDeclaration[] parameters) : this (body, (IEnumerable)parameters) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAnonymousMethodExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + AnonymousMethodExpression o = other as AnonymousMethodExpression; + return o != null && this.HasParameterList == o.HasParameterList && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs new file mode 100644 index 0000000000..940249d8d7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs @@ -0,0 +1,79 @@ +// +// AnonymousTypeCreateExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// new { [ExpressionList] } + /// + public class AnonymousTypeCreateExpression : Expression + { + public CSharpTokenNode NewToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Initializer { + get { return GetChildrenByRole (Roles.Expression); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public AnonymousTypeCreateExpression () + { + } + + public AnonymousTypeCreateExpression (IEnumerable initializer) + { + foreach (var ini in initializer) { + AddChild (ini, Roles.Expression); + } + } + + public AnonymousTypeCreateExpression (params Expression[] initializer) : this ((IEnumerable)initializer) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAnonymousTypeCreateExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as AnonymousTypeCreateExpression; + return o != null && this.Initializer.DoMatch(o.Initializer, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs new file mode 100644 index 0000000000..dffc3dd3dc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// new Type[Dimensions] + /// + public class ArrayCreateExpression : Expression + { + public readonly static Role AdditionalArraySpecifierRole = new Role("AdditionalArraySpecifier"); + public readonly static Role InitializerRole = new Role("Initializer", ArrayInitializerExpression.Null); + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole (Roles.Argument); } + } + + /// + /// Gets additional array ranks (those without size info). + /// Empty for "new int[5,1]"; will contain a single element for "new int[5][]". + /// + public AstNodeCollection AdditionalArraySpecifiers { + get { return GetChildrenByRole(AdditionalArraySpecifierRole); } + } + + public ArrayInitializerExpression Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole (InitializerRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArrayCreateExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArrayCreateExpression o = other as ArrayCreateExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.AdditionalArraySpecifiers.DoMatch(o.AdditionalArraySpecifiers, match) && this.Initializer.DoMatch(o.Initializer, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs new file mode 100644 index 0000000000..3c33d4d7b1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs @@ -0,0 +1,83 @@ +// +// ArrayInitializerExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// { Elements } + /// + public class ArrayInitializerExpression : Expression + { + #region Null + public new static readonly ArrayInitializerExpression Null = new NullArrayInitializerExpression (); + + sealed class NullArrayInitializerExpression : ArrayInitializerExpression + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public AstNodeCollection Elements { + get { return GetChildrenByRole(Roles.Expression); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArrayInitializerExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArrayInitializerExpression o = other as ArrayInitializerExpression; + return o != null && this.Elements.DoMatch(o.Elements, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AsExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AsExpression.cs new file mode 100644 index 0000000000..b1a1b80653 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AsExpression.cs @@ -0,0 +1,70 @@ +// +// AsExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Expression as TypeReference + /// + public class AsExpression : Expression + { + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public CSharpTokenNode AsToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AsExpression () + { + } + + public AsExpression (Expression expression, AstType type) + { + AddChild (expression, Roles.Expression); + AddChild (type, Roles.Type); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAsExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + AsExpression o = other as AsExpression; + return o != null && this.Expression.DoMatch(o.Expression, match) && this.Type.DoMatch(o.Type, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs new file mode 100644 index 0000000000..998ab78fb4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs @@ -0,0 +1,151 @@ +// +// AssignmentExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Left Operator= Right + /// + public class AssignmentExpression : Expression + { + // reuse roles from BinaryOperatorExpression + public readonly static Role LeftRole = BinaryOperatorExpression.LeftRole; + public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; + public readonly static Role RightRole = BinaryOperatorExpression.RightRole; + + public AssignmentExpression() + { + } + + public AssignmentExpression(Expression left, Expression right) + { + this.Left = left; + this.Right = right; + } + + public AssignmentExpression(Expression left, AssignmentOperatorType op, Expression right) + { + this.Left = left; + this.Operator = op; + this.Right = right; + } + + public AssignmentOperatorType Operator { + get; + set; + } + + public Expression Left { + get { return GetChildByRole (LeftRole); } + set { SetChildByRole(LeftRole, value); } + } + + public CSharpTokenNode OperatorToken { + get { return GetChildByRole (OperatorRole); } + } + + public Expression Right { + get { return GetChildByRole (RightRole); } + set { SetChildByRole(RightRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAssignmentExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + AssignmentExpression o = other as AssignmentExpression; + return o != null && (this.Operator == AssignmentOperatorType.Any || this.Operator == o.Operator) + && this.Left.DoMatch(o.Left, match) && this.Right.DoMatch(o.Right, match); + } + + public static string GetOperatorSymbol(AssignmentOperatorType op) + { + switch (op) { + case AssignmentOperatorType.Assign: + return "="; + case AssignmentOperatorType.Add: + return "+="; + case AssignmentOperatorType.Subtract: + return "-="; + case AssignmentOperatorType.Multiply: + return "*="; + case AssignmentOperatorType.Divide: + return "/="; + case AssignmentOperatorType.Modulus: + return "%="; + case AssignmentOperatorType.ShiftLeft: + return "<<="; + case AssignmentOperatorType.ShiftRight: + return ">>="; + case AssignmentOperatorType.BitwiseAnd: + return "&="; + case AssignmentOperatorType.BitwiseOr: + return "|="; + case AssignmentOperatorType.ExclusiveOr: + return "^="; + default: + throw new NotSupportedException("Invalid value for AssignmentOperatorType"); + } + } + } + + public enum AssignmentOperatorType + { + /// left = right + Assign, + + /// left += right + Add, + /// left -= right + Subtract, + /// left *= right + Multiply, + /// left /= right + Divide, + /// left %= right + Modulus, + + /// left <<= right + ShiftLeft, + /// left >>= right + ShiftRight, + + /// left &= right + BitwiseAnd, + /// left |= right + BitwiseOr, + /// left ^= right + ExclusiveOr, + + /// Any operator (for pattern matching) + Any + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BaseReferenceExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BaseReferenceExpression.cs new file mode 100644 index 0000000000..b75fb95344 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BaseReferenceExpression.cs @@ -0,0 +1,61 @@ +// +// BaseReferenceExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// base + /// + public class BaseReferenceExpression : Expression + { + public AstLocation Location { + get; + set; + } + + public override AstLocation StartLocation { + get { + return Location; + } + } + public override AstLocation EndLocation { + get { + return new AstLocation (Location.Line, Location.Column + "base".Length); + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitBaseReferenceExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + BaseReferenceExpression o = other as BaseReferenceExpression; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs new file mode 100644 index 0000000000..171e3e31c2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs @@ -0,0 +1,184 @@ +// +// BinaryOperatorExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Left Operator Right + /// + public class BinaryOperatorExpression : Expression + { + public readonly static Role LeftRole = new Role("Left", Expression.Null); + public readonly static Role OperatorRole = new Role("Operator", CSharpTokenNode.Null); + public readonly static Role RightRole = new Role("Right", Expression.Null); + + public BinaryOperatorExpression() + { + } + + public BinaryOperatorExpression(Expression left, BinaryOperatorType op, Expression right) + { + this.Left = left; + this.Operator = op; + this.Right = right; + } + + public BinaryOperatorType Operator { + get; + set; + } + + public Expression Left { + get { return GetChildByRole (LeftRole); } + set { SetChildByRole(LeftRole, value); } + } + + public CSharpTokenNode OperatorToken { + get { return GetChildByRole (OperatorRole); } + } + + public Expression Right { + get { return GetChildByRole (RightRole); } + set { SetChildByRole(RightRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitBinaryOperatorExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + BinaryOperatorExpression o = other as BinaryOperatorExpression; + return o != null && (this.Operator == BinaryOperatorType.Any || this.Operator == o.Operator) + && this.Left.DoMatch(o.Left, match) && this.Right.DoMatch(o.Right, match); + } + + public static string GetOperatorSymbol(BinaryOperatorType op) + { + switch (op) { + case BinaryOperatorType.BitwiseAnd: + return "&"; + case BinaryOperatorType.BitwiseOr: + return "|"; + case BinaryOperatorType.ConditionalAnd: + return "&&"; + case BinaryOperatorType.ConditionalOr: + return "||"; + case BinaryOperatorType.ExclusiveOr: + return "^"; + case BinaryOperatorType.GreaterThan: + return ">"; + case BinaryOperatorType.GreaterThanOrEqual: + return ">="; + case BinaryOperatorType.Equality: + return "=="; + case BinaryOperatorType.InEquality: + return "!="; + case BinaryOperatorType.LessThan: + return "<"; + case BinaryOperatorType.LessThanOrEqual: + return "<="; + case BinaryOperatorType.Add: + return "+"; + case BinaryOperatorType.Subtract: + return "-"; + case BinaryOperatorType.Multiply: + return "*"; + case BinaryOperatorType.Divide: + return "/"; + case BinaryOperatorType.Modulus: + return "%"; + case BinaryOperatorType.ShiftLeft: + return "<<"; + case BinaryOperatorType.ShiftRight: + return ">>"; + case BinaryOperatorType.NullCoalescing: + return "??"; + default: + throw new NotSupportedException("Invalid value for BinaryOperatorType"); + } + } + } + + public enum BinaryOperatorType + { + // We avoid 'logical or' on purpose, because it's not clear if that refers to the bitwise + // or to the short-circuiting (conditional) operator: + // MCS and old NRefactory used bitwise='|', logical='||' + // but the C# spec uses logical='|', conditional='||' + + /// left & right + BitwiseAnd, + /// left | right + BitwiseOr, + /// left && right + ConditionalAnd, + /// left || right + ConditionalOr, + /// left ^ right + ExclusiveOr, + + /// left > right + GreaterThan, + /// left >= right + GreaterThanOrEqual, + /// left == right + Equality, + /// left != right + InEquality, + /// left < right + LessThan, + /// left <= right + LessThanOrEqual, + + /// left + right + Add, + /// left - right + Subtract, + /// left * right + Multiply, + /// left / right + Divide, + /// left % right + Modulus, + + /// left << right + ShiftLeft, + /// left >> right + ShiftRight, + + /// left ?? right + NullCoalescing, + + /// + /// Any binary operator (used in pattern matching) + /// + Any + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CastExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CastExpression.cs new file mode 100644 index 0000000000..88c7dcfe36 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CastExpression.cs @@ -0,0 +1,74 @@ +// +// CastExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// (CastTo)Expression + /// + public class CastExpression : Expression + { + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CastExpression () + { + } + + public CastExpression (AstType castToType, Expression expression) + { + AddChild (castToType, Roles.Type); + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCastExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CastExpression o = other as CastExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.Expression.DoMatch(o.Expression, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CheckedExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CheckedExpression.cs new file mode 100644 index 0000000000..349976c68a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CheckedExpression.cs @@ -0,0 +1,71 @@ +// +// CheckedExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// checked(Expression) + /// + public class CheckedExpression : Expression + { + public CSharpTokenNode CheckedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public CheckedExpression () + { + } + + public CheckedExpression (Expression expression) + { + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCheckedExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CheckedExpression o = other as CheckedExpression; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ConditionalExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ConditionalExpression.cs new file mode 100644 index 0000000000..5e80994328 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ConditionalExpression.cs @@ -0,0 +1,85 @@ +// +// ConditionalExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Condition ? TrueExpression : FalseExpression + /// + public class ConditionalExpression : Expression + { + public readonly static Role ConditionRole = Roles.Condition; + public readonly static Role QuestionMarkRole = new Role("QuestionMark", CSharpTokenNode.Null); + public readonly static Role TrueRole = new Role("True", Expression.Null); + public readonly static Role ColonRole = Roles.Colon; + public readonly static Role FalseRole = new Role("False", Expression.Null); + + public Expression Condition { + get { return GetChildByRole(ConditionRole); } + set { SetChildByRole(ConditionRole, value); } + } + + public CSharpTokenNode QuestionMarkToken { + get { return GetChildByRole (QuestionMarkRole); } + } + + public Expression TrueExpression { + get { return GetChildByRole(TrueRole); } + set { SetChildByRole(TrueRole, value); } + } + + public CSharpTokenNode ColonToken { + get { return GetChildByRole (ColonRole); } + } + + public Expression FalseExpression { + get { return GetChildByRole(FalseRole); } + set { SetChildByRole(FalseRole, value); } + } + + public ConditionalExpression () + { + } + + public ConditionalExpression (Expression condition, Expression trueExpression, Expression falseExpression) + { + AddChild (condition, ConditionRole); + AddChild (trueExpression, TrueRole); + AddChild (falseExpression, FalseRole); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitConditionalExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ConditionalExpression o = other as ConditionalExpression; + return o != null && this.Condition.DoMatch(o.Condition, match) && this.TrueExpression.DoMatch(o.TrueExpression, match) && this.FalseExpression.DoMatch(o.FalseExpression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DefaultValueExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DefaultValueExpression.cs new file mode 100644 index 0000000000..1a91d6d086 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DefaultValueExpression.cs @@ -0,0 +1,72 @@ +// +// DefaultValueExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// default(Type) + /// + public class DefaultValueExpression : Expression + { + public CSharpTokenNode DefaultToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public DefaultValueExpression () + { + } + + public DefaultValueExpression (AstType type) + { + AddChild (type, Roles.Type); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitDefaultValueExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DefaultValueExpression o = other as DefaultValueExpression; + return o != null && this.Type.DoMatch(o.Type, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DirectionExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DirectionExpression.cs new file mode 100644 index 0000000000..0c19b2ca7d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DirectionExpression.cs @@ -0,0 +1,76 @@ +// +// DirectionExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum FieldDirection + { + None, + Out, + Ref + } + + /// + /// ref Expression + /// + public class DirectionExpression : Expression + { + public FieldDirection FieldDirection { + get; + set; + } + + public CSharpTokenNode FieldDirectionToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public DirectionExpression () + { + } + + public DirectionExpression (FieldDirection direction, Expression expression) + { + this.FieldDirection = direction; + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitDirectionExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DirectionExpression o = other as DirectionExpression; + return o != null && this.FieldDirection == o.FieldDirection && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs new file mode 100644 index 0000000000..3c23f54f88 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs @@ -0,0 +1,76 @@ +// +// EmptyExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Type<[EMPTY]> + /// + public class EmptyExpression : Expression, IRelocatable + { + AstLocation location; + + public override AstLocation StartLocation { + get { + return location; + } + } + + public override AstLocation EndLocation { + get { + return location; + } + } + + public EmptyExpression () + { + } + + public EmptyExpression (AstLocation location) + { + this.location = location; + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.location = startLocation; + } + #endregion + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitEmptyExpression (this, data); + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + var o = other as EmptyExpression; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/Expression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/Expression.cs new file mode 100644 index 0000000000..db0cee2575 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/Expression.cs @@ -0,0 +1,222 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Base class for expressions. + /// + /// + /// This class is useful even though it doesn't provide any additional functionality: + /// It can be used to communicate more information in APIs, e.g. "this subnode will always be an expression" + /// + public abstract class Expression : AstNode + { + #region Null + public new static readonly Expression Null = new NullExpression (); + + sealed class NullExpression : Expression + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator Expression(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : Expression, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public override NodeType NodeType { + get { + return NodeType.Expression; + } + } + + public new Expression Clone() + { + return (Expression)base.Clone(); + } + + // Make debugging easier by giving Expressions a ToString() implementation + public override string ToString() + { + if (IsNull) + return "Null"; + StringWriter w = new StringWriter(); + AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); + return w.ToString(); + } + + public Expression ReplaceWith(Func replaceFunction) + { + if (replaceFunction == null) + throw new ArgumentNullException("replaceFunction"); + return (Expression)base.ReplaceWith(node => replaceFunction((Expression)node)); + } + + #region Builder methods + /// + /// Builds an member reference expression using this expression as target. + /// + public MemberReferenceExpression Member(string memberName) + { + return new MemberReferenceExpression { Target = this, MemberName = memberName }; + } + + /// + /// Builds an indexer expression using this expression as target. + /// + public IndexerExpression Indexer(IEnumerable arguments) + { + IndexerExpression expr = new IndexerExpression(); + expr.Target = this; + expr.Arguments.AddRange(arguments); + return expr; + } + + /// + /// Builds an indexer expression using this expression as target. + /// + public IndexerExpression Indexer(params Expression[] arguments) + { + IndexerExpression expr = new IndexerExpression(); + expr.Target = this; + expr.Arguments.AddRange(arguments); + return expr; + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable arguments) + { + return Invoke(methodName, null, arguments); + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(string methodName, params Expression[] arguments) + { + return Invoke(methodName, null, arguments); + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) + { + InvocationExpression ie = new InvocationExpression(); + MemberReferenceExpression mre = new MemberReferenceExpression(); + mre.Target = this; + mre.MemberName = methodName; + mre.TypeArguments.AddRange(typeArguments); + ie.Target = mre; + ie.Arguments.AddRange(arguments); + return ie; + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(IEnumerable arguments) + { + InvocationExpression ie = new InvocationExpression(); + ie.Target = this; + ie.Arguments.AddRange(arguments); + return ie; + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(params Expression[] arguments) + { + InvocationExpression ie = new InvocationExpression(); + ie.Target = this; + ie.Arguments.AddRange(arguments); + return ie; + } + + public CastExpression CastTo(AstType type) + { + return new CastExpression { Type = type, Expression = this }; + } + + public CastExpression CastTo(Type type) + { + return new CastExpression { Type = AstType.Create(type), Expression = this }; + } + + public AsExpression CastAs(AstType type) + { + return new AsExpression { Type = type, Expression = this }; + } + + public AsExpression CastAs(Type type) + { + return new AsExpression { Type = AstType.Create(type), Expression = this }; + } + + public IsExpression IsType(AstType type) + { + return new IsExpression { Type = type, Expression = this }; + } + + public IsExpression IsType(Type type) + { + return new IsExpression { Type = AstType.Create(type), Expression = this }; + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs new file mode 100644 index 0000000000..e982f13201 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs @@ -0,0 +1,74 @@ +// +// IdentifierExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class IdentifierExpression : Expression + { + public IdentifierExpression() + { + } + + public IdentifierExpression(string identifier) + { + this.Identifier = identifier; + } + + public IdentifierExpression(string identifier, AstLocation location) + { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (identifier, location)); + } + +// public Identifier IdentifierToken { +// get { return GetChildByRole (Roles.Identifier); } +// } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIdentifierExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + IdentifierExpression o = other as IdentifierExpression; + return o != null && MatchString(this.Identifier, o.Identifier) && this.TypeArguments.DoMatch(o.TypeArguments, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IndexerExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IndexerExpression.cs new file mode 100644 index 0000000000..045d8d0388 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IndexerExpression.cs @@ -0,0 +1,82 @@ +// +// IndexerExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Target[Arguments] + /// + public class IndexerExpression : Expression + { + public Expression Target { + get { return GetChildByRole (Roles.TargetExpression); } + set { SetChildByRole(Roles.TargetExpression, value); } + } + + public CSharpTokenNode LBracketToken { + get { return GetChildByRole (Roles.LBracket); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole(Roles.Argument); } + } + + public CSharpTokenNode RBracketToken { + get { return GetChildByRole (Roles.RBracket); } + } + + public IndexerExpression () + { + } + + public IndexerExpression (Expression target, IEnumerable arguments) + { + AddChild (target, Roles.TargetExpression); + if (arguments != null) { + foreach (var arg in arguments) { + AddChild (arg, Roles.Argument); + } + } + } + + public IndexerExpression (Expression target, params Expression[] arguments) : this (target, (IEnumerable)arguments) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIndexerExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + IndexerExpression o = other as IndexerExpression; + return o != null && this.Target.DoMatch(o.Target, match) && this.Arguments.DoMatch(o.Arguments, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/InvocationExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/InvocationExpression.cs new file mode 100644 index 0000000000..84d0830fee --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/InvocationExpression.cs @@ -0,0 +1,82 @@ +// +// InvocationExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Target(Arguments) + /// + public class InvocationExpression : Expression + { + public Expression Target { + get { return GetChildByRole (Roles.TargetExpression); } + set { SetChildByRole(Roles.TargetExpression, value); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole(Roles.Argument); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitInvocationExpression (this, data); + } + + public InvocationExpression () + { + } + + public InvocationExpression (Expression target, IEnumerable arguments) + { + AddChild (target, Roles.TargetExpression); + if (arguments != null) { + foreach (var arg in arguments) { + AddChild (arg, Roles.Argument); + } + } + } + + public InvocationExpression (Expression target, params Expression[] arguments) : this (target, (IEnumerable)arguments) + { + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + InvocationExpression o = other as InvocationExpression; + return o != null && this.Target.DoMatch(o.Target, match) && this.Arguments.DoMatch(o.Arguments, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IsExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IsExpression.cs new file mode 100644 index 0000000000..a8c7b0e002 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IsExpression.cs @@ -0,0 +1,60 @@ +// +// TypeOfIsExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Expression is Type + /// + public class IsExpression : Expression + { + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public CSharpTokenNode IsToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIsExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + IsExpression o = other as IsExpression; + return o != null && this.Expression.DoMatch(o.Expression, match) && this.Type.DoMatch(o.Type, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/LambdaExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/LambdaExpression.cs new file mode 100644 index 0000000000..774bd6c4a3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/LambdaExpression.cs @@ -0,0 +1,63 @@ +// +// LambdaExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Parameters => Body + /// + public class LambdaExpression : Expression + { + public readonly static Role ArrowRole = new Role("Arrow", CSharpTokenNode.Null); + public static readonly Role BodyRole = new Role("Body", AstNode.Null); + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode ArrowToken { + get { return GetChildByRole (ArrowRole); } + } + + public AstNode Body { + get { return GetChildByRole (BodyRole); } + set { SetChildByRole (BodyRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitLambdaExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + LambdaExpression o = other as LambdaExpression; + return o != null && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs new file mode 100644 index 0000000000..4a7decbe0e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs @@ -0,0 +1,101 @@ +// +// MemberReferenceExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Target.MemberName + /// + public class MemberReferenceExpression : Expression + { + public Expression Target { + get { return GetChildByRole (Roles.TargetExpression); } + set { SetChildByRole(Roles.TargetExpression, value); } + } + + public string MemberName { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier MemberNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public CSharpTokenNode LChevronToken { + get { return GetChildByRole (Roles.LChevron); } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public CSharpTokenNode RChevronToken { + get { return GetChildByRole (Roles.RChevron); } + } + + public MemberReferenceExpression () + { + } + + public MemberReferenceExpression (Expression target, string memberName, IEnumerable arguments = null) + { + AddChild (target, Roles.TargetExpression); + MemberName = memberName; + if (arguments != null) { + foreach (var arg in arguments) { + AddChild (arg, Roles.TypeArgument); + } + } + } + + public MemberReferenceExpression (Expression target, string memberName, params AstType[] arguments) : this (target, memberName, (IEnumerable)arguments) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitMemberReferenceExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + MemberReferenceExpression o = other as MemberReferenceExpression; + return o != null && this.Target.DoMatch(o.Target, match) && MatchString(this.MemberName, o.MemberName) && this.TypeArguments.DoMatch(o.TypeArguments, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs new file mode 100644 index 0000000000..73bcb2e274 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs @@ -0,0 +1,51 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a named argument passed to a method or attribute. + /// + public class NamedArgumentExpression : Expression + { + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); + } + } + + public CSharpTokenNode AssignToken { + get { return GetChildByRole (Roles.Assign); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitNamedArgumentExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + NamedArgumentExpression o = other as NamedArgumentExpression; + return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NullReferenceExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NullReferenceExpression.cs new file mode 100644 index 0000000000..df95202b8d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NullReferenceExpression.cs @@ -0,0 +1,67 @@ +// +// NullReferenceExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// null + /// + public class NullReferenceExpression : Expression + { + AstLocation location; + public override AstLocation StartLocation { + get { + return location; + } + } + + public override AstLocation EndLocation { + get { + return new AstLocation (location.Line, location.Column + "null".Length); + } + } + + public NullReferenceExpression () + { + } + + public NullReferenceExpression (AstLocation location) + { + this.location = location; + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitNullReferenceExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + NullReferenceExpression o = other as NullReferenceExpression; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ObjectCreateExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ObjectCreateExpression.cs new file mode 100644 index 0000000000..7bb5dc821f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ObjectCreateExpression.cs @@ -0,0 +1,93 @@ +// +// ObjectCreateExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// new Type(Arguments) { Initializer } + /// + public class ObjectCreateExpression : Expression + { + public readonly static Role InitializerRole = ArrayCreateExpression.InitializerRole; + + public CSharpTokenNode NewToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole (Roles.Argument); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public ArrayInitializerExpression Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole (InitializerRole, value); } + } + + public ObjectCreateExpression () + { + } + + public ObjectCreateExpression (AstType type, IEnumerable arguments = null) + { + AddChild (type, Roles.Type); + if (arguments != null) { + foreach (var arg in arguments) { + AddChild (arg, Roles.Argument); + } + } + } + + public ObjectCreateExpression (AstType type, params Expression[] arguments) : this (type, (IEnumerable)arguments) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitObjectCreateExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ObjectCreateExpression o = other as ObjectCreateExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.Initializer.DoMatch(o.Initializer, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ParenthesizedExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ParenthesizedExpression.cs new file mode 100644 index 0000000000..8cdb5cfd17 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ParenthesizedExpression.cs @@ -0,0 +1,67 @@ +// +// ParenthesizedExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// ( Expression ) + /// + public class ParenthesizedExpression : Expression + { + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public ParenthesizedExpression() + { + } + + public ParenthesizedExpression(Expression expr) + { + Expression = expr; + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitParenthesizedExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ParenthesizedExpression o = other as ParenthesizedExpression; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs new file mode 100644 index 0000000000..21e805b671 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs @@ -0,0 +1,67 @@ +// +// PointerReferenceExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Target->MemberName + /// + public class PointerReferenceExpression : Expression + { + public readonly static Role ArrowRole = new Role("Arrow", CSharpTokenNode.Null); + + public Expression Target { + get { return GetChildByRole (Roles.TargetExpression); } + set { SetChildByRole(Roles.TargetExpression, value); } + } + + public string MemberName { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitPointerReferenceExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PointerReferenceExpression o = other as PointerReferenceExpression; + return o != null && MatchString(this.MemberName, o.MemberName) && this.TypeArguments.DoMatch(o.TypeArguments, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs new file mode 100644 index 0000000000..22e16e29ba --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs @@ -0,0 +1,97 @@ +// +// PrimitiveExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a literal value. + /// + public class PrimitiveExpression : Expression, IRelocatable + { + public static readonly object AnyValue = new object(); + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + } + + string literalValue; + public override AstLocation EndLocation { + get { + return new AstLocation (StartLocation.Line, StartLocation.Column + literalValue.Length); + } + } + + public object Value { + get; + set; + } + + public string LiteralValue { + get { + return literalValue; + } + } + + public PrimitiveExpression (object value) + { + this.Value = value; + } + + public PrimitiveExpression (object value, string literalValue) + { + this.Value = value; + this.literalValue = literalValue ?? ""; + } + + public PrimitiveExpression (object value, AstLocation startLocation, string literalValue) + { + this.Value = value; + this.startLocation = startLocation; + this.literalValue = literalValue ?? ""; + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.startLocation = startLocation; + } + #endregion + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitPrimitiveExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PrimitiveExpression o = other as PrimitiveExpression; + return o != null && (this.Value == AnyValue || object.Equals(this.Value, o.Value)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs new file mode 100644 index 0000000000..5cf8877030 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs @@ -0,0 +1,422 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +namespace ICSharpCode.NRefactory.CSharp +{ + public class QueryExpression : Expression + { + public static readonly Role ClauseRole = new Role("Clause"); + + #region Null + public new static readonly QueryExpression Null = new NullQueryExpression (); + + sealed class NullQueryExpression : QueryExpression + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public AstNodeCollection Clauses { + get { return GetChildrenByRole(ClauseRole); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitQueryExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryExpression o = other as QueryExpression; + return o != null && !o.IsNull && this.Clauses.DoMatch(o.Clauses, match); + } + } + + public abstract class QueryClause : AstNode + { + public override NodeType NodeType { + get { return NodeType.QueryClause; } + } + } + + /// + /// Represents a query continuation. + /// "(from .. select ..) into Identifier" or "(from .. group .. by ..) into Identifier" + /// Note that "join .. into .." is not a query continuation! + /// + /// This is always the first(!!) clause in a query expression. + /// The tree for "from a in b select c into d select e" looks like this: + /// new QueryExpression { + /// new QueryContinuationClause { + /// PrecedingQuery = new QueryExpression { + /// new QueryFromClause(a in b), + /// new QuerySelectClause(c) + /// }, + /// Identifier = d + /// }, + /// new QuerySelectClause(e) + /// } + /// + public class QueryContinuationClause : QueryClause + { + public static readonly Role PrecedingQueryRole = new Role("PrecedingQuery", QueryExpression.Null); + public static readonly Role IntoKeywordRole = Roles.Keyword; + + public QueryExpression PrecedingQuery { + get { return GetChildByRole(PrecedingQueryRole); } + set { SetChildByRole(PrecedingQueryRole, value); } + } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryContinuationClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryContinuationClause o = other as QueryContinuationClause; + return o != null && MatchString(this.Identifier, o.Identifier) && this.PrecedingQuery.DoMatch(o.PrecedingQuery, match); + } + } + + public class QueryFromClause : QueryClause + { + public static readonly Role FromKeywordRole = Roles.Keyword; + public static readonly Role InKeywordRole = Roles.InKeyword; + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryFromClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryFromClause o = other as QueryFromClause; + return o != null && this.Type.DoMatch(o.Type, match) && MatchString(this.Identifier, o.Identifier) + && this.Expression.DoMatch(o.Expression, match); + } + } + + public class QueryLetClause : QueryClause + { + public CSharpTokenNode LetKeyword { + get { return GetChildByRole(Roles.Keyword); } + } + + public string Identifier { + get { + return GetChildByRole(Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public CSharpTokenNode AssignToken { + get { return GetChildByRole(Roles.Assign); } + } + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryLetClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryLetClause o = other as QueryLetClause; + return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); + } + } + + + public class QueryWhereClause : QueryClause + { + public CSharpTokenNode WhereKeyword { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Condition { + get { return GetChildByRole (Roles.Condition); } + set { SetChildByRole (Roles.Condition, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryWhereClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryWhereClause o = other as QueryWhereClause; + return o != null && this.Condition.DoMatch(o.Condition, match); + } + } + + /// + /// Represents a join or group join clause. + /// + public class QueryJoinClause : QueryClause + { + public static readonly Role JoinKeywordRole = Roles.Keyword; + public static readonly Role TypeRole = Roles.Type; + public static readonly Role JoinIdentifierRole = Roles.Identifier; + public static readonly Role InKeywordRole = Roles.InKeyword; + public static readonly Role InExpressionRole = Roles.Expression; + public static readonly Role OnKeywordRole = new Role("OnKeyword", CSharpTokenNode.Null); + public static readonly Role OnExpressionRole = new Role("OnExpression", Expression.Null); + public static readonly Role EqualsKeywordRole = new Role("EqualsKeyword", CSharpTokenNode.Null); + public static readonly Role EqualsExpressionRole = new Role("EqualsExpression", Expression.Null); + public static readonly Role IntoKeywordRole = new Role("IntoKeyword", CSharpTokenNode.Null); + public static readonly Role IntoIdentifierRole = new Role("IntoIdentifier", Identifier.Null); + + public bool IsGroupJoin { + get { return !string.IsNullOrEmpty(this.IntoIdentifier); } + } + + public CSharpTokenNode JoinKeyword { + get { return GetChildByRole (JoinKeywordRole); } + } + + public AstType Type { + get { return GetChildByRole (TypeRole); } + set { SetChildByRole (TypeRole, value); } + } + + public string JoinIdentifier { + get { + return GetChildByRole(JoinIdentifierRole).Name; + } + set { + SetChildByRole(JoinIdentifierRole, Identifier.Create (value, AstLocation.Empty)); + } + } + + public CSharpTokenNode InKeyword { + get { return GetChildByRole (InKeywordRole); } + } + + public Expression InExpression { + get { return GetChildByRole (InExpressionRole); } + set { SetChildByRole (InExpressionRole, value); } + } + + public CSharpTokenNode OnKeyword { + get { return GetChildByRole (OnKeywordRole); } + } + + public Expression OnExpression { + get { return GetChildByRole (OnExpressionRole); } + set { SetChildByRole (OnExpressionRole, value); } + } + + public CSharpTokenNode EqualsKeyword { + get { return GetChildByRole (EqualsKeywordRole); } + } + + public Expression EqualsExpression { + get { return GetChildByRole (EqualsExpressionRole); } + set { SetChildByRole (EqualsExpressionRole, value); } + } + + public CSharpTokenNode IntoKeyword { + get { return GetChildByRole (IntoKeywordRole); } + } + + public string IntoIdentifier { + get { + return GetChildByRole (IntoIdentifierRole).Name; + } + set { + SetChildByRole(IntoIdentifierRole, Identifier.Create (value, AstLocation.Empty)); + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryJoinClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryJoinClause o = other as QueryJoinClause; + return o != null && this.IsGroupJoin == o.IsGroupJoin + && this.Type.DoMatch(o.Type, match) && MatchString(this.JoinIdentifier, o.JoinIdentifier) + && this.InExpression.DoMatch(o.InExpression, match) && this.OnExpression.DoMatch(o.OnExpression, match) + && this.EqualsExpression.DoMatch(o.EqualsExpression, match) + && MatchString(this.IntoIdentifier, o.IntoIdentifier); + } + } + + public class QueryOrderClause : QueryClause + { + public static readonly Role OrderingRole = new Role("Ordering"); + + public CSharpTokenNode Keyword { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstNodeCollection Orderings { + get { return GetChildrenByRole (OrderingRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryOrderClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryOrderClause o = other as QueryOrderClause; + return o != null && this.Orderings.DoMatch(o.Orderings, match); + } + } + + public class QueryOrdering : AstNode + { + public override NodeType NodeType { + get { return NodeType.Unknown; } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public QueryOrderingDirection Direction { + get; + set; + } + + public CSharpTokenNode DirectionToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryOrdering (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryOrdering o = other as QueryOrdering; + return o != null && this.Direction == o.Direction && this.Expression.DoMatch(o.Expression, match); + } + } + + public enum QueryOrderingDirection + { + None, + Ascending, + Descending + } + + public class QuerySelectClause : QueryClause + { + public CSharpTokenNode SelectKeyword { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQuerySelectClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QuerySelectClause o = other as QuerySelectClause; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } + + public class QueryGroupClause : QueryClause + { + public static readonly Role GroupKeywordRole = Roles.Keyword; + public static readonly Role ProjectionRole = new Role("Projection", Expression.Null); + public static readonly Role ByKeywordRole = new Role("ByKeyword", CSharpTokenNode.Null); + public static readonly Role KeyRole = new Role("Key", Expression.Null); + + public CSharpTokenNode GroupKeyword { + get { return GetChildByRole (GroupKeywordRole); } + } + + public Expression Projection { + get { return GetChildByRole (ProjectionRole); } + set { SetChildByRole (ProjectionRole, value); } + } + + public CSharpTokenNode ByKeyword { + get { return GetChildByRole (ByKeywordRole); } + } + + public Expression Key { + get { return GetChildByRole (KeyRole); } + set { SetChildByRole (KeyRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitQueryGroupClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryGroupClause o = other as QueryGroupClause; + return o != null && this.Projection.DoMatch(o.Projection, match) && this.Key.DoMatch(o.Key, match); + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/SizeOfExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/SizeOfExpression.cs new file mode 100644 index 0000000000..6e7a740d61 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/SizeOfExpression.cs @@ -0,0 +1,71 @@ +// +// SizeOfExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// sizeof(Type) + /// + public class SizeOfExpression : Expression + { + public CSharpTokenNode SizeOfToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public SizeOfExpression () + { + } + + public SizeOfExpression (AstType type) + { + AddChild (type, Roles.Type); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitSizeOfExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SizeOfExpression o = other as SizeOfExpression; + return o != null && this.Type.DoMatch(o.Type, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/StackAllocExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/StackAllocExpression.cs new file mode 100644 index 0000000000..ad7fc1a7ef --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/StackAllocExpression.cs @@ -0,0 +1,67 @@ +// +// StackAllocExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// stackalloc Type[Count] + /// + public class StackAllocExpression : Expression + { + public CSharpTokenNode StackAllocToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public CSharpTokenNode LBracketToken { + get { return GetChildByRole (Roles.LBracket); } + } + + public Expression CountExpression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode RBracketToken { + get { return GetChildByRole (Roles.RBracket); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitStackAllocExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + StackAllocExpression o = other as StackAllocExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.CountExpression.DoMatch(o.CountExpression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ThisReferenceExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ThisReferenceExpression.cs new file mode 100644 index 0000000000..5428cf04b9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ThisReferenceExpression.cs @@ -0,0 +1,61 @@ +// +// ThisReferenceExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// this + /// + public class ThisReferenceExpression : Expression + { + public AstLocation Location { + get; + set; + } + + public override AstLocation StartLocation { + get { + return Location; + } + } + public override AstLocation EndLocation { + get { + return new AstLocation (Location.Line, Location.Column + "this".Length); + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitThisReferenceExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ThisReferenceExpression o = other as ThisReferenceExpression; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeOfExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeOfExpression.cs new file mode 100644 index 0000000000..09e8931ff4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeOfExpression.cs @@ -0,0 +1,72 @@ +// +// TypeOfExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// typeof(Type) + /// + public class TypeOfExpression : Expression + { + public CSharpTokenNode TypeOfToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public TypeOfExpression () + { + } + + public TypeOfExpression (AstType type) + { + AddChild (type, Roles.Type); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitTypeOfExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeOfExpression o = other as TypeOfExpression; + return o != null && this.Type.DoMatch(o.Type, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeReferenceExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeReferenceExpression.cs new file mode 100644 index 0000000000..9104235f8a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeReferenceExpression.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents an AstType as an expression. + /// This is used when calling a method on a primitive type: "int.Parse()" + /// + public class TypeReferenceExpression : Expression + { + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeReferenceExpression(this, data); + } + + public TypeReferenceExpression () + { + } + + public TypeReferenceExpression (AstType type) + { + AddChild (type, Roles.Type); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeReferenceExpression o = other as TypeReferenceExpression; + return o != null && this.Type.DoMatch(o.Type, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs new file mode 100644 index 0000000000..fe0b2d2648 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs @@ -0,0 +1,124 @@ +// +// UnaryOperatorExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Operator Expression + /// + public class UnaryOperatorExpression : Expression + { + public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; + + public UnaryOperatorExpression() + { + } + + public UnaryOperatorExpression(UnaryOperatorType op, Expression expression) + { + this.Operator = op; + this.Expression = expression; + } + + public UnaryOperatorType Operator { + get; + set; + } + + public CSharpTokenNode OperatorToken { + get { return GetChildByRole (OperatorRole); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUnaryOperatorExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UnaryOperatorExpression o = other as UnaryOperatorExpression; + return o != null && this.Operator == o.Operator && this.Expression.DoMatch(o.Expression, match); + } + + public static string GetOperatorSymbol(UnaryOperatorType op) + { + switch (op) { + case UnaryOperatorType.Not: + return "!"; + case UnaryOperatorType.BitNot: + return "~"; + case UnaryOperatorType.Minus: + return "-"; + case UnaryOperatorType.Plus: + return "+"; + case UnaryOperatorType.Increment: + case UnaryOperatorType.PostIncrement: + return "++"; + case UnaryOperatorType.PostDecrement: + case UnaryOperatorType.Decrement: + return "--"; + case UnaryOperatorType.Dereference: + return "*"; + case UnaryOperatorType.AddressOf: + return "&"; + default: + throw new NotSupportedException("Invalid value for UnaryOperatorType"); + } + } + } + + public enum UnaryOperatorType + { + /// Logical not (!a) + Not, + /// Bitwise not (~a) + BitNot, + /// Unary minus (-a) + Minus, + /// Unary plus (+a) + Plus, + /// Pre increment (++a) + Increment, + /// Pre decrement (--a) + Decrement, + /// Post increment (a++) + PostIncrement, + /// Post decrement (a--) + PostDecrement, + /// Dereferencing (*a) + Dereference, + /// Get address (&a) + AddressOf + } + +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UncheckedExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UncheckedExpression.cs new file mode 100644 index 0000000000..6e9e61923a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UncheckedExpression.cs @@ -0,0 +1,71 @@ +// +// UncheckedExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// unchecked(Expression) + /// + public class UncheckedExpression : Expression + { + public CSharpTokenNode UncheckedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public UncheckedExpression () + { + } + + public UncheckedExpression (Expression expression) + { + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUncheckedExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UncheckedExpression o = other as UncheckedExpression; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UndocumentedExpression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UndocumentedExpression.cs new file mode 100644 index 0000000000..8bbd81a5f0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UndocumentedExpression.cs @@ -0,0 +1,77 @@ +// +// UndocumentedExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum UndocumentedExpressionType + { + ArgListAccess, // __arglist + ArgList, // __arglist (a1, a2, ..., an) + RefValue, // __refvalue (expr , type) + RefType, // __reftype (expr) + MakeRef // __makeref (expr) + } + + /// + /// Represents undocumented expressions. + /// + public class UndocumentedExpression : Expression + { + public UndocumentedExpressionType UndocumentedExpressionType { + get; set; + } + + public CSharpTokenNode UndocumentedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole(Roles.Argument); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUndocumentedExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UndocumentedExpression o = other as UndocumentedExpression; + return o != null && this.UndocumentedExpressionType == o.UndocumentedExpressionType && this.Arguments.DoMatch(o.Arguments, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs new file mode 100644 index 0000000000..95235527f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs @@ -0,0 +1,77 @@ +// +// Attribute.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Attribute(Arguments) + /// + public class Attribute : AstNode + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Arguments { + get { return base.GetChildrenByRole (Roles.Argument); } + } + + // HasArgumentList == false: [Empty] + public bool HasArgumentList { + get; + set; + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAttribute (this, data); + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + Attribute o = other as Attribute; + return o != null && this.Type.DoMatch (o.Type, match) && this.Arguments.DoMatch (o.Arguments, match); + } + + public override string ToString () + { + if (IsNull) + return "Null"; + var w = new System.IO.StringWriter (); + AcceptVisitor (new OutputVisitor (w, new CSharpFormattingOptions ()), null); + return w.ToString (); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs new file mode 100644 index 0000000000..bce347c92a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs @@ -0,0 +1,157 @@ +// +// AttributeSection.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// [AttributeTarget: Attributes] + /// + public class AttributeSection : AstNode + { + #region PatternPlaceholder + public static implicit operator AttributeSection(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : AttributeSection, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public static readonly Role AttributeRole = new Role("Attribute"); + public static readonly Role TargetRole = new Role("Target", CSharpTokenNode.Null); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public CSharpTokenNode LBracketToken { + get { return GetChildByRole (Roles.LBracket); } + } + + public string AttributeTarget { + get; + set; + } + + public AstNodeCollection Attributes { + get { return base.GetChildrenByRole (AttributeRole); } + } + + public CSharpTokenNode RBracketToken { + get { return GetChildByRole (Roles.RBracket); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAttributeSection (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + AttributeSection o = other as AttributeSection; + return o != null && this.AttributeTarget == o.AttributeTarget && this.Attributes.DoMatch(o.Attributes, match); + } + + public AttributeSection() + { + } + + public AttributeSection(Attribute attr) + { + this.Attributes.Add(attr); + } + +// public static string GetAttributeTargetName(AttributeTarget attributeTarget) +// { +// switch (attributeTarget) { +// case AttributeTarget.None: +// return null; +// case AttributeTarget.Assembly: +// return "assembly"; +// case AttributeTarget.Module: +// return "module"; +// case AttributeTarget.Type: +// return "type"; +// case AttributeTarget.Param: +// return "param"; +// case AttributeTarget.Field: +// return "field"; +// case AttributeTarget.Return: +// return "return"; +// case AttributeTarget.Method: +// return "method"; +// default: +// throw new NotSupportedException("Invalid value for AttributeTarget"); +// } +// } + } + + public enum AttributeTarget { + None, + Assembly, + Module, + + Type, + Param, + Field, + Return, + Method, + Unknown + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs new file mode 100644 index 0000000000..61b424f491 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs @@ -0,0 +1,106 @@ +// +// Comment.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum CommentType { + SingleLine, + MultiLine, + Documentation + } + + public class Comment : AstNode, IRelocatable + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public CommentType CommentType { + get; + set; + } + + public bool StartsLine { + get; + set; + } + + public string Content { + get; + set; + } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + } + + AstLocation endLocation; + public override AstLocation EndLocation { + get { + return endLocation; + } + } + + public Comment (string content, CommentType type = CommentType.SingleLine) + { + this.CommentType = type; + this.Content = content; + } + + public Comment (CommentType commentType, AstLocation startLocation, AstLocation endLocation) + { + this.CommentType = commentType; + this.startLocation = startLocation; + this.endLocation = endLocation; + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + int lineDelta = startLocation.Line - this.startLocation.Line; + endLocation = new AstLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column); + this.startLocation = startLocation; + } + #endregion + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitComment (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + Comment o = other as Comment; + return o != null && this.CommentType == o.CommentType && MatchString(this.Content, o.Content); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs new file mode 100644 index 0000000000..48c4e0ecb4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs @@ -0,0 +1,73 @@ +// +// Constraint.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// where TypeParameter : BaseTypes + /// + /// + /// new(), struct and class constraints are represented using a PrimitiveType "new", "struct" or "class" + /// + public class Constraint : AstNode + { + public readonly static Role ColonRole = TypeDeclaration.ColonRole; + public readonly static Role BaseTypeRole = TypeDeclaration.BaseTypeRole; + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public string TypeParameter { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public AstNodeCollection BaseTypes { + get { return GetChildrenByRole (BaseTypeRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitConstraint (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + Constraint o = other as Constraint; + return o != null && MatchString(this.TypeParameter, o.TypeParameter) && this.BaseTypes.DoMatch(o.BaseTypes, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs new file mode 100644 index 0000000000..c33c0bf246 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs @@ -0,0 +1,100 @@ +// +// DelegateDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// delegate ReturnType Name<TypeParameters>(Parameters) where Constraints; + /// + public class DelegateDeclaration : AttributedNode + { + public override NodeType NodeType { + get { + return NodeType.TypeDeclaration; + } + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole (Roles.TypeParameter); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public AstNodeCollection Constraints { + get { return GetChildrenByRole (Roles.Constraint); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitDelegateDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DelegateDeclaration o = other as DelegateDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && MatchString(this.Name, o.Name) + && this.TypeParameters.DoMatch(o.TypeParameters, match) && this.Parameters.DoMatch(o.Parameters, match) + && this.Constraints.DoMatch(o.Constraints, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs new file mode 100644 index 0000000000..7d9a33df4f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs @@ -0,0 +1,83 @@ +// +// ExternAliasDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// extern alias ; + /// + public class ExternAliasDeclaration : AstNode + { + public static readonly Role AliasRole = new Role ("Alias", CSharpTokenNode.Null); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public CSharpTokenNode ExternToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode AliasToken { + get { return GetChildByRole (AliasRole); } + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitExternAliasDeclaration (this, data); + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + var o = other as ExternAliasDeclaration; + return o != null && MatchString (this.Name, o.Name); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs new file mode 100644 index 0000000000..c580f3790c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs @@ -0,0 +1,123 @@ +// +// NamespaceDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// namespace Name { Members } + /// + public class NamespaceDeclaration : AstNode + { + public static readonly Role MemberRole = CompilationUnit.MemberRole; + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public string Name { + get { + StringBuilder builder = new StringBuilder (); + foreach (Identifier identifier in GetChildrenByRole (Roles.Identifier)) { + if (builder.Length > 0) + builder.Append ('.'); + builder.Append (identifier.Name); + } + return builder.ToString (); + } + set { + GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => Identifier.Create (ident, AstLocation.Empty))); + } + } + + public AstNodeCollection Identifiers { + get { return GetChildrenByRole (Roles.Identifier); } + } + + /// + /// Gets the full namespace name (including any parent namespaces) + /// + public string FullName { + get { + NamespaceDeclaration parentNamespace = Parent as NamespaceDeclaration; + if (parentNamespace != null) + return BuildQualifiedName (parentNamespace.FullName, Name); + return Name; + } + } + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public AstNodeCollection Members { + get { return GetChildrenByRole(MemberRole); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public NamespaceDeclaration () + { + } + + public NamespaceDeclaration (string name) + { + this.Name = name; + } + + public static string BuildQualifiedName (string name1, string name2) + { + if (string.IsNullOrEmpty (name1)) + return name2; + if (string.IsNullOrEmpty (name2)) + return name1; + return name1 + "." + name2; + } + + public void AddMember (AstNode child) + { + AddChild (child, MemberRole); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitNamespaceDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + NamespaceDeclaration o = other as NamespaceDeclaration; + return o != null && MatchString(this.Name, o.Name) && this.Members.DoMatch(o.Members, match); + } + } +}; diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs new file mode 100644 index 0000000000..945c936cd6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs @@ -0,0 +1,109 @@ +// +// TypeDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// class Name<TypeParameters> : BaseTypes where Constraints; + /// + public class TypeDeclaration : AttributedNode + { + public readonly static Role ColonRole = Roles.Colon; + public readonly static Role BaseTypeRole = new Role("BaseType", AstType.Null); + public readonly static Role MemberRole = new Role("Member"); + + public override NodeType NodeType { + get { + return NodeType.TypeDeclaration; + } + } + + public ClassType ClassType { + get; + set; + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole (Roles.TypeParameter); } + } + + public AstNodeCollection BaseTypes { + get { return GetChildrenByRole (BaseTypeRole); } + } + + public AstNodeCollection Constraints { + get { return GetChildrenByRole (Roles.Constraint); } + } + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public AstNodeCollection Members { + get { return GetChildrenByRole (MemberRole); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitTypeDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeDeclaration o = other as TypeDeclaration; + return o != null && this.ClassType == o.ClassType && this.MatchAttributesAndModifiers(o, match) + && MatchString(this.Name, o.Name) && this.TypeParameters.DoMatch(o.TypeParameters, match) + && this.BaseTypes.DoMatch(o.BaseTypes, match) && this.Constraints.DoMatch(o.Constraints, match) + && this.Members.DoMatch(o.Members, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs new file mode 100644 index 0000000000..ee2d58eb37 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs @@ -0,0 +1,62 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// [in|out] Name + /// + /// Represents a type parameter. + /// Note: mirroring the C# syntax, constraints are not part of the type parameter declaration, but belong + /// to the parent type or method. + /// + public class TypeParameterDeclaration : AstNode + { + public static readonly Role AttributeRole = AttributedNode.AttributeRole; + public static readonly Role VarianceRole = new Role("Variance"); + + public override NodeType NodeType { + get { return NodeType.Unknown; } + } + + public AstNodeCollection Attributes { + get { return GetChildrenByRole (AttributeRole); } + } + + public VarianceModifier Variance { + get; set; + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeParameterDeclaration(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeParameterDeclaration o = other as TypeParameterDeclaration; + return o != null && this.Variance == o.Variance && MatchString(this.Name, o.Name) && this.Attributes.DoMatch(o.Attributes, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs new file mode 100644 index 0000000000..7fd3dfa096 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs @@ -0,0 +1,96 @@ +// +// UsingAliasDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// using Alias = Import; + /// + public class UsingAliasDeclaration : AstNode + { + public static readonly Role AliasRole = new Role("Alias", Identifier.Null); + public static readonly Role ImportRole = UsingDeclaration.ImportRole; + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public CSharpTokenNode UsingToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public string Alias { + get { + return GetChildByRole (AliasRole).Name; + } + set { + SetChildByRole(AliasRole, Identifier.Create (value, AstLocation.Empty)); + } + } + + public CSharpTokenNode AssignToken { + get { return GetChildByRole (Roles.Assign); } + } + + public AstType Import { + get { return GetChildByRole (ImportRole); } + set { SetChildByRole (ImportRole, value); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public UsingAliasDeclaration () + { + } + + public UsingAliasDeclaration (string alias, string nameSpace) + { + AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole); + AddChild (new SimpleType (nameSpace), ImportRole); + } + + public UsingAliasDeclaration (string alias, AstType import) + { + AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole); + AddChild (import, ImportRole); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUsingAliasDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UsingAliasDeclaration o = other as UsingAliasDeclaration; + return o != null && MatchString(this.Alias, o.Alias) && this.Import.DoMatch(o.Import, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingDeclaration.cs new file mode 100644 index 0000000000..77c2697f85 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingDeclaration.cs @@ -0,0 +1,88 @@ +// +// UsingDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// using Import; + /// + public class UsingDeclaration : AstNode + { + public static readonly Role ImportRole = new Role("Import", AstType.Null); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public CSharpTokenNode UsingToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Import { + get { return GetChildByRole (ImportRole); } + set { SetChildByRole (ImportRole, value); } + } + + public string Namespace { + get { return this.Import.ToString(); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public UsingDeclaration () + { + } + + public UsingDeclaration (string nameSpace) + { + AddChild (new SimpleType (nameSpace), ImportRole); + } + + public UsingDeclaration (AstType import) + { + AddChild (import, ImportRole); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUsingDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UsingDeclaration o = other as UsingDeclaration; + return o != null && this.Import.DoMatch(o.Import, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs new file mode 100644 index 0000000000..4092d56713 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs @@ -0,0 +1,131 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// AST visitor. + /// + public interface IAstVisitor + { + S VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, T data); + S VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, T data); + S VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, T data); + S VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, T data); + S VisitAsExpression(AsExpression asExpression, T data); + S VisitAssignmentExpression(AssignmentExpression assignmentExpression, T data); + S VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, T data); + S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data); + S VisitCastExpression(CastExpression castExpression, T data); + S VisitCheckedExpression(CheckedExpression checkedExpression, T data); + S VisitConditionalExpression(ConditionalExpression conditionalExpression, T data); + S VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, T data); + S VisitDirectionExpression(DirectionExpression directionExpression, T data); + S VisitIdentifierExpression(IdentifierExpression identifierExpression, T data); + S VisitIndexerExpression(IndexerExpression indexerExpression, T data); + S VisitInvocationExpression(InvocationExpression invocationExpression, T data); + S VisitIsExpression(IsExpression isExpression, T data); + S VisitLambdaExpression(LambdaExpression lambdaExpression, T data); + S VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, T data); + S VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, T data); + S VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, T data); + S VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, T data); + S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data); + S VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, T data); + S VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, T data); + S VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, T data); + S VisitSizeOfExpression(SizeOfExpression sizeOfExpression, T data); + S VisitStackAllocExpression(StackAllocExpression stackAllocExpression, T data); + S VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, T data); + S VisitTypeOfExpression(TypeOfExpression typeOfExpression, T data); + S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data); + S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data); + S VisitUncheckedExpression(UncheckedExpression uncheckedExpression, T data); + S VisitEmptyExpression (EmptyExpression emptyExpression, T data); + + S VisitQueryExpression(QueryExpression queryExpression, T data); + S VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, T data); + S VisitQueryFromClause(QueryFromClause queryFromClause, T data); + S VisitQueryLetClause(QueryLetClause queryLetClause, T data); + S VisitQueryWhereClause(QueryWhereClause queryWhereClause, T data); + S VisitQueryJoinClause(QueryJoinClause queryJoinClause, T data); + S VisitQueryOrderClause(QueryOrderClause queryOrderClause, T data); + S VisitQueryOrdering(QueryOrdering queryOrdering, T data); + S VisitQuerySelectClause(QuerySelectClause querySelectClause, T data); + S VisitQueryGroupClause(QueryGroupClause queryGroupClause, T data); + + S VisitAttribute(Attribute attribute, T data); + S VisitAttributeSection(AttributeSection attributeSection, T data); + S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data); + S VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, T data); + S VisitTypeDeclaration(TypeDeclaration typeDeclaration, T data); + S VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration, T data); + S VisitUsingDeclaration(UsingDeclaration usingDeclaration, T data); + S VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, T data); + + S VisitBlockStatement(BlockStatement blockStatement, T data); + S VisitBreakStatement(BreakStatement breakStatement, T data); + S VisitCheckedStatement(CheckedStatement checkedStatement, T data); + S VisitContinueStatement(ContinueStatement continueStatement, T data); + S VisitDoWhileStatement(DoWhileStatement doWhileStatement, T data); + S VisitEmptyStatement(EmptyStatement emptyStatement, T data); + S VisitExpressionStatement(ExpressionStatement expressionStatement, T data); + S VisitFixedStatement(FixedStatement fixedStatement, T data); + S VisitForeachStatement(ForeachStatement foreachStatement, T data); + S VisitForStatement(ForStatement forStatement, T data); + S VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, T data); + S VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, T data); + S VisitGotoStatement(GotoStatement gotoStatement, T data); + S VisitIfElseStatement(IfElseStatement ifElseStatement, T data); + S VisitLabelStatement(LabelStatement labelStatement, T data); + S VisitLockStatement(LockStatement lockStatement, T data); + S VisitReturnStatement(ReturnStatement returnStatement, T data); + S VisitSwitchStatement(SwitchStatement switchStatement, T data); + S VisitSwitchSection(SwitchSection switchSection, T data); + S VisitCaseLabel(CaseLabel caseLabel, T data); + S VisitThrowStatement(ThrowStatement throwStatement, T data); + S VisitTryCatchStatement(TryCatchStatement tryCatchStatement, T data); + S VisitCatchClause(CatchClause catchClause, T data); + S VisitUncheckedStatement(UncheckedStatement uncheckedStatement, T data); + S VisitUnsafeStatement(UnsafeStatement unsafeStatement, T data); + S VisitUsingStatement(UsingStatement usingStatement, T data); + S VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, T data); + S VisitWhileStatement(WhileStatement whileStatement, T data); + S VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, T data); + S VisitYieldStatement(YieldStatement yieldStatement, T data); + + S VisitAccessor(Accessor accessor, T data); + S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data); + S VisitConstructorInitializer(ConstructorInitializer constructorInitializer, T data); + S VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, T data); + S VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, T data); + S VisitEventDeclaration(EventDeclaration eventDeclaration, T data); + S VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration, T data); + S VisitFieldDeclaration(FieldDeclaration fieldDeclaration, T data); + S VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, T data); + S VisitMethodDeclaration(MethodDeclaration methodDeclaration, T data); + S VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, T data); + S VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, T data); + S VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, T data); + S VisitVariableInitializer(VariableInitializer variableInitializer, T data); + S VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, T data); + S VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, T data); + + S VisitCompilationUnit(CompilationUnit compilationUnit, T data); + S VisitSimpleType(SimpleType simpleType, T data); + S VisitMemberType(MemberType memberType, T data); + S VisitComposedType(ComposedType composedType, T data); + S VisitArraySpecifier(ArraySpecifier arraySpecifier, T data); + S VisitPrimitiveType(PrimitiveType primitiveType, T data); + + S VisitComment(Comment comment, T data); + S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data); + S VisitConstraint(Constraint constraint, T data); + S VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, T data); + S VisitIdentifier(Identifier identifier, T data); + + S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs new file mode 100644 index 0000000000..48205191fc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs @@ -0,0 +1,35 @@ +// +// IRelocationable.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public interface IRelocatable + { + void SetStartLocation (AstLocation startLocation); + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs new file mode 100644 index 0000000000..12bd644752 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs @@ -0,0 +1,163 @@ +// +// Identifier.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class Identifier : AstNode, IRelocatable + { + public static readonly Identifier Null = new NullIdentifier (); + class NullIdentifier : Identifier + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + string name; + public string Name { + get { return this.name; } + set { + if (value == null) + throw new ArgumentNullException("value"); + this.name = value; + } + } + + AstLocation startLocation; + public override AstLocation StartLocation { + get { + return startLocation; + } + + } + + public virtual bool IsVerbatim { + get { + return false; + } + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.startLocation = startLocation; + } + #endregion + + public override AstLocation EndLocation { + get { + return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length); + } + } + + Identifier () + { + this.name = string.Empty; + } + + protected Identifier (string name, AstLocation location) + { + if (name == null) + throw new ArgumentNullException("name"); + this.Name = name; + this.startLocation = location; + } + + public static Identifier Create (string name) + { + return Create (name, AstLocation.Empty); + } + + public static Identifier Create (string name, AstLocation location) + { + if (name == null) + throw new ArgumentNullException("name"); + if (name.Length > 0 && name[0] == '@') + return new VerbatimIdentifier(name.Substring (1), location); + return new Identifier (name, location); + } + + public static Identifier Create (string name, AstLocation location, bool isVerbatim) + { + if (name == null) + throw new ArgumentNullException("name"); + + if (isVerbatim) + return new VerbatimIdentifier(name, location); + return new Identifier (name, location); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIdentifier (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + Identifier o = other as Identifier; + return o != null && !o.IsNull && MatchString(this.Name, o.Name); + } + + class VerbatimIdentifier : Identifier + { + public override AstLocation EndLocation { + get { + return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + 1); // @"..." + } + } + + public override bool IsVerbatim { + get { + return true; + } + } + + public VerbatimIdentifier(string name, AstLocation location) : base (name, location) + { + } + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs new file mode 100644 index 0000000000..771623eac5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs @@ -0,0 +1,119 @@ +// +// FullTypeName.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class MemberType : AstType + { + public static readonly Role TargetRole = new Role("Target", AstType.Null); + + public bool IsDoubleColon { get; set; } + + public AstType Target { + get { return GetChildByRole(TargetRole); } + set { SetChildByRole(TargetRole, value); } + } + + public string MemberName { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier MemberNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public MemberType () + { + } + + public MemberType (AstType target, string memberName) + { + this.Target = target; + this.MemberName = memberName; + } + + public MemberType (AstType target, string memberName, IEnumerable typeArguments) + { + this.Target = target; + this.MemberName = memberName; + foreach (var arg in typeArguments) { + AddChild (arg, Roles.TypeArgument); + } + } + + public MemberType (AstType target, string memberName, params AstType[] typeArguments) : this (target, memberName, (IEnumerable)typeArguments) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitMemberType (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + MemberType o = other as MemberType; + return o != null && this.IsDoubleColon == o.IsDoubleColon && MatchString(this.MemberName, o.MemberName) && this.Target.DoMatch(o.Target, match); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append(this.Target); + if (IsDoubleColon) + b.Append("::"); + else + b.Append('.'); + b.Append(this.MemberName); + if (this.TypeArguments.Any()) { + b.Append('<'); + b.Append(DotNet35Compat.StringJoin(", ", this.TypeArguments)); + b.Append('>'); + } + return b.ToString(); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs new file mode 100644 index 0000000000..700a3c04d1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs @@ -0,0 +1,74 @@ +// +// Modifiers.cs +// +// Author: +// Mike Krüger +// +// Copyright (C) 2008 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + // For compatibility with old nrefactory - same flags. + [Flags] + public enum Modifiers + { + None = 0, + + Private = 0x0001, + Internal = 0x0002, + Protected = 0x0004, + Public = 0x0008, + + Abstract = 0x0010, + Virtual = 0x0020, + Sealed = 0x0040, + Static = 0x0080, + Override = 0x0100, + Readonly = 0x0200, + Const = 0x0400, + New = 0x0800, + Partial = 0x1000, + + Extern = 0x2000, + Volatile = 0x4000, + Unsafe = 0x8000, + + //Overloads = 0x10000, + //WithEvents = 0x20000, + //Default = 0x40000, + Fixed = 0x80000, + + //ProtectedOrInternal = Internal | Protected, + //ProtectedAndInternal = 0x100000, (not supported in C#) + //SpecialName = 0x200000, + //Final = 0x400000, + //Literal = 0x800000, + VisibilityMask = Private | Internal | Protected | Public, + + /// + /// Special value used to match any modifiers during pattern matching. + /// + Any = unchecked((int)0x80000000) + }} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs new file mode 100644 index 0000000000..5fd175c771 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs @@ -0,0 +1,52 @@ +// +// NodeType.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum NodeType + { + Unknown, + /// + /// DomType + /// + TypeReference, + /// + /// Type or delegate declaration + /// + TypeDeclaration, + Member, + Statement, + Expression, + Token, + QueryClause, + /// + /// Placeholder for a pattern + /// + Pattern + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs new file mode 100644 index 0000000000..253f6ef3c3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs @@ -0,0 +1,1141 @@ +// +// ObservableAstVisitor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class ObservableAstVisitor: IAstVisitor + { + S VisitChildren (AstNode node, T data) + { + AstNode next; + for (var child = node.FirstChild; child != null; child = next) { + // Store next to allow the loop to continue + // if the visitor removes/replaces child. + next = child.NextSibling; + child.AcceptVisitor (this, data); + } + return default (S); + } + + public event Action CompilationUnitVisited; + + S IAstVisitor.VisitCompilationUnit (CompilationUnit unit, T data) + { + var handler = CompilationUnitVisited; + if (handler != null) + handler (unit, data); + return VisitChildren (unit, data); + } + + public event Action CommentVisited; + + S IAstVisitor.VisitComment (Comment comment, T data) + { + var handler = CommentVisited; + if (handler != null) + handler (comment, data); + return VisitChildren (comment, data); + } + + public event Action IdentifierVisited; + + S IAstVisitor.VisitIdentifier (Identifier identifier, T data) + { + var handler = IdentifierVisited; + if (handler != null) + handler (identifier, data); + return VisitChildren (identifier, data); + } + + public event Action CSharpTokenNodeVisited; + + S IAstVisitor.VisitCSharpTokenNode (CSharpTokenNode token, T data) + { + var handler = CSharpTokenNodeVisited; + if (handler != null) + handler (token, data); + return VisitChildren (token, data); + } + + public event Action PrimitiveTypeVisited; + + S IAstVisitor.VisitPrimitiveType (PrimitiveType primitiveType, T data) + { + var handler = PrimitiveTypeVisited; + if (handler != null) + handler (primitiveType, data); + return VisitChildren (primitiveType, data); + } + + public event Action ComposedTypeVisited; + + S IAstVisitor.VisitComposedType (ComposedType composedType, T data) + { + var handler = ComposedTypeVisited; + if (handler != null) + handler (composedType, data); + return VisitChildren (composedType, data); + } + + public event Action SimpleTypeVisited; + + S IAstVisitor.VisitSimpleType (SimpleType simpleType, T data) + { + var handler = SimpleTypeVisited; + if (handler != null) + handler (simpleType, data); + return VisitChildren (simpleType, data); + } + + public event Action MemberTypeVisited; + + S IAstVisitor.VisitMemberType (MemberType memberType, T data) + { + var handler = MemberTypeVisited; + if (handler != null) + handler (memberType, data); + return VisitChildren (memberType, data); + } + + public event Action AttributeVisited; + + S IAstVisitor.VisitAttribute (Attribute attribute, T data) + { + var handler = AttributeVisited; + if (handler != null) + handler (attribute, data); + return VisitChildren (attribute, data); + } + + public event Action AttributeSectionVisited; + + S IAstVisitor.VisitAttributeSection (AttributeSection attributeSection, T data) + { + var handler = AttributeSectionVisited; + if (handler != null) + handler (attributeSection, data); + return VisitChildren (attributeSection, data); + } + + public event Action DelegateDeclarationVisited; + + S IAstVisitor.VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, T data) + { + var handler = DelegateDeclarationVisited; + if (handler != null) + handler (delegateDeclaration, data); + return VisitChildren (delegateDeclaration, data); + } + + public event Action NamespaceDeclarationVisited; + + S IAstVisitor.VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, T data) + { + var handler = NamespaceDeclarationVisited; + if (handler != null) + handler (namespaceDeclaration, data); + return VisitChildren (namespaceDeclaration, data); + } + + public event Action TypeDeclarationVisited; + + S IAstVisitor.VisitTypeDeclaration (TypeDeclaration typeDeclaration, T data) + { + var handler = TypeDeclarationVisited; + if (handler != null) + handler (typeDeclaration, data); + return VisitChildren (typeDeclaration, data); + } + + public event Action TypeParameterDeclarationVisited; + + S IAstVisitor.VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, T data) + { + var handler = TypeParameterDeclarationVisited; + if (handler != null) + handler (typeParameterDeclaration, data); + return VisitChildren (typeParameterDeclaration, data); + } + + public event Action EnumMemberDeclarationVisited; + + S IAstVisitor.VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, T data) + { + var handler = EnumMemberDeclarationVisited; + if (handler != null) + handler (enumMemberDeclaration, data); + return VisitChildren (enumMemberDeclaration, data); + } + + public event Action UsingDeclarationVisited; + + S IAstVisitor.VisitUsingDeclaration (UsingDeclaration usingDeclaration, T data) + { + var handler = UsingDeclarationVisited; + if (handler != null) + handler (usingDeclaration, data); + return VisitChildren (usingDeclaration, data); + } + + public event Action UsingAliasDeclarationVisited; + + S IAstVisitor.VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, T data) + { + var handler = UsingAliasDeclarationVisited; + if (handler != null) + handler (usingDeclaration, data); + return VisitChildren (usingDeclaration, data); + } + + public event Action ExternAliasDeclarationVisited; + + S IAstVisitor.VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration, T data) + { + var handler = ExternAliasDeclarationVisited; + if (handler != null) + handler (externAliasDeclaration, data); + return VisitChildren (externAliasDeclaration, data); + } + + public event Action ConstructorDeclarationVisited; + + S IAstVisitor.VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, T data) + { + var handler = ConstructorDeclarationVisited; + if (handler != null) + handler (constructorDeclaration, data); + return VisitChildren (constructorDeclaration, data); + } + + public event Action ConstructorInitializerVisited; + + S IAstVisitor.VisitConstructorInitializer (ConstructorInitializer constructorInitializer, T data) + { + var handler = ConstructorInitializerVisited; + if (handler != null) + handler (constructorInitializer, data); + return VisitChildren (constructorInitializer, data); + } + + public event Action DestructorDeclarationVisited; + + S IAstVisitor.VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, T data) + { + var handler = DestructorDeclarationVisited; + if (handler != null) + handler (destructorDeclaration, data); + return VisitChildren (destructorDeclaration, data); + } + + public event Action EventDeclarationVisited; + + S IAstVisitor.VisitEventDeclaration (EventDeclaration eventDeclaration, T data) + { + var handler = EventDeclarationVisited; + if (handler != null) + handler (eventDeclaration, data); + return VisitChildren (eventDeclaration, data); + } + + public event Action CustomEventDeclarationVisited; + + S IAstVisitor.VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, T data) + { + var handler = CustomEventDeclarationVisited; + if (handler != null) + handler (eventDeclaration, data); + return VisitChildren (eventDeclaration, data); + } + + public event Action FieldDeclarationVisited; + + S IAstVisitor.VisitFieldDeclaration (FieldDeclaration fieldDeclaration, T data) + { + var handler = FieldDeclarationVisited; + if (handler != null) + handler (fieldDeclaration, data); + return VisitChildren (fieldDeclaration, data); + } + + public event Action FixedFieldDeclarationVisited; + + S IAstVisitor.VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, T data) + { + var handler = FixedFieldDeclarationVisited; + if (handler != null) + handler (fixedFieldDeclaration, data); + return VisitChildren (fixedFieldDeclaration, data); + } + + public event Action FixedVariableInitializerVisited; + + S IAstVisitor.VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, T data) + { + var handler = FixedVariableInitializerVisited; + if (handler != null) + handler (fixedVariableInitializer, data); + return VisitChildren (fixedVariableInitializer, data); + } + + public event Action IndexerDeclarationVisited; + + S IAstVisitor.VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, T data) + { + var handler = IndexerDeclarationVisited; + if (handler != null) + handler (indexerDeclaration, data); + return VisitChildren (indexerDeclaration, data); + } + + public event Action MethodDeclarationVisited; + + S IAstVisitor.VisitMethodDeclaration (MethodDeclaration methodDeclaration, T data) + { + var handler = MethodDeclarationVisited; + if (handler != null) + handler (methodDeclaration, data); + return VisitChildren (methodDeclaration, data); + } + + public event Action OperatorDeclarationVisited; + + S IAstVisitor.VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, T data) + { + var handler = OperatorDeclarationVisited; + if (handler != null) + handler (operatorDeclaration, data); + return VisitChildren (operatorDeclaration, data); + } + + public event Action PropertyDeclarationVisited; + + S IAstVisitor.VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, T data) + { + var handler = PropertyDeclarationVisited; + if (handler != null) + handler (propertyDeclaration, data); + return VisitChildren (propertyDeclaration, data); + } + + public event Action AccessorVisited; + + S IAstVisitor.VisitAccessor (Accessor accessor, T data) + { + var handler = AccessorVisited; + if (handler != null) + handler (accessor, data); + return VisitChildren (accessor, data); + } + + public event Action VariableInitializerVisited; + + S IAstVisitor.VisitVariableInitializer (VariableInitializer variableInitializer, T data) + { + var handler = VariableInitializerVisited; + if (handler != null) + handler (variableInitializer, data); + return VisitChildren (variableInitializer, data); + } + + public event Action ParameterDeclarationVisited; + + S IAstVisitor.VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, T data) + { + var handler = ParameterDeclarationVisited; + if (handler != null) + handler (parameterDeclaration, data); + return VisitChildren (parameterDeclaration, data); + } + + public event Action ConstraintVisited; + + S IAstVisitor.VisitConstraint (Constraint constraint, T data) + { + var handler = ConstraintVisited; + if (handler != null) + handler (constraint, data); + return VisitChildren (constraint, data); + } + + public event Action BlockStatementVisited; + + S IAstVisitor.VisitBlockStatement (BlockStatement blockStatement, T data) + { + var handler = BlockStatementVisited; + if (handler != null) + handler (blockStatement, data); + return VisitChildren (blockStatement, data); + } + + public event Action ExpressionStatementVisited; + + S IAstVisitor.VisitExpressionStatement (ExpressionStatement expressionStatement, T data) + { + var handler = ExpressionStatementVisited; + if (handler != null) + handler (expressionStatement, data); + return VisitChildren (expressionStatement, data); + } + + public event Action BreakStatementVisited; + + S IAstVisitor.VisitBreakStatement (BreakStatement breakStatement, T data) + { + var handler = BreakStatementVisited; + if (handler != null) + handler (breakStatement, data); + return VisitChildren (breakStatement, data); + } + + public event Action CheckedStatementVisited; + + S IAstVisitor.VisitCheckedStatement (CheckedStatement checkedStatement, T data) + { + var handler = CheckedStatementVisited; + if (handler != null) + handler (checkedStatement, data); + return VisitChildren (checkedStatement, data); + } + + public event Action ContinueStatementVisited; + + S IAstVisitor.VisitContinueStatement (ContinueStatement continueStatement, T data) + { + var handler = ContinueStatementVisited; + if (handler != null) + handler (continueStatement, data); + return VisitChildren (continueStatement, data); + } + + public event Action DoWhileStatementVisited; + + S IAstVisitor.VisitDoWhileStatement (DoWhileStatement doWhileStatement, T data) + { + var handler = DoWhileStatementVisited; + if (handler != null) + handler (doWhileStatement, data); + return VisitChildren (doWhileStatement, data); + } + + public event Action EmptyStatementVisited; + + S IAstVisitor.VisitEmptyStatement (EmptyStatement emptyStatement, T data) + { + var handler = EmptyStatementVisited; + if (handler != null) + handler (emptyStatement, data); + return VisitChildren (emptyStatement, data); + } + + public event Action FixedStatementVisited; + + S IAstVisitor.VisitFixedStatement (FixedStatement fixedStatement, T data) + { + var handler = FixedStatementVisited; + if (handler != null) + handler (fixedStatement, data); + return VisitChildren (fixedStatement, data); + } + + public event Action ForeachStatementVisited; + + S IAstVisitor.VisitForeachStatement (ForeachStatement foreachStatement, T data) + { + var handler = ForeachStatementVisited; + if (handler != null) + handler (foreachStatement, data); + return VisitChildren (foreachStatement, data); + } + + public event Action ForStatementVisited; + + S IAstVisitor.VisitForStatement (ForStatement forStatement, T data) + { + var handler = ForStatementVisited; + if (handler != null) + handler (forStatement, data); + return VisitChildren (forStatement, data); + } + + public event Action GotoCaseStatementVisited; + + S IAstVisitor.VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, T data) + { + var handler = GotoCaseStatementVisited; + if (handler != null) + handler (gotoCaseStatement, data); + return VisitChildren (gotoCaseStatement, data); + } + + public event Action GotoDefaultStatementVisited; + + S IAstVisitor.VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, T data) + { + var handler = GotoDefaultStatementVisited; + if (handler != null) + handler (gotoDefaultStatement, data); + return VisitChildren (gotoDefaultStatement, data); + } + + public event Action GotoStatementVisited; + + S IAstVisitor.VisitGotoStatement (GotoStatement gotoStatement, T data) + { + var handler = GotoStatementVisited; + if (handler != null) + handler (gotoStatement, data); + return VisitChildren (gotoStatement, data); + } + + public event Action IfElseStatementVisited; + + S IAstVisitor.VisitIfElseStatement (IfElseStatement ifElseStatement, T data) + { + var handler = IfElseStatementVisited; + if (handler != null) + handler (ifElseStatement, data); + return VisitChildren (ifElseStatement, data); + } + + public event Action LabelStatementVisited; + + S IAstVisitor.VisitLabelStatement (LabelStatement labelStatement, T data) + { + var handler = LabelStatementVisited; + if (handler != null) + handler (labelStatement, data); + return VisitChildren (labelStatement, data); + } + + public event Action LockStatementVisited; + + S IAstVisitor.VisitLockStatement (LockStatement lockStatement, T data) + { + var handler = LockStatementVisited; + if (handler != null) + handler (lockStatement, data); + return VisitChildren (lockStatement, data); + } + + public event Action ReturnStatementVisited; + + S IAstVisitor.VisitReturnStatement (ReturnStatement returnStatement, T data) + { + var handler = ReturnStatementVisited; + if (handler != null) + handler (returnStatement, data); + return VisitChildren (returnStatement, data); + } + + public event Action SwitchStatementVisited; + + S IAstVisitor.VisitSwitchStatement (SwitchStatement switchStatement, T data) + { + var handler = SwitchStatementVisited; + if (handler != null) + handler (switchStatement, data); + return VisitChildren (switchStatement, data); + } + + public event Action SwitchSectionVisited; + + S IAstVisitor.VisitSwitchSection (SwitchSection switchSection, T data) + { + var handler = SwitchSectionVisited; + if (handler != null) + handler (switchSection, data); + return VisitChildren (switchSection, data); + } + + public event Action CaseLabelVisited; + + S IAstVisitor.VisitCaseLabel (CaseLabel caseLabel, T data) + { + var handler = CaseLabelVisited; + if (handler != null) + handler (caseLabel, data); + return VisitChildren (caseLabel, data); + } + + public event Action ThrowStatementVisited; + + S IAstVisitor.VisitThrowStatement (ThrowStatement throwStatement, T data) + { + var handler = ThrowStatementVisited; + if (handler != null) + handler (throwStatement, data); + return VisitChildren (throwStatement, data); + } + + public event Action TryCatchStatementVisited; + + S IAstVisitor.VisitTryCatchStatement (TryCatchStatement tryCatchStatement, T data) + { + var handler = TryCatchStatementVisited; + if (handler != null) + handler (tryCatchStatement, data); + return VisitChildren (tryCatchStatement, data); + } + + public event Action CatchClauseVisited; + + S IAstVisitor.VisitCatchClause (CatchClause catchClause, T data) + { + var handler = CatchClauseVisited; + if (handler != null) + handler (catchClause, data); + return VisitChildren (catchClause, data); + } + + public event Action UncheckedStatementVisited; + + S IAstVisitor.VisitUncheckedStatement (UncheckedStatement uncheckedStatement, T data) + { + var handler = UncheckedStatementVisited; + if (handler != null) + handler (uncheckedStatement, data); + return VisitChildren (uncheckedStatement, data); + } + + public event Action UnsafeStatementVisited; + + S IAstVisitor.VisitUnsafeStatement (UnsafeStatement unsafeStatement, T data) + { + var handler = UnsafeStatementVisited; + if (handler != null) + handler (unsafeStatement, data); + return VisitChildren (unsafeStatement, data); + } + + public event Action UsingStatementVisited; + + S IAstVisitor.VisitUsingStatement (UsingStatement usingStatement, T data) + { + var handler = UsingStatementVisited; + if (handler != null) + handler (usingStatement, data); + return VisitChildren (usingStatement, data); + } + + public event Action VariableDeclarationStatementVisited; + + S IAstVisitor.VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, T data) + { + var handler = VariableDeclarationStatementVisited; + if (handler != null) + handler (variableDeclarationStatement, data); + return VisitChildren (variableDeclarationStatement, data); + } + + public event Action WhileStatementVisited; + + S IAstVisitor.VisitWhileStatement (WhileStatement whileStatement, T data) + { + var handler = WhileStatementVisited; + if (handler != null) + handler (whileStatement, data); + return VisitChildren (whileStatement, data); + } + + public event Action YieldBreakStatementVisited; + + S IAstVisitor.VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, T data) + { + var handler = YieldBreakStatementVisited; + if (handler != null) + handler (yieldBreakStatement, data); + return VisitChildren (yieldBreakStatement, data); + } + + public event Action YieldStatementVisited; + + S IAstVisitor.VisitYieldStatement (YieldStatement yieldStatement, T data) + { + var handler = YieldStatementVisited; + if (handler != null) + handler (yieldStatement, data); + return VisitChildren (yieldStatement, data); + } + + public event Action AnonymousMethodExpressionVisited; + + S IAstVisitor.VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, T data) + { + var handler = AnonymousMethodExpressionVisited; + if (handler != null) + handler (anonymousMethodExpression, data); + return VisitChildren (anonymousMethodExpression, data); + } + + public event Action LambdaExpressionVisited; + + S IAstVisitor.VisitLambdaExpression (LambdaExpression lambdaExpression, T data) + { + var handler = LambdaExpressionVisited; + if (handler != null) + handler (lambdaExpression, data); + return VisitChildren (lambdaExpression, data); + } + + public event Action AssignmentExpressionVisited; + + S IAstVisitor.VisitAssignmentExpression (AssignmentExpression assignmentExpression, T data) + { + var handler = AssignmentExpressionVisited; + if (handler != null) + handler (assignmentExpression, data); + return VisitChildren (assignmentExpression, data); + } + + public event Action BaseReferenceExpressionVisited; + + S IAstVisitor.VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, T data) + { + var handler = BaseReferenceExpressionVisited; + if (handler != null) + handler (baseReferenceExpression, data); + return VisitChildren (baseReferenceExpression, data); + } + + public event Action BinaryOperatorExpressionVisited; + + S IAstVisitor.VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, T data) + { + var handler = BinaryOperatorExpressionVisited; + if (handler != null) + handler (binaryOperatorExpression, data); + return VisitChildren (binaryOperatorExpression, data); + } + + public event Action CastExpressionVisited; + + S IAstVisitor.VisitCastExpression (CastExpression castExpression, T data) + { + var handler = CastExpressionVisited; + if (handler != null) + handler (castExpression, data); + return VisitChildren (castExpression, data); + } + + public event Action CheckedExpressionVisited; + + S IAstVisitor.VisitCheckedExpression (CheckedExpression checkedExpression, T data) + { + var handler = CheckedExpressionVisited; + if (handler != null) + handler (checkedExpression, data); + return VisitChildren (checkedExpression, data); + } + + public event Action ConditionalExpressionVisited; + + S IAstVisitor.VisitConditionalExpression (ConditionalExpression conditionalExpression, T data) + { + var handler = ConditionalExpressionVisited; + if (handler != null) + handler (conditionalExpression, data); + return VisitChildren (conditionalExpression, data); + } + + public event Action IdentifierExpressionVisited; + + S IAstVisitor.VisitIdentifierExpression (IdentifierExpression identifierExpression, T data) + { + var handler = IdentifierExpressionVisited; + if (handler != null) + handler (identifierExpression, data); + return VisitChildren (identifierExpression, data); + } + + public event Action IndexerExpressionVisited; + + S IAstVisitor.VisitIndexerExpression (IndexerExpression indexerExpression, T data) + { + var handler = IndexerExpressionVisited; + if (handler != null) + handler (indexerExpression, data); + return VisitChildren (indexerExpression, data); + } + + public event Action InvocationExpressionVisited; + + S IAstVisitor.VisitInvocationExpression (InvocationExpression invocationExpression, T data) + { + var handler = InvocationExpressionVisited; + if (handler != null) + handler (invocationExpression, data); + return VisitChildren (invocationExpression, data); + } + + public event Action DirectionExpressionVisited; + + S IAstVisitor.VisitDirectionExpression (DirectionExpression directionExpression, T data) + { + var handler = DirectionExpressionVisited; + if (handler != null) + handler (directionExpression, data); + return VisitChildren (directionExpression, data); + } + + public event Action MemberReferenceExpressionVisited; + + S IAstVisitor.VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, T data) + { + var handler = MemberReferenceExpressionVisited; + if (handler != null) + handler (memberReferenceExpression, data); + return VisitChildren (memberReferenceExpression, data); + } + + public event Action NullReferenceExpressionVisited; + + S IAstVisitor.VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, T data) + { + var handler = NullReferenceExpressionVisited; + if (handler != null) + handler (nullReferenceExpression, data); + return VisitChildren (nullReferenceExpression, data); + } + + public event Action ObjectCreateExpressionVisited; + + S IAstVisitor.VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, T data) + { + var handler = ObjectCreateExpressionVisited; + if (handler != null) + handler (objectCreateExpression, data); + return VisitChildren (objectCreateExpression, data); + } + + public event Action AnonymousTypeCreateExpressionVisited; + + S IAstVisitor.VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data) + { + var handler = AnonymousTypeCreateExpressionVisited; + if (handler != null) + handler (anonymousTypeCreateExpression, data); + return VisitChildren (anonymousTypeCreateExpression, data); + } + + public event Action ArrayCreateExpressionVisited; + + S IAstVisitor.VisitArrayCreateExpression (ArrayCreateExpression arraySCreateExpression, T data) + { + var handler = ArrayCreateExpressionVisited; + if (handler != null) + handler (arraySCreateExpression, data); + return VisitChildren (arraySCreateExpression, data); + } + + public event Action ParenthesizedExpressionVisited; + + S IAstVisitor.VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, T data) + { + var handler = ParenthesizedExpressionVisited; + if (handler != null) + handler (parenthesizedExpression, data); + return VisitChildren (parenthesizedExpression, data); + } + + public event Action PointerReferenceExpressionVisited; + + S IAstVisitor.VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, T data) + { + var handler = PointerReferenceExpressionVisited; + if (handler != null) + handler (pointerReferenceExpression, data); + return VisitChildren (pointerReferenceExpression, data); + } + + public event Action PrimitiveExpressionVisited; + + S IAstVisitor.VisitPrimitiveExpression (PrimitiveExpression primitiveExpression, T data) + { + var handler = PrimitiveExpressionVisited; + if (handler != null) + handler (primitiveExpression, data); + return VisitChildren (primitiveExpression, data); + } + + public event Action SizeOfExpressionVisited; + + S IAstVisitor.VisitSizeOfExpression (SizeOfExpression sizeOfExpression, T data) + { + var handler = SizeOfExpressionVisited; + if (handler != null) + handler (sizeOfExpression, data); + return VisitChildren (sizeOfExpression, data); + } + + public event Action StackAllocExpressionVisited; + + S IAstVisitor.VisitStackAllocExpression (StackAllocExpression stackAllocExpression, T data) + { + var handler = StackAllocExpressionVisited; + if (handler != null) + handler (stackAllocExpression, data); + return VisitChildren (stackAllocExpression, data); + } + + public event Action ThisReferenceExpressionVisited; + + S IAstVisitor.VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression, T data) + { + var handler = ThisReferenceExpressionVisited; + if (handler != null) + handler (thisReferenceExpression, data); + return VisitChildren (thisReferenceExpression, data); + } + + public event Action TypeOfExpressionVisited; + + S IAstVisitor.VisitTypeOfExpression (TypeOfExpression typeOfExpression, T data) + { + var handler = TypeOfExpressionVisited; + if (handler != null) + handler (typeOfExpression, data); + return VisitChildren (typeOfExpression, data); + } + + public event Action TypeReferenceExpressionVisited; + + S IAstVisitor.VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression, T data) + { + var handler = TypeReferenceExpressionVisited; + if (handler != null) + handler (typeReferenceExpression, data); + return VisitChildren (typeReferenceExpression, data); + } + + public event Action UnaryOperatorExpressionVisited; + + S IAstVisitor.VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, T data) + { + var handler = UnaryOperatorExpressionVisited; + if (handler != null) + handler (unaryOperatorExpression, data); + return VisitChildren (unaryOperatorExpression, data); + } + + public event Action UncheckedExpressionVisited; + + S IAstVisitor.VisitUncheckedExpression (UncheckedExpression uncheckedExpression, T data) + { + var handler = UncheckedExpressionVisited; + if (handler != null) + handler (uncheckedExpression, data); + return VisitChildren (uncheckedExpression, data); + } + + public event Action QueryExpressionVisited; + + S IAstVisitor.VisitQueryExpression (QueryExpression queryExpression, T data) + { + var handler = QueryExpressionVisited; + if (handler != null) + handler (queryExpression, data); + return VisitChildren (queryExpression, data); + } + + public event Action QueryContinuationClauseVisited; + + S IAstVisitor.VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause, T data) + { + var handler = QueryContinuationClauseVisited; + if (handler != null) + handler (queryContinuationClause, data); + return VisitChildren (queryContinuationClause, data); + } + + public event Action QueryFromClauseVisited; + + S IAstVisitor.VisitQueryFromClause (QueryFromClause queryFromClause, T data) + { + var handler = QueryFromClauseVisited; + if (handler != null) + handler (queryFromClause, data); + return VisitChildren (queryFromClause, data); + } + + public event Action QueryLetClauseVisited; + + S IAstVisitor.VisitQueryLetClause (QueryLetClause queryLetClause, T data) + { + var handler = QueryLetClauseVisited; + if (handler != null) + handler (queryLetClause, data); + return VisitChildren (queryLetClause, data); + } + + public event Action QueryWhereClauseVisited; + + S IAstVisitor.VisitQueryWhereClause (QueryWhereClause queryWhereClause, T data) + { + var handler = QueryWhereClauseVisited; + if (handler != null) + handler (queryWhereClause, data); + return VisitChildren (queryWhereClause, data); + } + + public event Action QueryJoinClauseVisited; + + S IAstVisitor.VisitQueryJoinClause (QueryJoinClause queryJoinClause, T data) + { + var handler = QueryJoinClauseVisited; + if (handler != null) + handler (queryJoinClause, data); + return VisitChildren (queryJoinClause, data); + } + + public event Action QueryOrderClauseVisited; + + S IAstVisitor.VisitQueryOrderClause (QueryOrderClause queryOrderClause, T data) + { + var handler = QueryOrderClauseVisited; + if (handler != null) + handler (queryOrderClause, data); + return VisitChildren (queryOrderClause, data); + } + + public event Action QueryOrderingVisited; + + S IAstVisitor.VisitQueryOrdering (QueryOrdering queryOrdering, T data) + { + var handler = QueryOrderingVisited; + if (handler != null) + handler (queryOrdering, data); + return VisitChildren (queryOrdering, data); + } + + public event Action QuerySelectClauseVisited; + + S IAstVisitor.VisitQuerySelectClause (QuerySelectClause querySelectClause, T data) + { + var handler = QuerySelectClauseVisited; + if (handler != null) + handler (querySelectClause, data); + return VisitChildren (querySelectClause, data); + } + + public event Action QueryGroupClauseVisited; + + S IAstVisitor.VisitQueryGroupClause (QueryGroupClause queryGroupClause, T data) + { + var handler = QueryGroupClauseVisited; + if (handler != null) + handler (queryGroupClause, data); + return VisitChildren (queryGroupClause, data); + } + + public event Action AsExpressionVisited; + + S IAstVisitor.VisitAsExpression (AsExpression asExpression, T data) + { + var handler = AsExpressionVisited; + if (handler != null) + handler (asExpression, data); + return VisitChildren (asExpression, data); + } + + public event Action IsExpressionVisited; + + S IAstVisitor.VisitIsExpression (IsExpression isExpression, T data) + { + var handler = IsExpressionVisited; + if (handler != null) + handler (isExpression, data); + return VisitChildren (isExpression, data); + } + + public event Action DefaultValueExpressionVisited; + + S IAstVisitor.VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, T data) + { + var handler = DefaultValueExpressionVisited; + if (handler != null) + handler (defaultValueExpression, data); + return VisitChildren (defaultValueExpression, data); + } + + public event Action UndocumentedExpressionVisited; + + S IAstVisitor.VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, T data) + { + var handler = UndocumentedExpressionVisited; + if (handler != null) + handler (undocumentedExpression, data); + return VisitChildren (undocumentedExpression, data); + } + + public event Action ArrayInitializerExpressionVisited; + + S IAstVisitor.VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, T data) + { + var handler = ArrayInitializerExpressionVisited; + if (handler != null) + handler (arrayInitializerExpression, data); + return VisitChildren (arrayInitializerExpression, data); + } + + public event Action ArraySpecifierVisited; + + S IAstVisitor.VisitArraySpecifier (ArraySpecifier arraySpecifier, T data) + { + var handler = ArraySpecifierVisited; + if (handler != null) + handler (arraySpecifier, data); + return VisitChildren (arraySpecifier, data); + } + + public event Action NamedArgumentExpressionVisited; + + S IAstVisitor.VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, T data) + { + var handler = NamedArgumentExpressionVisited; + if (handler != null) + handler (namedArgumentExpression, data); + return VisitChildren (namedArgumentExpression, data); + } + + public event Action EmptyExpressionVisited; + + S IAstVisitor.VisitEmptyExpression (EmptyExpression emptyExpression, T data) + { + var handler = EmptyExpressionVisited; + if (handler != null) + handler (emptyExpression, data); + return VisitChildren (emptyExpression, data); + } + + S IAstVisitor.VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern, T data) + { + return VisitChildren (placeholder, data); + } + } +} + + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs new file mode 100644 index 0000000000..26c93b21a7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs @@ -0,0 +1,88 @@ +// +// FullTypeName.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class PrimitiveType : AstType, IRelocatable + { + public string Keyword { get; set; } + public AstLocation Location { get; set; } + + public PrimitiveType() + { + } + + public PrimitiveType(string keyword) + { + this.Keyword = keyword; + } + + public PrimitiveType(string keyword, AstLocation location) + { + this.Keyword = keyword; + this.Location = location; + } + + public override AstLocation StartLocation { + get { + return Location; + } + } + public override AstLocation EndLocation { + get { + return new AstLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0)); + } + } + + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.Location = startLocation; + } + #endregion + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitPrimitiveType (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PrimitiveType o = other as PrimitiveType; + return o != null && MatchString(this.Keyword, o.Keyword); + } + + public override string ToString() + { + return Keyword ?? base.ToString(); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs new file mode 100644 index 0000000000..675b344a7f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Role.cs @@ -0,0 +1,67 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory +{ + /// + /// Represents the role a node plays within its parent. + /// + public abstract class Role + { + internal Role() {} // don't allow NRefactory consumers to derive from Role + + /// + /// Gets whether the specified node is valid in this role. + /// + public abstract bool IsValid(object node); + } + + /// + /// Represents the role a node plays within its parent. + /// All nodes with this role have type T. + /// + public sealed class Role : Role where T : class + { + readonly string name; // helps with debugging the AST + readonly T nullObject; + + /// + /// Gets the null object used when there's no node with this role. + /// Not every role has a null object; this property returns null for roles without a null object. + /// + /// + /// Roles used for non-collections should always have a null object, so that no AST property returns null. + /// However, roles used for collections only may leave out the null object. + /// + public T NullObject { + get { return nullObject; } + } + + public override bool IsValid(object node) + { + return node is T; + } + + public Role(string name) + { + if (name == null) + throw new ArgumentNullException("name"); + this.name = name; + } + + public Role(string name, T nullObject = null) + { + if (name == null) + throw new ArgumentNullException("name"); + this.nullObject = nullObject; + this.name = name; + } + + public override string ToString() + { + return name; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs new file mode 100644 index 0000000000..2609473e71 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs @@ -0,0 +1,107 @@ +// +// FullTypeName.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class SimpleType : AstType + { + public SimpleType() + { + } + + public SimpleType(string identifier) + { + this.Identifier = identifier; + } + + public SimpleType(string identifier, AstLocation location) + { + SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (identifier, location)); + } + + public SimpleType (string identifier, IEnumerable typeArguments) + { + this.Identifier = identifier; + foreach (var arg in typeArguments) { + AddChild (arg, Roles.TypeArgument); + } + } + + public SimpleType (string identifier, params AstType[] typeArguments) : this (identifier, (IEnumerable)typeArguments) + { + } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole (Roles.TypeArgument); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitSimpleType (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SimpleType o = other as SimpleType; + return o != null && MatchString(this.Identifier, o.Identifier) && this.TypeArguments.DoMatch(o.TypeArguments, match); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(this.Identifier); + if (this.TypeArguments.Any()) { + b.Append('<'); + b.Append(DotNet35Compat.StringJoin(", ", this.TypeArguments)); + b.Append('>'); + } + return b.ToString(); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs new file mode 100644 index 0000000000..50cf3e6cd4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs @@ -0,0 +1,157 @@ +// +// BlockStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// { Statements } + /// + public class BlockStatement : Statement, IEnumerable + { + public static readonly Role StatementRole = new Role("Statement", Statement.Null); + + #region Null + public static readonly new BlockStatement Null = new NullBlockStatement (); + sealed class NullBlockStatement : BlockStatement + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator BlockStatement(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : BlockStatement, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public AstNodeCollection Statements { + get { return GetChildrenByRole (StatementRole); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitBlockStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + BlockStatement o = other as BlockStatement; + return o != null && !o.IsNull && this.Statements.DoMatch(o.Statements, match); + } + + #region Builder methods + public void Add(Statement statement) + { + AddChild(statement, StatementRole); + } + + public void Add(Expression expression) + { + AddChild(new ExpressionStatement { Expression = expression }, StatementRole); + } + + public void AddRange(IEnumerable 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 IEnumerable.GetEnumerator() + { + return this.Statements.GetEnumerator(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.Statements.GetEnumerator(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/BreakStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/BreakStatement.cs new file mode 100644 index 0000000000..6599b5eafc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/BreakStatement.cs @@ -0,0 +1,49 @@ +// +// BreakStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// break; + /// + public class BreakStatement : Statement + { + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitBreakStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + BreakStatement o = other as BreakStatement; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/CheckedStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/CheckedStatement.cs new file mode 100644 index 0000000000..731649f4af --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/CheckedStatement.cs @@ -0,0 +1,63 @@ +// +// CheckedStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// checked BodyBlock + /// + public class CheckedStatement : Statement + { + public CSharpTokenNode CheckedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public CheckedStatement () + { + } + + public CheckedStatement (BlockStatement body) + { + AddChild (body, Roles.Body); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCheckedStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CheckedStatement o = other as CheckedStatement; + return o != null && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ContinueStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ContinueStatement.cs new file mode 100644 index 0000000000..1de6b5d505 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ContinueStatement.cs @@ -0,0 +1,49 @@ +// +// ContinueStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// continue; + /// + public class ContinueStatement : Statement + { + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitContinueStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ContinueStatement o = other as ContinueStatement; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/DoWhileStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/DoWhileStatement.cs new file mode 100644 index 0000000000..378fd43ab0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/DoWhileStatement.cs @@ -0,0 +1,79 @@ +// +// DoWhileStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// "do EmbeddedStatement while(Condition);" + /// + public class DoWhileStatement : Statement + { + public static readonly Role DoKeywordRole = new Role("DoKeyword", CSharpTokenNode.Null); + public static readonly Role WhileKeywordRole = new Role("WhileKeyword", CSharpTokenNode.Null); + + public CSharpTokenNode DoToken { + get { return GetChildByRole (DoKeywordRole); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public CSharpTokenNode WhileToken { + get { return GetChildByRole (WhileKeywordRole); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Condition { + get { return GetChildByRole (Roles.Condition); } + set { SetChildByRole (Roles.Condition, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitDoWhileStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DoWhileStatement o = other as DoWhileStatement; + return o != null && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match) && this.Condition.DoMatch(o.Condition, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs new file mode 100644 index 0000000000..c75adbec68 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs @@ -0,0 +1,69 @@ +// +// EmptyStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// ; + /// + public class EmptyStatement : Statement, IRelocatable + { + public AstLocation Location { + get; + set; + } + + public override AstLocation StartLocation { + get { + return Location; + } + } + + public override AstLocation EndLocation { + get { + return new AstLocation (Location.Line, Location.Column); + } + } + + #region IRelocationable implementation + void IRelocatable.SetStartLocation (AstLocation startLocation) + { + this.Location = startLocation; + } + #endregion + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitEmptyStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + EmptyStatement o = other as EmptyStatement; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ExpressionStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ExpressionStatement.cs new file mode 100644 index 0000000000..4e76bd5bbe --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ExpressionStatement.cs @@ -0,0 +1,63 @@ +// +// ExpressionStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Expression; + /// + public class ExpressionStatement : Statement + { + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitExpressionStatement (this, data); + } + + public ExpressionStatement() + { + } + + public ExpressionStatement(Expression expression) + { + this.Expression = expression; + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ExpressionStatement o = other as ExpressionStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs new file mode 100644 index 0000000000..9a8efbc9ac --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs @@ -0,0 +1,73 @@ +// +// FixedStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// fixed (Type Variables) EmbeddedStatement + /// + public class FixedStatement : Statement + { + public CSharpTokenNode FixedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Variables { + get { return GetChildrenByRole (Roles.Variable); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitFixedStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + FixedStatement o = other as FixedStatement; + return o != null && this.Type.DoMatch(o.Type, match) && this.Variables.DoMatch(o.Variables, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForStatement.cs new file mode 100644 index 0000000000..ebbe44022b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForStatement.cs @@ -0,0 +1,86 @@ +// +// ForStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// for (Initializers; Condition; Iterators) EmbeddedStatement + /// + public class ForStatement : Statement + { + public readonly static Role InitializerRole = new Role("Initializer", Statement.Null); + public readonly static Role IteratorRole = new Role("Iterator", Statement.Null); + + public CSharpTokenNode ForToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + /// + /// Gets the list of initializer statements. + /// Note: this contains multiple statements for "for (a = 2, b = 1; a > b; a--)", but contains + /// only a single statement for "for (int a = 2, b = 1; a > b; a--)" (a single VariableDeclarationStatement with two variables) + /// + public AstNodeCollection Initializers { + get { return GetChildrenByRole (InitializerRole); } + } + + public Expression Condition { + get { return GetChildByRole (Roles.Condition); } + set { SetChildByRole (Roles.Condition, value); } + } + + public AstNodeCollection Iterators { + get { return GetChildrenByRole (IteratorRole); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitForStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ForStatement o = other as ForStatement; + return o != null && this.Initializers.DoMatch(o.Initializers, match) && this.Condition.DoMatch(o.Condition, match) + && this.Iterators.DoMatch(o.Iterators, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs new file mode 100644 index 0000000000..52be5da59a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs @@ -0,0 +1,95 @@ +// +// ForeachStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// foreach (Type VariableName in InExpression) EmbeddedStatement + /// + public class ForeachStatement : Statement + { + public CSharpTokenNode ForeachToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType VariableType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public string VariableName { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier VariableNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); + } + } + + public CSharpTokenNode InToken { + get { return GetChildByRole (Roles.InKeyword); } + } + + public Expression InExpression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitForeachStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ForeachStatement o = other as ForeachStatement; + return o != null && this.VariableType.DoMatch(o.VariableType, match) && MatchString(this.VariableName, o.VariableName) + && this.InExpression.DoMatch(o.InExpression, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs new file mode 100644 index 0000000000..0bcc5e2388 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs @@ -0,0 +1,144 @@ +// +// GotoStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// "goto Label;" + /// + public class GotoStatement : Statement + { + public GotoStatement () + { + } + + public GotoStatement (string label) + { + this.Label = label; + } + + public CSharpTokenNode GotoToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public string Label { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + if (string.IsNullOrEmpty(value)) + SetChildByRole(Roles.Identifier, null); + else + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitGotoStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + GotoStatement o = other as GotoStatement; + return o != null && MatchString(this.Label, o.Label); + } + } + + /// + /// or "goto case LabelExpression;" + /// + public class GotoCaseStatement : Statement + { + public static readonly Role CaseKeywordRole = new Role("CaseKeyword", CSharpTokenNode.Null); + + public CSharpTokenNode GotoToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode CaseToken { + get { return GetChildByRole (CaseKeywordRole); } + } + + /// + /// Used for "goto case LabelExpression;" + /// + public Expression LabelExpression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitGotoCaseStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + GotoCaseStatement o = other as GotoCaseStatement; + return o != null && this.LabelExpression.DoMatch(o.LabelExpression, match); + } + } + + /// + /// or "goto default;" + /// + public class GotoDefaultStatement : Statement + { + public static readonly Role DefaultKeywordRole = new Role("DefaultKeyword", CSharpTokenNode.Null); + + public CSharpTokenNode GotoToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode DefaultToken { + get { return GetChildByRole (DefaultKeywordRole); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitGotoDefaultStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + GotoDefaultStatement o = other as GotoDefaultStatement; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/IfElseStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/IfElseStatement.cs new file mode 100644 index 0000000000..8fa84392d7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/IfElseStatement.cs @@ -0,0 +1,94 @@ +// +// IfElseStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// if (Condition) TrueStatement else FalseStatement + /// + public class IfElseStatement : Statement + { + public readonly static Role IfKeywordRole = Roles.Keyword; + public readonly static Role ConditionRole = Roles.Condition; + public readonly static Role QuestionMarkRole = new Role("QuestionMark", CSharpTokenNode.Null); + public readonly static Role TrueRole = new Role("True", Statement.Null); + public readonly static Role ElseKeywordRole = new Role("ElseKeyword", CSharpTokenNode.Null); + public readonly static Role FalseRole = new Role("False", Statement.Null); + + public CSharpTokenNode IfToken { + get { return GetChildByRole (IfKeywordRole); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Condition { + get { return GetChildByRole (ConditionRole); } + set { SetChildByRole (ConditionRole, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement TrueStatement { + get { return GetChildByRole (TrueRole); } + set { SetChildByRole (TrueRole, value); } + } + + public CSharpTokenNode ElseToken { + get { return GetChildByRole (ElseKeywordRole); } + } + + public Statement FalseStatement { + get { return GetChildByRole (FalseRole); } + set { SetChildByRole (FalseRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIfElseStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + IfElseStatement o = other as IfElseStatement; + return o != null && this.Condition.DoMatch(o.Condition, match) && this.TrueStatement.DoMatch(o.TrueStatement, match) && this.FalseStatement.DoMatch(o.FalseStatement, match); + } + + public IfElseStatement() + { + } + + public IfElseStatement(Expression condition, Statement trueStatement, Statement falseStatement = null) + { + this.Condition = condition; + this.TrueStatement = trueStatement; + this.FalseStatement = falseStatement; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs new file mode 100644 index 0000000000..b23c80a4c2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs @@ -0,0 +1,58 @@ +// +// LabelStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Label: + /// + public class LabelStatement : Statement + { + public string Label { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public CSharpTokenNode Colon { + get { return GetChildByRole (Roles.Colon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitLabelStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + LabelStatement o = other as LabelStatement; + return o != null && MatchString(this.Label, o.Label); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LockStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LockStatement.cs new file mode 100644 index 0000000000..7298e4f1da --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/LockStatement.cs @@ -0,0 +1,67 @@ +// +// LockStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// lock (Expression) EmbeddedStatement; + /// + public class LockStatement : Statement + { + public CSharpTokenNode LockToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitLockStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + LockStatement o = other as LockStatement; + return o != null && this.Expression.DoMatch(o.Expression, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ReturnStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ReturnStatement.cs new file mode 100644 index 0000000000..075a22589e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ReturnStatement.cs @@ -0,0 +1,67 @@ +// +// ReturnStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// return Expression; + /// + public class ReturnStatement : Statement + { + public CSharpTokenNode ReturnToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public ReturnStatement () + { + } + + public ReturnStatement (Expression returnExpression) + { + AddChild (returnExpression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitReturnStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ReturnStatement o = other as ReturnStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/Statement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/Statement.cs new file mode 100644 index 0000000000..e2d607571d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/Statement.cs @@ -0,0 +1,107 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Base class for statements. + /// + /// + /// This class is useful even though it doesn't provide any additional functionality: + /// It can be used to communicate more information in APIs, e.g. "this subnode will always be a statement" + /// + public abstract class Statement : AstNode + { + #region Null + public new static readonly Statement Null = new NullStatement (); + + sealed class NullStatement : Statement + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + #region PatternPlaceholder + public static implicit operator Statement(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : Statement, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public new Statement Clone() + { + return (Statement)base.Clone(); + } + + public Statement ReplaceWith(Func replaceFunction) + { + if (replaceFunction == null) + throw new ArgumentNullException("replaceFunction"); + return (Statement)base.ReplaceWith(node => replaceFunction((Statement)node)); + } + + public override NodeType NodeType { + get { return NodeType.Statement; } + } + + // Make debugging easier by giving Statements a ToString() implementation + public override string ToString() + { + if (IsNull) + return "Null"; + StringWriter w = new StringWriter(); + AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); + string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); + if (text.Length > 100) + return text.Substring(0, 97) + "..."; + else + return text; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs new file mode 100644 index 0000000000..c3fd4dd3fb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs @@ -0,0 +1,179 @@ +// +// SwitchStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// switch (Expression) { SwitchSections } + /// + public class SwitchStatement : Statement + { + public static readonly Role SwitchSectionRole = new Role("SwitchSection"); + + public CSharpTokenNode SwitchToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public AstNodeCollection SwitchSections { + get { return GetChildrenByRole (SwitchSectionRole); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitSwitchStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SwitchStatement o = other as SwitchStatement; + return o != null && this.Expression.DoMatch(o.Expression, match) && this.SwitchSections.DoMatch(o.SwitchSections, match); + } + } + + public class SwitchSection : AstNode + { + #region PatternPlaceholder + public static implicit operator SwitchSection(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : SwitchSection, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public static readonly Role CaseLabelRole = new Role("CaseLabel"); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public AstNodeCollection CaseLabels { + get { return GetChildrenByRole (CaseLabelRole); } + } + + public AstNodeCollection Statements { + get { return GetChildrenByRole (Roles.EmbeddedStatement); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitSwitchSection (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + SwitchSection o = other as SwitchSection; + return o != null && this.CaseLabels.DoMatch(o.CaseLabels, match) && this.Statements.DoMatch(o.Statements, match); + } + } + + public class CaseLabel : AstNode + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CaseLabel () + { + } + + public CaseLabel (Expression expression) + { + this.Expression = expression; + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCaseLabel (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CaseLabel o = other as CaseLabel; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ThrowStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ThrowStatement.cs new file mode 100644 index 0000000000..2eafdd977f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/ThrowStatement.cs @@ -0,0 +1,67 @@ +// +// ThrowStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// throw Expression; + /// + public class ThrowStatement : Statement + { + public CSharpTokenNode ThrowToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public ThrowStatement () + { + } + + public ThrowStatement (Expression expression) + { + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitThrowStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ThrowStatement o = other as ThrowStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs new file mode 100644 index 0000000000..77ef45e6b2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs @@ -0,0 +1,176 @@ +// +// TryCatchStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// try TryBlock CatchClauses finally FinallyBlock + /// + public class TryCatchStatement : Statement + { + public static readonly Role TryKeywordRole = new Role("TryKeyword", CSharpTokenNode.Null); + public static readonly Role TryBlockRole = new Role("TryBlock", BlockStatement.Null); + public static readonly Role CatchClauseRole = new Role("CatchClause"); + public static readonly Role FinallyKeywordRole = new Role("FinallyKeyword", CSharpTokenNode.Null); + public static readonly Role FinallyBlockRole = new Role("FinallyBlock", BlockStatement.Null); + + public CSharpTokenNode TryToken { + get { return GetChildByRole (TryKeywordRole); } + } + + public BlockStatement TryBlock { + get { return GetChildByRole (TryBlockRole); } + set { SetChildByRole (TryBlockRole, value); } + } + + public AstNodeCollection CatchClauses { + get { return GetChildrenByRole (CatchClauseRole); } + } + + public CSharpTokenNode FinallyToken { + get { return GetChildByRole (FinallyKeywordRole); } + } + + public BlockStatement FinallyBlock { + get { return GetChildByRole (FinallyBlockRole); } + set { SetChildByRole (FinallyBlockRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitTryCatchStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TryCatchStatement o = other as TryCatchStatement; + return o != null && this.TryBlock.DoMatch(o.TryBlock, match) && this.CatchClauses.DoMatch(o.CatchClauses, match) && this.FinallyBlock.DoMatch(o.FinallyBlock, match); + } + } + + /// + /// catch (Type VariableName) { Body } + /// + public class CatchClause : AstNode + { + #region PatternPlaceholder + public static implicit operator CatchClause(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : CatchClause, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public CSharpTokenNode CatchToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public string VariableName { + get { return GetChildByRole (Roles.Identifier).Name; } + set { + if (string.IsNullOrEmpty(value)) + SetChildByRole (Roles.Identifier, null); + else + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier VariableNameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); + } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCatchClause (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CatchClause o = other as CatchClause; + return o != null && this.Type.DoMatch(o.Type, match) && MatchString(this.VariableName, o.VariableName) && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UncheckedStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UncheckedStatement.cs new file mode 100644 index 0000000000..af40fa5a9f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UncheckedStatement.cs @@ -0,0 +1,63 @@ +// +// UncheckedStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// unchecked BodyBlock + /// + public class UncheckedStatement : Statement + { + public CSharpTokenNode UncheckedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public UncheckedStatement () + { + } + + public UncheckedStatement (BlockStatement body) + { + AddChild (body, Roles.Body); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUncheckedStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UncheckedStatement o = other as UncheckedStatement; + return o != null && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UnsafeStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UnsafeStatement.cs new file mode 100644 index 0000000000..c5ccb63af3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UnsafeStatement.cs @@ -0,0 +1,54 @@ +// +// UnsafeStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// unsafe { Body } + /// + public class UnsafeStatement : Statement + { + public CSharpTokenNode UnsafeToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUnsafeStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UnsafeStatement o = other as UnsafeStatement; + return o != null && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UsingStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UsingStatement.cs new file mode 100644 index 0000000000..27714d61bf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/UsingStatement.cs @@ -0,0 +1,72 @@ +// +// UsingStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// using (ResourceAcquisition) EmbeddedStatement + /// + public class UsingStatement : Statement + { + public static readonly Role ResourceAcquisitionRole = new Role("ResourceAcquisition", AstNode.Null); + + public CSharpTokenNode UsingToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + /// + /// Either a VariableDeclarationStatement, or an Expression. + /// + public AstNode ResourceAcquisition { + get { return GetChildByRole (ResourceAcquisitionRole); } + set { SetChildByRole (ResourceAcquisitionRole, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUsingStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UsingStatement o = other as UsingStatement; + return o != null && this.ResourceAcquisition.DoMatch(o.ResourceAcquisition, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs new file mode 100644 index 0000000000..54f473684e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs @@ -0,0 +1,80 @@ +// +// VariableDeclarationStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class VariableDeclarationStatement : Statement + { + public static readonly Role ModifierRole = AttributedNode.ModifierRole; + + public VariableDeclarationStatement() + { + } + + public VariableDeclarationStatement(AstType type, string name, Expression initializer = null) + { + this.Type = type; + this.Variables.Add(new VariableInitializer(name, initializer)); + } + + public Modifiers Modifiers { + get { return AttributedNode.GetModifiers(this); } + set { AttributedNode.SetModifiers(this, value); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Variables { + get { return GetChildrenByRole (Roles.Variable); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public VariableInitializer GetVariable (string name) + { + return Variables.FirstOrDefault (vi => vi.Name == name); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitVariableDeclarationStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + VariableDeclarationStatement o = other as VariableDeclarationStatement; + return o != null && this.Modifiers == o.Modifiers && this.Type.DoMatch(o.Type, match) && this.Variables.DoMatch(o.Variables, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/WhileStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/WhileStatement.cs new file mode 100644 index 0000000000..01470b3ab2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/WhileStatement.cs @@ -0,0 +1,69 @@ +// +// WhileStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// "while (Condition) EmbeddedStatement" + /// + public class WhileStatement : Statement + { + public static readonly Role WhileKeywordRole = new Role("WhileKeyword", CSharpTokenNode.Null); + + public CSharpTokenNode WhileToken { + get { return GetChildByRole (WhileKeywordRole); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public Expression Condition { + get { return GetChildByRole (Roles.Condition); } + set { SetChildByRole (Roles.Condition, value); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public Statement EmbeddedStatement { + get { return GetChildByRole (Roles.EmbeddedStatement); } + set { SetChildByRole (Roles.EmbeddedStatement, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitWhileStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + WhileStatement o = other as WhileStatement; + return o != null && this.Condition.DoMatch(o.Condition, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldBreakStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldBreakStatement.cs new file mode 100644 index 0000000000..4c572615ad --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldBreakStatement.cs @@ -0,0 +1,60 @@ +// +// YieldBreakStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// yield break; + /// + public class YieldBreakStatement : Statement + { + public static readonly Role YieldKeywordRole = new Role("YieldKeyword", CSharpTokenNode.Null); + public static readonly Role BreakKeywordRole = new Role("BreakKeyword", CSharpTokenNode.Null); + + public CSharpTokenNode YieldToken { + get { return GetChildByRole (YieldKeywordRole); } + } + + public CSharpTokenNode BreakToken { + get { return GetChildByRole (BreakKeywordRole); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitYieldBreakStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + YieldBreakStatement o = other as YieldBreakStatement; + return o != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs new file mode 100644 index 0000000000..001815f3a8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs @@ -0,0 +1,65 @@ +// +// YieldStatement.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// yield return Expression; + /// + public class YieldStatement : Statement + { + public static readonly Role YieldKeywordRole = new Role("YieldKeyword", CSharpTokenNode.Null); + public static readonly Role ReturnKeywordRole = new Role("ReturnKeyword", CSharpTokenNode.Null); + + public CSharpTokenNode YieldToken { + get { return GetChildByRole (YieldKeywordRole); } + } + + public CSharpTokenNode ReturnToken { + get { return GetChildByRole (ReturnKeywordRole); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode SemicolonToken { + get { return GetChildByRole (Roles.Semicolon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitYieldStatement (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + YieldStatement o = other as YieldStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs new file mode 100644 index 0000000000..748948f6a7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs @@ -0,0 +1,71 @@ +// +// PropertyDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// get/set/add/remove + /// + public class Accessor : AttributedNode + { + public static readonly new Accessor Null = new NullAccessor (); + sealed class NullAccessor : Accessor + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + } + + public override NodeType NodeType { + get { return NodeType.Unknown; } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAccessor (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + Accessor o = other as Accessor; + return o != null && !o.IsNull && this.MatchAttributesAndModifiers(o, match) && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs new file mode 100644 index 0000000000..019c55444a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs @@ -0,0 +1,71 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public abstract class AttributedNode : AstNode + { + public static readonly Role AttributeRole = new Role("Attribute"); + public static readonly Role ModifierRole = new Role("Modifier"); + + public AstNodeCollection Attributes { + get { return base.GetChildrenByRole (AttributeRole); } + } + + public Modifiers Modifiers { + get { return GetModifiers(this); } + set { SetModifiers(this, value); } + } + + public IEnumerable ModifierTokens { + get { return GetChildrenByRole (ModifierRole); } + } + + internal static Modifiers GetModifiers(AstNode node) + { + Modifiers m = 0; + foreach (CSharpModifierToken t in node.GetChildrenByRole (ModifierRole)) { + m |= t.Modifier; + } + return m; + } + + internal static void SetModifiers(AstNode node, Modifiers newValue) + { + Modifiers oldValue = GetModifiers(node); + AstNode insertionPos = node.GetChildrenByRole(AttributeRole).LastOrDefault(); + foreach (Modifiers m in CSharpModifierToken.AllModifiers) { + if ((m & newValue) != 0) { + if ((m & oldValue) == 0) { + // Modifier was added + var newToken = new CSharpModifierToken(AstLocation.Empty, m); + node.InsertChildAfter(insertionPos, newToken, ModifierRole); + insertionPos = newToken; + } else { + // Modifier already exists + insertionPos = node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m); + } + } else { + if ((m & oldValue) != 0) { + // Modifier was removed + node.GetChildrenByRole (ModifierRole).First(t => t.Modifier == m).Remove(); + } + } + } + } + + protected bool MatchAttributesAndModifiers (AttributedNode o, PatternMatching.Match match) + { + return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch (o.Attributes, match); + } + + public bool HasModifier (Modifiers mod) + { + return (Modifiers & mod) == mod; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs new file mode 100644 index 0000000000..afcc2d47d6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs @@ -0,0 +1,154 @@ +// +// ConstructorDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class ConstructorDeclaration : AttributedNode + { + public static readonly Role InitializerRole = new Role("Initializer", ConstructorInitializer.Null); + + /// + /// Gets/Sets the name of the class containing the constructor. + /// This property can be used to inform the output visitor about the class name when writing a constructor declaration + /// without writing the complete type declaration. It is ignored when the constructor has a type declaration as parent. + /// + public string Name { get; set; } + + public Identifier IdentifierToken { + get { return GetChildByRole (Roles.Identifier); } + set { SetChildByRole (Roles.Identifier, value); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public ConstructorInitializer Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole( InitializerRole, value); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitConstructorDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ConstructorDeclaration o = other as ConstructorDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) && this.Parameters.DoMatch(o.Parameters, match) + && this.Initializer.DoMatch(o.Initializer, match) && this.Body.DoMatch(o.Body, match); + } + } + + public enum ConstructorInitializerType { + Base, + This + } + + public class ConstructorInitializer : AstNode + { + public static readonly new ConstructorInitializer Null = new NullConstructorInitializer (); + class NullConstructorInitializer : ConstructorInitializer + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public ConstructorInitializerType ConstructorInitializerType { + get; + set; + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole (Roles.Argument); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitConstructorInitializer (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ConstructorInitializer o = other as ConstructorInitializer; + return o != null && !o.IsNull && this.ConstructorInitializerType == o.ConstructorInitializerType && this.Arguments.DoMatch(o.Arguments, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs new file mode 100644 index 0000000000..829682e73f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs @@ -0,0 +1,76 @@ +// +// DestructorDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + public class DestructorDeclaration : AttributedNode + { + public static readonly Role TildeRole = new Role("Tilde", CSharpTokenNode.Null); + + public CSharpTokenNode TildeToken { + get { return GetChildByRole (TildeRole); } + } + + /// + /// Gets/Sets the name of the class containing the destructor. + /// This property can be used to inform the output visitor about the class name when writing a destructor declaration + /// without writing the complete type declaration. It is ignored when the destructor has a type declaration as parent. + /// + public string Name { get; set; } + + public Identifier IdentifierToken { + get { return GetChildByRole (Roles.Identifier); } + set { SetChildByRole (Roles.Identifier, value); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitDestructorDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DestructorDeclaration o = other as DestructorDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs new file mode 100644 index 0000000000..8c31562983 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs @@ -0,0 +1,74 @@ +// +// EnumMemberDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class EnumMemberDeclaration : AttributedNode + { + public static readonly Role InitializerRole = new Role("Initializer", Expression.Null); + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public Expression Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole (InitializerRole, value); } + } + + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitEnumMemberDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + EnumMemberDeclaration o = other as EnumMemberDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && MatchString(this.Name, o.Name) && this.Initializer.DoMatch(o.Initializer, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs new file mode 100644 index 0000000000..49d28ede35 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs @@ -0,0 +1,94 @@ +// +// EventDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class EventDeclaration : AttributedNode + { + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection Variables { + get { return GetChildrenByRole (Roles.Variable); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitEventDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + EventDeclaration o = other as EventDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && this.Variables.DoMatch(o.Variables, match); + } + } + + public class CustomEventDeclaration : MemberDeclaration + { + public static readonly Role AddAccessorRole = new Role("AddAccessor", Accessor.Null); + public static readonly Role RemoveAccessorRole = new Role("RemoveAccessor", Accessor.Null); + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public Accessor AddAccessor { + get { return GetChildByRole (AddAccessorRole); } + set { SetChildByRole (AddAccessorRole, value); } + } + + public Accessor RemoveAccessor { + get { return GetChildByRole (RemoveAccessorRole); } + set { SetChildByRole (RemoveAccessorRole, value); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCustomEventDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CustomEventDeclaration o = other as CustomEventDeclaration; + return o != null && this.MatchMember(o, match) + && this.AddAccessor.DoMatch(o.AddAccessor, match) && this.RemoveAccessor.DoMatch(o.RemoveAccessor, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs new file mode 100644 index 0000000000..1003aa9b75 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs @@ -0,0 +1,59 @@ +// +// FieldDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class FieldDeclaration : AttributedNode + { + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection Variables { + get { return GetChildrenByRole (Roles.Variable); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitFieldDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + FieldDeclaration o = other as FieldDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && this.Variables.DoMatch(o.Variables, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs new file mode 100644 index 0000000000..2fde822604 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs @@ -0,0 +1,64 @@ +// +// FixedFieldDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class FixedFieldDeclaration : AttributedNode + { + public static readonly Role VariableRole = new Role ("FixedVariable"); + + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public CSharpTokenNode FixedToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Variables { + get { return GetChildrenByRole (VariableRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitFixedFieldDeclaration (this, data); + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + var o = other as FixedFieldDeclaration; + return o != null && this.MatchAttributesAndModifiers (o, match) + && this.ReturnType.DoMatch (o.ReturnType, match) && this.Variables.DoMatch (o.Variables, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs new file mode 100644 index 0000000000..1d5d9da935 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs @@ -0,0 +1,95 @@ +// +// FixedFieldDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Name [ CountExpression ] + /// + public class FixedVariableInitializer : AstNode + { + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public FixedVariableInitializer() + { + } + + public FixedVariableInitializer (string name, Expression initializer = null) + { + this.Name = name; + this.CountExpression = initializer; + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public CSharpTokenNode LBracketToken { + get { return GetChildByRole (Roles.LBracket); } + } + + public Expression CountExpression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CSharpTokenNode RBracketToken { + get { return GetChildByRole (Roles.RBracket); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitFixedVariableInitializer (this, data); + } + + protected internal override bool DoMatch (AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var o = other as FixedVariableInitializer; + return o != null && MatchString (this.Name, o.Name) && this.CountExpression.DoMatch (o.CountExpression, match); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs new file mode 100644 index 0000000000..4d19c97d73 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs @@ -0,0 +1,79 @@ +// +// IndexerDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class IndexerDeclaration : MemberDeclaration + { + public static readonly Role GetterRole = PropertyDeclaration.GetterRole; + public static readonly Role SetterRole = PropertyDeclaration.SetterRole; + + public CSharpTokenNode LBracketToken { + get { return GetChildByRole (Roles.LBracket); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode RBracketToken { + get { return GetChildByRole (Roles.RBracket); } + } + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public Accessor Getter { + get { return GetChildByRole(GetterRole); } + set { SetChildByRole(GetterRole, value); } + } + + public Accessor Setter { + get { return GetChildByRole(SetterRole); } + set { SetChildByRole(SetterRole, value); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIndexerDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + IndexerDeclaration o = other as IndexerDeclaration; + return o != null && this.MatchMember(o, match) && this.Parameters.DoMatch(o.Parameters, match) + && this.Getter.DoMatch(o.Getter, match) && this.Setter.DoMatch(o.Setter, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs new file mode 100644 index 0000000000..f2fd816830 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs @@ -0,0 +1,74 @@ +// +// AbstractMember.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + public abstract class MemberDeclaration : AttributedNode + { + public static readonly Role PrivateImplementationTypeRole = new Role("PrivateImplementationType", AstType.Null); + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + /// + /// Only supported on members that can be declared in an interface. + /// + public AstType PrivateImplementationType { + get { return GetChildByRole (PrivateImplementationTypeRole); } + set { SetChildByRole (PrivateImplementationTypeRole, value); } + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public override NodeType NodeType { + get { return NodeType.Member; } + } + + protected bool MatchMember(MemberDeclaration o, PatternMatching.Match match) + { + return MatchAttributesAndModifiers(o, match) && this.ReturnType.DoMatch(o.ReturnType, match) + && this.PrivateImplementationType.DoMatch(o.PrivateImplementationType, match) && MatchString(this.Name, o.Name); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs new file mode 100644 index 0000000000..556c0a3a4c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs @@ -0,0 +1,79 @@ +// +// MethodDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class MethodDeclaration : MemberDeclaration + { + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole (Roles.TypeParameter); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public AstNodeCollection Constraints { + get { return GetChildrenByRole (Roles.Constraint); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + public bool IsExtensionMethod { + get { + ParameterDeclaration pd = (ParameterDeclaration)GetChildByRole (Roles.Parameter); + return pd != null && pd.ParameterModifier == ParameterModifier.This; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitMethodDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + MethodDeclaration o = other as MethodDeclaration; + return o != null && this.MatchMember(o, match) && this.TypeParameters.DoMatch(o.TypeParameters, match) + && this.Parameters.DoMatch(o.Parameters, match) && this.Constraints.DoMatch(o.Constraints, match) + && this.Body.DoMatch(o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs new file mode 100644 index 0000000000..31d1232323 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs @@ -0,0 +1,149 @@ +// +// OperatorDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum OperatorType + { + // Values must correspond to Mono.CSharp.Operator.OpType + // due to the casts used in OperatorDeclaration. + + // Unary operators + LogicalNot = Mono.CSharp.Operator.OpType.LogicalNot, + OnesComplement = Mono.CSharp.Operator.OpType.OnesComplement, + Increment = Mono.CSharp.Operator.OpType.Increment, + Decrement = Mono.CSharp.Operator.OpType.Decrement, + True = Mono.CSharp.Operator.OpType.True, + False = Mono.CSharp.Operator.OpType.False, + + // Unary and Binary operators + Addition = Mono.CSharp.Operator.OpType.Addition, + Subtraction = Mono.CSharp.Operator.OpType.Subtraction, + + UnaryPlus = Mono.CSharp.Operator.OpType.UnaryPlus, + UnaryNegation = Mono.CSharp.Operator.OpType.UnaryNegation, + + // Binary operators + Multiply = Mono.CSharp.Operator.OpType.Multiply, + Division = Mono.CSharp.Operator.OpType.Division, + Modulus = Mono.CSharp.Operator.OpType.Modulus, + BitwiseAnd = Mono.CSharp.Operator.OpType.BitwiseAnd, + BitwiseOr = Mono.CSharp.Operator.OpType.BitwiseOr, + ExclusiveOr = Mono.CSharp.Operator.OpType.ExclusiveOr, + LeftShift = Mono.CSharp.Operator.OpType.LeftShift, + RightShift = Mono.CSharp.Operator.OpType.RightShift, + Equality = Mono.CSharp.Operator.OpType.Equality, + Inequality = Mono.CSharp.Operator.OpType.Inequality, + GreaterThan = Mono.CSharp.Operator.OpType.GreaterThan, + LessThan = Mono.CSharp.Operator.OpType.LessThan, + GreaterThanOrEqual = Mono.CSharp.Operator.OpType.GreaterThanOrEqual, + LessThanOrEqual = Mono.CSharp.Operator.OpType.LessThanOrEqual, + + // Implicit and Explicit + Implicit = Mono.CSharp.Operator.OpType.Implicit, + Explicit = Mono.CSharp.Operator.OpType.Explicit + } + + public class OperatorDeclaration : AttributedNode + { + public static readonly Role OperatorTypeRole = new Role ("OperatorType", CSharpTokenNode.Null); + public static readonly Role OperatorKeywordRole = Roles.Keyword; + + public OperatorType OperatorType { + get; + set; + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public CSharpTokenNode LParToken { + get { return GetChildByRole (Roles.LPar); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole (Roles.Parameter); } + } + + public CSharpTokenNode RParToken { + get { return GetChildByRole (Roles.RPar); } + } + + public BlockStatement Body { + get { return GetChildByRole (Roles.Body); } + set { SetChildByRole (Roles.Body, value); } + } + + /// + /// Gets the operator type from the method name, or null, if the method does not represent one of the known operator types. + /// + public static OperatorType? GetOperatorType(string methodName) + { + return (OperatorType?)Mono.CSharp.Operator.GetType(methodName); + } + + /// + /// Gets the method name for the operator type. ("op_Addition", "op_Implicit", etc.) + /// + public static string GetName (OperatorType type) + { + return Mono.CSharp.Operator.GetMetadataName ((Mono.CSharp.Operator.OpType)type); + } + + /// + /// Gets the token for the operator type ("+", "implicit", etc.) + /// + public static string GetToken (OperatorType type) + { + return Mono.CSharp.Operator.GetName ((Mono.CSharp.Operator.OpType)type); + } + + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitOperatorDeclaration (this, data); + } + + public string Name { + get { return GetName (this.OperatorType); } + } + + protected internal override bool DoMatch (AstNode other, PatternMatching.Match match) + { + OperatorDeclaration o = other as OperatorDeclaration; + return o != null && this.MatchAttributesAndModifiers (o, match) && this.OperatorType == o.OperatorType + && this.ReturnType.DoMatch (o.ReturnType, match) + && this.Parameters.DoMatch (o.Parameters, match) && this.Body.DoMatch (o.Body, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs new file mode 100644 index 0000000000..287611ef69 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs @@ -0,0 +1,113 @@ +// +// ParameterDeclarationExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum ParameterModifier { + None, + Ref, + Out, + Params, + This + } + + public class ParameterDeclaration : AstNode + { + public static readonly Role AttributeRole = AttributedNode.AttributeRole; + public static readonly Role ModifierRole = new Role("Modifier", CSharpTokenNode.Null); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public AstNodeCollection Attributes { + get { return GetChildrenByRole (AttributeRole); } + } + + public ParameterModifier ParameterModifier { + get; + set; + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public Expression DefaultExpression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitParameterDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ParameterDeclaration o = other as ParameterDeclaration; + return o != null && this.Attributes.DoMatch(o.Attributes, match) && this.ParameterModifier == o.ParameterModifier + && this.Type.DoMatch(o.Type, match) && MatchString(this.Name, o.Name) + && this.DefaultExpression.DoMatch(o.DefaultExpression, match); + } + + public ParameterDeclaration() + { + } + + public ParameterDeclaration(AstType type, string name) + { + this.Type = type; + this.Name = name; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs new file mode 100644 index 0000000000..2d1376a0ed --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs @@ -0,0 +1,64 @@ +// +// PropertyDeclaration.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + public class PropertyDeclaration : MemberDeclaration + { + public static readonly Role GetterRole = new Role("Getter", Accessor.Null); + public static readonly Role SetterRole = new Role("Setter", Accessor.Null); + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public Accessor Getter { + get { return GetChildByRole(GetterRole); } + set { SetChildByRole(GetterRole, value); } + } + + public Accessor Setter { + get { return GetChildByRole(SetterRole); } + set { SetChildByRole(SetterRole, value); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitPropertyDeclaration (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PropertyDeclaration o = other as PropertyDeclaration; + return o != null && this.MatchMember(o, match) + && this.Getter.DoMatch(o.Getter, match) && this.Setter.DoMatch(o.Setter, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs new file mode 100644 index 0000000000..6e1d572727 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs @@ -0,0 +1,121 @@ +// +// VariableInitializer.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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. + +namespace ICSharpCode.NRefactory.CSharp +{ + public class VariableInitializer : AstNode + { + #region PatternPlaceholder + public static implicit operator VariableInitializer(PatternMatching.Pattern pattern) + { + return pattern != null ? new PatternPlaceholder(pattern) : null; + } + + sealed class PatternPlaceholder : VariableInitializer, PatternMatching.INode + { + readonly PatternMatching.Pattern child; + + public PatternPlaceholder(PatternMatching.Pattern child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Pattern; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPatternPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return child.DoMatch(other, match); + } + + bool PatternMatching.INode.DoMatchCollection(Role role, PatternMatching.INode pos, PatternMatching.Match match, PatternMatching.BacktrackingInfo backtrackingInfo) + { + return child.DoMatchCollection(role, pos, match, backtrackingInfo); + } + } + #endregion + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public VariableInitializer() + { + } + + public VariableInitializer(string name, Expression initializer = null) + { + this.Name = name; + this.Initializer = initializer; + } + + public string Name { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier NameToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } + } + + public CSharpTokenNode AssignToken { + get { return GetChildByRole (Roles.Assign); } + } + + public Expression Initializer { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitVariableInitializer (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + VariableInitializer o = other as VariableInitializer; + return o != null && MatchString(this.Name, o.Name) && this.Initializer.DoMatch(o.Initializer, match); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs new file mode 100644 index 0000000000..2b08ae116d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs @@ -0,0 +1,1608 @@ +// +// AstFormattingVisitor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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.Text; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.CSharp.Refactoring; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class AstFormattingVisitor : DepthFirstAstVisitor + { + CSharpFormattingOptions policy; + ITextEditorAdapter data; + IActionFactory factory; + List changes = new List (); + Indent curIndent = new Indent (); + + public int IndentLevel { + get { + return curIndent.Level; + } + set { + curIndent.Level = value; + } + } + + public int CurrentSpaceIndents { + get; + set; + } + + public List Changes { + get { return this.changes; } + } + + public bool CorrectBlankLines { + get; + set; + } + + public bool HadErrors { + get; + set; + } + + public AstFormattingVisitor (CSharpFormattingOptions policy, ITextEditorAdapter data, IActionFactory factory) + { + if (factory == null) + throw new ArgumentNullException ("factory"); + this.policy = policy; + this.data = data; + this.curIndent.TabsToSpaces = this.data.TabsToSpaces; + this.curIndent.TabSize = this.data.TabSize; + this.factory = factory; + CorrectBlankLines = true; + } + + public override object VisitCompilationUnit (CompilationUnit unit, object data) + { + base.VisitCompilationUnit (unit, data); + return null; + } + + public void EnsureBlankLinesAfter (AstNode node, int blankLines) + { + if (!CorrectBlankLines) + return; + var loc = node.EndLocation; + int line = loc.Line; + do { + line++; + } while (line < data.LineCount && data.GetEditableLength (line) == data.GetIndentation (line).Length); + var start = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + + int foundBlankLines = line - loc.Line - 1; + + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < blankLines - foundBlankLines; i++) + sb.Append (data.EolMarker); + + int ws = start; + while (ws < data.Length && IsSpacing (data.GetCharAt (ws))) + ws++; + int removedChars = ws - start; + if (foundBlankLines > blankLines) + removedChars += data.GetLineEndOffset (loc.Line + foundBlankLines - blankLines) - data.GetLineEndOffset (loc.Line); + AddChange (start, removedChars, sb.ToString ()); + } + + public void EnsureBlankLinesBefore (AstNode node, int blankLines) + { + if (!CorrectBlankLines) + return; + var loc = node.StartLocation; + int line = loc.Line; + do { + line--; + } while (line > 0 && data.GetEditableLength (line) == data.GetIndentation (line).Length); + int end = data.GetLineOffset (loc.Line); + int start = line >= 1 ? data.GetLineEndOffset (line) : 0; + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < blankLines; i++) + sb.Append (data.EolMarker); + AddChange (start, end - start, sb.ToString ()); + } + + public override object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data) + { + if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) + EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings); + if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) + EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings); + + return null; + } + + public override object VisitUsingAliasDeclaration (UsingAliasDeclaration usingDeclaration, object data) + { + if (!(usingDeclaration.PrevSibling is UsingDeclaration || usingDeclaration.PrevSibling is UsingAliasDeclaration)) + EnsureBlankLinesBefore (usingDeclaration, policy.BlankLinesBeforeUsings); + if (!(usingDeclaration.NextSibling is UsingDeclaration || usingDeclaration.NextSibling is UsingAliasDeclaration)) + EnsureBlankLinesAfter (usingDeclaration, policy.BlankLinesAfterUsings); + return null; + } + + public override object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data) + { + var firstNsMember = namespaceDeclaration.Members.FirstOrDefault (); + if (firstNsMember != null) + EnsureBlankLinesBefore (firstNsMember, policy.BlankLinesBeforeFirstDeclaration); + FixIndentationForceNewLine (namespaceDeclaration.StartLocation); + EnforceBraceStyle (policy.NamespaceBraceStyle, namespaceDeclaration.LBraceToken, namespaceDeclaration.RBraceToken); + if (policy.IndentNamespaceBody) + IndentLevel++; + object result = base.VisitNamespaceDeclaration (namespaceDeclaration, data); + if (policy.IndentNamespaceBody) + IndentLevel--; + FixIndentation (namespaceDeclaration.RBraceToken.StartLocation); + return result; + } + + public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) + { + FixIndentationForceNewLine (typeDeclaration.StartLocation); + BraceStyle braceStyle; + bool indentBody = false; + switch (typeDeclaration.ClassType) { + case ClassType.Class: + braceStyle = policy.ClassBraceStyle; + indentBody = policy.IndentClassBody; + break; + case ClassType.Struct: + braceStyle = policy.StructBraceStyle; + indentBody = policy.IndentStructBody; + break; + case ClassType.Interface: + braceStyle = policy.InterfaceBraceStyle; + indentBody = policy.IndentInterfaceBody; + break; + case ClassType.Enum: + braceStyle = policy.EnumBraceStyle; + indentBody = policy.IndentEnumBody; + break; + default: + throw new InvalidOperationException ("unsupported class type : " + typeDeclaration.ClassType); + } + EnforceBraceStyle (braceStyle, typeDeclaration.LBraceToken, typeDeclaration.RBraceToken); + + if (indentBody) + IndentLevel++; + object result = base.VisitTypeDeclaration (typeDeclaration, data); + if (indentBody) + IndentLevel--; + + if (typeDeclaration.NextSibling is TypeDeclaration || typeDeclaration.NextSibling is DelegateDeclaration) + EnsureBlankLinesAfter (typeDeclaration, policy.BlankLinesBetweenTypes); + return result; + } + + bool IsSimpleAccessor (Accessor accessor) + { + if (accessor.IsNull || accessor.Body.IsNull || accessor.Body.FirstChild == null) + return true; + if (accessor.Body.Statements.Count () != 1) + return false; + return !(accessor.Body.Statements.FirstOrDefault () is BlockStatement); + + } + + bool IsSpacing (char ch) + { + return ch == ' ' || ch == '\t'; + } + + int SearchLastNonWsChar (int startOffset, int endOffset) + { + startOffset = System.Math.Max (0, startOffset); + endOffset = System.Math.Max (startOffset, endOffset); + if (startOffset >= endOffset) + return startOffset; + int result = -1; + bool inComment = false; + + for (int i = startOffset; i < endOffset && i < data.Length; i++) { + char ch = data.GetCharAt (i); + if (IsSpacing (ch)) + continue; + if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') + return result; + if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '*') { + inComment = true; + i++; + continue; + } + if (inComment && ch == '*' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') { + inComment = false; + i++; + continue; + } + if (!inComment) + result = i; + } + return result; + } + + void ForceSpace (int startOffset, int endOffset, bool forceSpace) + { + int lastNonWs = SearchLastNonWsChar (startOffset, endOffset); + AddChange (lastNonWs + 1, System.Math.Max (0, endOffset - lastNonWs - 1), forceSpace ? " " : ""); + } +// void ForceSpacesAfter (AstNode n, bool forceSpaces) +// { +// if (n == null) +// return; +// AstLocation location = n.EndLocation; +// int offset = data.LocationToOffset (location.Line, location.Column); +// int i = offset; +// while (i < data.Length && IsSpacing (data.GetCharAt (i))) { +// i++; +// } +// ForceSpace (offset - 1, i, forceSpaces); +// } + + void ForceSpacesAfter (AstNode n, bool forceSpaces) + { + if (n == null) + return; + AstLocation location = n.EndLocation; + int offset = data.LocationToOffset (location.Line, location.Column); + if (location.Column > data.GetEditableLength (location.Line)) + return; + int i = offset; + while (i < data.Length && IsSpacing (data.GetCharAt (i))) { + i++; + } + ForceSpace (offset - 1, i, forceSpaces); + } + +// int ForceSpacesBefore (AstNode n, bool forceSpaces) +// { +// if (n == null || n.IsNull) +// return 0; +// AstLocation location = n.StartLocation; +// +// int offset = data.LocationToOffset (location.Line, location.Column); +// int i = offset - 1; +// +// while (i >= 0 && IsSpacing (data.GetCharAt (i))) { +// i--; +// } +// ForceSpace (i, offset, forceSpaces); +// return i; +// } + + int ForceSpacesBefore (AstNode n, bool forceSpaces) + { + if (n == null || n.IsNull) + return 0; + AstLocation location = n.StartLocation; + // respect manual line breaks. + if (location.Column <= 1 || data.GetIndentation (location.Line).Length == location.Column - 1) + return 0; + + int offset = data.LocationToOffset (location.Line, location.Column); + int i = offset - 1; + while (i >= 0 && IsSpacing (data.GetCharAt (i))) { + i--; + } + ForceSpace (i, offset, forceSpaces); + return i; + } + + public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) + { + FixIndentationForceNewLine (propertyDeclaration.StartLocation); + bool oneLine = false; + switch (policy.PropertyFormatting) { + case PropertyFormatting.AllowOneLine: + bool isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); + if (!isSimple || propertyDeclaration.LBraceToken.StartLocation.Line != propertyDeclaration.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); + } else { + ForceSpacesBefore (propertyDeclaration.Getter, true); + ForceSpacesBefore (propertyDeclaration.Setter, true); + ForceSpacesBefore (propertyDeclaration.RBraceToken, true); + oneLine = true; + } + break; + case PropertyFormatting.ForceNewLine: + EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); + break; + case PropertyFormatting.ForceOneLine: + isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); + if (isSimple) { + int offset = this.data.LocationToOffset (propertyDeclaration.LBraceToken.StartLocation.Line, propertyDeclaration.LBraceToken.StartLocation.Column); + + int start = SearchWhitespaceStart (offset); + int end = SearchWhitespaceEnd (offset); + AddChange (start, offset - start, " "); + AddChange (offset + 1, end - offset - 2, " "); + + offset = this.data.LocationToOffset (propertyDeclaration.RBraceToken.StartLocation.Line, propertyDeclaration.RBraceToken.StartLocation.Column); + start = SearchWhitespaceStart (offset); + AddChange (start, offset - start, " "); + oneLine = true; + + } else { + EnforceBraceStyle (policy.PropertyBraceStyle, propertyDeclaration.LBraceToken, propertyDeclaration.RBraceToken); + } + break; + } + if (policy.IndentPropertyBody) + IndentLevel++; + ///System.Console.WriteLine ("one line: " + oneLine); + if (!propertyDeclaration.Getter.IsNull) { + if (!oneLine) { + if (!IsLineIsEmptyUpToEol (propertyDeclaration.Getter.StartLocation)) { + int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + string indentString = this.curIndent.IndentString; + AddChange (start, offset - start, this.data.EolMarker + indentString); + } else { + FixIndentation (propertyDeclaration.Getter.StartLocation); + } + } else { + int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + AddChange (start, offset - start, " "); + + ForceSpacesBefore (propertyDeclaration.Getter.Body.LBraceToken, true); + ForceSpacesBefore (propertyDeclaration.Getter.Body.RBraceToken, true); + } + if (!propertyDeclaration.Getter.Body.IsNull) { + if (!policy.AllowPropertyGetBlockInline || propertyDeclaration.Getter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Getter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertyGetBraceStyle, propertyDeclaration.Getter.Body.LBraceToken, propertyDeclaration.Getter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (propertyDeclaration.Getter.Body, policy.IndentBlocks, data); + } + } + + if (!propertyDeclaration.Setter.IsNull) { + if (!oneLine) { + if (!IsLineIsEmptyUpToEol (propertyDeclaration.Setter.StartLocation)) { + int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + string indentString = this.curIndent.IndentString; + AddChange (start, offset - start, this.data.EolMarker + indentString); + } else { + FixIndentation (propertyDeclaration.Setter.StartLocation); + } + } else { + int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int start = SearchWhitespaceStart (offset); + AddChange (start, offset - start, " "); + + ForceSpacesBefore (propertyDeclaration.Setter.Body.LBraceToken, true); + ForceSpacesBefore (propertyDeclaration.Setter.Body.RBraceToken, true); + } + if (!propertyDeclaration.Setter.Body.IsNull) { + if (!policy.AllowPropertySetBlockInline || propertyDeclaration.Setter.Body.LBraceToken.StartLocation.Line != propertyDeclaration.Setter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertySetBraceStyle, propertyDeclaration.Setter.Body.LBraceToken, propertyDeclaration.Setter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (propertyDeclaration.Setter.Body, policy.IndentBlocks, data); + } + } + + if (policy.IndentPropertyBody) + IndentLevel--; + if (IsMember (propertyDeclaration.NextSibling)) + EnsureBlankLinesAfter (propertyDeclaration, policy.BlankLinesBetweenMembers); + return null; + } + + public override object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data) + { + ForceSpacesBefore (indexerDeclaration.LBracketToken, policy.SpaceBeforeIndexerDeclarationBracket); + ForceSpacesAfter (indexerDeclaration.LBracketToken, policy.SpaceWithinIndexerDeclarationBracket); + ForceSpacesBefore (indexerDeclaration.RBracketToken, policy.SpaceWithinIndexerDeclarationBracket); + + FormatCommas (indexerDeclaration, policy.SpaceBeforeIndexerDeclarationParameterComma, policy.SpaceAfterIndexerDeclarationParameterComma); + + + FixIndentationForceNewLine (indexerDeclaration.StartLocation); + EnforceBraceStyle (policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken); + if (policy.IndentPropertyBody) + IndentLevel++; + + if (!indexerDeclaration.Getter.IsNull) { + FixIndentation (indexerDeclaration.Getter.StartLocation); + if (!indexerDeclaration.Getter.Body.IsNull) { + if (!policy.AllowPropertyGetBlockInline || indexerDeclaration.Getter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Getter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertyGetBraceStyle, indexerDeclaration.Getter.Body.LBraceToken, indexerDeclaration.Getter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (indexerDeclaration.Getter.Body, policy.IndentBlocks, data); + } + } + + if (!indexerDeclaration.Setter.IsNull) { + FixIndentation (indexerDeclaration.Setter.StartLocation); + if (!indexerDeclaration.Setter.Body.IsNull) { + if (!policy.AllowPropertySetBlockInline || indexerDeclaration.Setter.Body.LBraceToken.StartLocation.Line != indexerDeclaration.Setter.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.PropertySetBraceStyle, indexerDeclaration.Setter.Body.LBraceToken, indexerDeclaration.Setter.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (indexerDeclaration.Setter.Body, policy.IndentBlocks, data); + } + } + if (policy.IndentPropertyBody) + IndentLevel--; + if (IsMember (indexerDeclaration.NextSibling)) + EnsureBlankLinesAfter (indexerDeclaration, policy.BlankLinesBetweenMembers); + return null; + } + + static bool IsSimpleEvent (AstNode node) + { + return node is EventDeclaration; + } + + public override object VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, object data) + { + FixIndentationForceNewLine (eventDeclaration.StartLocation); + EnforceBraceStyle (policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken); + if (policy.IndentEventBody) + IndentLevel++; + + if (!eventDeclaration.AddAccessor.IsNull) { + FixIndentation (eventDeclaration.AddAccessor.StartLocation); + if (!eventDeclaration.AddAccessor.Body.IsNull) { + if (!policy.AllowEventAddBlockInline || eventDeclaration.AddAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.AddAccessor.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.EventAddBraceStyle, eventDeclaration.AddAccessor.Body.LBraceToken, eventDeclaration.AddAccessor.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + + VisitBlockWithoutFixIndentation (eventDeclaration.AddAccessor.Body, policy.IndentBlocks, data); + } + } + + if (!eventDeclaration.RemoveAccessor.IsNull) { + FixIndentation (eventDeclaration.RemoveAccessor.StartLocation); + if (!eventDeclaration.RemoveAccessor.Body.IsNull) { + if (!policy.AllowEventRemoveBlockInline || eventDeclaration.RemoveAccessor.Body.LBraceToken.StartLocation.Line != eventDeclaration.RemoveAccessor.Body.RBraceToken.StartLocation.Line) { + EnforceBraceStyle (policy.EventRemoveBraceStyle, eventDeclaration.RemoveAccessor.Body.LBraceToken, eventDeclaration.RemoveAccessor.Body.RBraceToken); + } else { + nextStatementIndent = " "; + } + VisitBlockWithoutFixIndentation (eventDeclaration.RemoveAccessor.Body, policy.IndentBlocks, data); + } + } + + if (policy.IndentEventBody) + IndentLevel--; + + if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields); + } else if (IsMember (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers); + } + return null; + } + + public override object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) + { + FixIndentationForceNewLine (eventDeclaration.StartLocation); + if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields); + } else if (IsMember (eventDeclaration.NextSibling)) { + EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenMembers); + } + return null; + } + + public override object VisitAccessor (Accessor accessor, object data) + { + FixIndentationForceNewLine (accessor.StartLocation); + object result = base.VisitAccessor (accessor, data); + return result; + } + + public override object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) + { + FixIndentationForceNewLine (fieldDeclaration.StartLocation); + FormatCommas (fieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); + if (fieldDeclaration.NextSibling is FieldDeclaration || fieldDeclaration.NextSibling is FixedFieldDeclaration) { + EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenFields); + } else if (IsMember (fieldDeclaration.NextSibling)) { + EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenMembers); + } + return base.VisitFieldDeclaration (fieldDeclaration, data); + } + + public override object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) + { + FixIndentationForceNewLine (fixedFieldDeclaration.StartLocation); + FormatCommas (fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); + if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) { + EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenFields); + } else if (IsMember (fixedFieldDeclaration.NextSibling)) { + EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenMembers); + } + return base.VisitFixedFieldDeclaration (fixedFieldDeclaration, data); + } + + public override object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) + { + FixIndentationForceNewLine (enumMemberDeclaration.StartLocation); + return base.VisitEnumMemberDeclaration (enumMemberDeclaration, data); + } + + public override object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) + { + FixIndentation (delegateDeclaration.StartLocation); + + ForceSpacesBefore (delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses); + if (delegateDeclaration.Parameters.Any ()) { + ForceSpacesAfter (delegateDeclaration.LParToken, policy.SpaceWithinDelegateDeclarationParentheses); + ForceSpacesBefore (delegateDeclaration.RParToken, policy.SpaceWithinDelegateDeclarationParentheses); + } else { + ForceSpacesAfter (delegateDeclaration.LParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses); + ForceSpacesBefore (delegateDeclaration.RParToken, policy.SpaceBetweenEmptyDelegateDeclarationParentheses); + } + FormatCommas (delegateDeclaration, policy.SpaceBeforeDelegateDeclarationParameterComma, policy.SpaceAfterDelegateDeclarationParameterComma); + + if (delegateDeclaration.NextSibling is TypeDeclaration || delegateDeclaration.NextSibling is DelegateDeclaration) { + EnsureBlankLinesAfter (delegateDeclaration, policy.BlankLinesBetweenTypes); + } else if (IsMember (delegateDeclaration.NextSibling)) { + EnsureBlankLinesAfter (delegateDeclaration, policy.BlankLinesBetweenMembers); + } + + return base.VisitDelegateDeclaration (delegateDeclaration, data); + } + + static bool IsMember (AstNode nextSibling) + { + return nextSibling != null && nextSibling.NodeType == NodeType.Member; + } + + public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) + { + FixIndentationForceNewLine (methodDeclaration.StartLocation); + + ForceSpacesBefore (methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); + if (methodDeclaration.Parameters.Any ()) { + ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); + ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses); + } else { + ForceSpacesAfter (methodDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + ForceSpacesBefore (methodDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + } + FormatCommas (methodDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma); + + if (!methodDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.MethodBraceStyle, methodDeclaration.Body.LBraceToken, methodDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + base.VisitBlockStatement (methodDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (methodDeclaration.NextSibling)) + EnsureBlankLinesAfter (methodDeclaration, policy.BlankLinesBetweenMembers); + + return null; + } + + public override object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) + { + FixIndentationForceNewLine (operatorDeclaration.StartLocation); + + ForceSpacesBefore (operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); + if (operatorDeclaration.Parameters.Any ()) { + ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceWithinMethodDeclarationParentheses); + ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceWithinMethodDeclarationParentheses); + } else { + ForceSpacesAfter (operatorDeclaration.LParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + ForceSpacesBefore (operatorDeclaration.RParToken, policy.SpaceBetweenEmptyMethodDeclarationParentheses); + } + FormatCommas (operatorDeclaration, policy.SpaceBeforeMethodDeclarationParameterComma, policy.SpaceAfterMethodDeclarationParameterComma); + + if (!operatorDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.MethodBraceStyle, operatorDeclaration.Body.LBraceToken, operatorDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + base.VisitBlockStatement (operatorDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (operatorDeclaration.NextSibling)) + EnsureBlankLinesAfter (operatorDeclaration, policy.BlankLinesBetweenMembers); + + return null; + } + + public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) + { + FixIndentationForceNewLine (constructorDeclaration.StartLocation); + + ForceSpacesBefore (constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses); + if (constructorDeclaration.Parameters.Any ()) { + ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceWithinConstructorDeclarationParentheses); + ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceWithinConstructorDeclarationParentheses); + } else { + ForceSpacesAfter (constructorDeclaration.LParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); + ForceSpacesBefore (constructorDeclaration.RParToken, policy.SpaceBetweenEmptyConstructorDeclarationParentheses); + } + FormatCommas (constructorDeclaration, policy.SpaceBeforeConstructorDeclarationParameterComma, policy.SpaceAfterConstructorDeclarationParameterComma); + + object result = null; + if (!constructorDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.ConstructorBraceStyle, constructorDeclaration.Body.LBraceToken, constructorDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + result = base.VisitBlockStatement (constructorDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (constructorDeclaration.NextSibling)) + EnsureBlankLinesAfter (constructorDeclaration, policy.BlankLinesBetweenMembers); + return result; + } + + public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) + { + FixIndentationForceNewLine (destructorDeclaration.StartLocation); + + CSharpTokenNode lParen = destructorDeclaration.LParToken; + int offset = this.data.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column); + ForceSpaceBefore (offset, policy.SpaceBeforeConstructorDeclarationParentheses); + + object result = null; + if (!destructorDeclaration.Body.IsNull) { + EnforceBraceStyle (policy.DestructorBraceStyle, destructorDeclaration.Body.LBraceToken, destructorDeclaration.Body.RBraceToken); + if (policy.IndentMethodBody) + IndentLevel++; + result = base.VisitBlockStatement (destructorDeclaration.Body, data); + if (policy.IndentMethodBody) + IndentLevel--; + } + if (IsMember (destructorDeclaration.NextSibling)) + EnsureBlankLinesAfter (destructorDeclaration, policy.BlankLinesBetweenMembers); + return result; + } + + #region Statements + public override object VisitExpressionStatement (ExpressionStatement expressionStatement, object data) + { + FixStatementIndentation (expressionStatement.StartLocation); + FixSemicolon (expressionStatement.SemicolonToken); + return base.VisitExpressionStatement (expressionStatement, data); + } + + object VisitBlockWithoutFixIndentation (BlockStatement blockStatement, bool indent, object data) + { + if (indent) + IndentLevel++; + object result = base.VisitBlockStatement (blockStatement, data); + if (indent) + IndentLevel--; + return result; + } + + public override object VisitBlockStatement (BlockStatement blockStatement, object data) + { + FixIndentation (blockStatement.StartLocation); + object result = VisitBlockWithoutFixIndentation (blockStatement, policy.IndentBlocks, data); + FixIndentation (blockStatement.EndLocation, -1); + return result; + } + + public override object VisitComment (Comment comment, object data) + { + if (comment.StartsLine && !HadErrors && comment.StartLocation.Column > 1) + FixIndentation (comment.StartLocation); + return null; + } + + public override object VisitBreakStatement (BreakStatement breakStatement, object data) + { + FixStatementIndentation (breakStatement.StartLocation); + return null; + } + + public override object VisitCheckedStatement (CheckedStatement checkedStatement, object data) + { + FixStatementIndentation (checkedStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, checkedStatement.Body); + } + + public override object VisitContinueStatement (ContinueStatement continueStatement, object data) + { + FixStatementIndentation (continueStatement.StartLocation); + return null; + } + + public override object VisitEmptyStatement (EmptyStatement emptyStatement, object data) + { + FixStatementIndentation (emptyStatement.StartLocation); + return null; + } + + public override object VisitFixedStatement (FixedStatement fixedStatement, object data) + { + FixStatementIndentation (fixedStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, fixedStatement.EmbeddedStatement); + } + + public override object VisitForeachStatement (ForeachStatement foreachStatement, object data) + { + FixStatementIndentation (foreachStatement.StartLocation); + ForceSpacesBefore (foreachStatement.LParToken, policy.SpaceBeforeForeachParentheses); + + ForceSpacesAfter (foreachStatement.LParToken, policy.SpacesWithinForeachParentheses); + ForceSpacesBefore (foreachStatement.RParToken, policy.SpacesWithinForeachParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForEachBraceForcement, foreachStatement.EmbeddedStatement); + } + + object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, AstNode node) + { + return FixEmbeddedStatment (braceStyle, braceForcement, null, false, node); + } + + object FixEmbeddedStatment (BraceStyle braceStyle, BraceForcement braceForcement, CSharpTokenNode token, bool allowInLine, AstNode node) + { + if (node == null) + return null; + int originalLevel = curIndent.Level; + bool isBlock = node is BlockStatement; + switch (braceForcement) { + case BraceForcement.DoNotChange: + //nothing + break; + case BraceForcement.AddBraces: + if (!isBlock) { + AstNode n = node.Parent.GetCSharpNodeBefore (node); + int start = data.LocationToOffset (n.EndLocation.Line, n.EndLocation.Column); + var next = n.GetNextNode (); + int offset = data.LocationToOffset (next.StartLocation.Line, next.StartLocation.Column); + string startBrace = ""; + switch (braceStyle) { + case BraceStyle.EndOfLineWithoutSpace: + startBrace = "{"; + break; + case BraceStyle.EndOfLine: + startBrace = " {"; + break; + case BraceStyle.NextLine: + startBrace = data.EolMarker + curIndent.IndentString + "{"; + break; + case BraceStyle.NextLineShifted2: + case BraceStyle.NextLineShifted: + startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; + break; + } + if (IsLineIsEmptyUpToEol (data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column))) + startBrace += data.EolMarker + data.GetIndentation (node.StartLocation.Line); + AddChange (start, offset - start, startBrace); + } + break; + case BraceForcement.RemoveBraces: + if (isBlock) { + BlockStatement block = node as BlockStatement; + if (block.Statements.Count () == 1) { + int offset1 = data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column); + int start = SearchWhitespaceStart (offset1); + + int offset2 = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + int end = SearchWhitespaceStart (offset2 - 1); + + AddChange (start, offset1 - start + 1, null); + AddChange (end + 1, offset2 - end, null); + node = block.FirstChild; + isBlock = false; + } + } + break; + } + if (isBlock) { + BlockStatement block = node as BlockStatement; + if (allowInLine && block.StartLocation.Line == block.EndLocation.Line && block.Statements.Count () <= 1) { + if (block.Statements.Count () == 1) + nextStatementIndent = " "; + } else { + EnforceBraceStyle (braceStyle, block.LBraceToken, block.RBraceToken); + } + if (braceStyle == BraceStyle.NextLineShifted2) + curIndent.Level++; + } else { + if (allowInLine && token.StartLocation.Line == node.EndLocation.Line) { + nextStatementIndent = " "; + } + } + if (!(policy.AlignEmbeddedIfStatements && node is IfElseStatement && node.Parent is IfElseStatement || + policy.AlignEmbeddedUsingStatements && node is UsingStatement && node.Parent is UsingStatement)) + curIndent.Level++; + object result = isBlock ? base.VisitBlockStatement ((BlockStatement)node, null) : node.AcceptVisitor (this, null); + curIndent.Level = originalLevel; + switch (braceForcement) { + case BraceForcement.DoNotChange: + break; + case BraceForcement.AddBraces: + if (!isBlock) { + int offset = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + if (!char.IsWhiteSpace (data.GetCharAt (offset))) + offset++; + string startBrace = ""; + switch (braceStyle) { + case BraceStyle.DoNotChange: + startBrace = null; + break; + case BraceStyle.EndOfLineWithoutSpace: + startBrace = data.EolMarker + curIndent.IndentString + "}"; + break; + case BraceStyle.EndOfLine: + startBrace = data.EolMarker + curIndent.IndentString + "}"; + break; + case BraceStyle.NextLine: + startBrace = data.EolMarker + curIndent.IndentString + "}"; + break; + case BraceStyle.NextLineShifted2: + case BraceStyle.NextLineShifted: + startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; + break; + } + if (startBrace != null) + AddChange (offset, 0, startBrace); + } + break; + } + return result; + } + + void EnforceBraceStyle (BraceStyle braceStyle, AstNode lbrace, AstNode rbrace) + { + if (lbrace.IsNull || rbrace.IsNull) + return; + +// LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line); + int lbraceOffset = data.LocationToOffset (lbrace.StartLocation.Line, lbrace.StartLocation.Column); + +// LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line); + int rbraceOffset = data.LocationToOffset (rbrace.StartLocation.Line, rbrace.StartLocation.Column); + int whitespaceStart = SearchWhitespaceStart (lbraceOffset); + int whitespaceEnd = SearchWhitespaceLineStart (rbraceOffset); + string startIndent = ""; + string endIndent = ""; + switch (braceStyle) { + case BraceStyle.DoNotChange: + startIndent = endIndent = null; + break; + case BraceStyle.EndOfLineWithoutSpace: + startIndent = ""; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + break; + case BraceStyle.EndOfLine: + var prevNode = lbrace.GetPrevNode (); + if (prevNode is Comment) { + // delete old bracket + AddChange (whitespaceStart, lbraceOffset - whitespaceStart + 1, ""); + + while (prevNode is Comment) { + prevNode = prevNode.GetPrevNode (); + } + whitespaceStart = data.LocationToOffset (prevNode.EndLocation.Line, prevNode.EndLocation.Column); + lbraceOffset = whitespaceStart; + startIndent = " {"; + } else { + startIndent = " "; + } + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + break; + case BraceStyle.NextLine: + startIndent = data.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + break; + case BraceStyle.NextLineShifted2: + case BraceStyle.NextLineShifted: + startIndent = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + break; + } + + if (lbraceOffset > 0 && startIndent != null) + AddChange (whitespaceStart, lbraceOffset - whitespaceStart, startIndent); + if (rbraceOffset > 0 && endIndent != null) + AddChange (whitespaceEnd, rbraceOffset - whitespaceEnd, endIndent); + } + + void AddChange (int offset, int removedChars, string insertedText) + { + if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars + && c.InsertedText == insertedText)) + return; + string currentText = data.GetTextAt (offset, removedChars); + if (currentText == insertedText) + return; + if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}'))) + throw new InvalidOperationException ("Tried to remove non ws chars: '" + currentText + "'"); + foreach (var change in changes) { + if (change.Offset == offset) { + if (removedChars > 0 && insertedText == change.InsertedText) { + change.RemovedChars = removedChars; +// change.InsertedText = insertedText; + return; + } + if (!string.IsNullOrEmpty (change.InsertedText)) { + change.InsertedText += insertedText; + } else { + change.InsertedText = insertedText; + } + change.RemovedChars = System.Math.Max (removedChars, change.RemovedChars); + return; + } + } + //Console.WriteLine ("offset={0}, removedChars={1}, insertedText={2}", offset, removedChars, insertedText == null ? "" : insertedText.Replace ("\n", "\\n").Replace ("\t", "\\t").Replace (" ", ".")); + //Console.WriteLine (Environment.StackTrace); + + changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText)); + } + + public bool IsLineIsEmptyUpToEol (AstLocation startLocation) + { + return IsLineIsEmptyUpToEol (data.LocationToOffset (startLocation.Line, startLocation.Column) - 1); + } + + bool IsLineIsEmptyUpToEol (int startOffset) + { + for (int offset = startOffset - 1; offset >= 0; offset--) { + char ch = data.GetCharAt (offset); + if (ch != ' ' && ch != '\t') + return ch == '\n' || ch == '\r'; + } + return true; + } + + int SearchWhitespaceStart (int startOffset) + { + if (startOffset < 0) + throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); + for (int offset = startOffset - 1; offset >= 0; offset--) { + char ch = data.GetCharAt (offset); + if (!Char.IsWhiteSpace (ch)) { + return offset + 1; + } + } + return 0; + } + + int SearchWhitespaceEnd (int startOffset) + { + if (startOffset > data.Length) + throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); + for (int offset = startOffset + 1; offset < data.Length; offset++) { + char ch = data.GetCharAt (offset); + if (!Char.IsWhiteSpace (ch)) { + return offset + 1; + } + } + return data.Length - 1; + } + + int SearchWhitespaceLineStart (int startOffset) + { + if (startOffset < 0) + throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); + for (int offset = startOffset - 1; offset >= 0; offset--) { + char ch = data.GetCharAt (offset); + if (ch != ' ' && ch != '\t') { + return offset + 1; + } + } + return 0; + } + + public override object VisitForStatement (ForStatement forStatement, object data) + { + FixStatementIndentation (forStatement.StartLocation); + foreach (AstNode node in forStatement.Children) { + if (node.Role == ForStatement.Roles.Semicolon) { + if (node.NextSibling is CSharpTokenNode || node.NextSibling is EmptyStatement) + continue; + ForceSpacesBefore (node, policy.SpaceBeforeForSemicolon); + ForceSpacesAfter (node, policy.SpaceAfterForSemicolon); + } + } + + ForceSpacesBefore (forStatement.LParToken, policy.SpaceBeforeForParentheses); + + ForceSpacesAfter (forStatement.LParToken, policy.SpacesWithinForParentheses); + ForceSpacesBefore (forStatement.RParToken, policy.SpacesWithinForParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.ForBraceForcement, forStatement.EmbeddedStatement); + } + + public override object VisitGotoStatement (GotoStatement gotoStatement, object data) + { + FixStatementIndentation (gotoStatement.StartLocation); + return VisitChildren (gotoStatement, data); + } + + public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) + { + ForceSpacesBefore (ifElseStatement.LParToken, policy.SpaceBeforeIfParentheses); + + ForceSpacesAfter (ifElseStatement.LParToken, policy.SpacesWithinIfParentheses); + ForceSpacesBefore (ifElseStatement.RParToken, policy.SpacesWithinIfParentheses); + + if (!(ifElseStatement.Parent is IfElseStatement && ((IfElseStatement)ifElseStatement.Parent).FalseStatement == ifElseStatement)) + FixStatementIndentation (ifElseStatement.StartLocation); + + if (!ifElseStatement.Condition.IsNull) + ifElseStatement.Condition.AcceptVisitor (this, data); + + if (!ifElseStatement.TrueStatement.IsNull) + FixEmbeddedStatment (policy.StatementBraceStyle, policy.IfElseBraceForcement, ifElseStatement.IfToken, policy.AllowIfBlockInline, ifElseStatement.TrueStatement); + + if (!ifElseStatement.FalseStatement.IsNull) { + PlaceOnNewLine (policy.PlaceElseOnNewLine || !(ifElseStatement.TrueStatement is BlockStatement) && policy.IfElseBraceForcement != BraceForcement.AddBraces, ifElseStatement.ElseToken); + var forcement = policy.IfElseBraceForcement; + if (ifElseStatement.FalseStatement is IfElseStatement) { + forcement = BraceForcement.DoNotChange; + PlaceOnNewLine (policy.PlaceElseIfOnNewLine, ((IfElseStatement)ifElseStatement.FalseStatement).IfToken); + } + FixEmbeddedStatment (policy.StatementBraceStyle, forcement, ifElseStatement.ElseToken, policy.AllowIfBlockInline, ifElseStatement.FalseStatement); + } + + return null; + } + + public override object VisitLabelStatement (LabelStatement labelStatement, object data) + { + // TODO + return VisitChildren (labelStatement, data); + } + + public override object VisitLockStatement (LockStatement lockStatement, object data) + { + FixStatementIndentation (lockStatement.StartLocation); + ForceSpacesBefore (lockStatement.LParToken, policy.SpaceBeforeLockParentheses); + + ForceSpacesAfter (lockStatement.LParToken, policy.SpacesWithinLockParentheses); + ForceSpacesBefore (lockStatement.RParToken, policy.SpacesWithinLockParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, lockStatement.EmbeddedStatement); + } + + public override object VisitReturnStatement (ReturnStatement returnStatement, object data) + { + FixStatementIndentation (returnStatement.StartLocation); + return VisitChildren (returnStatement, data); + } + + public override object VisitSwitchStatement (SwitchStatement switchStatement, object data) + { + FixStatementIndentation (switchStatement.StartLocation); + ForceSpacesBefore (switchStatement.LParToken, policy.SpaceBeforeSwitchParentheses); + + ForceSpacesAfter (switchStatement.LParToken, policy.SpacesWithinSwitchParentheses); + ForceSpacesBefore (switchStatement.RParToken, policy.SpacesWithinSwitchParentheses); + + EnforceBraceStyle (policy.StatementBraceStyle, switchStatement.LBraceToken, switchStatement.RBraceToken); + object result = VisitChildren (switchStatement, data); + return result; + } + + public override object VisitSwitchSection (SwitchSection switchSection, object data) + { + if (policy.IndentSwitchBody) + curIndent.Level++; + + foreach (CaseLabel label in switchSection.CaseLabels) { + FixStatementIndentation (label.StartLocation); + } + if (policy.IndentCaseBody) + curIndent.Level++; + + foreach (var stmt in switchSection.Statements) { + stmt.AcceptVisitor (this, null); + } + if (policy.IndentCaseBody) + curIndent.Level--; + + if (policy.IndentSwitchBody) + curIndent.Level--; + return null; + } + + public override object VisitCaseLabel (CaseLabel caseLabel, object data) + { + // handled in switchsection + return null; + } + + public override object VisitThrowStatement (ThrowStatement throwStatement, object data) + { + FixStatementIndentation (throwStatement.StartLocation); + return VisitChildren (throwStatement, data); + } + + public override object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data) + { + FixStatementIndentation (tryCatchStatement.StartLocation); + + if (!tryCatchStatement.TryBlock.IsNull) + FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.TryBlock); + + foreach (CatchClause clause in tryCatchStatement.CatchClauses) { + PlaceOnNewLine (policy.PlaceCatchOnNewLine, clause.CatchToken); + if (!clause.LParToken.IsNull) { + ForceSpacesBefore (clause.LParToken, policy.SpaceBeforeCatchParentheses); + + ForceSpacesAfter (clause.LParToken, policy.SpacesWithinCatchParentheses); + ForceSpacesBefore (clause.RParToken, policy.SpacesWithinCatchParentheses); + } + FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, clause.Body); + } + + if (!tryCatchStatement.FinallyBlock.IsNull) { + PlaceOnNewLine (policy.PlaceFinallyOnNewLine, tryCatchStatement.FinallyToken); + + FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, tryCatchStatement.FinallyBlock); + } + + return VisitChildren (tryCatchStatement, data); + } + + public override object VisitCatchClause (CatchClause catchClause, object data) + { + // Handled in TryCatchStatement + return null; + } + + public override object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data) + { + FixStatementIndentation (uncheckedStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.FixedBraceForcement, uncheckedStatement.Body); + } + + public override object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data) + { + FixStatementIndentation (unsafeStatement.StartLocation); + return FixEmbeddedStatment (policy.StatementBraceStyle, BraceForcement.DoNotChange, unsafeStatement.Body); + } + + public override object VisitUsingStatement (UsingStatement usingStatement, object data) + { + FixStatementIndentation (usingStatement.StartLocation); + ForceSpacesBefore (usingStatement.LParToken, policy.SpaceBeforeUsingParentheses); + + ForceSpacesAfter (usingStatement.LParToken, policy.SpacesWithinUsingParentheses); + ForceSpacesBefore (usingStatement.RParToken, policy.SpacesWithinUsingParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.UsingBraceForcement, usingStatement.EmbeddedStatement); + } + + public override object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data) + { + if (!variableDeclarationStatement.SemicolonToken.IsNull) + FixStatementIndentation (variableDeclarationStatement.StartLocation); + + if ((variableDeclarationStatement.Modifiers & Modifiers.Const) == Modifiers.Const) { + ForceSpacesAround (variableDeclarationStatement.Type, true); + } else { + ForceSpacesAfter (variableDeclarationStatement.Type, true); + } + foreach (var initializer in variableDeclarationStatement.Variables) { + initializer.AcceptVisitor (this, data); + } + FormatCommas (variableDeclarationStatement, policy.SpaceBeforeLocalVariableDeclarationComma, policy.SpaceAfterLocalVariableDeclarationComma); + FixSemicolon (variableDeclarationStatement.SemicolonToken); + return null; + } + + public override object VisitDoWhileStatement (DoWhileStatement doWhileStatement, object data) + { + FixStatementIndentation (doWhileStatement.StartLocation); + PlaceOnNewLine (policy.PlaceWhileOnNewLine, doWhileStatement.WhileToken); + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.WhileBraceForcement, doWhileStatement.EmbeddedStatement); + } + + public override object VisitWhileStatement (WhileStatement whileStatement, object data) + { + FixStatementIndentation (whileStatement.StartLocation); + ForceSpacesBefore (whileStatement.LParToken, policy.SpaceBeforeWhileParentheses); + + ForceSpacesAfter (whileStatement.LParToken, policy.SpacesWithinWhileParentheses); + ForceSpacesBefore (whileStatement.RParToken, policy.SpacesWithinWhileParentheses); + + return FixEmbeddedStatment (policy.StatementBraceStyle, policy.WhileBraceForcement, whileStatement.EmbeddedStatement); + } + + public override object VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, object data) + { + FixStatementIndentation (yieldBreakStatement.StartLocation); + return null; + } + + public override object VisitYieldStatement (YieldStatement yieldStatement, object data) + { + FixStatementIndentation (yieldStatement.StartLocation); + return null; + } + + public override object VisitVariableInitializer (VariableInitializer variableInitializer, object data) + { + if (!variableInitializer.AssignToken.IsNull) + ForceSpacesAround (variableInitializer.AssignToken, policy.SpaceAroundAssignment); + if (!variableInitializer.Initializer.IsNull) + variableInitializer.Initializer.AcceptVisitor (this, data); + return data; + } + + #endregion + + #region Expressions + public override object VisitComposedType (ComposedType composedType, object data) + { + var spec = composedType.ArraySpecifiers.FirstOrDefault (); + if (spec != null) + ForceSpacesBefore (spec.LBracketToken, policy.SpaceBeforeArrayDeclarationBrackets); + + return base.VisitComposedType (composedType, data); + } + + public override object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data) + { + ForceSpacesAround (assignmentExpression.OperatorToken, policy.SpaceAroundAssignment); + return base.VisitAssignmentExpression (assignmentExpression, data); + } + + public override object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data) + { + bool forceSpaces = false; + switch (binaryOperatorExpression.Operator) { + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + forceSpaces = policy.SpaceAroundEqualityOperator; + break; + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.GreaterThanOrEqual: + case BinaryOperatorType.LessThan: + case BinaryOperatorType.LessThanOrEqual: + forceSpaces = policy.SpaceAroundRelationalOperator; + break; + case BinaryOperatorType.ConditionalAnd: + case BinaryOperatorType.ConditionalOr: + forceSpaces = policy.SpaceAroundLogicalOperator; + break; + case BinaryOperatorType.BitwiseAnd: + case BinaryOperatorType.BitwiseOr: + case BinaryOperatorType.ExclusiveOr: + forceSpaces = policy.SpaceAroundBitwiseOperator; + break; + case BinaryOperatorType.Add: + case BinaryOperatorType.Subtract: + forceSpaces = policy.SpaceAroundAdditiveOperator; + break; + case BinaryOperatorType.Multiply: + case BinaryOperatorType.Divide: + case BinaryOperatorType.Modulus: + forceSpaces = policy.SpaceAroundMultiplicativeOperator; + break; + case BinaryOperatorType.ShiftLeft: + case BinaryOperatorType.ShiftRight: + forceSpaces = policy.SpaceAroundShiftOperator; + break; + case BinaryOperatorType.NullCoalescing: + forceSpaces = policy.SpaceAroundNullCoalescingOperator; + break; + } + ForceSpacesAround (binaryOperatorExpression.OperatorToken, forceSpaces); + + return base.VisitBinaryOperatorExpression (binaryOperatorExpression, data); + } + + public override object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data) + { + ForceSpacesBefore (conditionalExpression.QuestionMarkToken, policy.SpaceBeforeConditionalOperatorCondition); + ForceSpacesAfter (conditionalExpression.QuestionMarkToken, policy.SpaceAfterConditionalOperatorCondition); + ForceSpacesBefore (conditionalExpression.ColonToken, policy.SpaceBeforeConditionalOperatorSeparator); + ForceSpacesAfter (conditionalExpression.ColonToken, policy.SpaceAfterConditionalOperatorSeparator); + return base.VisitConditionalExpression (conditionalExpression, data); + } + + public override object VisitCastExpression (CastExpression castExpression, object data) + { + if (castExpression.RParToken != null) { + ForceSpacesAfter (castExpression.LParToken, policy.SpacesWithinCastParentheses); + ForceSpacesBefore (castExpression.RParToken, policy.SpacesWithinCastParentheses); + + ForceSpacesAfter (castExpression.RParToken, policy.SpaceAfterTypecast); + } + return base.VisitCastExpression (castExpression, data); + } + + void ForceSpacesAround (AstNode node, bool forceSpaces) + { + if (node.IsNull) + return; + ForceSpacesBefore (node, forceSpaces); + ForceSpacesAfter (node, forceSpaces); + } + + void FormatCommas (AstNode parent, bool before, bool after) + { + if (parent.IsNull) + return; + foreach (CSharpTokenNode comma in parent.Children.Where (node => node.Role == FieldDeclaration.Roles.Comma)) { + ForceSpacesAfter (comma, after); + ForceSpacesBefore (comma, before); + } + } + + public override object VisitInvocationExpression (InvocationExpression invocationExpression, object data) + { + ForceSpacesBefore (invocationExpression.LParToken, policy.SpaceBeforeMethodCallParentheses); + if (invocationExpression.Arguments.Any ()) { + ForceSpacesAfter (invocationExpression.LParToken, policy.SpaceWithinMethodCallParentheses); + ForceSpacesBefore (invocationExpression.RParToken, policy.SpaceWithinMethodCallParentheses); + } else { + ForceSpacesAfter (invocationExpression.LParToken, policy.SpaceBetweenEmptyMethodCallParentheses); + ForceSpacesBefore (invocationExpression.RParToken, policy.SpaceBetweenEmptyMethodCallParentheses); + } + FormatCommas (invocationExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); + + return base.VisitInvocationExpression (invocationExpression, data); + } + + public override object VisitIndexerExpression (IndexerExpression indexerExpression, object data) + { + ForceSpacesBefore (indexerExpression.LBracketToken, policy.SpacesBeforeBrackets); + ForceSpacesAfter (indexerExpression.LBracketToken, policy.SpacesWithinBrackets); + ForceSpacesBefore (indexerExpression.RBracketToken, policy.SpacesWithinBrackets); + FormatCommas (indexerExpression, policy.SpaceBeforeBracketComma, policy.SpaceAfterBracketComma); + + return base.VisitIndexerExpression (indexerExpression, data); + } + + public override object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data) + { + ForceSpacesAfter (parenthesizedExpression.LParToken, policy.SpacesWithinParentheses); + ForceSpacesBefore (parenthesizedExpression.RParToken, policy.SpacesWithinParentheses); + return base.VisitParenthesizedExpression (parenthesizedExpression, data); + } + + public override object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data) + { + ForceSpacesBefore (sizeOfExpression.LParToken, policy.SpaceBeforeSizeOfParentheses); + ForceSpacesAfter (sizeOfExpression.LParToken, policy.SpacesWithinSizeOfParentheses); + ForceSpacesBefore (sizeOfExpression.RParToken, policy.SpacesWithinSizeOfParentheses); + return base.VisitSizeOfExpression (sizeOfExpression, data); + } + + public override object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data) + { + ForceSpacesBefore (typeOfExpression.LParToken, policy.SpaceBeforeTypeOfParentheses); + ForceSpacesAfter (typeOfExpression.LParToken, policy.SpacesWithinTypeOfParentheses); + ForceSpacesBefore (typeOfExpression.RParToken, policy.SpacesWithinTypeOfParentheses); + return base.VisitTypeOfExpression (typeOfExpression, data); + } + + public override object VisitCheckedExpression (CheckedExpression checkedExpression, object data) + { + ForceSpacesAfter (checkedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); + ForceSpacesBefore (checkedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); + return base.VisitCheckedExpression (checkedExpression, data); + } + + public override object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data) + { + ForceSpacesAfter (uncheckedExpression.LParToken, policy.SpacesWithinCheckedExpressionParantheses); + ForceSpacesBefore (uncheckedExpression.RParToken, policy.SpacesWithinCheckedExpressionParantheses); + return base.VisitUncheckedExpression (uncheckedExpression, data); + } + + public override object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data) + { + ForceSpacesBefore (objectCreateExpression.LParToken, policy.SpaceBeforeNewParentheses); + + if (objectCreateExpression.Arguments.Any ()) { + if (!objectCreateExpression.LParToken.IsNull) + ForceSpacesAfter (objectCreateExpression.LParToken, policy.SpacesWithinNewParentheses); + if (!objectCreateExpression.RParToken.IsNull) + ForceSpacesBefore (objectCreateExpression.RParToken, policy.SpacesWithinNewParentheses); + } else { + if (!objectCreateExpression.LParToken.IsNull) + ForceSpacesAfter (objectCreateExpression.LParToken, policy.SpacesBetweenEmptyNewParentheses); + if (!objectCreateExpression.RParToken.IsNull) + ForceSpacesBefore (objectCreateExpression.RParToken, policy.SpacesBetweenEmptyNewParentheses); + } + FormatCommas (objectCreateExpression, policy.SpaceBeforeNewParameterComma, policy.SpaceAfterNewParameterComma); + + return base.VisitObjectCreateExpression (objectCreateExpression, data); + } + + public override object VisitArrayCreateExpression (ArrayCreateExpression arrayObjectCreateExpression, object data) + { + FormatCommas (arrayObjectCreateExpression, policy.SpaceBeforeMethodCallParameterComma, policy.SpaceAfterMethodCallParameterComma); + return base.VisitArrayCreateExpression (arrayObjectCreateExpression, data); + } + + public override object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) + { + ForceSpacesAfter (lambdaExpression.ArrowToken, true); + ForceSpacesBefore (lambdaExpression.ArrowToken, true); + + return base.VisitLambdaExpression (lambdaExpression, data); + } + + #endregion + + void ForceSpaceBefore (int offset, bool forceSpace) + { + bool insertedSpace = false; + do { + char ch = data.GetCharAt (offset); + //Console.WriteLine (ch); + if (!IsSpacing (ch) && (insertedSpace || !forceSpace)) + break; + if (ch == ' ' && forceSpace) { + if (insertedSpace) { + AddChange (offset, 1, null); + } else { + insertedSpace = true; + } + } else if (forceSpace) { + if (!insertedSpace) { + AddChange (offset, IsSpacing (ch) ? 1 : 0, " "); + insertedSpace = true; + } else if (IsSpacing (ch)) { + AddChange (offset, 1, null); + } + } + + offset--; + } while (offset >= 0); + } + + + + /* + int GetLastNonWsChar (LineSegment line, int lastColumn) + { + int result = -1; + bool inComment = false; + for (int i = 0; i < lastColumn; i++) { + char ch = data.GetCharAt (line.Offset + i); + if (Char.IsWhiteSpace (ch)) + continue; + if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') + return result; + if (ch == '/' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '*') { + inComment = true; + i++; + continue; + } + if (inComment && ch == '*' && i + 1 < line.EditableLength && data.GetCharAt (line.Offset + i + 1) == '/') { + inComment = false; + i++; + continue; + } + if (!inComment) + result = i; + } + return result; + } + */ + + + public void FixSemicolon (CSharpTokenNode semicolon) + { + if (semicolon.IsNull) + return; + int endOffset = data.LocationToOffset (semicolon.StartLocation.Line, semicolon.StartLocation.Column); + int offset = endOffset; + while (offset - 1 > 0 && char.IsWhiteSpace (data.GetCharAt (offset - 1))) { + offset--; + } + if (offset < endOffset) { + AddChange (offset, endOffset - offset, null); + } + } + + void PlaceOnNewLine (bool newLine, AstNode keywordNode) + { + if (keywordNode == null) + return; + int offset = data.LocationToOffset (keywordNode.StartLocation.Line, keywordNode.StartLocation.Column); + + int whitespaceStart = SearchWhitespaceStart (offset); + string indentString = newLine ? data.EolMarker + this.curIndent.IndentString : " "; + AddChange (whitespaceStart, offset - whitespaceStart, indentString); + } + + string nextStatementIndent = null; + + void FixStatementIndentation (AstLocation location) + { + int offset = data.LocationToOffset (location.Line, location.Column); + if (offset <= 0) { + Console.WriteLine ("possible wrong offset"); + Console.WriteLine (Environment.StackTrace); + return; + } + bool isEmpty = IsLineIsEmptyUpToEol (offset); + int lineStart = SearchWhitespaceLineStart (offset); + string indentString = nextStatementIndent == null ? (isEmpty ? "" : data.EolMarker) + this.curIndent.IndentString : nextStatementIndent; + nextStatementIndent = null; + AddChange (lineStart, offset - lineStart, indentString); + } + + void FixIndentation (AstLocation location) + { + FixIndentation (location, 0); + } + + void FixIndentation (AstLocation location, int relOffset) + { + if (location.Line < 1 || location.Line > data.LineCount) { + Console.WriteLine ("Invalid location " + location); + Console.WriteLine (Environment.StackTrace); + return; + } + + string lineIndent = data.GetIndentation (location.Line); + string indentString = this.curIndent.IndentString; + if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) { + AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + } + } + + void FixIndentationForceNewLine (AstLocation location) + { + string lineIndent = data.GetIndentation (location.Line); + string indentString = this.curIndent.IndentString; + if (location.Column - 1 == lineIndent.Length) { + AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + } else { + int offset = data.LocationToOffset (location.Line, location.Column); + int start = SearchWhitespaceLineStart (offset); + if (start > 0) { + char ch = data.GetCharAt (start - 1); + if (ch == '\n') { + start--; + if (start > 1 && data.GetCharAt (start - 1) == '\r') + start--; + } else if (ch == '\r') { + start--; + } + AddChange (start, offset - start, data.EolMarker + indentString); + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/CSharpFormattingOptions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/CSharpFormattingOptions.cs new file mode 100644 index 0000000000..17c4a5899d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/CSharpFormattingOptions.cs @@ -0,0 +1,962 @@ +// +// CSharpFormattingOptions.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Reflection; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + public enum BraceStyle + { + DoNotChange, + EndOfLine, + EndOfLineWithoutSpace, + NextLine, + NextLineShifted, + NextLineShifted2 + } + + public enum BraceForcement + { + DoNotChange, + RemoveBraces, + AddBraces + } + + public enum ArrayInitializerPlacement + { + AlwaysNewLine, + AlwaysSameLine + } + + public enum PropertyFormatting + { + AllowOneLine, + ForceOneLine, + ForceNewLine + } + + public class CSharpFormattingOptions + { + public string Name { + get; + set; + } + + public bool IsBuiltIn { + get; + set; + } + + public CSharpFormattingOptions Clone () + { + return (CSharpFormattingOptions)MemberwiseClone (); + } + + #region Indentation + public bool IndentNamespaceBody { // tested + get; + set; + } + + public bool IndentClassBody { // tested + get; + set; + } + + public bool IndentInterfaceBody { // tested + get; + set; + } + + public bool IndentStructBody { // tested + get; + set; + } + + public bool IndentEnumBody { // tested + get; + set; + } + + public bool IndentMethodBody { // tested + get; + set; + } + + public bool IndentPropertyBody { // tested + get; + set; + } + + public bool IndentEventBody { // tested + get; + set; + } + + public bool IndentBlocks { // tested + get; + set; + } + + public bool IndentSwitchBody { // tested + get; + set; + } + + public bool IndentCaseBody { // tested + get; + set; + } + + public bool IndentBreakStatements { // tested + get; + set; + } + + public bool AlignEmbeddedUsingStatements { // tested + get; + set; + } + + public bool AlignEmbeddedIfStatements { // tested + get; + set; + } + + public PropertyFormatting PropertyFormatting { // tested + get; + set; + } + + #endregion + + #region Braces + public BraceStyle NamespaceBraceStyle { // tested + get; + set; + } + + public BraceStyle ClassBraceStyle { // tested + get; + set; + } + + public BraceStyle InterfaceBraceStyle { // tested + get; + set; + } + + public BraceStyle StructBraceStyle { // tested + get; + set; + } + + public BraceStyle EnumBraceStyle { // tested + get; + set; + } + + public BraceStyle MethodBraceStyle { // tested + get; + set; + } + + public BraceStyle AnonymousMethodBraceStyle { + get; + set; + } + + public BraceStyle ConstructorBraceStyle { // tested + get; + set; + } + + public BraceStyle DestructorBraceStyle { // tested + get; + set; + } + + public BraceStyle PropertyBraceStyle { // tested + get; + set; + } + + public BraceStyle PropertyGetBraceStyle { // tested + get; + set; + } + + public BraceStyle PropertySetBraceStyle { // tested + get; + set; + } + + public bool AllowPropertyGetBlockInline { // tested + get; + set; + } + + public bool AllowPropertySetBlockInline { // tested + get; + set; + } + + public BraceStyle EventBraceStyle { // tested + get; + set; + } + + public BraceStyle EventAddBraceStyle { // tested + get; + set; + } + + public BraceStyle EventRemoveBraceStyle { // tested + get; + set; + } + + public bool AllowEventAddBlockInline { // tested + get; + set; + } + + public bool AllowEventRemoveBlockInline { // tested + get; + set; + } + + public BraceStyle StatementBraceStyle { // tested + get; + set; + } + + public bool AllowIfBlockInline { + get; + set; + } + + #endregion + + #region Force Braces + public BraceForcement IfElseBraceForcement { // tested + get; + set; + } + + public BraceForcement ForBraceForcement { // tested + get; + set; + } + + public BraceForcement ForEachBraceForcement { // tested + get; + set; + } + + public BraceForcement WhileBraceForcement { // tested + get; + set; + } + + public BraceForcement UsingBraceForcement { // tested + get; + set; + } + + public BraceForcement FixedBraceForcement { // tested + get; + set; + } + + #endregion + + #region NewLines + public bool PlaceElseOnNewLine { // tested + get; + set; + } + + public bool PlaceElseIfOnNewLine { // tested + get; + set; + } + + public bool PlaceCatchOnNewLine { // tested + get; + set; + } + + public bool PlaceFinallyOnNewLine { // tested + get; + set; + } + + public bool PlaceWhileOnNewLine { // tested + get; + set; + } + + public ArrayInitializerPlacement PlaceArrayInitializersOnNewLine { + get; + set; + } + #endregion + + #region Spaces + // Methods + public bool SpaceBeforeMethodDeclarationParentheses { // tested + get; + set; + } + + public bool SpaceBetweenEmptyMethodDeclarationParentheses { + get; + set; + } + + public bool SpaceBeforeMethodDeclarationParameterComma { // tested + get; + set; + } + + public bool SpaceAfterMethodDeclarationParameterComma { // tested + get; + set; + } + + public bool SpaceWithinMethodDeclarationParentheses { // tested + get; + set; + } + + // Method calls + public bool SpaceBeforeMethodCallParentheses { // tested + get; + set; + } + + public bool SpaceBetweenEmptyMethodCallParentheses { // tested + get; + set; + } + + public bool SpaceBeforeMethodCallParameterComma { // tested + get; + set; + } + + public bool SpaceAfterMethodCallParameterComma { // tested + get; + set; + } + + public bool SpaceWithinMethodCallParentheses { // tested + get; + set; + } + + // fields + + public bool SpaceBeforeFieldDeclarationComma { // tested + get; + set; + } + + public bool SpaceAfterFieldDeclarationComma { // tested + get; + set; + } + + // local variables + + public bool SpaceBeforeLocalVariableDeclarationComma { // tested + get; + set; + } + + public bool SpaceAfterLocalVariableDeclarationComma { // tested + get; + set; + } + + // constructors + + public bool SpaceBeforeConstructorDeclarationParentheses { // tested + get; + set; + } + + public bool SpaceBetweenEmptyConstructorDeclarationParentheses { // tested + get; + set; + } + + public bool SpaceBeforeConstructorDeclarationParameterComma { // tested + get; + set; + } + + public bool SpaceAfterConstructorDeclarationParameterComma { // tested + get; + set; + } + + public bool SpaceWithinConstructorDeclarationParentheses { // tested + get; + set; + } + + // indexer + public bool SpaceBeforeIndexerDeclarationBracket { // tested + get; + set; + } + + public bool SpaceWithinIndexerDeclarationBracket { // tested + get; + set; + } + + public bool SpaceBeforeIndexerDeclarationParameterComma { + get; + set; + } + + public bool SpaceAfterIndexerDeclarationParameterComma { + get; + set; + } + + // delegates + + public bool SpaceBeforeDelegateDeclarationParentheses { + get; + set; + } + + public bool SpaceBetweenEmptyDelegateDeclarationParentheses { + get; + set; + } + + public bool SpaceBeforeDelegateDeclarationParameterComma { + get; + set; + } + + public bool SpaceAfterDelegateDeclarationParameterComma { + get; + set; + } + + public bool SpaceWithinDelegateDeclarationParentheses { + get; + set; + } + + public bool SpaceBeforeNewParentheses { // tested + get; + set; + } + + public bool SpaceBeforeIfParentheses { // tested + get; + set; + } + + public bool SpaceBeforeWhileParentheses { // tested + get; + set; + } + + public bool SpaceBeforeForParentheses { // tested + get; + set; + } + + public bool SpaceBeforeForeachParentheses { // tested + get; + set; + } + + public bool SpaceBeforeCatchParentheses { // tested + get; + set; + } + + public bool SpaceBeforeSwitchParentheses { // tested + get; + set; + } + + public bool SpaceBeforeLockParentheses { // tested + get; + set; + } + + public bool SpaceBeforeUsingParentheses { // tested + get; + set; + } + + public bool SpaceAroundAssignment { // tested + get; + set; + } + + public bool SpaceAroundLogicalOperator { // tested + get; + set; + } + + public bool SpaceAroundEqualityOperator { // tested + get; + set; + } + + public bool SpaceAroundRelationalOperator { // tested + get; + set; + } + + public bool SpaceAroundBitwiseOperator { // tested + get; + set; + } + + public bool SpaceAroundAdditiveOperator { // tested + get; + set; + } + + public bool SpaceAroundMultiplicativeOperator { // tested + get; + set; + } + + public bool SpaceAroundShiftOperator { // tested + get; + set; + } + + public bool SpaceAroundNullCoalescingOperator { + get; + set; + } + + public bool SpacesWithinParentheses { // tested + get; + set; + } + + public bool SpacesWithinIfParentheses { // tested + get; + set; + } + + public bool SpacesWithinWhileParentheses { // tested + get; + set; + } + + public bool SpacesWithinForParentheses { // tested + get; + set; + } + + public bool SpacesWithinForeachParentheses { // tested + get; + set; + } + + public bool SpacesWithinCatchParentheses { // tested + get; + set; + } + + public bool SpacesWithinSwitchParentheses { // tested + get; + set; + } + + public bool SpacesWithinLockParentheses { // tested + get; + set; + } + + public bool SpacesWithinUsingParentheses { // tested + get; + set; + } + + public bool SpacesWithinCastParentheses { // tested + get; + set; + } + + public bool SpacesWithinSizeOfParentheses { // tested + get; + set; + } + + public bool SpaceBeforeSizeOfParentheses { // tested + get; + set; + } + + public bool SpacesWithinTypeOfParentheses { // tested + get; + set; + } + + public bool SpacesWithinNewParentheses { // tested + get; + set; + } + + public bool SpacesBetweenEmptyNewParentheses { // tested + get; + set; + } + + public bool SpaceBeforeNewParameterComma { // tested + get; + set; + } + + public bool SpaceAfterNewParameterComma { // tested + get; + set; + } + + public bool SpaceBeforeTypeOfParentheses { // tested + get; + set; + } + + public bool SpacesWithinCheckedExpressionParantheses { // tested + get; + set; + } + + public bool SpaceBeforeConditionalOperatorCondition { // tested + get; + set; + } + + public bool SpaceAfterConditionalOperatorCondition { // tested + get; + set; + } + + public bool SpaceBeforeConditionalOperatorSeparator { // tested + get; + set; + } + + public bool SpaceAfterConditionalOperatorSeparator { // tested + get; + set; + } + + // brackets + public bool SpacesWithinBrackets { // tested + get; + set; + } + + public bool SpacesBeforeBrackets { // tested + get; + set; + } + + public bool SpaceBeforeBracketComma { // tested + get; + set; + } + + public bool SpaceAfterBracketComma { // tested + get; + set; + } + + public bool SpaceBeforeForSemicolon { // tested + get; + set; + } + + public bool SpaceAfterForSemicolon { // tested + get; + set; + } + + public bool SpaceAfterTypecast { // tested + get; + set; + } + + public bool SpaceBeforeArrayDeclarationBrackets { // tested + get; + set; + } + + #endregion + + #region Blank Lines + public int BlankLinesBeforeUsings { + get; + set; + } + + public int BlankLinesAfterUsings { + get; + set; + } + + public int BlankLinesBeforeFirstDeclaration { + get; + set; + } + + public int BlankLinesBetweenTypes { + get; + set; + } + + public int BlankLinesBetweenFields { + get; + set; + } + + public int BlankLinesBetweenEventFields { + get; + set; + } + + public int BlankLinesBetweenMembers { + get; + set; + } + + #endregion + + public CSharpFormattingOptions () + { + IndentNamespaceBody = true; + IndentClassBody = IndentInterfaceBody = IndentStructBody = IndentEnumBody = true; + IndentMethodBody = IndentPropertyBody = IndentEventBody = true; + IndentBlocks = true; + IndentSwitchBody = false; + IndentCaseBody = true; + IndentBreakStatements = true; + NamespaceBraceStyle = BraceStyle.NextLine; + ClassBraceStyle = InterfaceBraceStyle = StructBraceStyle = EnumBraceStyle = BraceStyle.NextLine; + MethodBraceStyle = ConstructorBraceStyle = DestructorBraceStyle = BraceStyle.NextLine; + AnonymousMethodBraceStyle = BraceStyle.EndOfLine; + + PropertyBraceStyle = PropertyGetBraceStyle = PropertySetBraceStyle = BraceStyle.EndOfLine; + AllowPropertyGetBlockInline = AllowPropertySetBlockInline = true; + + EventBraceStyle = EventAddBraceStyle = EventRemoveBraceStyle = BraceStyle.EndOfLine; + AllowEventAddBlockInline = AllowEventRemoveBlockInline = true; + StatementBraceStyle = BraceStyle.EndOfLine; + + PlaceElseOnNewLine = false; + PlaceCatchOnNewLine = false; + PlaceFinallyOnNewLine = false; + PlaceWhileOnNewLine = false; + PlaceArrayInitializersOnNewLine = ArrayInitializerPlacement.AlwaysSameLine; + + SpaceBeforeMethodCallParentheses = true; + SpaceBeforeMethodDeclarationParentheses = true; + SpaceBeforeConstructorDeclarationParentheses = true; + SpaceBeforeDelegateDeclarationParentheses = true; + SpaceAfterMethodCallParameterComma = true; + SpaceAfterConstructorDeclarationParameterComma = true; + + SpaceBeforeNewParentheses = true; + SpacesWithinNewParentheses = false; + SpacesBetweenEmptyNewParentheses = false; + SpaceBeforeNewParameterComma = false; + SpaceAfterNewParameterComma = true; + + SpaceBeforeIfParentheses = true; + SpaceBeforeWhileParentheses = true; + SpaceBeforeForParentheses = true; + SpaceBeforeForeachParentheses = true; + SpaceBeforeCatchParentheses = true; + SpaceBeforeSwitchParentheses = true; + SpaceBeforeLockParentheses = true; + SpaceBeforeUsingParentheses = true; + SpaceAroundAssignment = true; + SpaceAroundLogicalOperator = true; + SpaceAroundEqualityOperator = true; + SpaceAroundRelationalOperator = true; + SpaceAroundBitwiseOperator = true; + SpaceAroundAdditiveOperator = true; + SpaceAroundMultiplicativeOperator = true; + SpaceAroundShiftOperator = true; + SpaceAroundNullCoalescingOperator = true; + SpacesWithinParentheses = false; + SpaceWithinMethodCallParentheses = false; + SpaceWithinMethodDeclarationParentheses = false; + SpacesWithinIfParentheses = false; + SpacesWithinWhileParentheses = false; + SpacesWithinForParentheses = false; + SpacesWithinForeachParentheses = false; + SpacesWithinCatchParentheses = false; + SpacesWithinSwitchParentheses = false; + SpacesWithinLockParentheses = false; + SpacesWithinUsingParentheses = false; + SpacesWithinCastParentheses = false; + SpacesWithinSizeOfParentheses = false; + SpacesWithinTypeOfParentheses = false; + SpacesWithinCheckedExpressionParantheses = false; + SpaceBeforeConditionalOperatorCondition = true; + SpaceAfterConditionalOperatorCondition = true; + SpaceBeforeConditionalOperatorSeparator = true; + SpaceAfterConditionalOperatorSeparator = true; + + SpacesWithinBrackets = false; + SpacesBeforeBrackets = true; + SpaceBeforeBracketComma = false; + SpaceAfterBracketComma = true; + + SpaceBeforeForSemicolon = false; + SpaceAfterForSemicolon = true; + SpaceAfterTypecast = false; + + AlignEmbeddedIfStatements = true; + AlignEmbeddedUsingStatements = true; + PropertyFormatting = PropertyFormatting.AllowOneLine; + SpaceBeforeMethodDeclarationParameterComma = false; + SpaceAfterMethodDeclarationParameterComma = true; + SpaceBeforeFieldDeclarationComma = false; + SpaceAfterFieldDeclarationComma = true; + SpaceBeforeLocalVariableDeclarationComma = false; + SpaceAfterLocalVariableDeclarationComma = true; + + SpaceBeforeIndexerDeclarationBracket = true; + SpaceWithinIndexerDeclarationBracket = false; + SpaceBeforeIndexerDeclarationParameterComma = false; + + + SpaceAfterIndexerDeclarationParameterComma = true; + + BlankLinesBeforeUsings = 0; + BlankLinesAfterUsings = 1; + + + BlankLinesBeforeFirstDeclaration = 0; + BlankLinesBetweenTypes = 1; + BlankLinesBetweenFields = 0; + BlankLinesBetweenEventFields = 0; + BlankLinesBetweenMembers = 1; + } + + /*public static CSharpFormattingOptions Load (FilePath selectedFile) + { + using (var stream = System.IO.File.OpenRead (selectedFile)) { + return Load (stream); + } + } + + public static CSharpFormattingOptions Load (System.IO.Stream input) + { + CSharpFormattingOptions result = new CSharpFormattingOptions (); + result.Name = "noname"; + using (XmlTextReader reader = new XmlTextReader (input)) { + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Element) { + if (reader.LocalName == "Property") { + var info = typeof(CSharpFormattingOptions).GetProperty (reader.GetAttribute ("name")); + string valString = reader.GetAttribute ("value"); + object value; + if (info.PropertyType == typeof(bool)) { + value = Boolean.Parse (valString); + } else if (info.PropertyType == typeof(int)) { + value = Int32.Parse (valString); + } else { + value = Enum.Parse (info.PropertyType, valString); + } + info.SetValue (result, value, null); + } else if (reader.LocalName == "FormattingProfile") { + result.Name = reader.GetAttribute ("name"); + } + } else if (reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "FormattingProfile") { + //Console.WriteLine ("result:" + result.Name); + return result; + } + } + } + return result; + } + + public void Save (string fileName) + { + using (var writer = new XmlTextWriter (fileName, Encoding.Default)) { + writer.Formatting = System.Xml.Formatting.Indented; + writer.Indentation = 1; + writer.IndentChar = '\t'; + writer.WriteStartElement ("FormattingProfile"); + writer.WriteAttributeString ("name", Name); + foreach (PropertyInfo info in typeof (CSharpFormattingOptions).GetProperties ()) { + if (info.GetCustomAttributes (false).Any (o => o.GetType () == typeof(ItemPropertyAttribute))) { + writer.WriteStartElement ("Property"); + writer.WriteAttributeString ("name", info.Name); + writer.WriteAttributeString ("value", info.GetValue (this, null).ToString ()); + writer.WriteEndElement (); + } + } + writer.WriteEndElement (); + } + } + + public bool Equals (CSharpFormattingOptions other) + { + foreach (PropertyInfo info in typeof (CSharpFormattingOptions).GetProperties ()) { + if (info.GetCustomAttributes (false).Any (o => o.GetType () == typeof(ItemPropertyAttribute))) { + object val = info.GetValue (this, null); + object otherVal = info.GetValue (other, null); + if (val == null) { + if (otherVal == null) + continue; + return false; + } + if (!val.Equals (otherVal)) { + //Console.WriteLine ("!equal"); + return false; + } + } + } + //Console.WriteLine ("== equal"); + return true; + }*/ + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs new file mode 100644 index 0000000000..4568f8736e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs @@ -0,0 +1,83 @@ +// +// ITextEditorAdapter.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory +{ + public interface ITextEditorAdapter + { + bool TabsToSpaces { get; } + + int TabSize { get; } + + string EolMarker { get; } + + string Text { get; } + + int Length { get; } + + int LocationToOffset (int line, int col); + char GetCharAt (int offset); + string GetTextAt (int offset, int length); + + int LineCount { get; } + + int GetEditableLength (int lineNumber); + string GetIndentation (int lineNumber); + int GetLineOffset (int lineNumber); + int GetLineLength (int lineNumber); + int GetLineEndOffset (int lineNumber); + + void Replace (int offset, int count, string text); + } + + /* + public static class ITextEditorAdapterHelperMethods + { + public static void AcceptChanges (this ITextEditorAdapter adapter, List changes) + { + for (int i = 0; i < changes.Count; i++) { + changes [i].PerformChange (adapter); + var replaceChange = changes [i]; + for (int j = i + 1; j < changes.Count; j++) { + var change = changes [j]; + if (replaceChange.Offset >= 0 && change.Offset >= 0) { + if (replaceChange.Offset < change.Offset) { + change.Offset -= replaceChange.RemovedChars; + if (!string.IsNullOrEmpty (replaceChange.InsertedText)) + change.Offset += replaceChange.InsertedText.Length; + } else if (replaceChange.Offset < change.Offset + change.RemovedChars) { + change.RemovedChars -= replaceChange.RemovedChars; + change.Offset = replaceChange.Offset + (!string.IsNullOrEmpty (replaceChange.InsertedText) ? replaceChange.InsertedText.Length : 0); + } + } + } + } + } + }*/ +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs new file mode 100644 index 0000000000..017d8c9b49 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs @@ -0,0 +1,89 @@ +// +// Indent.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.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; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class Indent + { + public int Level { + get; + set; + } + + public int ExtraSpaces { + get; + set; + } + + public bool TabsToSpaces { + get; + set; + } + + public int TabSize { + get; + set; + } + + public Indent () + { + } + + public Indent (int level, int extraSpaces) + { + this.Level = level; + this.ExtraSpaces = extraSpaces; + } + + public static Indent operator+ (Indent left, Indent right) + { + return new Indent (left.Level + right.Level, left.ExtraSpaces + right.ExtraSpaces); + } + + public static Indent operator- (Indent left, Indent right) + { + return new Indent (left.Level - right.Level, left.ExtraSpaces - right.ExtraSpaces); + } + + public string IndentString { + get { + return (TabsToSpaces ? new string (' ', Level * TabSize) : new string ('\t', Level)) + new string (' ', ExtraSpaces); + } + } + + public string SingleIndent { + get { + return TabsToSpaces ? new string (' ', TabSize) : "\t"; + } + } + + public override string ToString () + { + return string.Format ("[Indent: Level={0}, ExtraSpaces={1}]", Level, ExtraSpaces); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs new file mode 100644 index 0000000000..ac1966296c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Output formatter for the Output visitor. + /// + public interface IOutputFormatter + { + void StartNode(AstNode node); + void EndNode(AstNode node); + + /// + /// Writes an identifier. + /// If the identifier conflicts with a keyword, the output visitor will + /// call WriteToken("@") before calling WriteIdentifier(). + /// + void WriteIdentifier(string identifier); + + /// + /// Writes a keyword to the output. + /// + void WriteKeyword(string keyword); + + /// + /// Writes a token to the output. + /// + void WriteToken(string token); + void Space(); + + void OpenBrace(BraceStyle style); + void CloseBrace(BraceStyle style); + + void Indent(); + void Unindent(); + + void NewLine(); + + void WriteComment(CommentType commentType, string content); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs new file mode 100644 index 0000000000..8e2e5981b3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -0,0 +1,325 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Inserts the parentheses into the AST that are needed to ensure the AST can be printed correctly. + /// For example, if the AST contains + /// BinaryOperatorExpresson(2, Mul, BinaryOperatorExpression(1, Add, 1))); printing that AST + /// would incorrectly result in "2 * 1 + 1". By running InsertParenthesesVisitor, the necessary + /// parentheses are inserted: "2 * (1 + 1)". + /// + public class InsertParenthesesVisitor : DepthFirstAstVisitor + { + /// + /// Gets/Sets whether the visitor should insert parentheses to make the code better looking. + /// If this property is false, it will insert parentheses only where strictly required by the language spec. + /// + public bool InsertParenthesesForReadability { get; set; } + + const int Primary = 16; + const int QueryOrLambda = 15; + const int Unary = 14; + const int RelationalAndTypeTesting = 10; + const int Equality = 9; + const int Conditional = 2; + const int Assignment = 1; + + /// + /// Gets the row number in the C# 4.0 spec operator precedence table. + /// + static int GetPrecedence(Expression expr) + { + // Note: the operator precedence table on MSDN is incorrect + if (expr is QueryExpression) { + // Not part of the table in the C# spec, but we need to ensure that queries within + // primary expressions get parenthesized. + return QueryOrLambda; + } + UnaryOperatorExpression uoe = expr as UnaryOperatorExpression; + if (uoe != null) { + if (uoe.Operator == UnaryOperatorType.PostDecrement || uoe.Operator == UnaryOperatorType.PostIncrement) + return Primary; + else + return Unary; + } + if (expr is CastExpression) + return Unary; + BinaryOperatorExpression boe = expr as BinaryOperatorExpression; + if (boe != null) { + switch (boe.Operator) { + case BinaryOperatorType.Multiply: + case BinaryOperatorType.Divide: + case BinaryOperatorType.Modulus: + return 13; // multiplicative + case BinaryOperatorType.Add: + case BinaryOperatorType.Subtract: + return 12; // additive + case BinaryOperatorType.ShiftLeft: + case BinaryOperatorType.ShiftRight: + return 11; + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.GreaterThanOrEqual: + case BinaryOperatorType.LessThan: + case BinaryOperatorType.LessThanOrEqual: + return RelationalAndTypeTesting; + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + return Equality; + case BinaryOperatorType.BitwiseAnd: + return 8; + case BinaryOperatorType.ExclusiveOr: + return 7; + case BinaryOperatorType.BitwiseOr: + return 6; + case BinaryOperatorType.ConditionalAnd: + return 5; + case BinaryOperatorType.ConditionalOr: + return 4; + case BinaryOperatorType.NullCoalescing: + return 3; + default: + throw new NotSupportedException("Invalid value for BinaryOperatorType"); + } + } + if (expr is IsExpression || expr is AsExpression) + return RelationalAndTypeTesting; + if (expr is ConditionalExpression) + return Conditional; + if (expr is AssignmentExpression || expr is LambdaExpression) + return Assignment; + // anything else: primary expression + return Primary; + } + + /// + /// Parenthesizes the expression if it does not have the minimum required precedence. + /// + static void ParenthesizeIfRequired(Expression expr, int minimumPrecedence) + { + if (GetPrecedence(expr) < minimumPrecedence) { + Parenthesize(expr); + } + } + + static void Parenthesize(Expression expr) + { + expr.ReplaceWith(e => new ParenthesizedExpression { Expression = e }); + } + + // Primary expressions + public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + { + ParenthesizeIfRequired(memberReferenceExpression.Target, Primary); + return base.VisitMemberReferenceExpression(memberReferenceExpression, data); + } + + public override object VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) + { + ParenthesizeIfRequired(pointerReferenceExpression.Target, Primary); + return base.VisitPointerReferenceExpression(pointerReferenceExpression, data); + } + + public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data) + { + ParenthesizeIfRequired(invocationExpression.Target, Primary); + return base.VisitInvocationExpression(invocationExpression, data); + } + + public override object VisitIndexerExpression(IndexerExpression indexerExpression, object data) + { + ParenthesizeIfRequired(indexerExpression.Target, Primary); + return base.VisitIndexerExpression(indexerExpression, data); + } + + // Unary expressions + public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + ParenthesizeIfRequired(unaryOperatorExpression.Expression, GetPrecedence(unaryOperatorExpression)); + UnaryOperatorExpression child = unaryOperatorExpression.Expression as UnaryOperatorExpression; + if (child != null && InsertParenthesesForReadability) + Parenthesize(child); + return base.VisitUnaryOperatorExpression(unaryOperatorExpression, data); + } + + public override object VisitCastExpression(CastExpression castExpression, object data) + { + ParenthesizeIfRequired(castExpression.Expression, InsertParenthesesForReadability ? Primary : Unary); + // There's a nasty issue in the C# grammar: cast expressions including certain operators are ambiguous in some cases + // "(int)-1" is fine, but "(A)-b" is not a cast. + UnaryOperatorExpression uoe = castExpression.Expression as UnaryOperatorExpression; + if (uoe != null && !(uoe.Operator == UnaryOperatorType.BitNot || uoe.Operator == UnaryOperatorType.Not)) { + if (TypeCanBeMisinterpretedAsExpression(castExpression.Type)) { + Parenthesize(castExpression.Expression); + } + } + // The above issue can also happen with PrimitiveExpressions representing negative values: + PrimitiveExpression pe = castExpression.Expression as PrimitiveExpression; + if (pe != null && pe.Value != null && TypeCanBeMisinterpretedAsExpression(castExpression.Type)) { + TypeCode typeCode = Type.GetTypeCode(pe.Value.GetType()); + switch (typeCode) { + case TypeCode.SByte: + if ((sbyte)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + case TypeCode.Int16: + if ((short)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + case TypeCode.Int32: + if ((int)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + case TypeCode.Int64: + if ((long)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + case TypeCode.Single: + if ((float)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + case TypeCode.Double: + if ((double)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + case TypeCode.Decimal: + if ((decimal)pe.Value < 0) + Parenthesize(castExpression.Expression); + break; + } + } + return base.VisitCastExpression(castExpression, data); + } + + static bool TypeCanBeMisinterpretedAsExpression(AstType type) + { + // SimpleTypes can always be misinterpreted as IdentifierExpressions + // MemberTypes can be misinterpreted as MemberReferenceExpressions if they don't use double colon + // PrimitiveTypes or ComposedTypes can never be misinterpreted as expressions. + MemberType mt = type as MemberType; + if (mt != null) + return !mt.IsDoubleColon; + else + return type is SimpleType; + } + + // Binary Operators + public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + int precedence = GetPrecedence(binaryOperatorExpression); + if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) { + if (InsertParenthesesForReadability) { + ParenthesizeIfRequired(binaryOperatorExpression.Left, Primary); + ParenthesizeIfRequired(binaryOperatorExpression.Right, Primary); + } else { + // ?? is right-associate + ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence + 1); + ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence); + } + } else { + if (InsertParenthesesForReadability && precedence < Equality) { + // In readable mode, boost the priority of the left-hand side if the operator + // there isn't the same as the operator on this expression. + if (GetBinaryOperatorType(binaryOperatorExpression.Left) == binaryOperatorExpression.Operator) { + ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence); + } else { + ParenthesizeIfRequired(binaryOperatorExpression.Left, Equality); + } + ParenthesizeIfRequired(binaryOperatorExpression.Right, Equality); + } else { + // all other binary operators are left-associative + ParenthesizeIfRequired(binaryOperatorExpression.Left, precedence); + ParenthesizeIfRequired(binaryOperatorExpression.Right, precedence + 1); + } + } + return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); + } + + BinaryOperatorType? GetBinaryOperatorType(Expression expr) + { + BinaryOperatorExpression boe = expr as BinaryOperatorExpression; + if (boe != null) + return boe.Operator; + else + return null; + } + + public override object VisitIsExpression(IsExpression isExpression, object data) + { + if (InsertParenthesesForReadability) { + // few people know the precedence of 'is', so always put parentheses in nice-looking mode. + ParenthesizeIfRequired(isExpression.Expression, Primary); + } else { + ParenthesizeIfRequired(isExpression.Expression, RelationalAndTypeTesting); + } + return base.VisitIsExpression(isExpression, data); + } + + public override object VisitAsExpression(AsExpression asExpression, object data) + { + if (InsertParenthesesForReadability) { + // few people know the precedence of 'as', so always put parentheses in nice-looking mode. + ParenthesizeIfRequired(asExpression.Expression, Primary); + } else { + ParenthesizeIfRequired(asExpression.Expression, RelationalAndTypeTesting); + } + return base.VisitAsExpression(asExpression, data); + } + + // Conditional operator + public override object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) + { + // Associativity here is a bit tricky: + // (a ? b : c ? d : e) == (a ? b : (c ? d : e)) + // (a ? b ? c : d : e) == (a ? (b ? c : d) : e) + // Only ((a ? b : c) ? d : e) strictly needs the additional parentheses + if (InsertParenthesesForReadability) { + // Precedence of ?: can be confusing; so always put parentheses in nice-looking mode. + ParenthesizeIfRequired(conditionalExpression.Condition, Primary); + ParenthesizeIfRequired(conditionalExpression.TrueExpression, Primary); + ParenthesizeIfRequired(conditionalExpression.FalseExpression, Primary); + } else { + ParenthesizeIfRequired(conditionalExpression.Condition, Conditional + 1); + ParenthesizeIfRequired(conditionalExpression.TrueExpression, Conditional); + ParenthesizeIfRequired(conditionalExpression.FalseExpression, Conditional); + } + return base.VisitConditionalExpression(conditionalExpression, data); + } + + public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) + { + // assignment is right-associative + ParenthesizeIfRequired(assignmentExpression.Left, Assignment + 1); + if (InsertParenthesesForReadability) { + ParenthesizeIfRequired(assignmentExpression.Right, RelationalAndTypeTesting + 1); + } else { + ParenthesizeIfRequired(assignmentExpression.Right, Assignment); + } + return base.VisitAssignmentExpression(assignmentExpression, data); + } + + // don't need to handle lambdas, they have lowest precedence and unambiguous associativity + + public override object VisitQueryExpression(QueryExpression queryExpression, object data) + { + // Query expressions are strange beasts: + // "var a = -from b in c select d;" is valid, so queries bind stricter than unary expressions. + // However, the end of the query is greedy. So their start sort of has a high precedence, + // while their end has a very low precedence. We handle this by checking whether a query is used + // as left part of a binary operator, and parenthesize it if required. + if (queryExpression.Role == BinaryOperatorExpression.LeftRole) + Parenthesize(queryExpression); + if (queryExpression.Parent is IsExpression || queryExpression.Parent is AsExpression) + Parenthesize(queryExpression); + if (InsertParenthesesForReadability) { + // when readability is desired, always parenthesize query expressions within unary or binary operators + if (queryExpression.Parent is UnaryOperatorExpression || queryExpression.Parent is BinaryOperatorExpression) + Parenthesize(queryExpression); + } + return base.VisitQueryExpression(queryExpression, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs new file mode 100644 index 0000000000..34589023dd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -0,0 +1,2385 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; + +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Outputs the AST. + /// + public class OutputVisitor : IAstVisitor, IPatternAstVisitor + { + readonly IOutputFormatter formatter; + readonly CSharpFormattingOptions policy; + readonly Stack containerStack = new Stack (); + readonly Stack positionStack = new Stack (); + + /// + /// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written. + /// + LastWritten lastWritten; + + enum LastWritten + { + Whitespace, + Other, + KeywordOrIdentifier, + Plus, + Minus, + Ampersand, + QuestionMark, + Division + } + + public OutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy) + { + if (textWriter == null) + throw new ArgumentNullException ("textWriter"); + if (formattingPolicy == null) + throw new ArgumentNullException ("formattingPolicy"); + this.formatter = new TextWriterOutputFormatter (textWriter); + this.policy = formattingPolicy; + } + + public OutputVisitor (IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy) + { + if (formatter == null) + throw new ArgumentNullException ("formatter"); + if (formattingPolicy == null) + throw new ArgumentNullException ("formattingPolicy"); + this.formatter = formatter; + this.policy = formattingPolicy; + } + + #region StartNode/EndNode + public event EventHandler OutputStarted; + + protected virtual void OnOutputStarted (AstNodeEventArgs e) + { + EventHandler handler = this.OutputStarted; + if (handler != null) + handler (this, e); + } + + public event EventHandler OutputFinished; + + protected virtual void OnOutputFinished (AstNodeEventArgs e) + { + EventHandler handler = this.OutputFinished; + if (handler != null) + handler (this, e); + } + + [Serializable] + public sealed class AstNodeEventArgs : EventArgs + { + public AstNode AstNode { + get; + private set; + } + + public AstNodeEventArgs (AstNode node) + { + this.AstNode = node; + } + } + + void StartNode (AstNode node) + { + // Ensure that nodes are visited in the proper nested order. + // Jumps to different subtrees are allowed only for the child of a placeholder node. + Debug.Assert (containerStack.Count == 0 || node.Parent == containerStack.Peek () || containerStack.Peek ().NodeType == NodeType.Pattern); + if (positionStack.Count > 0) + WriteSpecialsUpToNode (node); + containerStack.Push (node); + positionStack.Push (node.FirstChild); + OnOutputStarted (new AstNodeEventArgs (node)); + formatter.StartNode (node); + } + + object EndNode (AstNode node) + { + Debug.Assert (node == containerStack.Peek ()); + AstNode pos = positionStack.Pop (); + Debug.Assert (pos == null || pos.Parent == node); + WriteSpecials (pos, null); + containerStack.Pop (); + OnOutputFinished (new AstNodeEventArgs (node)); + formatter.EndNode (node); + return null; + } + #endregion + + #region WriteSpecials + /// + /// Writes all specials from start to end (exclusive). Does not touch the positionStack. + /// + void WriteSpecials (AstNode start, AstNode end) + { + for (AstNode pos = start; pos != end; pos = pos.NextSibling) { + if (pos.Role == AstNode.Roles.Comment) { + pos.AcceptVisitor (this, null); + } + } + } + + /// + /// Writes all specials between the current position (in the positionStack) and the next + /// node with the specified role. Advances the current position. + /// + void WriteSpecialsUpToRole (Role role) + { + for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { + if (pos.Role == role) { + WriteSpecials (positionStack.Pop (), pos); + positionStack.Push (pos); + break; + } + } + } + + /// + /// Writes all specials between the current position (in the positionStack) and the specified node. + /// Advances the current position. + /// + void WriteSpecialsUpToNode (AstNode node) + { + 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); + break; + } + } + } + #endregion + + #region Comma + /// + /// Writes a comma. + /// + /// The next node after the comma. + /// When set prevents printing a space after comma. + void Comma (AstNode nextNode, bool noSpaceAfterComma = false) + { + WriteSpecialsUpToRole (AstNode.Roles.Comma, nextNode); + Space (policy.SpaceBeforeBracketComma); // TODO: Comma policy has changed. + formatter.WriteToken (","); + lastWritten = LastWritten.Other; + Space (!noSpaceAfterComma && policy.SpaceAfterBracketComma); // TODO: Comma policy has changed. + } + + void WriteCommaSeparatedList (IEnumerable list) + { + bool isFirst = true; + foreach (AstNode node in list) { + if (isFirst) { + isFirst = false; + } else { + Comma (node); + } + node.AcceptVisitor (this, null); + } + } + + void WriteCommaSeparatedListInParenthesis (IEnumerable list, bool spaceWithin) + { + LPar (); + if (list.Any ()) { + Space (spaceWithin); + WriteCommaSeparatedList (list); + Space (spaceWithin); + } + RPar (); + } + + #if DOTNET35 + void WriteCommaSeparatedList(IEnumerable list) + { + WriteCommaSeparatedList(list.SafeCast()); + } + + void WriteCommaSeparatedList(IEnumerable list) + { + WriteCommaSeparatedList(list.SafeCast()); + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); + } + + #endif + + void WriteCommaSeparatedListInBrackets (IEnumerable list, bool spaceWithin) + { + WriteToken ("[", AstNode.Roles.LBracket); + if (list.Any ()) { + Space (spaceWithin); + WriteCommaSeparatedList (list.SafeCast ()); + Space (spaceWithin); + } + WriteToken ("]", AstNode.Roles.RBracket); + } + + void WriteCommaSeparatedListInBrackets (IEnumerable list) + { + WriteToken ("[", AstNode.Roles.LBracket); + if (list.Any ()) { + Space (policy.SpacesWithinBrackets); + WriteCommaSeparatedList (list.SafeCast ()); + Space (policy.SpacesWithinBrackets); + } + WriteToken ("]", AstNode.Roles.RBracket); + } + #endregion + + #region Write tokens + /// + /// Writes a keyword, and all specials up to + /// + void WriteKeyword (string keyword, Role tokenRole = null) + { + WriteSpecialsUpToRole (tokenRole ?? AstNode.Roles.Keyword); + if (lastWritten == LastWritten.KeywordOrIdentifier) + formatter.Space (); + formatter.WriteKeyword (keyword); + lastWritten = LastWritten.KeywordOrIdentifier; + } + + void WriteIdentifier (string identifier, Role identifierRole = null) + { + WriteSpecialsUpToRole (identifierRole ?? AstNode.Roles.Identifier); + if (IsKeyword (identifier, containerStack.Peek ())) { + if (lastWritten == LastWritten.KeywordOrIdentifier) + Space (); // this space is not strictly required, so we call Space() + formatter.WriteToken ("@"); + } else if (lastWritten == LastWritten.KeywordOrIdentifier) { + formatter.Space (); // this space is strictly required, so we directly call the formatter + } + formatter.WriteIdentifier (identifier); + lastWritten = LastWritten.KeywordOrIdentifier; + } + + void WriteToken (string token, Role tokenRole) + { + WriteSpecialsUpToRole (tokenRole); + // Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token. + // Note that we don't need to handle tokens like = because there's no valid + // C# program that contains the single token twice in a row. + // (for +, - and &, this can happen with unary operators; + // for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0"; + // and for /, this can happen with "1/ *ptr" or "1/ //comment".) + if (lastWritten == LastWritten.Plus && token [0] == '+' + || lastWritten == LastWritten.Minus && token [0] == '-' + || lastWritten == LastWritten.Ampersand && token [0] == '&' + || lastWritten == LastWritten.QuestionMark && token [0] == '?' + || lastWritten == LastWritten.Division && token [0] == '*') { + formatter.Space (); + } + formatter.WriteToken (token); + if (token == "+") + lastWritten = LastWritten.Plus; + else if (token == "-") + lastWritten = LastWritten.Minus; + else if (token == "&") + lastWritten = LastWritten.Ampersand; + else if (token == "?") + lastWritten = LastWritten.QuestionMark; + else if (token == "/") + lastWritten = LastWritten.Division; + else + lastWritten = LastWritten.Other; + } + + void LPar () + { + WriteToken ("(", AstNode.Roles.LPar); + } + + void RPar () + { + WriteToken (")", AstNode.Roles.LPar); + } + + /// + /// Marks the end of a statement + /// + void Semicolon () + { + Role role = containerStack.Peek ().Role; // get the role of the current node + if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) { + WriteToken (";", AstNode.Roles.Semicolon); + NewLine (); + } + } + + /// + /// Writes a space depending on policy. + /// + void Space (bool addSpace = true) + { + if (addSpace) { + formatter.Space (); + lastWritten = LastWritten.Whitespace; + } + } + + void NewLine () + { + formatter.NewLine (); + lastWritten = LastWritten.Whitespace; + } + + void OpenBrace (BraceStyle style) + { + WriteSpecialsUpToRole (AstNode.Roles.LBrace); + formatter.OpenBrace (style); + lastWritten = LastWritten.Other; + } + + void CloseBrace (BraceStyle style) + { + WriteSpecialsUpToRole (AstNode.Roles.RBrace); + formatter.CloseBrace (style); + lastWritten = LastWritten.Other; + } + + #endregion + + #region IsKeyword Test + static readonly HashSet unconditionalKeywords = new HashSet { + "abstract", "as", "base", "bool", "break", "byte", "case", "catch", + "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", + "do", "double", "else", "enum", "event", "explicit", "extern", "false", + "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", + "in", "int", "interface", "internal", "is", "lock", "long", "namespace", + "new", "null", "object", "operator", "out", "override", "params", "private", + "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", + "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", + "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", + "using", "virtual", "void", "volatile", "while" + }; + static readonly HashSet queryKeywords = new HashSet { + "from", "where", "join", "on", "equals", "into", "let", "orderby", + "ascending", "descending", "select", "group", "by" + }; + + /// + /// Determines whether the specified identifier is a keyword in the given context. + /// + public static bool IsKeyword (string identifier, AstNode context) + { + if (unconditionalKeywords.Contains (identifier)) + return true; + if (context.Ancestors.Any (a => a is QueryExpression)) { + if (queryKeywords.Contains (identifier)) + return true; + } + return false; + } + + #endregion + + #region Write constructs + void WriteTypeArguments (IEnumerable typeArguments) + { + if (typeArguments.Any ()) { + WriteToken ("<", AstNode.Roles.LChevron); + WriteCommaSeparatedList (typeArguments); + WriteToken (">", AstNode.Roles.RChevron); + } + } + + void WriteTypeParameters (IEnumerable typeParameters) + { + if (typeParameters.Any ()) { + WriteToken ("<", AstNode.Roles.LChevron); + WriteCommaSeparatedList (typeParameters.SafeCast ()); + WriteToken (">", AstNode.Roles.RChevron); + } + } + + void WriteModifiers (IEnumerable modifierTokens) + { + foreach (CSharpModifierToken modifier in modifierTokens) { + modifier.AcceptVisitor (this, null); + } + } + + void WriteQualifiedIdentifier (IEnumerable identifiers) + { + bool first = true; + foreach (Identifier ident in identifiers) { + if (first) { + first = false; + if (lastWritten == LastWritten.KeywordOrIdentifier) + formatter.Space (); + } else { + WriteSpecialsUpToRole (AstNode.Roles.Dot, ident); + formatter.WriteToken ("."); + lastWritten = LastWritten.Other; + } + WriteSpecialsUpToNode (ident); + formatter.WriteIdentifier (ident.Name); + lastWritten = LastWritten.KeywordOrIdentifier; + } + } + + void WriteEmbeddedStatement (Statement embeddedStatement) + { + if (embeddedStatement.IsNull) + return; + BlockStatement block = embeddedStatement as BlockStatement; + if (block != null) + VisitBlockStatement (block, null); + else { + NewLine (); + formatter.Indent (); + embeddedStatement.AcceptVisitor (this, null); + formatter.Unindent (); + } + } + + void WriteMethodBody (BlockStatement body) + { + if (body.IsNull) + Semicolon (); + else + VisitBlockStatement (body, null); + } + + void WriteAttributes (IEnumerable attributes) + { + foreach (AttributeSection attr in attributes) { + attr.AcceptVisitor (this, null); + } + } + + void WritePrivateImplementationType (AstType privateImplementationType) + { + if (!privateImplementationType.IsNull) { + privateImplementationType.AcceptVisitor (this, null); + WriteToken (".", AstNode.Roles.Dot); + } + } + + #endregion + + #region Expressions + public object VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, object data) + { + StartNode (anonymousMethodExpression); + WriteKeyword ("delegate"); + if (anonymousMethodExpression.HasParameterList) { + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (anonymousMethodExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + } + anonymousMethodExpression.Body.AcceptVisitor (this, data); + return EndNode (anonymousMethodExpression); + } + + public object VisitUndocumentedExpression (UndocumentedExpression undocumentedExpression, object data) + { + StartNode (undocumentedExpression); + switch (undocumentedExpression.UndocumentedExpressionType) { + case UndocumentedExpressionType.ArgList: + case UndocumentedExpressionType.ArgListAccess: + WriteKeyword ("__arglist"); + break; + case UndocumentedExpressionType.MakeRef: + WriteKeyword ("__makeref"); + break; + case UndocumentedExpressionType.RefType: + WriteKeyword ("__reftype"); + break; + case UndocumentedExpressionType.RefValue: + WriteKeyword ("__refvalue"); + break; + } + if (undocumentedExpression.Arguments.Count > 0) { + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (undocumentedExpression.Arguments, policy.SpaceWithinMethodCallParentheses); + } + return EndNode (undocumentedExpression); + } + + public object VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression, object data) + { + StartNode (arrayCreateExpression); + WriteKeyword ("new"); + arrayCreateExpression.Type.AcceptVisitor (this, data); + WriteCommaSeparatedListInBrackets (arrayCreateExpression.Arguments); + foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) + specifier.AcceptVisitor (this, data); + arrayCreateExpression.Initializer.AcceptVisitor (this, data); + return EndNode (arrayCreateExpression); + } + + public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data) + { + StartNode (arrayInitializerExpression); + BraceStyle style; + if (policy.PlaceArrayInitializersOnNewLine == ArrayInitializerPlacement.AlwaysNewLine) + style = BraceStyle.NextLine; + else + style = BraceStyle.EndOfLine; + OpenBrace (style); + bool isFirst = true; + foreach (AstNode node in arrayInitializerExpression.Elements) { + if (isFirst) { + isFirst = false; + } else { + Comma (node); + NewLine (); + } + node.AcceptVisitor (this, null); + } + NewLine (); + CloseBrace (style); + return EndNode (arrayInitializerExpression); + } + + public object VisitAsExpression (AsExpression asExpression, object data) + { + StartNode (asExpression); + asExpression.Expression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("as"); + Space (); + asExpression.Type.AcceptVisitor (this, data); + return EndNode (asExpression); + } + + public object VisitAssignmentExpression (AssignmentExpression assignmentExpression, object data) + { + StartNode (assignmentExpression); + assignmentExpression.Left.AcceptVisitor (this, data); + Space (policy.SpaceAroundAssignment); + WriteToken (AssignmentExpression.GetOperatorSymbol (assignmentExpression.Operator), AssignmentExpression.OperatorRole); + Space (policy.SpaceAroundAssignment); + assignmentExpression.Right.AcceptVisitor (this, data); + return EndNode (assignmentExpression); + } + + public object VisitBaseReferenceExpression (BaseReferenceExpression baseReferenceExpression, object data) + { + StartNode (baseReferenceExpression); + WriteKeyword ("base"); + return EndNode (baseReferenceExpression); + } + + public object VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression, object data) + { + StartNode (binaryOperatorExpression); + binaryOperatorExpression.Left.AcceptVisitor (this, data); + bool spacePolicy; + switch (binaryOperatorExpression.Operator) { + case BinaryOperatorType.BitwiseAnd: + case BinaryOperatorType.BitwiseOr: + case BinaryOperatorType.ExclusiveOr: + spacePolicy = policy.SpaceAroundBitwiseOperator; + break; + case BinaryOperatorType.ConditionalAnd: + case BinaryOperatorType.ConditionalOr: + spacePolicy = policy.SpaceAroundLogicalOperator; + break; + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.GreaterThanOrEqual: + case BinaryOperatorType.LessThanOrEqual: + case BinaryOperatorType.LessThan: + spacePolicy = policy.SpaceAroundRelationalOperator; + break; + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + spacePolicy = policy.SpaceAroundEqualityOperator; + break; + case BinaryOperatorType.Add: + case BinaryOperatorType.Subtract: + spacePolicy = policy.SpaceAroundAdditiveOperator; + break; + case BinaryOperatorType.Multiply: + case BinaryOperatorType.Divide: + case BinaryOperatorType.Modulus: + spacePolicy = policy.SpaceAroundMultiplicativeOperator; + break; + case BinaryOperatorType.ShiftLeft: + case BinaryOperatorType.ShiftRight: + spacePolicy = policy.SpaceAroundShiftOperator; + break; + case BinaryOperatorType.NullCoalescing: + spacePolicy = true; + break; + default: + throw new NotSupportedException ("Invalid value for BinaryOperatorType"); + } + Space (spacePolicy); + WriteToken (BinaryOperatorExpression.GetOperatorSymbol (binaryOperatorExpression.Operator), BinaryOperatorExpression.OperatorRole); + Space (spacePolicy); + binaryOperatorExpression.Right.AcceptVisitor (this, data); + return EndNode (binaryOperatorExpression); + } + + public object VisitCastExpression (CastExpression castExpression, object data) + { + StartNode (castExpression); + LPar (); + Space (policy.SpacesWithinCastParentheses); + castExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinCastParentheses); + RPar (); + Space (policy.SpaceAfterTypecast); + castExpression.Expression.AcceptVisitor (this, data); + return EndNode (castExpression); + } + + public object VisitCheckedExpression (CheckedExpression checkedExpression, object data) + { + StartNode (checkedExpression); + WriteKeyword ("checked"); + LPar (); + Space (policy.SpacesWithinCheckedExpressionParantheses); + checkedExpression.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinCheckedExpressionParantheses); + RPar (); + return EndNode (checkedExpression); + } + + public object VisitConditionalExpression (ConditionalExpression conditionalExpression, object data) + { + StartNode (conditionalExpression); + conditionalExpression.Condition.AcceptVisitor (this, data); + + Space (policy.SpaceBeforeConditionalOperatorCondition); + WriteToken ("?", ConditionalExpression.QuestionMarkRole); + Space (policy.SpaceAfterConditionalOperatorCondition); + + conditionalExpression.TrueExpression.AcceptVisitor (this, data); + + Space (policy.SpaceBeforeConditionalOperatorSeparator); + WriteToken (":", ConditionalExpression.ColonRole); + Space (policy.SpaceAfterConditionalOperatorSeparator); + + conditionalExpression.FalseExpression.AcceptVisitor (this, data); + + return EndNode (conditionalExpression); + } + + public object VisitDefaultValueExpression (DefaultValueExpression defaultValueExpression, object data) + { + StartNode (defaultValueExpression); + + WriteKeyword ("default"); + LPar (); + Space (policy.SpacesWithinTypeOfParentheses); + defaultValueExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinTypeOfParentheses); + RPar (); + + return EndNode (defaultValueExpression); + } + + public object VisitDirectionExpression (DirectionExpression directionExpression, object data) + { + StartNode (directionExpression); + + switch (directionExpression.FieldDirection) { + case FieldDirection.Out: + WriteKeyword ("out"); + break; + case FieldDirection.Ref: + WriteKeyword ("ref"); + break; + default: + throw new NotSupportedException ("Invalid value for FieldDirection"); + } + Space (); + directionExpression.Expression.AcceptVisitor (this, data); + + return EndNode (directionExpression); + } + + public object VisitIdentifierExpression (IdentifierExpression identifierExpression, object data) + { + StartNode (identifierExpression); + WriteIdentifier (identifierExpression.Identifier); + WriteTypeArguments (identifierExpression.TypeArguments); + return EndNode (identifierExpression); + } + + public object VisitIndexerExpression (IndexerExpression indexerExpression, object data) + { + StartNode (indexerExpression); + indexerExpression.Target.AcceptVisitor (this, data); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInBrackets (indexerExpression.Arguments); + return EndNode (indexerExpression); + } + + public object VisitInvocationExpression (InvocationExpression invocationExpression, object data) + { + StartNode (invocationExpression); + invocationExpression.Target.AcceptVisitor (this, data); + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (invocationExpression.Arguments, policy.SpaceWithinMethodCallParentheses); + return EndNode (invocationExpression); + } + + public object VisitIsExpression (IsExpression isExpression, object data) + { + StartNode (isExpression); + isExpression.Expression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("is"); + isExpression.Type.AcceptVisitor (this, data); + return EndNode (isExpression); + } + + public object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) + { + StartNode (lambdaExpression); + if (LambdaNeedsParenthesis (lambdaExpression)) { + WriteCommaSeparatedListInParenthesis (lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + } else { + lambdaExpression.Parameters.Single ().AcceptVisitor (this, data); + } + Space (); + WriteToken ("=>", LambdaExpression.ArrowRole); + Space (); + lambdaExpression.Body.AcceptVisitor (this, data); + return EndNode (lambdaExpression); + } + + bool LambdaNeedsParenthesis (LambdaExpression lambdaExpression) + { + if (lambdaExpression.Parameters.Count != 1) + return true; + var p = lambdaExpression.Parameters.Single (); + return !(p.Type.IsNull && p.ParameterModifier == ParameterModifier.None); + } + + public object VisitMemberReferenceExpression (MemberReferenceExpression memberReferenceExpression, object data) + { + StartNode (memberReferenceExpression); + memberReferenceExpression.Target.AcceptVisitor (this, data); + WriteToken (".", MemberReferenceExpression.Roles.Dot); + WriteIdentifier (memberReferenceExpression.MemberName); + WriteTypeArguments (memberReferenceExpression.TypeArguments); + return EndNode (memberReferenceExpression); + } + + public object VisitNamedArgumentExpression (NamedArgumentExpression namedArgumentExpression, object data) + { + StartNode (namedArgumentExpression); + WriteIdentifier (namedArgumentExpression.Identifier); + if (namedArgumentExpression.Parent is ArrayInitializerExpression) { + Space(); + WriteToken("=", NamedArgumentExpression.Roles.Assign); + } else { + WriteToken(":", NamedArgumentExpression.Roles.Colon); + } + Space (); + namedArgumentExpression.Expression.AcceptVisitor (this, data); + return EndNode (namedArgumentExpression); + } + + public object VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, object data) + { + StartNode (nullReferenceExpression); + WriteKeyword ("null"); + return EndNode (nullReferenceExpression); + } + + public object VisitObjectCreateExpression (ObjectCreateExpression objectCreateExpression, object data) + { + StartNode (objectCreateExpression); + WriteKeyword ("new"); + objectCreateExpression.Type.AcceptVisitor (this, data); + bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull; + // also use parenthesis if there is an '(' token and this isn't an anonymous type + if (!objectCreateExpression.LParToken.IsNull && !objectCreateExpression.Type.IsNull) + useParenthesis = true; + if (useParenthesis) { + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (objectCreateExpression.Arguments, policy.SpaceWithinMethodCallParentheses); + } + objectCreateExpression.Initializer.AcceptVisitor (this, data); + return EndNode (objectCreateExpression); + } + + public object VisitAnonymousTypeCreateExpression (AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + { + StartNode (anonymousTypeCreateExpression); + WriteKeyword ("new"); + Space (); + LPar (); + RPar (); + Space (); + OpenBrace (policy.AnonymousMethodBraceStyle); + foreach (AstNode node in anonymousTypeCreateExpression.Initializer) { + node.AcceptVisitor (this, null); + if (node.NextSibling != null) + Comma (node); + NewLine (); + } + CloseBrace (policy.AnonymousMethodBraceStyle); + return EndNode (anonymousTypeCreateExpression); + } + + public object VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, object data) + { + StartNode (parenthesizedExpression); + LPar (); + Space (policy.SpacesWithinParentheses); + parenthesizedExpression.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinParentheses); + RPar (); + return EndNode (parenthesizedExpression); + } + + public object VisitPointerReferenceExpression (PointerReferenceExpression pointerReferenceExpression, object data) + { + StartNode (pointerReferenceExpression); + pointerReferenceExpression.Target.AcceptVisitor (this, data); + WriteToken ("->", PointerReferenceExpression.ArrowRole); + WriteIdentifier (pointerReferenceExpression.MemberName); + WriteTypeArguments (pointerReferenceExpression.TypeArguments); + return EndNode (pointerReferenceExpression); + } + + public object VisitEmptyExpression (EmptyExpression emptyExpression, object data) + { + StartNode (emptyExpression); + return EndNode (emptyExpression); + } + + #region VisitPrimitiveExpression + public object VisitPrimitiveExpression (PrimitiveExpression primitiveExpression, object data) + { + StartNode (primitiveExpression); + if (!string.IsNullOrEmpty (primitiveExpression.LiteralValue)) { + formatter.WriteToken (primitiveExpression.LiteralValue); + } else { + WritePrimitiveValue (primitiveExpression.Value); + } + return EndNode (primitiveExpression); + } + + void WritePrimitiveValue (object val) + { + if (val == null) { + // usually NullReferenceExpression should be used for this, but we'll handle it anyways + WriteKeyword ("null"); + return; + } + + if (val is bool) { + if ((bool)val) { + WriteKeyword ("true"); + } else { + WriteKeyword ("false"); + } + return; + } + + if (val is string) { + formatter.WriteToken ("\"" + ConvertString (val.ToString ()) + "\""); + lastWritten = LastWritten.Other; + } else if (val is char) { + formatter.WriteToken ("'" + ConvertCharLiteral ((char)val) + "'"); + lastWritten = LastWritten.Other; + } else if (val is decimal) { + formatter.WriteToken (((decimal)val).ToString (NumberFormatInfo.InvariantInfo) + "m"); + lastWritten = LastWritten.Other; + } else if (val is float) { + float f = (float)val; + if (float.IsInfinity (f) || float.IsNaN (f)) { + // Strictly speaking, these aren't PrimitiveExpressions; + // but we still support writing these to make life easier for code generators. + WriteKeyword ("float"); + WriteToken (".", AstNode.Roles.Dot); + if (float.IsPositiveInfinity (f)) + WriteIdentifier ("PositiveInfinity"); + else if (float.IsNegativeInfinity (f)) + WriteIdentifier ("NegativeInfinity"); + else + WriteIdentifier ("NaN"); + return; + } + formatter.WriteToken (f.ToString ("R", NumberFormatInfo.InvariantInfo) + "f"); + lastWritten = LastWritten.Other; + } else if (val is double) { + double f = (double)val; + if (double.IsInfinity (f) || double.IsNaN (f)) { + // Strictly speaking, these aren't PrimitiveExpressions; + // but we still support writing these to make life easier for code generators. + WriteKeyword ("double"); + WriteToken (".", AstNode.Roles.Dot); + if (double.IsPositiveInfinity (f)) + WriteIdentifier ("PositiveInfinity"); + else if (double.IsNegativeInfinity (f)) + WriteIdentifier ("NegativeInfinity"); + else + WriteIdentifier ("NaN"); + return; + } + string number = f.ToString ("R", NumberFormatInfo.InvariantInfo); + if (number.IndexOf ('.') < 0 && number.IndexOf ('E') < 0) + number += ".0"; + formatter.WriteToken (number); + // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix + lastWritten = LastWritten.KeywordOrIdentifier; + } else if (val is IFormattable) { + StringBuilder b = new StringBuilder (); +// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) { +// b.Append("0x"); +// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo)); +// } else { + b.Append (((IFormattable)val).ToString (null, NumberFormatInfo.InvariantInfo)); +// } + if (val is uint || val is ulong) { + b.Append ("u"); + } + if (val is long || val is ulong) { + b.Append ("L"); + } + formatter.WriteToken (b.ToString ()); + // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix + lastWritten = LastWritten.KeywordOrIdentifier; + } else { + formatter.WriteToken (val.ToString ()); + lastWritten = LastWritten.Other; + } + } + + static string ConvertCharLiteral (char ch) + { + if (ch == '\'') + return "\\'"; + return ConvertChar (ch); + } + + /// + /// Gets the escape sequence for the specified character. + /// + /// This method does not convert ' or ". + public static string ConvertChar(char ch) + { + switch (ch) { + case '\\': + return "\\\\"; + case '\0': + return "\\0"; + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\f': + return "\\f"; + case '\n': + return "\\n"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + default: + if (char.IsControl(ch) || char.IsSurrogate(ch) || + // print all uncommon white spaces as numbers + (char.IsWhiteSpace(ch) && ch != ' ')) { + return "\\u" + ((int)ch).ToString ("x4"); + } else { + return ch.ToString (); + } + } + } + + /// + /// Converts special characters to escape sequences within the given string. + /// + public static string ConvertString(string str) + { + StringBuilder sb = new StringBuilder (); + foreach (char ch in str) { + if (ch == '"') + sb.Append ("\\\""); + else + sb.Append (ConvertChar (ch)); + } + return sb.ToString (); + } + + #endregion + + public object VisitSizeOfExpression (SizeOfExpression sizeOfExpression, object data) + { + StartNode (sizeOfExpression); + + WriteKeyword ("sizeof"); + LPar (); + Space (policy.SpacesWithinSizeOfParentheses); + sizeOfExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinSizeOfParentheses); + RPar (); + + return EndNode (sizeOfExpression); + } + + public object VisitStackAllocExpression (StackAllocExpression stackAllocExpression, object data) + { + StartNode (stackAllocExpression); + WriteKeyword ("stackalloc"); + stackAllocExpression.Type.AcceptVisitor (this, data); + WriteCommaSeparatedListInBrackets (new[] { stackAllocExpression.CountExpression }); + return EndNode (stackAllocExpression); + } + + public object VisitThisReferenceExpression (ThisReferenceExpression thisReferenceExpression, object data) + { + StartNode (thisReferenceExpression); + WriteKeyword ("this"); + return EndNode (thisReferenceExpression); + } + + public object VisitTypeOfExpression (TypeOfExpression typeOfExpression, object data) + { + StartNode (typeOfExpression); + + WriteKeyword ("typeof"); + LPar (); + Space (policy.SpacesWithinTypeOfParentheses); + typeOfExpression.Type.AcceptVisitor (this, data); + Space (policy.SpacesWithinTypeOfParentheses); + RPar (); + + return EndNode (typeOfExpression); + } + + public object VisitTypeReferenceExpression (TypeReferenceExpression typeReferenceExpression, object data) + { + StartNode (typeReferenceExpression); + typeReferenceExpression.Type.AcceptVisitor (this, data); + return EndNode (typeReferenceExpression); + } + + public object VisitUnaryOperatorExpression (UnaryOperatorExpression unaryOperatorExpression, object data) + { + StartNode (unaryOperatorExpression); + UnaryOperatorType opType = unaryOperatorExpression.Operator; + string opSymbol = UnaryOperatorExpression.GetOperatorSymbol (opType); + if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) + WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); + unaryOperatorExpression.Expression.AcceptVisitor (this, data); + if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) + WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); + return EndNode (unaryOperatorExpression); + } + + public object VisitUncheckedExpression (UncheckedExpression uncheckedExpression, object data) + { + StartNode (uncheckedExpression); + WriteKeyword ("unchecked"); + LPar (); + Space (policy.SpacesWithinCheckedExpressionParantheses); + uncheckedExpression.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinCheckedExpressionParantheses); + RPar (); + return EndNode (uncheckedExpression); + } + + #endregion + + #region Query Expressions + public object VisitQueryExpression (QueryExpression queryExpression, object data) + { + StartNode (queryExpression); + bool indent = !(queryExpression.Parent is QueryContinuationClause); + if (indent) { + formatter.Indent(); + NewLine(); + } + bool first = true; + foreach (var clause in queryExpression.Clauses) { + if (first) { + first = false; + } else { + if (!(clause is QueryContinuationClause)) + NewLine (); + } + clause.AcceptVisitor (this, data); + } + if (indent) + formatter.Unindent(); + return EndNode (queryExpression); + } + + public object VisitQueryContinuationClause (QueryContinuationClause queryContinuationClause, object data) + { + StartNode (queryContinuationClause); + queryContinuationClause.PrecedingQuery.AcceptVisitor (this, data); + Space (); + WriteKeyword ("into", QueryContinuationClause.IntoKeywordRole); + Space (); + WriteIdentifier (queryContinuationClause.Identifier); + return EndNode (queryContinuationClause); + } + + public object VisitQueryFromClause (QueryFromClause queryFromClause, object data) + { + StartNode (queryFromClause); + WriteKeyword ("from", QueryFromClause.FromKeywordRole); + queryFromClause.Type.AcceptVisitor (this, data); + Space (); + WriteIdentifier (queryFromClause.Identifier); + Space (); + WriteKeyword ("in", QueryFromClause.InKeywordRole); + Space (); + queryFromClause.Expression.AcceptVisitor (this, data); + return EndNode (queryFromClause); + } + + public object VisitQueryLetClause (QueryLetClause queryLetClause, object data) + { + StartNode (queryLetClause); + WriteKeyword ("let"); + Space (); + WriteIdentifier (queryLetClause.Identifier); + Space (policy.SpaceAroundAssignment); + WriteToken ("=", QueryLetClause.Roles.Assign); + Space (policy.SpaceAroundAssignment); + queryLetClause.Expression.AcceptVisitor (this, data); + return EndNode (queryLetClause); + } + + public object VisitQueryWhereClause (QueryWhereClause queryWhereClause, object data) + { + StartNode (queryWhereClause); + WriteKeyword ("where"); + Space (); + queryWhereClause.Condition.AcceptVisitor (this, data); + return EndNode (queryWhereClause); + } + + public object VisitQueryJoinClause (QueryJoinClause queryJoinClause, object data) + { + StartNode (queryJoinClause); + WriteKeyword ("join", QueryJoinClause.JoinKeywordRole); + queryJoinClause.Type.AcceptVisitor (this, data); + Space (); + WriteIdentifier (queryJoinClause.JoinIdentifier, QueryJoinClause.JoinIdentifierRole); + Space (); + WriteKeyword ("in", QueryJoinClause.InKeywordRole); + Space (); + queryJoinClause.InExpression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("on", QueryJoinClause.OnKeywordRole); + Space (); + queryJoinClause.OnExpression.AcceptVisitor (this, data); + Space (); + WriteKeyword ("equals", QueryJoinClause.EqualsKeywordRole); + Space (); + queryJoinClause.EqualsExpression.AcceptVisitor (this, data); + if (queryJoinClause.IsGroupJoin) { + Space (); + WriteKeyword ("into", QueryJoinClause.IntoKeywordRole); + WriteIdentifier (queryJoinClause.IntoIdentifier, QueryJoinClause.IntoIdentifierRole); + } + return EndNode (queryJoinClause); + } + + public object VisitQueryOrderClause (QueryOrderClause queryOrderClause, object data) + { + StartNode (queryOrderClause); + WriteKeyword ("orderby"); + Space (); + WriteCommaSeparatedList (queryOrderClause.Orderings.SafeCast ()); + return EndNode (queryOrderClause); + } + + public object VisitQueryOrdering (QueryOrdering queryOrdering, object data) + { + StartNode (queryOrdering); + queryOrdering.Expression.AcceptVisitor (this, data); + switch (queryOrdering.Direction) { + case QueryOrderingDirection.Ascending: + Space (); + WriteKeyword ("ascending"); + break; + case QueryOrderingDirection.Descending: + Space (); + WriteKeyword ("descending"); + break; + } + return EndNode (queryOrdering); + } + + public object VisitQuerySelectClause (QuerySelectClause querySelectClause, object data) + { + StartNode (querySelectClause); + WriteKeyword ("select"); + Space (); + querySelectClause.Expression.AcceptVisitor (this, data); + return EndNode (querySelectClause); + } + + public object VisitQueryGroupClause (QueryGroupClause queryGroupClause, object data) + { + StartNode (queryGroupClause); + WriteKeyword ("group", QueryGroupClause.GroupKeywordRole); + Space (); + queryGroupClause.Projection.AcceptVisitor (this, data); + Space (); + WriteKeyword ("by", QueryGroupClause.ByKeywordRole); + Space (); + queryGroupClause.Key.AcceptVisitor (this, data); + return EndNode (queryGroupClause); + } + + #endregion + + #region GeneralScope + public object VisitAttribute (Attribute attribute, object data) + { + StartNode (attribute); + attribute.Type.AcceptVisitor (this, data); + Space (policy.SpaceBeforeMethodCallParentheses); + if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole (AstNode.Roles.LPar).IsNull) + WriteCommaSeparatedListInParenthesis (attribute.Arguments, policy.SpaceWithinMethodCallParentheses); + return EndNode (attribute); + } + + public object VisitAttributeSection (AttributeSection attributeSection, object data) + { + StartNode (attributeSection); + WriteToken ("[", AstNode.Roles.LBracket); + if (!string.IsNullOrEmpty (attributeSection.AttributeTarget)) { + WriteToken (attributeSection.AttributeTarget, AttributeSection.TargetRole); + WriteToken (":", AttributeSection.Roles.Colon); + Space (); + } + WriteCommaSeparatedList (attributeSection.Attributes.SafeCast ()); + WriteToken ("]", AstNode.Roles.RBracket); + if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) + Space (); + else + NewLine (); + return EndNode (attributeSection); + } + + public object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) + { + StartNode (delegateDeclaration); + WriteAttributes (delegateDeclaration.Attributes); + WriteModifiers (delegateDeclaration.ModifierTokens); + WriteKeyword ("delegate"); + delegateDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WriteIdentifier (delegateDeclaration.Name); + WriteTypeParameters (delegateDeclaration.TypeParameters); + Space (policy.SpaceBeforeDelegateDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (delegateDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + foreach (Constraint constraint in delegateDeclaration.Constraints) { + constraint.AcceptVisitor (this, data); + } + Semicolon (); + return EndNode (delegateDeclaration); + } + + public object VisitNamespaceDeclaration (NamespaceDeclaration namespaceDeclaration, object data) + { + StartNode (namespaceDeclaration); + WriteKeyword ("namespace"); + WriteQualifiedIdentifier (namespaceDeclaration.Identifiers); + OpenBrace (policy.NamespaceBraceStyle); + foreach (var member in namespaceDeclaration.Members) + member.AcceptVisitor (this, data); + CloseBrace (policy.NamespaceBraceStyle); + NewLine (); + return EndNode (namespaceDeclaration); + } + + public object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) + { + StartNode (typeDeclaration); + WriteAttributes (typeDeclaration.Attributes); + WriteModifiers (typeDeclaration.ModifierTokens); + BraceStyle braceStyle; + switch (typeDeclaration.ClassType) { + case ClassType.Enum: + WriteKeyword ("enum"); + braceStyle = policy.EnumBraceStyle; + break; + case ClassType.Interface: + WriteKeyword ("interface"); + braceStyle = policy.InterfaceBraceStyle; + break; + case ClassType.Struct: + WriteKeyword ("struct"); + braceStyle = policy.StructBraceStyle; + break; + default: + WriteKeyword ("class"); + braceStyle = policy.ClassBraceStyle; + break; + } + WriteIdentifier (typeDeclaration.Name); + WriteTypeParameters (typeDeclaration.TypeParameters); + if (typeDeclaration.BaseTypes.Any ()) { + Space (); + WriteToken (":", TypeDeclaration.ColonRole); + Space (); + WriteCommaSeparatedList (typeDeclaration.BaseTypes); + } + foreach (Constraint constraint in typeDeclaration.Constraints) { + constraint.AcceptVisitor (this, data); + } + OpenBrace (braceStyle); + if (typeDeclaration.ClassType == ClassType.Enum) { + bool first = true; + foreach (var member in typeDeclaration.Members) { + if (first) { + first = false; + } else { + Comma (member, noSpaceAfterComma: true); + NewLine (); + } + member.AcceptVisitor (this, data); + } + NewLine (); + } else { + foreach (var member in typeDeclaration.Members) { + member.AcceptVisitor (this, data); + } + } + CloseBrace (braceStyle); + NewLine (); + return EndNode (typeDeclaration); + } + + public object VisitUsingAliasDeclaration (UsingAliasDeclaration usingAliasDeclaration, object data) + { + StartNode (usingAliasDeclaration); + WriteKeyword ("using"); + WriteIdentifier (usingAliasDeclaration.Alias, UsingAliasDeclaration.AliasRole); + Space (policy.SpaceAroundEqualityOperator); + WriteToken ("=", AstNode.Roles.Assign); + Space (policy.SpaceAroundEqualityOperator); + usingAliasDeclaration.Import.AcceptVisitor (this, data); + Semicolon (); + return EndNode (usingAliasDeclaration); + } + + public object VisitUsingDeclaration (UsingDeclaration usingDeclaration, object data) + { + StartNode (usingDeclaration); + WriteKeyword ("using"); + usingDeclaration.Import.AcceptVisitor (this, data); + Semicolon (); + return EndNode (usingDeclaration); + } + + public object VisitExternAliasDeclaration (ExternAliasDeclaration externAliasDeclaration, object data) + { + StartNode (externAliasDeclaration); + WriteKeyword ("extern"); + Space (); + WriteKeyword ("alias"); + Space (); + externAliasDeclaration.NameToken.AcceptVisitor (this, data); + Semicolon (); + return EndNode (externAliasDeclaration); + } + + #endregion + + #region Statements + public object VisitBlockStatement (BlockStatement blockStatement, object data) + { + StartNode (blockStatement); + BraceStyle style; + if (blockStatement.Parent is AnonymousMethodExpression || blockStatement.Parent is LambdaExpression) { + style = policy.AnonymousMethodBraceStyle; + } else if (blockStatement.Parent is ConstructorDeclaration) { + style = policy.ConstructorBraceStyle; + } else if (blockStatement.Parent is DestructorDeclaration) { + style = policy.DestructorBraceStyle; + } else if (blockStatement.Parent is MethodDeclaration) { + style = policy.MethodBraceStyle; + } else if (blockStatement.Parent is Accessor) { + if (blockStatement.Parent.Role == PropertyDeclaration.GetterRole) + style = policy.PropertyGetBraceStyle; + else if (blockStatement.Parent.Role == PropertyDeclaration.SetterRole) + style = policy.PropertySetBraceStyle; + else if (blockStatement.Parent.Role == CustomEventDeclaration.AddAccessorRole) + style = policy.EventAddBraceStyle; + else if (blockStatement.Parent.Role == CustomEventDeclaration.RemoveAccessorRole) + style = policy.EventRemoveBraceStyle; + else + throw new NotSupportedException ("Unknown type of accessor"); + } else { + style = policy.StatementBraceStyle; + } + OpenBrace (style); + foreach (var node in blockStatement.Statements) { + node.AcceptVisitor (this, data); + } + CloseBrace (style); + NewLine (); + return EndNode (blockStatement); + } + + public object VisitBreakStatement (BreakStatement breakStatement, object data) + { + StartNode (breakStatement); + WriteKeyword ("break"); + Semicolon (); + return EndNode (breakStatement); + } + + public object VisitCheckedStatement (CheckedStatement checkedStatement, object data) + { + StartNode (checkedStatement); + WriteKeyword ("checked"); + checkedStatement.Body.AcceptVisitor (this, data); + return EndNode (checkedStatement); + } + + public object VisitContinueStatement (ContinueStatement continueStatement, object data) + { + StartNode (continueStatement); + WriteKeyword ("continue"); + Semicolon (); + return EndNode (continueStatement); + } + + public object VisitDoWhileStatement (DoWhileStatement doWhileStatement, object data) + { + StartNode (doWhileStatement); + WriteKeyword ("do", DoWhileStatement.DoKeywordRole); + WriteEmbeddedStatement (doWhileStatement.EmbeddedStatement); + WriteKeyword ("while", DoWhileStatement.WhileKeywordRole); + Space (policy.SpaceBeforeWhileParentheses); + LPar (); + Space (policy.SpacesWithinWhileParentheses); + doWhileStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpacesWithinWhileParentheses); + RPar (); + Semicolon (); + return EndNode (doWhileStatement); + } + + public object VisitEmptyStatement (EmptyStatement emptyStatement, object data) + { + StartNode (emptyStatement); + Semicolon (); + return EndNode (emptyStatement); + } + + public object VisitExpressionStatement (ExpressionStatement expressionStatement, object data) + { + StartNode (expressionStatement); + expressionStatement.Expression.AcceptVisitor (this, data); + Semicolon (); + return EndNode (expressionStatement); + } + + public object VisitFixedStatement (FixedStatement fixedStatement, object data) + { + StartNode (fixedStatement); + WriteKeyword ("fixed"); + Space (policy.SpaceBeforeUsingParentheses); + LPar (); + Space (policy.SpacesWithinUsingParentheses); + fixedStatement.Type.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (fixedStatement.Variables); + Space (policy.SpacesWithinUsingParentheses); + RPar (); + WriteEmbeddedStatement (fixedStatement.EmbeddedStatement); + return EndNode (fixedStatement); + } + + public object VisitForeachStatement (ForeachStatement foreachStatement, object data) + { + StartNode (foreachStatement); + WriteKeyword ("foreach"); + Space (policy.SpaceBeforeForeachParentheses); + LPar (); + Space (policy.SpacesWithinForeachParentheses); + foreachStatement.VariableType.AcceptVisitor (this, data); + Space (); + WriteIdentifier (foreachStatement.VariableName); + WriteKeyword ("in", ForeachStatement.Roles.InKeyword); + Space (); + foreachStatement.InExpression.AcceptVisitor (this, data); + Space (policy.SpacesWithinForeachParentheses); + RPar (); + WriteEmbeddedStatement (foreachStatement.EmbeddedStatement); + return EndNode (foreachStatement); + } + + public object VisitForStatement (ForStatement forStatement, object data) + { + StartNode (forStatement); + WriteKeyword ("for"); + Space (policy.SpaceBeforeForParentheses); + LPar (); + Space (policy.SpacesWithinForParentheses); + + WriteCommaSeparatedList (forStatement.Initializers.SafeCast ()); + Space (policy.SpaceBeforeForSemicolon); + WriteToken (";", AstNode.Roles.Semicolon); + Space (policy.SpaceAfterForSemicolon); + + forStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpaceBeforeForSemicolon); + WriteToken (";", AstNode.Roles.Semicolon); + Space (policy.SpaceAfterForSemicolon); + + WriteCommaSeparatedList (forStatement.Iterators.SafeCast ()); + + Space (policy.SpacesWithinForParentheses); + RPar (); + WriteEmbeddedStatement (forStatement.EmbeddedStatement); + return EndNode (forStatement); + } + + public object VisitGotoCaseStatement (GotoCaseStatement gotoCaseStatement, object data) + { + StartNode (gotoCaseStatement); + WriteKeyword ("goto"); + WriteKeyword ("case", GotoCaseStatement.CaseKeywordRole); + Space (); + gotoCaseStatement.LabelExpression.AcceptVisitor (this, data); + Semicolon (); + return EndNode (gotoCaseStatement); + } + + public object VisitGotoDefaultStatement (GotoDefaultStatement gotoDefaultStatement, object data) + { + StartNode (gotoDefaultStatement); + WriteKeyword ("goto"); + WriteKeyword ("default", GotoDefaultStatement.DefaultKeywordRole); + Semicolon (); + return EndNode (gotoDefaultStatement); + } + + public object VisitGotoStatement (GotoStatement gotoStatement, object data) + { + StartNode (gotoStatement); + WriteKeyword ("goto"); + WriteIdentifier (gotoStatement.Label); + Semicolon (); + return EndNode (gotoStatement); + } + + public object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) + { + StartNode (ifElseStatement); + WriteKeyword ("if", IfElseStatement.IfKeywordRole); + Space (policy.SpaceBeforeIfParentheses); + LPar (); + Space (policy.SpacesWithinIfParentheses); + ifElseStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpacesWithinIfParentheses); + RPar (); + WriteEmbeddedStatement (ifElseStatement.TrueStatement); + if (!ifElseStatement.FalseStatement.IsNull) { + WriteKeyword ("else", IfElseStatement.ElseKeywordRole); + WriteEmbeddedStatement (ifElseStatement.FalseStatement); + } + return EndNode (ifElseStatement); + } + + public object VisitLabelStatement (LabelStatement labelStatement, object data) + { + StartNode (labelStatement); + WriteIdentifier (labelStatement.Label); + WriteToken (":", LabelStatement.Roles.Colon); + bool foundLabelledStatement = false; + for (AstNode tmp = labelStatement.NextSibling; tmp != null; tmp = tmp.NextSibling) { + if (tmp.Role == labelStatement.Role) { + foundLabelledStatement = true; + } + } + if (!foundLabelledStatement) { + // introduce an EmptyStatement so that the output becomes syntactically valid + WriteToken(";", LabelStatement.Roles.Semicolon); + } + NewLine (); + return EndNode (labelStatement); + } + + public object VisitLockStatement (LockStatement lockStatement, object data) + { + StartNode (lockStatement); + WriteKeyword ("lock"); + Space (policy.SpaceBeforeLockParentheses); + LPar (); + Space (policy.SpacesWithinLockParentheses); + lockStatement.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinLockParentheses); + RPar (); + WriteEmbeddedStatement (lockStatement.EmbeddedStatement); + return EndNode (lockStatement); + } + + public object VisitReturnStatement (ReturnStatement returnStatement, object data) + { + StartNode (returnStatement); + WriteKeyword ("return"); + if (!returnStatement.Expression.IsNull) { + Space (); + returnStatement.Expression.AcceptVisitor (this, data); + } + Semicolon (); + return EndNode (returnStatement); + } + + public object VisitSwitchStatement (SwitchStatement switchStatement, object data) + { + StartNode (switchStatement); + WriteKeyword ("switch"); + Space (policy.SpaceBeforeSwitchParentheses); + LPar (); + Space (policy.SpacesWithinSwitchParentheses); + switchStatement.Expression.AcceptVisitor (this, data); + Space (policy.SpacesWithinSwitchParentheses); + RPar (); + OpenBrace (policy.StatementBraceStyle); + if (!policy.IndentSwitchBody) + formatter.Unindent (); + + foreach (var section in switchStatement.SwitchSections) + section.AcceptVisitor (this, data); + + if (!policy.IndentSwitchBody) + formatter.Indent (); + CloseBrace (policy.StatementBraceStyle); + NewLine (); + return EndNode (switchStatement); + } + + public object VisitSwitchSection (SwitchSection switchSection, object data) + { + StartNode (switchSection); + bool first = true; + foreach (var label in switchSection.CaseLabels) { + if (!first) + NewLine (); + label.AcceptVisitor (this, data); + first = false; + } + if (policy.IndentCaseBody) + formatter.Indent (); + + foreach (var statement in switchSection.Statements) { + NewLine (); + statement.AcceptVisitor (this, data); + } + + if (policy.IndentCaseBody) + formatter.Unindent (); + + return EndNode (switchSection); + } + + public object VisitCaseLabel (CaseLabel caseLabel, object data) + { + StartNode (caseLabel); + if (caseLabel.Expression.IsNull) { + WriteKeyword ("default"); + } else { + WriteKeyword ("case"); + Space (); + caseLabel.Expression.AcceptVisitor (this, data); + } + WriteToken (":", CaseLabel.Roles.Colon); + return EndNode (caseLabel); + } + + public object VisitThrowStatement (ThrowStatement throwStatement, object data) + { + StartNode (throwStatement); + WriteKeyword ("throw"); + if (!throwStatement.Expression.IsNull) { + Space (); + throwStatement.Expression.AcceptVisitor (this, data); + } + Semicolon (); + return EndNode (throwStatement); + } + + public object VisitTryCatchStatement (TryCatchStatement tryCatchStatement, object data) + { + StartNode (tryCatchStatement); + WriteKeyword ("try", TryCatchStatement.TryKeywordRole); + tryCatchStatement.TryBlock.AcceptVisitor (this, data); + foreach (var catchClause in tryCatchStatement.CatchClauses) + catchClause.AcceptVisitor (this, data); + if (!tryCatchStatement.FinallyBlock.IsNull) { + WriteKeyword ("finally", TryCatchStatement.FinallyKeywordRole); + tryCatchStatement.FinallyBlock.AcceptVisitor (this, data); + } + return EndNode (tryCatchStatement); + } + + public object VisitCatchClause (CatchClause catchClause, object data) + { + StartNode (catchClause); + WriteKeyword ("catch"); + if (!catchClause.Type.IsNull) { + Space (policy.SpaceBeforeCatchParentheses); + LPar (); + Space (policy.SpacesWithinCatchParentheses); + catchClause.Type.AcceptVisitor (this, data); + if (!string.IsNullOrEmpty(catchClause.VariableName)) { + Space (); + WriteIdentifier (catchClause.VariableName); + } + Space (policy.SpacesWithinCatchParentheses); + RPar (); + } + catchClause.Body.AcceptVisitor (this, data); + return EndNode (catchClause); + } + + public object VisitUncheckedStatement (UncheckedStatement uncheckedStatement, object data) + { + StartNode (uncheckedStatement); + WriteKeyword ("unchecked"); + uncheckedStatement.Body.AcceptVisitor (this, data); + return EndNode (uncheckedStatement); + } + + public object VisitUnsafeStatement (UnsafeStatement unsafeStatement, object data) + { + StartNode (unsafeStatement); + WriteKeyword ("unsafe"); + unsafeStatement.Body.AcceptVisitor (this, data); + return EndNode (unsafeStatement); + } + + public object VisitUsingStatement (UsingStatement usingStatement, object data) + { + StartNode (usingStatement); + WriteKeyword ("using"); + Space (policy.SpaceBeforeUsingParentheses); + LPar (); + Space (policy.SpacesWithinUsingParentheses); + + usingStatement.ResourceAcquisition.AcceptVisitor (this, data); + + Space (policy.SpacesWithinUsingParentheses); + RPar (); + + WriteEmbeddedStatement (usingStatement.EmbeddedStatement); + + return EndNode (usingStatement); + } + + public object VisitVariableDeclarationStatement (VariableDeclarationStatement variableDeclarationStatement, object data) + { + StartNode (variableDeclarationStatement); + variableDeclarationStatement.Type.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (variableDeclarationStatement.Variables); + Semicolon (); + return EndNode (variableDeclarationStatement); + } + + public object VisitWhileStatement (WhileStatement whileStatement, object data) + { + StartNode (whileStatement); + WriteKeyword ("while", WhileStatement.WhileKeywordRole); + Space (policy.SpaceBeforeWhileParentheses); + LPar (); + Space (policy.SpacesWithinWhileParentheses); + whileStatement.Condition.AcceptVisitor (this, data); + Space (policy.SpacesWithinWhileParentheses); + RPar (); + WriteEmbeddedStatement (whileStatement.EmbeddedStatement); + return EndNode (whileStatement); + } + + public object VisitYieldBreakStatement (YieldBreakStatement yieldBreakStatement, object data) + { + StartNode (yieldBreakStatement); + WriteKeyword ("yield", YieldBreakStatement.YieldKeywordRole); + WriteKeyword ("break", YieldBreakStatement.BreakKeywordRole); + Semicolon (); + return EndNode (yieldBreakStatement); + } + + public object VisitYieldStatement (YieldStatement yieldStatement, object data) + { + StartNode (yieldStatement); + WriteKeyword ("yield", YieldStatement.YieldKeywordRole); + WriteKeyword ("return", YieldStatement.ReturnKeywordRole); + Space (); + yieldStatement.Expression.AcceptVisitor (this, data); + Semicolon (); + return EndNode (yieldStatement); + } + + #endregion + + #region TypeMembers + public object VisitAccessor (Accessor accessor, object data) + { + StartNode (accessor); + WriteAttributes (accessor.Attributes); + WriteModifiers (accessor.ModifierTokens); + if (accessor.Role == PropertyDeclaration.GetterRole) { + WriteKeyword ("get"); + } else if (accessor.Role == PropertyDeclaration.SetterRole) { + WriteKeyword ("set"); + } else if (accessor.Role == CustomEventDeclaration.AddAccessorRole) { + WriteKeyword ("add"); + } else if (accessor.Role == CustomEventDeclaration.RemoveAccessorRole) { + WriteKeyword ("remove"); + } + WriteMethodBody (accessor.Body); + return EndNode (accessor); + } + + public object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) + { + StartNode (constructorDeclaration); + WriteAttributes (constructorDeclaration.Attributes); + WriteModifiers (constructorDeclaration.ModifierTokens); + TypeDeclaration type = constructorDeclaration.Parent as TypeDeclaration; + WriteIdentifier (type != null ? type.Name : constructorDeclaration.Name); + Space (policy.SpaceBeforeConstructorDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (constructorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + if (!constructorDeclaration.Initializer.IsNull) { + Space (); + constructorDeclaration.Initializer.AcceptVisitor (this, data); + } + WriteMethodBody (constructorDeclaration.Body); + return EndNode (constructorDeclaration); + } + + public object VisitConstructorInitializer (ConstructorInitializer constructorInitializer, object data) + { + StartNode (constructorInitializer); + WriteToken (":", ConstructorInitializer.Roles.Colon); + Space (); + if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.This) { + WriteKeyword ("this"); + } else { + WriteKeyword ("base"); + } + Space (policy.SpaceBeforeMethodCallParentheses); + WriteCommaSeparatedListInParenthesis (constructorInitializer.Arguments, policy.SpaceWithinMethodCallParentheses); + return EndNode (constructorInitializer); + } + + public object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) + { + StartNode (destructorDeclaration); + WriteAttributes (destructorDeclaration.Attributes); + WriteModifiers (destructorDeclaration.ModifierTokens); + WriteToken ("~", DestructorDeclaration.TildeRole); + TypeDeclaration type = destructorDeclaration.Parent as TypeDeclaration; + WriteIdentifier (type != null ? type.Name : destructorDeclaration.Name); + Space (policy.SpaceBeforeConstructorDeclarationParentheses); + LPar (); + RPar (); + WriteMethodBody (destructorDeclaration.Body); + return EndNode (destructorDeclaration); + } + + public object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) + { + StartNode (enumMemberDeclaration); + WriteAttributes (enumMemberDeclaration.Attributes); + WriteModifiers (enumMemberDeclaration.ModifierTokens); + WriteIdentifier (enumMemberDeclaration.Name); + if (!enumMemberDeclaration.Initializer.IsNull) { + Space (policy.SpaceAroundAssignment); + WriteToken ("=", EnumMemberDeclaration.Roles.Assign); + Space (policy.SpaceAroundAssignment); + enumMemberDeclaration.Initializer.AcceptVisitor (this, data); + } + return EndNode (enumMemberDeclaration); + } + + public object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) + { + StartNode (eventDeclaration); + WriteAttributes (eventDeclaration.Attributes); + WriteModifiers (eventDeclaration.ModifierTokens); + WriteKeyword ("event"); + eventDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (eventDeclaration.Variables); + Semicolon (); + return EndNode (eventDeclaration); + } + + public object VisitCustomEventDeclaration (CustomEventDeclaration customEventDeclaration, object data) + { + StartNode (customEventDeclaration); + WriteAttributes (customEventDeclaration.Attributes); + WriteModifiers (customEventDeclaration.ModifierTokens); + WriteKeyword ("event"); + customEventDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WritePrivateImplementationType (customEventDeclaration.PrivateImplementationType); + WriteIdentifier (customEventDeclaration.Name); + OpenBrace (policy.EventBraceStyle); + // output add/remove in their original order + foreach (AstNode node in customEventDeclaration.Children) { + if (node.Role == CustomEventDeclaration.AddAccessorRole || node.Role == CustomEventDeclaration.RemoveAccessorRole) { + node.AcceptVisitor (this, data); + } + } + CloseBrace (policy.EventBraceStyle); + NewLine (); + return EndNode (customEventDeclaration); + } + + public object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) + { + StartNode (fieldDeclaration); + WriteAttributes (fieldDeclaration.Attributes); + WriteModifiers (fieldDeclaration.ModifierTokens); + fieldDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (fieldDeclaration.Variables); + Semicolon (); + return EndNode (fieldDeclaration); + } + + public object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) + { + StartNode (fixedFieldDeclaration); + WriteAttributes (fixedFieldDeclaration.Attributes); + WriteModifiers (fixedFieldDeclaration.ModifierTokens); + WriteKeyword ("fixed"); + Space (); + fixedFieldDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WriteCommaSeparatedList (fixedFieldDeclaration.Variables); + Semicolon (); + return EndNode (fixedFieldDeclaration); + } + + public object VisitFixedVariableInitializer (FixedVariableInitializer fixedVariableInitializer, object data) + { + StartNode (fixedVariableInitializer); + WriteIdentifier (fixedVariableInitializer.Name); + if (!fixedVariableInitializer.CountExpression.IsNull) { + WriteToken ("[", AstNode.Roles.LBracket); + Space (policy.SpacesWithinBrackets); + fixedVariableInitializer.CountExpression.AcceptVisitor (this, data); + Space (policy.SpacesWithinBrackets); + WriteToken ("]", AstNode.Roles.RBracket); + } + return EndNode (fixedVariableInitializer); + } + + public object VisitIndexerDeclaration (IndexerDeclaration indexerDeclaration, object data) + { + StartNode (indexerDeclaration); + WriteAttributes (indexerDeclaration.Attributes); + WriteModifiers (indexerDeclaration.ModifierTokens); + indexerDeclaration.ReturnType.AcceptVisitor (this, data); + WritePrivateImplementationType (indexerDeclaration.PrivateImplementationType); + WriteKeyword ("this"); + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInBrackets (indexerDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + OpenBrace (policy.PropertyBraceStyle); + // output get/set in their original order + foreach (AstNode node in indexerDeclaration.Children) { + if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { + node.AcceptVisitor (this, data); + } + } + CloseBrace (policy.PropertyBraceStyle); + NewLine (); + return EndNode (indexerDeclaration); + } + + public object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) + { + StartNode (methodDeclaration); + WriteAttributes (methodDeclaration.Attributes); + WriteModifiers (methodDeclaration.ModifierTokens); + methodDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WritePrivateImplementationType (methodDeclaration.PrivateImplementationType); + WriteIdentifier (methodDeclaration.Name); + WriteTypeParameters (methodDeclaration.TypeParameters); + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (methodDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + foreach (Constraint constraint in methodDeclaration.Constraints) { + constraint.AcceptVisitor (this, data); + } + WriteMethodBody (methodDeclaration.Body); + return EndNode (methodDeclaration); + } + + public object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) + { + StartNode (operatorDeclaration); + WriteAttributes (operatorDeclaration.Attributes); + WriteModifiers (operatorDeclaration.ModifierTokens); + if (operatorDeclaration.OperatorType == OperatorType.Explicit) { + WriteKeyword ("explicit", OperatorDeclaration.OperatorTypeRole); + } else if (operatorDeclaration.OperatorType == OperatorType.Implicit) { + WriteKeyword ("implicit", OperatorDeclaration.OperatorTypeRole); + } else { + operatorDeclaration.ReturnType.AcceptVisitor (this, data); + } + WriteKeyword ("operator", OperatorDeclaration.OperatorKeywordRole); + Space (); + if (operatorDeclaration.OperatorType == OperatorType.Explicit + || operatorDeclaration.OperatorType == OperatorType.Implicit) { + operatorDeclaration.ReturnType.AcceptVisitor (this, data); + } else { + WriteToken (OperatorDeclaration.GetToken (operatorDeclaration.OperatorType), OperatorDeclaration.OperatorTypeRole); + } + Space (policy.SpaceBeforeMethodDeclarationParentheses); + WriteCommaSeparatedListInParenthesis (operatorDeclaration.Parameters, policy.SpaceWithinMethodDeclarationParentheses); + WriteMethodBody (operatorDeclaration.Body); + return EndNode (operatorDeclaration); + } + + public object VisitParameterDeclaration (ParameterDeclaration parameterDeclaration, object data) + { + StartNode (parameterDeclaration); + WriteAttributes (parameterDeclaration.Attributes); + switch (parameterDeclaration.ParameterModifier) { + case ParameterModifier.Ref: + WriteKeyword ("ref", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.Out: + WriteKeyword ("out", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.Params: + WriteKeyword ("params", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.This: + WriteKeyword ("this", ParameterDeclaration.ModifierRole); + break; + } + parameterDeclaration.Type.AcceptVisitor (this, data); + if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty (parameterDeclaration.Name)) + Space (); + if (!string.IsNullOrEmpty (parameterDeclaration.Name)) + WriteIdentifier (parameterDeclaration.Name); + if (!parameterDeclaration.DefaultExpression.IsNull) { + Space (policy.SpaceAroundAssignment); + WriteToken ("=", ParameterDeclaration.Roles.Assign); + Space (policy.SpaceAroundAssignment); + parameterDeclaration.DefaultExpression.AcceptVisitor (this, data); + } + return EndNode (parameterDeclaration); + } + + public object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) + { + StartNode (propertyDeclaration); + WriteAttributes (propertyDeclaration.Attributes); + WriteModifiers (propertyDeclaration.ModifierTokens); + propertyDeclaration.ReturnType.AcceptVisitor (this, data); + Space (); + WritePrivateImplementationType (propertyDeclaration.PrivateImplementationType); + WriteIdentifier (propertyDeclaration.Name); + OpenBrace (policy.PropertyBraceStyle); + // output get/set in their original order + foreach (AstNode node in propertyDeclaration.Children) { + if (node.Role == IndexerDeclaration.GetterRole || node.Role == IndexerDeclaration.SetterRole) { + node.AcceptVisitor (this, data); + } + } + CloseBrace (policy.PropertyBraceStyle); + NewLine (); + return EndNode (propertyDeclaration); + } + + #endregion + + #region Other nodes + public object VisitVariableInitializer (VariableInitializer variableInitializer, object data) + { + StartNode (variableInitializer); + WriteIdentifier (variableInitializer.Name); + if (!variableInitializer.Initializer.IsNull) { + Space (policy.SpaceAroundAssignment); + WriteToken ("=", VariableInitializer.Roles.Assign); + Space (policy.SpaceAroundAssignment); + variableInitializer.Initializer.AcceptVisitor (this, data); + } + return EndNode (variableInitializer); + } + + public object VisitCompilationUnit (CompilationUnit compilationUnit, object data) + { + // don't do node tracking as we visit all children directly + foreach (AstNode node in compilationUnit.Children) + node.AcceptVisitor (this, data); + return null; + } + + public object VisitSimpleType (SimpleType simpleType, object data) + { + StartNode (simpleType); + WriteIdentifier (simpleType.Identifier); + WriteTypeArguments (simpleType.TypeArguments); + return EndNode (simpleType); + } + + public object VisitMemberType (MemberType memberType, object data) + { + StartNode (memberType); + memberType.Target.AcceptVisitor (this, data); + if (memberType.IsDoubleColon) + WriteToken ("::", MemberType.Roles.Dot); + else + WriteToken (".", MemberType.Roles.Dot); + WriteIdentifier (memberType.MemberName); + WriteTypeArguments (memberType.TypeArguments); + return EndNode (memberType); + } + + public object VisitComposedType (ComposedType composedType, object data) + { + StartNode (composedType); + composedType.BaseType.AcceptVisitor (this, data); + if (composedType.HasNullableSpecifier) + WriteToken ("?", ComposedType.NullableRole); + for (int i = 0; i < composedType.PointerRank; i++) + WriteToken ("*", ComposedType.PointerRole); + foreach (var node in composedType.ArraySpecifiers) + node.AcceptVisitor (this, data); + return EndNode (composedType); + } + + public object VisitArraySpecifier (ArraySpecifier arraySpecifier, object data) + { + StartNode (arraySpecifier); + WriteToken ("[", ArraySpecifier.Roles.LBracket); + foreach (var comma in arraySpecifier.GetChildrenByRole(ArraySpecifier.Roles.Comma)) { + WriteSpecialsUpToNode (comma); + formatter.WriteToken (","); + lastWritten = LastWritten.Other; + } + WriteToken ("]", ArraySpecifier.Roles.RBracket); + return EndNode (arraySpecifier); + } + + public object VisitPrimitiveType (PrimitiveType primitiveType, object data) + { + StartNode (primitiveType); + WriteKeyword (primitiveType.Keyword); + if (primitiveType.Keyword == "new") { + // new() constraint + LPar (); + RPar (); + } + return EndNode (primitiveType); + } + + public object VisitComment (Comment comment, 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(comment); + formatter.WriteComment (comment.CommentType, comment.Content); + formatter.EndNode(comment); + lastWritten = LastWritten.Whitespace; + return null; + } + + public object VisitTypeParameterDeclaration (TypeParameterDeclaration typeParameterDeclaration, object data) + { + StartNode (typeParameterDeclaration); + WriteAttributes (typeParameterDeclaration.Attributes); + switch (typeParameterDeclaration.Variance) { + case VarianceModifier.Invariant: + break; + case VarianceModifier.Covariant: + WriteKeyword ("out"); + break; + case VarianceModifier.Contravariant: + WriteKeyword ("in"); + break; + default: + throw new NotSupportedException ("Invalid value for VarianceModifier"); + } + WriteIdentifier (typeParameterDeclaration.Name); + return EndNode (typeParameterDeclaration); + } + + public object VisitConstraint (Constraint constraint, object data) + { + StartNode (constraint); + Space (); + WriteKeyword ("where"); + WriteIdentifier (constraint.TypeParameter); + Space (); + WriteToken (":", Constraint.ColonRole); + Space (); + WriteCommaSeparatedList (constraint.BaseTypes); + return EndNode (constraint); + } + + public object VisitCSharpTokenNode (CSharpTokenNode cSharpTokenNode, object data) + { + CSharpModifierToken mod = cSharpTokenNode as CSharpModifierToken; + if (mod != null) { + StartNode (mod); + WriteKeyword (CSharpModifierToken.GetModifierName (mod.Modifier)); + return EndNode (mod); + } else { + throw new NotSupportedException ("Should never visit individual tokens"); + } + } + + public object VisitIdentifier (Identifier identifier, object data) + { + StartNode (identifier); + WriteIdentifier (identifier.Name); + return EndNode (identifier); + } + + #endregion + + #region Pattern Nodes + public object VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern, object data) + { + StartNode (placeholder); + pattern.AcceptVisitor (this, data); + return EndNode (placeholder); + } + + object IPatternAstVisitor.VisitAnyNode (AnyNode anyNode, object data) + { + if (!string.IsNullOrEmpty (anyNode.GroupName)) { + WriteIdentifier (anyNode.GroupName); + WriteToken (":", AstNode.Roles.Colon); + } + WriteKeyword ("anyNode"); + return null; + } + + object IPatternAstVisitor.VisitBackreference (Backreference backreference, object data) + { + WriteKeyword ("backreference"); + LPar (); + WriteIdentifier (backreference.ReferencedGroupName); + RPar (); + return null; + } + + object IPatternAstVisitor.VisitIdentifierExpressionBackreference (IdentifierExpressionBackreference identifierExpressionBackreference, object data) + { + WriteKeyword ("identifierBackreference"); + LPar (); + WriteIdentifier (identifierExpressionBackreference.ReferencedGroupName); + RPar (); + return null; + } + + object IPatternAstVisitor.VisitChoice (Choice choice, object data) + { + WriteKeyword ("choice"); + Space (); + LPar (); + NewLine (); + formatter.Indent (); + foreach (INode alternative in choice) { + VisitNodeInPattern (alternative, data); + if (alternative != choice.Last ()) + WriteToken (",", AstNode.Roles.Comma); + NewLine (); + } + formatter.Unindent (); + RPar (); + return null; + } + + object IPatternAstVisitor.VisitNamedNode (NamedNode namedNode, object data) + { + if (!string.IsNullOrEmpty (namedNode.GroupName)) { + WriteIdentifier (namedNode.GroupName); + WriteToken (":", AstNode.Roles.Colon); + } + VisitNodeInPattern (namedNode.ChildNode, data); + return null; + } + + object IPatternAstVisitor.VisitRepeat (Repeat repeat, object data) + { + WriteKeyword ("repeat"); + LPar (); + if (repeat.MinCount != 0 || repeat.MaxCount != int.MaxValue) { + WriteIdentifier (repeat.MinCount.ToString ()); + WriteToken (",", AstNode.Roles.Comma); + WriteIdentifier (repeat.MaxCount.ToString ()); + WriteToken (",", AstNode.Roles.Comma); + } + VisitNodeInPattern (repeat.ChildNode, data); + RPar (); + return null; + } + + object IPatternAstVisitor.VisitOptionalNode (OptionalNode optionalNode, object data) + { + WriteKeyword ("optional"); + LPar (); + VisitNodeInPattern (optionalNode.ChildNode, data); + RPar (); + return null; + } + + void VisitNodeInPattern (INode childNode, object data) + { + AstNode astNode = childNode as AstNode; + if (astNode != null) { + astNode.AcceptVisitor (this, data); + } else { + Pattern pattern = childNode as Pattern; + if (pattern != null) { + pattern.AcceptVisitor (this, data); + } else { + throw new InvalidOperationException ("Unknown node type in pattern"); + } + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs new file mode 100644 index 0000000000..a901cb78a0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -0,0 +1,181 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Writes C# code into a TextWriter. + /// + public class TextWriterOutputFormatter : IOutputFormatter + { + readonly TextWriter textWriter; + int indentation; + bool needsIndent = true; + + public int Indentation { + get { + return this.indentation; + } + set { + this.indentation = value; + } + } + + public string IndentationString { get; set; } + + public TextWriterOutputFormatter(TextWriter textWriter) + { + if (textWriter == null) + throw new ArgumentNullException("textWriter"); + this.textWriter = textWriter; + this.IndentationString = "\t"; + } + + public void WriteIdentifier(string ident) + { + WriteIndentation(); + textWriter.Write(ident); + } + + public void WriteKeyword(string keyword) + { + WriteIndentation(); + textWriter.Write(keyword); + } + + public void WriteToken(string token) + { + WriteIndentation(); + textWriter.Write(token); + } + + public void Space() + { + WriteIndentation(); + textWriter.Write(' '); + } + + public void OpenBrace(BraceStyle style) + { + switch (style) { + case BraceStyle.DoNotChange: + case BraceStyle.EndOfLine: + WriteIndentation(); + textWriter.Write(' '); + textWriter.Write('{'); + break; + case BraceStyle.EndOfLineWithoutSpace: + WriteIndentation(); + textWriter.Write('{'); + break; + case BraceStyle.NextLine: + NewLine (); + WriteIndentation(); + textWriter.Write('{'); + break; + + case BraceStyle.NextLineShifted: + NewLine (); + Indent(); + WriteIndentation(); + textWriter.Write('{'); + NewLine(); + return; + case BraceStyle.NextLineShifted2: + NewLine (); + Indent(); + WriteIndentation(); + textWriter.Write('{'); + break; + default: + throw new ArgumentOutOfRangeException (); + } + Indent(); + NewLine(); + } + + public void CloseBrace(BraceStyle style) + { + switch (style) { + case BraceStyle.DoNotChange: + case BraceStyle.EndOfLine: + case BraceStyle.EndOfLineWithoutSpace: + case BraceStyle.NextLine: + Unindent(); + WriteIndentation(); + textWriter.Write('}'); + break; + case BraceStyle.NextLineShifted: + WriteIndentation(); + textWriter.Write('}'); + Unindent(); + break; + case BraceStyle.NextLineShifted2: + Unindent(); + WriteIndentation(); + textWriter.Write('}'); + Unindent(); + break; + default: + throw new ArgumentOutOfRangeException (); + } + } + + void WriteIndentation() + { + if (needsIndent) { + needsIndent = false; + for (int i = 0; i < indentation; i++) { + textWriter.Write(this.IndentationString); + } + } + } + + public void NewLine() + { + textWriter.WriteLine(); + needsIndent = true; + } + + public void Indent() + { + indentation++; + } + + public void Unindent() + { + indentation--; + } + + public void WriteComment(CommentType commentType, string content) + { + WriteIndentation(); + switch (commentType) { + case CommentType.SingleLine: + textWriter.Write("//"); + textWriter.WriteLine(content); + break; + case CommentType.MultiLine: + textWriter.Write("/*"); + textWriter.Write(content); + textWriter.Write("*/"); + break; + case CommentType.Documentation: + textWriter.Write("///"); + textWriter.WriteLine(content); + break; + } + } + + public virtual void StartNode(AstNode node) + { + } + + public virtual void EndNode(AstNode node) + { + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs new file mode 100644 index 0000000000..d9274ecee8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -0,0 +1,3155 @@ +// +// CSharpParser.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2009 Novell, Inc (http://www.novell.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.Linq; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Mono.CSharp; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp +{ + public class CSharpParser + { + class ConversionVisitor : StructuralVisitor + { + CompilationUnit unit = new CompilationUnit (); + internal bool convertTypeSystemMode; + + public CompilationUnit Unit { + get { + return unit; + } + set { + unit = value; + } + } + + public LocationsBag LocationsBag { + get; + private set; + } + + public ConversionVisitor (bool convertTypeSystemMode, LocationsBag locationsBag) + { + this.convertTypeSystemMode = convertTypeSystemMode; + this.LocationsBag = locationsBag; + } + + public static AstLocation Convert (Mono.CSharp.Location loc) + { + return new AstLocation (loc.Row, loc.Column); + } + + + #region Global + Stack namespaceStack = new Stack (); + + void AddTypeArguments (ATypeNameExpression texpr, AstType result) + { + if (texpr.TypeArguments == null || texpr.TypeArguments.Args == null) + return; + var loc = LocationsBag.GetLocations (texpr.TypeArguments); + if (loc != null && loc.Count >= 2) + result.AddChild (new CSharpTokenNode (Convert (loc [loc.Count - 2]), 1), AstType.Roles.LChevron); + int i = 0; + foreach (var arg in texpr.TypeArguments.Args) { + result.AddChild (ConvertToType (arg), AstType.Roles.TypeArgument); + if (loc != null && i < loc.Count - 2) + result.AddChild (new CSharpTokenNode (Convert (loc [i++]), 1), AstType.Roles.Comma); + } + if (loc != null && loc.Count >= 2) + result.AddChild (new CSharpTokenNode (Convert (loc [loc.Count - 1]), 1), AstType.Roles.RChevron); + } + + AstType ConvertToType (MemberName memberName) + { + AstType result; + if (memberName.Left != null) { + result = new MemberType () { MemberName = memberName.Name }; + result.AddChild (ConvertToType (memberName.Left), MemberType.TargetRole); + } else { + result = new SimpleType () { Identifier = memberName.Name }; + } + if (memberName.TypeArguments != null && !memberName.TypeArguments.IsEmpty) { + foreach (var arg in memberName.TypeArguments.Args) { + result.AddChild (ConvertToType (arg), AstType.Roles.TypeArgument); + } + } + return result; + } + + AstType ConvertToType (Mono.CSharp.Expression typeName) + { + if (typeName == null) // may happen in typeof(Generic<,,,,>) + return new SimpleType (); + + if (typeName is TypeExpression) { + var typeExpr = (Mono.CSharp.TypeExpression)typeName; + return new PrimitiveType (typeExpr.GetSignatureForError (), Convert (typeExpr.Location)); + } + + if (typeName is Mono.CSharp.QualifiedAliasMember) { + var qam = (Mono.CSharp.QualifiedAliasMember)typeName; + var memberType = new MemberType (); + memberType.Target = new SimpleType (qam.alias, Convert (qam.Location)); + memberType.IsDoubleColon = true; + memberType.MemberName = qam.Name; + return memberType; + } + + if (typeName is MemberAccess) { + MemberAccess ma = (MemberAccess)typeName; + + var memberType = new MemberType (); + memberType.AddChild (ConvertToType (ma.LeftExpression), MemberType.TargetRole); + memberType.MemberNameToken = Identifier.Create (ma.Name, Convert (ma.Location)); + + AddTypeArguments (ma, memberType); + return memberType; + } + + if (typeName is SimpleName) { + var sn = (SimpleName)typeName; + var result = new SimpleType (sn.Name, Convert (sn.Location)); + AddTypeArguments (sn, result); + return result; + } + + if (typeName is ComposedCast) { + var cc = (ComposedCast)typeName; + var baseType = ConvertToType (cc.Left); + var result = new ComposedType () { BaseType = baseType }; + var ccSpec = cc.Spec; + while (ccSpec != null) { + if (ccSpec.IsNullable) { + result.HasNullableSpecifier = true; + } else if (ccSpec.IsPointer) { + result.PointerRank++; + } else { + var location = LocationsBag.GetLocations (ccSpec); + var spec = new ArraySpecifier () { Dimensions = ccSpec.Dimension }; + spec.AddChild (new CSharpTokenNode (Convert (ccSpec.Location), 1), FieldDeclaration.Roles.LBracket); + if (location != null) + spec.AddChild (new CSharpTokenNode (Convert (location [0]), 1), FieldDeclaration.Roles.RBracket); + + result.ArraySpecifiers.Add (spec); + } + ccSpec = ccSpec.Next; + } + return result; + } + + if (typeName is SpecialContraintExpr) { + var sce = (SpecialContraintExpr)typeName; + switch (sce.Constraint) { + case SpecialConstraint.Class: + return new PrimitiveType ("class", Convert (sce.Location)); + case SpecialConstraint.Struct: + return new PrimitiveType ("struct", Convert (sce.Location)); + case SpecialConstraint.Constructor: + return new PrimitiveType ("new", Convert (sce.Location)); + } + } + System.Console.WriteLine ("Error while converting :" + typeName + " - unknown type name"); + System.Console.WriteLine (Environment.StackTrace); + return new SimpleType ("unknown"); + } + + IEnumerable GetAttributes (List optAttributes) + { + if (optAttributes == null) + yield break; + foreach (var attr in optAttributes) { + Attribute result = new Attribute (); + result.Type = ConvertToType (attr.TypeNameExpression); + var loc = LocationsBag.GetLocations (attr); + result.HasArgumentList = loc != null; + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), AttributeSection.Roles.LPar); + + if (attr.PosArguments != null) { + foreach (var arg in attr.PosArguments) { + result.AddChild ((Expression)arg.Expr.Accept (this), Attribute.Roles.Argument); + } + } + if (attr.NamedArguments != null) { + foreach (NamedArgument na in attr.NamedArguments) { + var newArg = new AssignmentExpression (); + newArg.Operator = AssignmentOperatorType.Assign; + newArg.AddChild (new IdentifierExpression (na.Name, Convert (na.Location)), AssignmentExpression.LeftRole); + + var argLoc = LocationsBag.GetLocations (na); + if (argLoc != null) + newArg.AddChild (new CSharpTokenNode (Convert (argLoc[0]), 1), AssignmentExpression.Roles.Assign); + newArg.AddChild ((Expression)na.Expr.Accept (this), AssignmentExpression.RightRole); + result.AddChild (newArg, Attribute.Roles.Argument); + } + } + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), AttributeSection.Roles.RPar); + + yield return result; + } + } + + AttributeSection ConvertAttributeSection (List optAttributes) + { + if (optAttributes == null) + return null; + + AttributeSection result = new AttributeSection (); + var loc = LocationsBag.GetLocations (optAttributes); + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), AttributeSection.Roles.LBracket); + + result.AttributeTarget = optAttributes.First ().ExplicitTarget; + foreach (var attr in GetAttributes (optAttributes)) { + result.AddChild (attr, AttributeSection.AttributeRole); + } + + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), AttributeSection.Roles.RBracket); + return result; + } + + public override void Visit (UsingsBag.Namespace nspace) + { + NamespaceDeclaration nDecl = null; + if (nspace.Name != null) { + nDecl = new NamespaceDeclaration (); + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.NamespaceLocation), "namespace".Length), NamespaceDeclaration.Roles.Keyword); + ConvertNamespaceName (nspace.Name, nDecl); + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.OpenBrace), 1), NamespaceDeclaration.Roles.LBrace); + AddToNamespace (nDecl); + namespaceStack.Push (nDecl); + + } + VisitNamespaceUsings (nspace); + VisitNamespaceBody (nspace); + + if (nDecl != null) { + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.CloseBrace), 1), NamespaceDeclaration.Roles.RBrace); + if (!nspace.OptSemicolon.IsNull) + nDecl.AddChild (new CSharpTokenNode (Convert (nspace.OptSemicolon), 1), NamespaceDeclaration.Roles.Semicolon); + + namespaceStack.Pop (); + } + } + + void ConvertNamespaceName (MemberName memberName, NamespaceDeclaration namespaceDecl) + { + AstNode insertPos = null; + while (memberName != null) { + Identifier newIdent = Identifier.Create (memberName.Name, Convert (memberName.Location)); + namespaceDecl.InsertChildBefore (insertPos, newIdent, NamespaceDeclaration.Roles.Identifier); + insertPos = newIdent; + memberName = memberName.Left; + } + } + + public override void Visit (UsingsBag.Using u) + { + UsingDeclaration ud = new UsingDeclaration (); + ud.AddChild (new CSharpTokenNode (Convert (u.UsingLocation), "using".Length), UsingDeclaration.Roles.Keyword); + ud.AddChild (ConvertImport (u.NSpace), UsingDeclaration.ImportRole); + ud.AddChild (new CSharpTokenNode (Convert (u.SemicolonLocation), 1), UsingDeclaration.Roles.Semicolon); + AddToNamespace (ud); + } + + public override void Visit (UsingsBag.AliasUsing u) + { + UsingAliasDeclaration ud = new UsingAliasDeclaration (); + ud.AddChild (new CSharpTokenNode (Convert (u.UsingLocation), "using".Length), UsingAliasDeclaration.Roles.Keyword); + ud.AddChild (Identifier.Create (u.Identifier.Value, Convert (u.Identifier.Location)), UsingAliasDeclaration.AliasRole); + ud.AddChild (new CSharpTokenNode (Convert (u.AssignLocation), 1), UsingAliasDeclaration.Roles.Assign); + ud.AddChild (ConvertImport (u.Nspace), UsingAliasDeclaration.ImportRole); + ud.AddChild (new CSharpTokenNode (Convert (u.SemicolonLocation), 1), UsingAliasDeclaration.Roles.Semicolon); + AddToNamespace (ud); + } + + public override void Visit (UsingsBag.ExternAlias u) + { + var ud = new ExternAliasDeclaration (); + ud.AddChild (new CSharpTokenNode (Convert (u.ExternLocation), "extern".Length), ExternAliasDeclaration.Roles.Keyword); + ud.AddChild (new CSharpTokenNode (Convert (u.AliasLocation), "alias".Length), ExternAliasDeclaration.AliasRole); + ud.AddChild (Identifier.Create (u.Identifier.Value, Convert (u.Identifier.Location)), ExternAliasDeclaration.Roles.Identifier); + ud.AddChild (new CSharpTokenNode (Convert (u.SemicolonLocation), 1), UsingAliasDeclaration.Roles.Semicolon); + AddToNamespace (ud); + } + + AstType ConvertImport (MemberName memberName) + { + if (memberName.Left != null) { + // left.name + var t = new MemberType(); + t.IsDoubleColon = memberName.IsDoubleColon; + t.AddChild (ConvertImport (memberName.Left), MemberType.TargetRole); + t.AddChild (Identifier.Create (memberName.Name, Convert(memberName.Location)), MemberType.Roles.Identifier); + AddTypeArguments (t, (List)null, memberName.TypeArguments); + return t; + } else { + SimpleType t = new SimpleType(); + t.AddChild (Identifier.Create (memberName.Name, Convert(memberName.Location)), SimpleType.Roles.Identifier); + AddTypeArguments (t, (List)null, memberName.TypeArguments); + return t; + } + } + + public override void Visit (MemberCore member) + { + Console.WriteLine ("Unknown member:"); + Console.WriteLine (member.GetType () + "-> Member {0}", member.GetSignatureForError ()); + } + + Stack typeStack = new Stack (); + + public override void Visit (Class c) + { + TypeDeclaration newType = new TypeDeclaration (); + newType.ClassType = ClassType.Class; + AddAttributeSection (newType, c); + + var location = LocationsBag.GetMemberLocation (c); + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location[0]), "class".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (c.MemberName.Name, Convert (c.MemberName.Location)), AstNode.Roles.Identifier); + if (c.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (c.MemberName); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); + AddTypeParameters (newType, typeArgLocation, c.MemberName.TypeArguments); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); + AddConstraints (newType, c); + } + if (c.TypeBaseExpressions != null) { + foreach (var baseTypes in c.TypeBaseExpressions) { + newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + } + } + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (c); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (Struct s) + { + TypeDeclaration newType = new TypeDeclaration (); + newType.ClassType = ClassType.Struct; + AddAttributeSection (newType, s); + var location = LocationsBag.GetMemberLocation (s); + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location[0]), "struct".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (s.MemberName.Name, Convert (s.MemberName.Location)), AstNode.Roles.Identifier); + if (s.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (s.MemberName); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); + AddTypeParameters (newType, typeArgLocation, s.MemberName.TypeArguments); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); + AddConstraints (newType, s); + } + + if (s.TypeBaseExpressions != null) { + foreach (var baseTypes in s.TypeBaseExpressions) { + newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + } + } + + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (s); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (Interface i) + { + TypeDeclaration newType = new TypeDeclaration (); + newType.ClassType = ClassType.Interface; + AddAttributeSection (newType, i); + var location = LocationsBag.GetMemberLocation (i); + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location[0]), "interface".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (i.MemberName.Name, Convert (i.MemberName.Location)), AstNode.Roles.Identifier); + if (i.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (i.MemberName); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); + AddTypeParameters (newType, typeArgLocation, i.MemberName.TypeArguments); + if (typeArgLocation != null) + newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); + AddConstraints (newType, i); + } + if (i.TypeBaseExpressions != null) { + foreach (var baseTypes in i.TypeBaseExpressions) { + newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + } + } + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (i); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (Mono.CSharp.Delegate d) + { + DelegateDeclaration newDelegate = new DelegateDeclaration (); + var location = LocationsBag.GetMemberLocation (d); + AddAttributeSection (newDelegate, d); + AddModifiers (newDelegate, location); + if (location != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), TypeDeclaration.Roles.Keyword); + newDelegate.AddChild (ConvertToType (d.ReturnType), AstNode.Roles.Type); + newDelegate.AddChild (Identifier.Create (d.MemberName.Name, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); + if (d.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (d.MemberName); + if (typeArgLocation != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); + AddTypeParameters (newDelegate, typeArgLocation, d.MemberName.TypeArguments); + if (typeArgLocation != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); + AddConstraints (newDelegate, d); + } + if (location != null) + newDelegate.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DelegateDeclaration.Roles.LPar); + AddParameter (newDelegate, d.Parameters); + + if (location != null) { + newDelegate.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DelegateDeclaration.Roles.RPar); + newDelegate.AddChild (new CSharpTokenNode (Convert (location[3]), 1), DelegateDeclaration.Roles.Semicolon); + } + AddType (newDelegate); + } + + void AddType (AttributedNode child) + { + if (typeStack.Count > 0) { + typeStack.Peek ().AddChild (child, TypeDeclaration.MemberRole); + } else { + AddToNamespace (child); + } + } + + void AddToNamespace (AstNode child) + { + if (namespaceStack.Count > 0) { + namespaceStack.Peek ().AddChild (child, NamespaceDeclaration.MemberRole); + } else { + unit.AddChild (child, CompilationUnit.MemberRole); + } + } + + public override void Visit (Mono.CSharp.Enum e) + { + TypeDeclaration newType = new TypeDeclaration (); + AddAttributeSection (newType, e); + newType.ClassType = ClassType.Enum; + var location = LocationsBag.GetMemberLocation (e); + + AddModifiers (newType, location); + if (location != null) + newType.AddChild (new CSharpTokenNode (Convert (location [0]), "enum".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (e.MemberName.Name, Convert (e.MemberName.Location)), AstNode.Roles.Identifier); + + if (e.BaseTypeExpression != null) + newType.AddChild (ConvertToType (e.BaseTypeExpression), TypeDeclaration.BaseTypeRole); + + if (location != null && location.Count > 1) + newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + typeStack.Push (newType); + base.Visit (e); + if (location != null && location.Count > 2) { + newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Pop (); + AddType (newType); + } + + public override void Visit (EnumMember em) + { + 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 ((Expression)em.Initializer.Accept (this), EnumMemberDeclaration.InitializerRole); + } + + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + } + #endregion + + #region Type members + + + public override void Visit (FixedField f) + { + var location = LocationsBag.GetMemberLocation (f); + + var newField = new FixedFieldDeclaration (); + AddAttributeSection (newField, f); + AddModifiers (newField, location); + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location [0]), "fixed".Length), FixedFieldDeclaration.Roles.Keyword); + newField.AddChild (ConvertToType (f.TypeName), FixedFieldDeclaration.Roles.Type); + + var variable = new FixedVariableInitializer (); + variable.AddChild (Identifier.Create (f.MemberName.Name, Convert (f.MemberName.Location)), FixedFieldDeclaration.Roles.Identifier); + if (!f.Initializer.IsNull) { + var bracketLocations = LocationsBag.GetLocations (f.Initializer); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.LBracket); + + variable.AddChild ((Expression)f.Initializer.Accept (this), FieldDeclaration.Roles.Expression); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.RBracket); + } + newField.AddChild (variable, FixedFieldDeclaration.VariableRole); + + if (f.Declarators != null) { + foreach (var decl in f.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newField.AddChild (new CSharpTokenNode (Convert (declLoc [0]), 1), FieldDeclaration.Roles.Comma); + + variable = new FixedVariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), FieldDeclaration.Roles.Identifier); + if (!decl.Initializer.IsNull) { + var bracketLocations = LocationsBag.GetLocations (f.Initializer); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.LBracket); + variable.AddChild ((Expression)decl.Initializer.Accept (this), FieldDeclaration.Roles.Expression); + if (bracketLocations != null && bracketLocations.Count > 1) + variable.AddChild (new CSharpTokenNode (Convert (bracketLocations [0]), 1), FixedFieldDeclaration.Roles.RBracket); + } + newField.AddChild (variable, FixedFieldDeclaration.VariableRole); + } + } + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location[1]), 1), FieldDeclaration.Roles.Semicolon); + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + + } + + public override void Visit (Field f) + { + var location = LocationsBag.GetMemberLocation (f); + + FieldDeclaration newField = new FieldDeclaration (); + AddAttributeSection (newField, f); + AddModifiers (newField, location); + newField.AddChild (ConvertToType (f.TypeName), FieldDeclaration.Roles.Type); + + VariableInitializer variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (f.MemberName.Name, Convert (f.MemberName.Location)), FieldDeclaration.Roles.Identifier); + + if (f.Initializer != null) { + if (location != null) + variable.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)f.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + if (f.Declarators != null) { + foreach (var decl in f.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newField.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + + variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + } + } + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), FieldDeclaration.Roles.Semicolon); + + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + } + + public override void Visit (Const f) + { + var location = LocationsBag.GetMemberLocation (f); + + FieldDeclaration newField = new FieldDeclaration (); + AddAttributeSection (newField, f); + AddModifiers (newField, location); + if (location != null) + newField.AddChild (new CSharpModifierToken (Convert (location [0]), Modifiers.Const), AttributedNode.ModifierRole); + newField.AddChild (ConvertToType (f.TypeName), FieldDeclaration.Roles.Type); + + VariableInitializer variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (f.MemberName.Name, Convert (f.MemberName.Location)), VariableInitializer.Roles.Identifier); + + if (f.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (f.Initializer.Location), 1), VariableInitializer.Roles.Assign); + variable.AddChild ((Expression)f.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + if (f.Declarators != null) { + foreach (var decl in f.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newField.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + + variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), FieldDeclaration.Roles.Identifier); + if (decl.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newField.AddChild (variable, FieldDeclaration.Roles.Variable); + } + } + if (location != null) + newField.AddChild (new CSharpTokenNode (Convert (location[1]), 1), FieldDeclaration.Roles.Semicolon); + + typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole); + + + } + + public override void Visit (Operator o) + { + OperatorDeclaration newOperator = new OperatorDeclaration (); + newOperator.OperatorType = (OperatorType)o.OperatorType; + + var location = LocationsBag.GetMemberLocation (o); + AddAttributeSection (newOperator, o); + AddModifiers (newOperator, location); + + newOperator.AddChild (ConvertToType (o.TypeName), AstNode.Roles.Type); + + if (o.OperatorType == Operator.OpType.Implicit) { + if (location != null) { + newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "implicit".Length), OperatorDeclaration.OperatorTypeRole); + newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); + } + } else if (o.OperatorType == Operator.OpType.Explicit) { + if (location != null) { + newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "explicit".Length), OperatorDeclaration.OperatorTypeRole); + newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); + } + } else { + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); + + int opLength = OperatorDeclaration.GetToken(newOperator.OperatorType).Length; + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), opLength), OperatorDeclaration.OperatorTypeRole); + } + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[2]), 1), OperatorDeclaration.Roles.LPar); + AddParameter (newOperator, o.ParameterInfo); + if (location != null) + newOperator.AddChild (new CSharpTokenNode (Convert (location[3]), 1), OperatorDeclaration.Roles.RPar); + + if (o.Block != null) + newOperator.AddChild ((BlockStatement)o.Block.Accept (this), OperatorDeclaration.Roles.Body); + + typeStack.Peek ().AddChild (newOperator, TypeDeclaration.MemberRole); + } + + public void AddAttributeSection (AstNode parent, Attributable a) + { + if (a.OptAttributes == null) + return; + foreach (var attr in a.OptAttributes.Sections) { + parent.AddChild (ConvertAttributeSection (attr), AttributedNode.AttributeRole); + } + } + + public override void Visit (Indexer indexer) + { + IndexerDeclaration newIndexer = new IndexerDeclaration (); + AddAttributeSection (newIndexer, indexer); + var location = LocationsBag.GetMemberLocation (indexer); + AddModifiers (newIndexer, location); + + if (indexer.MemberName.Left != null) + newIndexer.AddChild (ConvertToType (indexer.MemberName.Left), IndexerDeclaration.PrivateImplementationTypeRole); + newIndexer.AddChild (ConvertToType (indexer.TypeName), IndexerDeclaration.Roles.Type); + + if (location != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IndexerDeclaration.Roles.LBracket); + AddParameter (newIndexer, indexer.ParameterInfo); + if (location != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IndexerDeclaration.Roles.RBracket); + + if (location != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (location[2]), 1), IndexerDeclaration.Roles.LBrace); + if (indexer.Get != null) { + Accessor getAccessor = new Accessor (); + var getLocation = LocationsBag.GetMemberLocation (indexer.Get); + AddAttributeSection (getAccessor, indexer.Get); + AddModifiers (getAccessor, getLocation); + if (getLocation != null) + getAccessor.AddChild (new CSharpTokenNode (Convert (indexer.Get.Location), "get".Length), PropertyDeclaration.Roles.Keyword); + if (indexer.Get.Block != null) { + getAccessor.AddChild ((BlockStatement)indexer.Get.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (getLocation != null && getLocation.Count > 0) + newIndexer.AddChild (new CSharpTokenNode (Convert (getLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newIndexer.AddChild (getAccessor, PropertyDeclaration.GetterRole); + } + + if (indexer.Set != null) { + Accessor setAccessor = new Accessor (); + var setLocation = LocationsBag.GetMemberLocation (indexer.Set); + AddAttributeSection (setAccessor, indexer.Set); + AddModifiers (setAccessor, setLocation); + if (setLocation != null) + setAccessor.AddChild (new CSharpTokenNode (Convert (indexer.Set.Location), "set".Length), PropertyDeclaration.Roles.Keyword); + + if (indexer.Set.Block != null) { + setAccessor.AddChild ((BlockStatement)indexer.Set.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (setLocation != null && setLocation.Count > 0) + newIndexer.AddChild (new CSharpTokenNode (Convert (setLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newIndexer.AddChild (setAccessor, PropertyDeclaration.SetterRole); + } + + if (location != null) { + newIndexer.AddChild (new CSharpTokenNode (Convert (location[3]), 1), IndexerDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newIndexer.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Peek ().AddChild (newIndexer, TypeDeclaration.MemberRole); + } + + public override void Visit (Method m) + { + MethodDeclaration newMethod = new MethodDeclaration (); + 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); + + newMethod.AddChild (Identifier.Create (m.MethodName.Name, Convert (m.Location)), AstNode.Roles.Identifier); + + if (m.MemberName.TypeArguments != null) { + var typeArgLocation = LocationsBag.GetLocations (m.MemberName); + if (typeArgLocation != null) + newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); + AddTypeParameters (newMethod, typeArgLocation, m.MemberName.TypeArguments); + if (typeArgLocation != null) + newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); + AddConstraints (newMethod, m.GenericMethod); + } + + if (location != null) + newMethod.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LPar); + AddParameter (newMethod, m.ParameterInfo); + + if (location != null) + newMethod.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RPar); + if (m.Block != null) { + var bodyBlock = (BlockStatement)m.Block.Accept (this); +// if (m.Block is ToplevelBlock) { +// newMethod.AddChild (bodyBlock.FirstChild.NextSibling, MethodDeclaration.Roles.Body); +// } else { + newMethod.AddChild (bodyBlock, MethodDeclaration.Roles.Body); +// } + } else if (location != null && location.Count < 3) { + // parser error, set end node to max value. + newMethod.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + typeStack.Peek ().AddChild (newMethod, TypeDeclaration.MemberRole); + } + + static Dictionary modifierTable = new Dictionary (); + static string[] keywordTable; + + static ConversionVisitor () + { + modifierTable [Mono.CSharp.Modifiers.NEW] = ICSharpCode.NRefactory.CSharp.Modifiers.New; + modifierTable [Mono.CSharp.Modifiers.PUBLIC] = ICSharpCode.NRefactory.CSharp.Modifiers.Public; + modifierTable [Mono.CSharp.Modifiers.PROTECTED] = ICSharpCode.NRefactory.CSharp.Modifiers.Protected; + modifierTable [Mono.CSharp.Modifiers.PRIVATE] = ICSharpCode.NRefactory.CSharp.Modifiers.Private; + modifierTable [Mono.CSharp.Modifiers.INTERNAL] = ICSharpCode.NRefactory.CSharp.Modifiers.Internal; + modifierTable [Mono.CSharp.Modifiers.ABSTRACT] = ICSharpCode.NRefactory.CSharp.Modifiers.Abstract; + modifierTable [Mono.CSharp.Modifiers.VIRTUAL] = ICSharpCode.NRefactory.CSharp.Modifiers.Virtual; + modifierTable [Mono.CSharp.Modifiers.SEALED] = ICSharpCode.NRefactory.CSharp.Modifiers.Sealed; + modifierTable [Mono.CSharp.Modifiers.STATIC] = ICSharpCode.NRefactory.CSharp.Modifiers.Static; + modifierTable [Mono.CSharp.Modifiers.OVERRIDE] = ICSharpCode.NRefactory.CSharp.Modifiers.Override; + modifierTable [Mono.CSharp.Modifiers.READONLY] = ICSharpCode.NRefactory.CSharp.Modifiers.Readonly; + modifierTable [Mono.CSharp.Modifiers.PARTIAL] = ICSharpCode.NRefactory.CSharp.Modifiers.Partial; + 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; + + keywordTable = new string[255]; + for (int i = 0; i< keywordTable.Length; i++) + keywordTable [i] = "unknown"; + + keywordTable [(int)BuiltinTypeSpec.Type.Other] = "void"; + keywordTable [(int)BuiltinTypeSpec.Type.String] = "string"; + keywordTable [(int)BuiltinTypeSpec.Type.Int] = "int"; + keywordTable [(int)BuiltinTypeSpec.Type.Object] = "object"; + keywordTable [(int)BuiltinTypeSpec.Type.Float] = "float"; + keywordTable [(int)BuiltinTypeSpec.Type.Double] = "double"; + keywordTable [(int)BuiltinTypeSpec.Type.Long] = "long"; + keywordTable [(int)BuiltinTypeSpec.Type.Byte] = "byte"; + keywordTable [(int)BuiltinTypeSpec.Type.UInt] = "uint"; + keywordTable [(int)BuiltinTypeSpec.Type.ULong] = "ulong"; + keywordTable [(int)BuiltinTypeSpec.Type.Short] = "short"; + keywordTable [(int)BuiltinTypeSpec.Type.UShort] = "ushort"; + keywordTable [(int)BuiltinTypeSpec.Type.SByte] = "sbyte"; + keywordTable [(int)BuiltinTypeSpec.Type.Decimal] = "decimal"; + keywordTable [(int)BuiltinTypeSpec.Type.Char] = "char"; + } + + void AddModifiers (AttributedNode parent, LocationsBag.MemberLocations location) + { + 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); + } + } + + public override void Visit (Property p) + { + PropertyDeclaration newProperty = new PropertyDeclaration (); + AddAttributeSection (newProperty, p); + var location = LocationsBag.GetMemberLocation (p); + AddModifiers (newProperty, location); + newProperty.AddChild (ConvertToType (p.TypeName), AstNode.Roles.Type); + if (p.MemberName.Left != null) + newProperty.AddChild (ConvertToType (p.MemberName.Left), PropertyDeclaration.PrivateImplementationTypeRole); + + newProperty.AddChild (Identifier.Create (p.MemberName.Name, Convert (p.Location)), PropertyDeclaration.Roles.Identifier); + + if (location != null) + newProperty.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LBrace); + + if (p.Get != null) { + Accessor getAccessor = new Accessor (); + AddAttributeSection (getAccessor, p.Get); + var getLocation = LocationsBag.GetMemberLocation (p.Get); + AddModifiers (getAccessor, getLocation); + getAccessor.AddChild (new CSharpTokenNode (Convert (p.Get.Location), "get".Length), PropertyDeclaration.Roles.Keyword); + + if (p.Get.Block != null) { + getAccessor.AddChild ((BlockStatement)p.Get.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (getLocation != null && getLocation.Count > 0) + newProperty.AddChild (new CSharpTokenNode (Convert (getLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newProperty.AddChild (getAccessor, PropertyDeclaration.GetterRole); + } + + if (p.Set != null) { + Accessor setAccessor = new Accessor (); + AddAttributeSection (setAccessor, p.Set); + var setLocation = LocationsBag.GetMemberLocation (p.Set); + AddModifiers (setAccessor, setLocation); + setAccessor.AddChild (new CSharpTokenNode (Convert (p.Set.Location), "set".Length), PropertyDeclaration.Roles.Keyword); + + if (p.Set.Block != null) { + setAccessor.AddChild ((BlockStatement)p.Set.Block.Accept (this), MethodDeclaration.Roles.Body); + } else { + if (setLocation != null && setLocation.Count > 0) + newProperty.AddChild (new CSharpTokenNode (Convert (setLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); + } + if (location != null && location.Count > 1) { + newProperty.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newProperty.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + + typeStack.Peek ().AddChild (newProperty, TypeDeclaration.MemberRole); + } + + public override void Visit (Constructor c) + { + ConstructorDeclaration newConstructor = new ConstructorDeclaration (); + AddAttributeSection (newConstructor, c); + var location = LocationsBag.GetMemberLocation (c); + AddModifiers (newConstructor, location); + newConstructor.AddChild (Identifier.Create (c.MemberName.Name, Convert (c.MemberName.Location)), AstNode.Roles.Identifier); + if (location != null) + newConstructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LPar); + + AddParameter (newConstructor, c.ParameterInfo); + if (location != null) + newConstructor.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RPar); + + if (c.Initializer != null) { + var initializer = new ConstructorInitializer (); + initializer.ConstructorInitializerType = c.Initializer is ConstructorBaseInitializer ? ConstructorInitializerType.Base : ConstructorInitializerType.This; + var initializerLocation = LocationsBag.GetLocations (c.Initializer); + + if (initializerLocation != null) + newConstructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.Colon); + if (initializerLocation != null) + initializer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.LPar); + AddArguments (initializer, LocationsBag.GetLocations (c.Initializer.Arguments), c.Initializer.Arguments); + if (initializerLocation != null) + initializer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.RPar); + newConstructor.AddChild (initializer, ConstructorDeclaration.InitializerRole); + } + + if (c.Block != null) + newConstructor.AddChild ((BlockStatement)c.Block.Accept (this), ConstructorDeclaration.Roles.Body); + + typeStack.Peek ().AddChild (newConstructor, TypeDeclaration.MemberRole); + } + + public override void Visit (Destructor d) + { + DestructorDeclaration newDestructor = new DestructorDeclaration (); + AddAttributeSection (newDestructor, d); + var location = LocationsBag.GetMemberLocation (d); + AddModifiers (newDestructor, location); + if (location != null) + newDestructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), DestructorDeclaration.TildeRole); + newDestructor.AddChild (Identifier.Create (d.MemberName.Name, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); + + if (location != null) { + newDestructor.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DestructorDeclaration.Roles.LPar); + newDestructor.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DestructorDeclaration.Roles.RPar); + } + + if (d.Block != null) + newDestructor.AddChild ((BlockStatement)d.Block.Accept (this), DestructorDeclaration.Roles.Body); + + typeStack.Peek ().AddChild (newDestructor, TypeDeclaration.MemberRole); + } + + public override void Visit (EventField e) + { + EventDeclaration newEvent = new EventDeclaration (); + AddAttributeSection (newEvent, e); + var location = LocationsBag.GetMemberLocation (e); + AddModifiers (newEvent, location); + + if (location != null) + newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), EventDeclaration.Roles.Keyword); + newEvent.AddChild (ConvertToType (e.TypeName), AstNode.Roles.Type); + + VariableInitializer variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (e.MemberName.Name, Convert (e.MemberName.Location)), FieldDeclaration.Roles.Identifier); + + if (e.Initializer != null) { + if (location != null) + variable.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)e.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newEvent.AddChild (variable, FieldDeclaration.Roles.Variable); + if (e.Declarators != null) { + foreach (var decl in e.Declarators) { + var declLoc = LocationsBag.GetLocations (decl); + if (declLoc != null) + newEvent.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + + variable = new VariableInitializer (); + variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier); + + if (decl.Initializer != null) { + variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + newEvent.AddChild (variable, FieldDeclaration.Roles.Variable); + } + } + + if (location != null) + newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), EventDeclaration.Roles.Semicolon); + + typeStack.Peek ().AddChild (newEvent, TypeDeclaration.MemberRole); + } + + public override void Visit (EventProperty ep) + { + CustomEventDeclaration newEvent = new CustomEventDeclaration (); + AddAttributeSection (newEvent, ep); + var location = LocationsBag.GetMemberLocation (ep); + AddModifiers (newEvent, location); + + if (location != null) + newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), CustomEventDeclaration.Roles.Keyword); + newEvent.AddChild (ConvertToType (ep.TypeName), CustomEventDeclaration.Roles.Type); + if (ep.MemberName.Left != null) + newEvent.AddChild (ConvertToType (ep.MemberName.Left), CustomEventDeclaration.PrivateImplementationTypeRole); + + newEvent.AddChild (Identifier.Create (ep.MemberName.Name, Convert (ep.Location)), CustomEventDeclaration.Roles.Identifier); + + if (location != null && location.Count >= 2) + newEvent.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CustomEventDeclaration.Roles.LBrace); + + if (ep.Add != null) { + Accessor addAccessor = new Accessor (); + AddAttributeSection (addAccessor, ep.Add); + var addLocation = LocationsBag.GetMemberLocation (ep.Add); + AddModifiers (addAccessor, addLocation); + addAccessor.AddChild (new CSharpTokenNode (Convert (ep.Add.Location), "add".Length), CustomEventDeclaration.Roles.Keyword); + if (ep.Add.Block != null) + addAccessor.AddChild ((BlockStatement)ep.Add.Block.Accept (this), CustomEventDeclaration.Roles.Body); + newEvent.AddChild (addAccessor, CustomEventDeclaration.AddAccessorRole); + } + + if (ep.Remove != null) { + Accessor removeAccessor = new Accessor (); + AddAttributeSection (removeAccessor, ep.Remove); + var removeLocation = LocationsBag.GetMemberLocation (ep.Remove); + AddModifiers (removeAccessor, removeLocation); + removeAccessor.AddChild (new CSharpTokenNode (Convert (ep.Remove.Location), "remove".Length), CustomEventDeclaration.Roles.Keyword); + + if (ep.Remove.Block != null) + removeAccessor.AddChild ((BlockStatement)ep.Remove.Block.Accept (this), CustomEventDeclaration.Roles.Body); + newEvent.AddChild (removeAccessor, CustomEventDeclaration.RemoveAccessorRole); + } + if (location != null && location.Count >= 3) { + newEvent.AddChild (new CSharpTokenNode (Convert (location[2]), 1), CustomEventDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newEvent.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + + typeStack.Peek ().AddChild (newEvent, TypeDeclaration.MemberRole); + } + + #endregion + + #region Statements + public override object Visit (Mono.CSharp.Statement stmt) + { + Console.WriteLine ("unknown statement:" + stmt); + return null; + } + + public override object Visit (BlockVariableDeclaration blockVariableDeclaration) + { + var result = new VariableDeclarationStatement (); + result.AddChild (ConvertToType (blockVariableDeclaration.TypeExpression), VariableDeclarationStatement.Roles.Type); + + var varInit = new VariableInitializer (); + var location = LocationsBag.GetLocations (blockVariableDeclaration); + varInit.AddChild (Identifier.Create (blockVariableDeclaration.Variable.Name, Convert (blockVariableDeclaration.Variable.Location)), VariableInitializer.Roles.Identifier); + if (blockVariableDeclaration.Initializer != null) { + if (location != null) + varInit.AddChild (new CSharpTokenNode (Convert (location[0]), 1), VariableInitializer.Roles.Assign); + varInit.AddChild ((Expression)blockVariableDeclaration.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + + result.AddChild (varInit, VariableDeclarationStatement.Roles.Variable); + + if (blockVariableDeclaration.Declarators != null) { + foreach (var decl in blockVariableDeclaration.Declarators) { + var loc = LocationsBag.GetLocations (decl); + var init = new VariableInitializer (); + if (loc != null && loc.Count > 0) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), VariableInitializer.Roles.Comma); + init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + if (loc != null && loc.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), VariableInitializer.Roles.Assign); + init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } else { + } + result.AddChild (init, VariableDeclarationStatement.Roles.Variable); + } + } + if (location != null && (blockVariableDeclaration.Initializer == null || location.Count > 1)) + result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), VariableDeclarationStatement.Roles.Semicolon); + return result; + } + + public override object Visit (BlockConstantDeclaration blockVariableDeclaration) + { + var result = new VariableDeclarationStatement (); + + var location = LocationsBag.GetLocations (blockVariableDeclaration); + if (location != null) + result.AddChild (new CSharpModifierToken (Convert (location [0]), ICSharpCode.NRefactory.CSharp.Modifiers.Const), VariableDeclarationStatement.ModifierRole); + + result.AddChild (ConvertToType (blockVariableDeclaration.TypeExpression), VariableDeclarationStatement.Roles.Type); + + var varInit = new VariableInitializer (); + varInit.AddChild (Identifier.Create (blockVariableDeclaration.Variable.Name, Convert (blockVariableDeclaration.Variable.Location)), VariableInitializer.Roles.Identifier); + if (blockVariableDeclaration.Initializer != null) { + if (location != null) + varInit.AddChild (new CSharpTokenNode (Convert (location[1]), 1), VariableInitializer.Roles.Assign); + varInit.AddChild ((Expression)blockVariableDeclaration.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + + result.AddChild (varInit, VariableDeclarationStatement.Roles.Variable); + + if (blockVariableDeclaration.Declarators != null) { + foreach (var decl in blockVariableDeclaration.Declarators) { + var loc = LocationsBag.GetLocations (decl); + var init = new VariableInitializer (); + init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + if (loc != null) + init.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), VariableInitializer.Roles.Assign); + init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + if (loc != null && loc.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (loc[1]), 1), VariableInitializer.Roles.Comma); + } else { + if (loc != null && loc.Count > 0) + result.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), VariableInitializer.Roles.Comma); + } + result.AddChild (init, VariableDeclarationStatement.Roles.Variable); + } + } + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), VariableDeclarationStatement.Roles.Semicolon); + } else { + // parser error, set end node to max value. + result.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + return result; + } + + public override object Visit (Mono.CSharp.EmptyStatement emptyStatement) + { + var result = new EmptyStatement (); + result.Location = Convert (emptyStatement.loc); + return result; + } + + public override object Visit (EmptyExpressionStatement emptyExpressionStatement) + { + return new EmptyExpression (Convert (emptyExpressionStatement.Location)); + } + + public override object Visit (If ifStatement) + { + var result = new IfElseStatement (); + + var location = LocationsBag.GetLocations (ifStatement); + + result.AddChild (new CSharpTokenNode (Convert (ifStatement.loc), "if".Length), IfElseStatement.IfKeywordRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IfElseStatement.Roles.LPar); + result.AddChild ((Expression)ifStatement.Expr.Accept (this), IfElseStatement.Roles.Condition); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IfElseStatement.Roles.RPar); + + if (ifStatement.TrueStatement != null) + result.AddChild ((Statement)ifStatement.TrueStatement.Accept (this), IfElseStatement.TrueRole); + + if (ifStatement.FalseStatement != null) { + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), "else".Length), IfElseStatement.ElseKeywordRole); + result.AddChild ((Statement)ifStatement.FalseStatement.Accept (this), IfElseStatement.FalseRole); + } + + return result; + } + + public override object Visit (Do doStatement) + { + var result = new DoWhileStatement (); + var location = LocationsBag.GetLocations (doStatement); + result.AddChild (new CSharpTokenNode (Convert (doStatement.loc), "do".Length), DoWhileStatement.DoKeywordRole); + result.AddChild ((Statement)doStatement.EmbeddedStatement.Accept (this), WhileStatement.Roles.EmbeddedStatement); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "while".Length), DoWhileStatement.WhileKeywordRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DoWhileStatement.Roles.LPar); + result.AddChild ((Expression)doStatement.expr.Accept (this), DoWhileStatement.Roles.Condition); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DoWhileStatement.Roles.RPar); + result.AddChild (new CSharpTokenNode (Convert (location[3]), 1), DoWhileStatement.Roles.Semicolon); + } + + return result; + } + + public override object Visit (While whileStatement) + { + var result = new WhileStatement (); + var location = LocationsBag.GetLocations (whileStatement); + result.AddChild (new CSharpTokenNode (Convert (whileStatement.loc), "while".Length), WhileStatement.WhileKeywordRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), WhileStatement.Roles.LPar); + if (whileStatement.expr != null) + result.AddChild ((Expression)whileStatement.expr.Accept (this), WhileStatement.Roles.Condition); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), WhileStatement.Roles.RPar); + if (whileStatement.Statement != null) + result.AddChild ((Statement)whileStatement.Statement.Accept (this), WhileStatement.Roles.EmbeddedStatement); + return result; + } + + void AddStatementOrList (ForStatement forStatement, Mono.CSharp.Statement init, Role role) + { + if (init == null) + return; + if (init is StatementList) { + foreach (var stmt in ((StatementList)init).Statements) { + forStatement.AddChild ((Statement)stmt.Accept (this), role); + } + } else if (init is Mono.CSharp.EmptyStatement) { + + } else { + forStatement.AddChild ((Statement)init.Accept (this), role); + } + } + + public override object Visit (For forStatement) + { + var result = new ForStatement (); + + var location = LocationsBag.GetLocations (forStatement); + + result.AddChild (new CSharpTokenNode (Convert (forStatement.loc), "for".Length), ForStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), ForStatement.Roles.LPar); + + AddStatementOrList (result, forStatement.InitStatement, 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) + result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForStatement.Roles.Semicolon); + + AddStatementOrList (result, forStatement.Increment, ForStatement.IteratorRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [3]), 1), ForStatement.Roles.RPar); + + if (forStatement.Statement != null) + result.AddChild ((Statement)forStatement.Statement.Accept (this), ForStatement.Roles.EmbeddedStatement); + + return result; + } + + public override object Visit (StatementExpression statementExpression) + { + var result = new ExpressionStatement (); + object expr = statementExpression.Expr.Accept (this); + 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 (Return returnStatement) + { + var result = new ReturnStatement (); + + result.AddChild (new CSharpTokenNode (Convert (returnStatement.loc), "return".Length), ReturnStatement.Roles.Keyword); + if (returnStatement.Expr != null) + result.AddChild ((Expression)returnStatement.Expr.Accept (this), ReturnStatement.Roles.Expression); + + var location = LocationsBag.GetLocations (returnStatement); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ReturnStatement.Roles.Semicolon); + + return result; + } + + public override object Visit (Goto gotoStatement) + { + var result = new GotoStatement (); + var location = LocationsBag.GetLocations (gotoStatement); + result.AddChild (new CSharpTokenNode (Convert (gotoStatement.loc), "goto".Length), GotoStatement.Roles.Keyword); + result.AddChild (Identifier.Create (gotoStatement.Target, Convert (gotoStatement.loc)), GotoStatement.Roles.Identifier); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), GotoStatement.Roles.Semicolon); + + return result; + } + + public override object Visit (LabeledStatement labeledStatement) + { + var result = new LabelStatement (); + result.AddChild (Identifier.Create (labeledStatement.Name, Convert (labeledStatement.loc)), LabelStatement.Roles.Identifier); + return result; + } + + public override object Visit (GotoDefault gotoDefault) + { + var result = new GotoDefaultStatement (); + result.AddChild (new CSharpTokenNode (Convert (gotoDefault.loc), "goto".Length), GotoDefaultStatement.Roles.Keyword); + var location = LocationsBag.GetLocations (gotoDefault); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[0]), "default".Length), GotoDefaultStatement.DefaultKeywordRole); + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), GotoDefaultStatement.Roles.Semicolon); + } + + return result; + } + + public override object Visit (GotoCase gotoCase) + { + var result = new GotoCaseStatement (); + result.AddChild (new CSharpTokenNode (Convert (gotoCase.loc), "goto".Length), GotoCaseStatement.Roles.Keyword); + + var location = LocationsBag.GetLocations (gotoCase); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "case".Length), GotoCaseStatement.CaseKeywordRole); + result.AddChild ((Expression)gotoCase.Expr.Accept (this), GotoCaseStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), GotoCaseStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Throw throwStatement) + { + var result = new ThrowStatement (); + var location = LocationsBag.GetLocations (throwStatement); + + result.AddChild (new CSharpTokenNode (Convert (throwStatement.loc), "throw".Length), ThrowStatement.Roles.Keyword); + if (throwStatement.Expr != null) + result.AddChild ((Expression)throwStatement.Expr.Accept (this), ThrowStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ThrowStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Break breakStatement) + { + var result = new BreakStatement (); + var location = LocationsBag.GetLocations (breakStatement); + + result.AddChild (new CSharpTokenNode (Convert (breakStatement.loc), "break".Length), BreakStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), BreakStatement.Roles.Semicolon); + return result; + } + + public override object Visit (Continue continueStatement) + { + var result = new ContinueStatement (); + var location = LocationsBag.GetLocations (continueStatement); + result.AddChild (new CSharpTokenNode (Convert (continueStatement.loc), "continue".Length), ContinueStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ContinueStatement.Roles.Semicolon); + return result; + } + + public static bool IsLower (Location left, Location right) + { + return left.Row < right.Row || left.Row == right.Row && left.Column < right.Column; + } + + public UsingStatement CreateUsingStatement (Block blockStatement) + { + var usingResult = new UsingStatement (); + Mono.CSharp.Statement cur = blockStatement.Statements[0]; + if (cur is Using) { + Using u = (Using)cur; + usingResult.AddChild (new CSharpTokenNode (Convert (u.loc), "using".Length), UsingStatement.Roles.Keyword); + usingResult.AddChild (new CSharpTokenNode (Convert (blockStatement.StartLocation), 1), UsingStatement.Roles.LPar); + if (u.Variables != null) { + var initializer = new VariableInitializer () { + NameToken = Identifier.Create (u.Variables.Variable.Name, Convert (u.Variables.Variable.Location)), + }; + + var loc = LocationsBag.GetLocations (u.Variables); + if (loc != null) + initializer.AddChild (new CSharpTokenNode (Convert (loc[1]), 1), VariableInitializer.Roles.Assign); + if (u.Variables.Initializer != null) + initializer.Initializer = u.Variables.Initializer.Accept (this) as Expression; + + var varDec = new VariableDeclarationStatement () { + Type = ConvertToType (u.Variables.TypeExpression), + Variables = { initializer } + }; + usingResult.AddChild (varDec, UsingStatement.ResourceAcquisitionRole); + } + cur = u.Statement; + usingResult.AddChild (new CSharpTokenNode (Convert (blockStatement.EndLocation), 1), UsingStatement.Roles.RPar); + usingResult.AddChild ((Statement)cur.Accept (this), UsingStatement.Roles.EmbeddedStatement); + } + return usingResult; + } + + void AddBlockChildren (BlockStatement result, Block blockStatement, ref int curLocal) + { + if (convertTypeSystemMode) { + return; + } + foreach (Mono.CSharp.Statement stmt in blockStatement.Statements) { + if (stmt == null) + continue; + /* if (curLocal < localVariables.Count && IsLower (localVariables[curLocal].Location, stmt.loc)) { + result.AddChild (CreateVariableDeclaration (localVariables[curLocal]), AstNode.Roles.Statement); + curLocal++; + }*/ + if (stmt is Block && !(stmt is ToplevelBlock || stmt is ExplicitBlock)) { + AddBlockChildren (result, (Block)stmt, ref curLocal); + } else { + result.AddChild ((Statement)stmt.Accept (this), BlockStatement.StatementRole); + } + } + } + + public override object Visit (Block blockStatement) + { + if (blockStatement.IsCompilerGenerated && blockStatement.Statements.Any ()) { + if (blockStatement.Statements.First () is Using) + return CreateUsingStatement (blockStatement); + return blockStatement.Statements.Last ().Accept (this); + } + var result = new BlockStatement (); + result.AddChild (new CSharpTokenNode (Convert (blockStatement.StartLocation), 1), AstNode.Roles.LBrace); + int curLocal = 0; + AddBlockChildren (result, blockStatement, ref curLocal); + + result.AddChild (new CSharpTokenNode (Convert (blockStatement.EndLocation), 1), AstNode.Roles.RBrace); + return result; + } + + public override object Visit (Switch switchStatement) + { + var result = new SwitchStatement (); + + var location = LocationsBag.GetLocations (switchStatement); + result.AddChild (new CSharpTokenNode (Convert (switchStatement.loc), "switch".Length), SwitchStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), SwitchStatement.Roles.LPar); + if (switchStatement.Expr != null) + result.AddChild ((Expression)switchStatement.Expr.Accept (this), SwitchStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), SwitchStatement.Roles.RPar); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), SwitchStatement.Roles.LBrace); + foreach (var section in switchStatement.Sections) { + var newSection = new SwitchSection (); + foreach (var caseLabel in section.Labels) { + var newLabel = new CaseLabel (); + newLabel.AddChild (new CSharpTokenNode (Convert (caseLabel.Location), "case".Length), SwitchStatement.Roles.Keyword); + if (caseLabel.Label != null) + newLabel.AddChild ((Expression)caseLabel.Label.Accept (this), SwitchStatement.Roles.Expression); + + newSection.AddChild (newLabel, SwitchSection.CaseLabelRole); + } + + var blockStatement = section.Block; + var bodyBlock = new BlockStatement (); + int curLocal = 0; + AddBlockChildren (bodyBlock, blockStatement, ref curLocal); + foreach (var statement in bodyBlock.Statements) { + statement.Remove (); + newSection.AddChild (statement, SwitchSection.Roles.EmbeddedStatement); + + } + result.AddChild (newSection, SwitchStatement.SwitchSectionRole); + } + + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[3]), 1), SwitchStatement.Roles.RBrace); + } else { + // parser error, set end node to max value. + result.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + + return result; + } + + public override object Visit (Lock lockStatement) + { + var result = new LockStatement (); + var location = LocationsBag.GetLocations (lockStatement); + result.AddChild (new CSharpTokenNode (Convert (lockStatement.loc), "lock".Length), LockStatement.Roles.Keyword); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), LockStatement.Roles.LPar); + result.AddChild ((Expression)lockStatement.Expr.Accept (this), LockStatement.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), LockStatement.Roles.RPar); + result.AddChild ((Statement)lockStatement.Statement.Accept (this), LockStatement.Roles.EmbeddedStatement); + + return result; + } + + public override object Visit (Unchecked uncheckedStatement) + { + var result = new UncheckedStatement (); + result.AddChild (new CSharpTokenNode (Convert (uncheckedStatement.loc), "unchecked".Length), UncheckedStatement.Roles.Keyword); + result.AddChild ((BlockStatement)uncheckedStatement.Block.Accept (this), UncheckedStatement.Roles.Body); + return result; + } + + + public override object Visit (Checked checkedStatement) + { + var result = new CheckedStatement (); + result.AddChild (new CSharpTokenNode (Convert (checkedStatement.loc), "checked".Length), CheckedStatement.Roles.Keyword); + result.AddChild ((BlockStatement)checkedStatement.Block.Accept (this), CheckedStatement.Roles.Body); + return result; + } + + public override object Visit (Unsafe unsafeStatement) + { + var result = new UnsafeStatement (); + result.AddChild (new CSharpTokenNode (Convert (unsafeStatement.loc), "unsafe".Length), UnsafeStatement.Roles.Keyword); + result.AddChild ((BlockStatement)unsafeStatement.Block.Accept (this), UnsafeStatement.Roles.Body); + return result; + } + + public override object Visit (Fixed fixedStatement) + { + var result = new FixedStatement (); + var location = LocationsBag.GetLocations (fixedStatement); + + result.AddChild (new CSharpTokenNode (Convert (fixedStatement.loc), "fixed".Length), FixedStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), FixedStatement.Roles.LPar); + + if (fixedStatement.Variables != null) { + var blockVariableDeclaration = fixedStatement.Variables; + result.AddChild (ConvertToType (blockVariableDeclaration.TypeExpression), FixedStatement.Roles.Type); + var varInit = new VariableInitializer (); + var initLocation = LocationsBag.GetLocations (blockVariableDeclaration); + varInit.AddChild (Identifier.Create (blockVariableDeclaration.Variable.Name, Convert (blockVariableDeclaration.Variable.Location)), VariableInitializer.Roles.Identifier); + if (blockVariableDeclaration.Initializer != null) { + if (initLocation != null) + varInit.AddChild (new CSharpTokenNode (Convert (location[0]), 1), VariableInitializer.Roles.Assign); + varInit.AddChild ((Expression)blockVariableDeclaration.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } + + result.AddChild (varInit, FixedStatement.Roles.Variable); + + if (blockVariableDeclaration.Declarators != null) { + foreach (var decl in blockVariableDeclaration.Declarators) { + var loc = LocationsBag.GetLocations (decl); + var init = new VariableInitializer (); + if (loc != null && loc.Count > 0) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), VariableInitializer.Roles.Comma); + init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); + if (decl.Initializer != null) { + if (loc != null && loc.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), VariableInitializer.Roles.Assign); + init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); + } else { + } + result.AddChild (init, FixedStatement.Roles.Variable); + } + } + } + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), FixedStatement.Roles.RPar); + result.AddChild ((Statement)fixedStatement.Statement.Accept (this), FixedStatement.Roles.EmbeddedStatement); + return result; + } + + public override object Visit (TryFinally tryFinallyStatement) + { + TryCatchStatement result; + var location = LocationsBag.GetLocations (tryFinallyStatement); + + if (tryFinallyStatement.Stmt is TryCatch) { + result = (TryCatchStatement)tryFinallyStatement.Stmt.Accept (this); + } else { + result = new TryCatchStatement (); + result.AddChild (new CSharpTokenNode (Convert (tryFinallyStatement.loc), "try".Length), TryCatchStatement.TryKeywordRole); + if (tryFinallyStatement.Stmt != null) + result.AddChild ((BlockStatement)tryFinallyStatement.Stmt.Accept (this), TryCatchStatement.TryBlockRole); + } + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "finally".Length), TryCatchStatement.FinallyKeywordRole); + result.AddChild ((BlockStatement)tryFinallyStatement.Fini.Accept (this), TryCatchStatement.FinallyBlockRole); + + return result; + } + + CatchClause ConvertCatch (Catch ctch) + { + CatchClause result = new CatchClause (); + var location = LocationsBag.GetLocations (ctch); + result.AddChild (new CSharpTokenNode (Convert (ctch.loc), "catch".Length), CatchClause.Roles.Keyword); + if (ctch.TypeExpression != null) { + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), CatchClause.Roles.LPar); + + result.AddChild (ConvertToType (ctch.TypeExpression), CatchClause.Roles.Type); + if (ctch.Variable != null && !string.IsNullOrEmpty (ctch.Variable.Name)) + result.AddChild (Identifier.Create (ctch.Variable.Name, Convert (ctch.Variable.Location)), CatchClause.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CatchClause.Roles.RPar); + } + + if (ctch.Block != null) + result.AddChild ((BlockStatement)ctch.Block.Accept (this), CatchClause.Roles.Body); + + return result; + } + + public override object Visit (TryCatch tryCatchStatement) + { + var result = new TryCatchStatement (); + result.AddChild (new CSharpTokenNode (Convert (tryCatchStatement.loc), "try".Length), TryCatchStatement.TryKeywordRole); + if (tryCatchStatement.Block != null) + result.AddChild ((BlockStatement)tryCatchStatement.Block.Accept (this), TryCatchStatement.TryBlockRole); + foreach (Catch ctch in tryCatchStatement.Specific) { + result.AddChild (ConvertCatch (ctch), TryCatchStatement.CatchClauseRole); + } + if (tryCatchStatement.General != null) + result.AddChild (ConvertCatch (tryCatchStatement.General), TryCatchStatement.CatchClauseRole); + + return result; + } + + public override object Visit (Using usingStatement) + { + var result = new UsingStatement (); + var location = LocationsBag.GetLocations (usingStatement); + + result.AddChild (new CSharpTokenNode (Convert (usingStatement.loc), "using".Length), UsingStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), UsingStatement.Roles.LPar); + if (usingStatement.Expression != null) + result.AddChild ((AstNode)usingStatement.Expression.Accept (this), UsingStatement.ResourceAcquisitionRole); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), UsingStatement.Roles.RPar); + + if (usingStatement.Statement != null) + result.AddChild ((Statement)usingStatement.Statement.Accept (this), UsingStatement.Roles.EmbeddedStatement); + return result; + } + + public override object Visit (Foreach foreachStatement) + { + var result = new ForeachStatement (); + + var location = LocationsBag.GetLocations (foreachStatement); + + result.AddChild (new CSharpTokenNode (Convert (foreachStatement.loc), "foreach".Length), ForeachStatement.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), ForeachStatement.Roles.LPar); + + if (foreachStatement.TypeExpr != null) + result.AddChild (ConvertToType (foreachStatement.TypeExpr), ForeachStatement.Roles.Type); + if (foreachStatement.Variable != null) + result.AddChild (Identifier.Create (foreachStatement.Variable.Name, Convert (foreachStatement.Variable.Location)), ForeachStatement.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [1]), "in".Length), ForeachStatement.Roles.InKeyword); + + if (foreachStatement.Expr != null) + result.AddChild ((Expression)foreachStatement.Expr.Accept (this), ForeachStatement.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [2]), 1), ForeachStatement.Roles.RPar); + if (foreachStatement.Statement != null) + result.AddChild ((Statement)foreachStatement.Statement.Accept (this), ForeachStatement.Roles.EmbeddedStatement); + + return result; + } + + public override object Visit (Yield yieldStatement) + { + var result = new YieldStatement (); + var location = LocationsBag.GetLocations (yieldStatement); + + result.AddChild (new CSharpTokenNode (Convert (yieldStatement.loc), "yield".Length), YieldStatement.YieldKeywordRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "return".Length), YieldStatement.ReturnKeywordRole); + if (yieldStatement.Expr != null) + result.AddChild ((Expression)yieldStatement.Expr.Accept (this), YieldStatement.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), YieldStatement.Roles.Semicolon); + + return result; + } + + public override object Visit (YieldBreak yieldBreakStatement) + { + var result = new YieldBreakStatement (); + var location = LocationsBag.GetLocations (yieldBreakStatement); + result.AddChild (new CSharpTokenNode (Convert (yieldBreakStatement.loc), "yield".Length), YieldBreakStatement.YieldKeywordRole); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[0]), "break".Length), YieldBreakStatement.BreakKeywordRole); + result.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), YieldBreakStatement.Roles.Semicolon); + } + return result; + } + #endregion + + #region Expression + public override object Visit (Mono.CSharp.Expression expression) + { + Console.WriteLine ("Visit unknown expression:" + expression); + System.Console.WriteLine (Environment.StackTrace); + return null; + } + + public override object Visit (Mono.CSharp.DefaultParameterValueExpression defaultParameterValueExpression) + { + return defaultParameterValueExpression.Child.Accept (this); + } + + public override object Visit (TypeExpression typeExpression) + { + return new TypeReferenceExpression (new PrimitiveType (keywordTable [(int)typeExpression.Type.BuiltinType], Convert (typeExpression.Location))); + } + + public override object Visit (LocalVariableReference localVariableReference) + { + return Identifier.Create (localVariableReference.Name, Convert (localVariableReference.Location));; + } + + public override object Visit (MemberAccess memberAccess) + { + Expression result; + if (memberAccess.LeftExpression is Indirection) { + var ind = memberAccess.LeftExpression as Indirection; + result = new PointerReferenceExpression (); + result.AddChild ((Expression)ind.Expr.Accept (this), PointerReferenceExpression.Roles.TargetExpression); + result.AddChild (new CSharpTokenNode (Convert (ind.Location), "->".Length), PointerReferenceExpression.ArrowRole); + } else { + result = new MemberReferenceExpression (); + if (memberAccess.LeftExpression != null) { + var leftExpr = memberAccess.LeftExpression.Accept (this); + result.AddChild ((Expression)leftExpr, MemberReferenceExpression.Roles.TargetExpression); + } + } + + result.AddChild (Identifier.Create (memberAccess.Name, Convert (memberAccess.Location)), MemberReferenceExpression.Roles.Identifier); + + if (memberAccess.TypeArguments != null) { + var location = LocationsBag.GetLocations (memberAccess); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MemberReferenceExpression.Roles.LChevron); + AddTypeArguments (result, location, memberAccess.TypeArguments); + if (location != null && location.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MemberReferenceExpression.Roles.RChevron); + } + return result; + } + + public override object Visit (QualifiedAliasMember qualifiedAliasMember) + { + var result = new MemberType (); + result.Target = new SimpleType (qualifiedAliasMember.alias, Convert (qualifiedAliasMember.Location)); + result.IsDoubleColon = true; + var location = LocationsBag.GetLocations (qualifiedAliasMember); + result.AddChild (Identifier.Create (qualifiedAliasMember.Name, location != null ? Convert (location[0]) : AstLocation.Empty), MemberReferenceExpression.Roles.Identifier); + return new TypeReferenceExpression () { Type = result }; + } + + public override object Visit (Constant constant) + { + if (constant.GetValue () == null) + return new NullReferenceExpression (Convert (constant.Location)); + string literalValue; + if (constant is ILiteralConstant) { + literalValue = new string (((ILiteralConstant)constant).ParsedValue); + } else { + literalValue = constant.GetValueAsLiteral (); + } + var result = new PrimitiveExpression (constant.GetValue (), Convert (constant.Location), literalValue); + return result; + } + + public override object Visit (SimpleName simpleName) + { + var result = new IdentifierExpression (); + result.AddChild (Identifier.Create (simpleName.Name, Convert (simpleName.Location)), IdentifierExpression.Roles.Identifier); + if (simpleName.TypeArguments != null) { + var location = LocationsBag.GetLocations (simpleName); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IdentifierExpression.Roles.LChevron); + AddTypeArguments (result, location, simpleName.TypeArguments); + if (location != null && location.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IdentifierExpression.Roles.RChevron); + } + return result; + } + + public override object Visit (BooleanExpression booleanExpression) + { + return booleanExpression.Expr.Accept (this); + } + + + public override object Visit (Mono.CSharp.ParenthesizedExpression parenthesizedExpression) + { + var result = new ParenthesizedExpression (); + var location = LocationsBag.GetLocations (parenthesizedExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ParenthesizedExpression.Roles.LPar); + result.AddChild ((Expression)parenthesizedExpression.Expr.Accept (this), ParenthesizedExpression.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ParenthesizedExpression.Roles.RPar); + return result; + } + + public override object Visit (Unary unaryExpression) + { + var result = new UnaryOperatorExpression (); + switch (unaryExpression.Oper) { + case Unary.Operator.UnaryPlus: + result.Operator = UnaryOperatorType.Plus; + break; + case Unary.Operator.UnaryNegation: + result.Operator = UnaryOperatorType.Minus; + break; + case Unary.Operator.LogicalNot: + result.Operator = UnaryOperatorType.Not; + break; + case Unary.Operator.OnesComplement: + result.Operator = UnaryOperatorType.BitNot; + break; + case Unary.Operator.AddressOf: + result.Operator = UnaryOperatorType.AddressOf; + break; + } + result.AddChild (new CSharpTokenNode (Convert (unaryExpression.Location), 1), UnaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)unaryExpression.Expr.Accept (this), UnaryOperatorExpression.Roles.Expression); + return result; + } + + public override object Visit (UnaryMutator unaryMutatorExpression) + { + var result = new UnaryOperatorExpression (); + + var expression = (Expression)unaryMutatorExpression.Expr.Accept (this); + switch (unaryMutatorExpression.UnaryMutatorMode) { + case UnaryMutator.Mode.PostDecrement: + result.Operator = UnaryOperatorType.PostDecrement; + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + break; + case UnaryMutator.Mode.PostIncrement: + result.Operator = UnaryOperatorType.PostIncrement; + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + break; + + case UnaryMutator.Mode.PreIncrement: + result.Operator = UnaryOperatorType.Increment; + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + break; + case UnaryMutator.Mode.PreDecrement: + result.Operator = UnaryOperatorType.Decrement; + result.AddChild (new CSharpTokenNode (Convert (unaryMutatorExpression.Location), 2), UnaryOperatorExpression.OperatorRole); + result.AddChild (expression, UnaryOperatorExpression.Roles.Expression); + break; + } + + return result; + } + + public override object Visit (Indirection indirectionExpression) + { + var result = new UnaryOperatorExpression (); + result.Operator = UnaryOperatorType.Dereference; + var location = LocationsBag.GetLocations (indirectionExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 2), UnaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)indirectionExpression.Expr.Accept (this), UnaryOperatorExpression.Roles.Expression); + return result; + } + + public override object Visit (Is isExpression) + { + var result = new IsExpression (); + result.AddChild ((Expression)isExpression.Expr.Accept (this), IsExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (isExpression.Location), "is".Length), IsExpression.Roles.Keyword); + result.AddChild (ConvertToType (isExpression.ProbeType), IsExpression.Roles.Type); + return result; + } + + public override object Visit (As asExpression) + { + var result = new AsExpression (); + result.AddChild ((Expression)asExpression.Expr.Accept (this), AsExpression.Roles.Expression); + result.AddChild (new CSharpTokenNode (Convert (asExpression.Location), "as".Length), AsExpression.Roles.Keyword); + result.AddChild (ConvertToType (asExpression.ProbeType), AsExpression.Roles.Type); + return result; + } + + public override object Visit (Cast castExpression) + { + var result = new CastExpression (); + var location = LocationsBag.GetLocations (castExpression); + + result.AddChild (new CSharpTokenNode (Convert (castExpression.Location), 1), CastExpression.Roles.LPar); + if (castExpression.TargetType != null) + result.AddChild (ConvertToType (castExpression.TargetType), CastExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), CastExpression.Roles.RPar); + if (castExpression.Expr != null) + result.AddChild ((Expression)castExpression.Expr.Accept (this), CastExpression.Roles.Expression); + return result; + } + + public override object Visit (ComposedCast composedCast) + { + var result = new ComposedType (); + result.AddChild (ConvertToType (composedCast.Left), ComposedType.Roles.Type); + + var spec = composedCast.Spec; + while (spec != null) { + if (spec.IsNullable) { + result.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.NullableRole); + } else if (spec.IsPointer) { + result.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.PointerRole); + } else { + var aSpec = new ArraySpecifier (); + aSpec.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.Roles.LBracket); + var location = LocationsBag.GetLocations (spec); + if (location != null) + aSpec.AddChild (new CSharpTokenNode (Convert (spec.Location), 1), ComposedType.Roles.RBracket); + result.AddChild (aSpec, ComposedType.ArraySpecifierRole); + } + spec = spec.Next; + } + + return result; + } + + public override object Visit (Mono.CSharp.DefaultValueExpression defaultValueExpression) + { + var result = new DefaultValueExpression (); + result.AddChild (new CSharpTokenNode (Convert (defaultValueExpression.Location), "default".Length), CastExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (defaultValueExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), CastExpression.Roles.LPar); + result.AddChild (ConvertToType (defaultValueExpression.Expr), CastExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CastExpression.Roles.RPar); + return result; + } + + public override object Visit (Binary binaryExpression) + { + var result = new BinaryOperatorExpression (); + int opLength = 1; + switch (binaryExpression.Oper) { + case Binary.Operator.Multiply: + result.Operator = BinaryOperatorType.Multiply; + break; + case Binary.Operator.Division: + result.Operator = BinaryOperatorType.Divide; + break; + case Binary.Operator.Modulus: + result.Operator = BinaryOperatorType.Modulus; + break; + case Binary.Operator.Addition: + result.Operator = BinaryOperatorType.Add; + break; + case Binary.Operator.Subtraction: + result.Operator = BinaryOperatorType.Subtract; + break; + case Binary.Operator.LeftShift: + result.Operator = BinaryOperatorType.ShiftLeft; + opLength = 2; + break; + case Binary.Operator.RightShift: + result.Operator = BinaryOperatorType.ShiftRight; + opLength = 2; + break; + case Binary.Operator.LessThan: + result.Operator = BinaryOperatorType.LessThan; + break; + case Binary.Operator.GreaterThan: + result.Operator = BinaryOperatorType.GreaterThan; + break; + case Binary.Operator.LessThanOrEqual: + result.Operator = BinaryOperatorType.LessThanOrEqual; + opLength = 2; + break; + case Binary.Operator.GreaterThanOrEqual: + result.Operator = BinaryOperatorType.GreaterThanOrEqual; + opLength = 2; + break; + case Binary.Operator.Equality: + result.Operator = BinaryOperatorType.Equality; + opLength = 2; + break; + case Binary.Operator.Inequality: + result.Operator = BinaryOperatorType.InEquality; + opLength = 2; + break; + case Binary.Operator.BitwiseAnd: + result.Operator = BinaryOperatorType.BitwiseAnd; + break; + case Binary.Operator.ExclusiveOr: + result.Operator = BinaryOperatorType.ExclusiveOr; + break; + case Binary.Operator.BitwiseOr: + result.Operator = BinaryOperatorType.BitwiseOr; + break; + case Binary.Operator.LogicalAnd: + result.Operator = BinaryOperatorType.ConditionalAnd; + opLength = 2; + break; + case Binary.Operator.LogicalOr: + result.Operator = BinaryOperatorType.ConditionalOr; + opLength = 2; + break; + } + + result.AddChild ((Expression)binaryExpression.Left.Accept (this), BinaryOperatorExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (binaryExpression.Location), opLength), BinaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)binaryExpression.Right.Accept (this), BinaryOperatorExpression.RightRole); + return result; + } + + public override object Visit (Mono.CSharp.Nullable.NullCoalescingOperator nullCoalescingOperator) + { + var result = new BinaryOperatorExpression (); + result.Operator = BinaryOperatorType.NullCoalescing; + result.AddChild ((Expression)nullCoalescingOperator.Left.Accept (this), BinaryOperatorExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (nullCoalescingOperator.Location), 2), BinaryOperatorExpression.OperatorRole); + result.AddChild ((Expression)nullCoalescingOperator.Right.Accept (this), BinaryOperatorExpression.RightRole); + return result; + } + + public override object Visit (Conditional conditionalExpression) + { + var result = new ConditionalExpression (); + + result.AddChild ((Expression)conditionalExpression.Expr.Accept (this), ConditionalExpression.Roles.Condition); + var location = LocationsBag.GetLocations (conditionalExpression); + + result.AddChild (new CSharpTokenNode (Convert (conditionalExpression.Location), 1), ConditionalExpression.QuestionMarkRole); + result.AddChild ((Expression)conditionalExpression.TrueExpr.Accept (this), ConditionalExpression.TrueRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConditionalExpression.ColonRole); + result.AddChild ((Expression)conditionalExpression.FalseExpr.Accept (this), ConditionalExpression.FalseRole); + return result; + } + + void AddParameter (AstNode parent, Mono.CSharp.AParametersCollection parameters) + { + if (parameters == null) + return; + var paramLocation = LocationsBag.GetLocations (parameters); + + for (int i = 0; i < parameters.Count; i++) { + if (paramLocation != null && i > 0 && i - 1 < paramLocation.Count) + parent.AddChild (new CSharpTokenNode (Convert (paramLocation [i - 1]), 1), ParameterDeclaration.Roles.Comma); + var p = (Parameter)parameters.FixedParameters [i]; + var location = LocationsBag.GetLocations (p); + + ParameterDeclaration parameterDeclarationExpression = new ParameterDeclaration (); + AddAttributeSection (parameterDeclarationExpression, p); + switch (p.ModFlags) { + case Parameter.Modifier.OUT: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Out; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "out".Length), ParameterDeclaration.Roles.Keyword); + break; + case Parameter.Modifier.REF: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Ref; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "ref".Length), ParameterDeclaration.Roles.Keyword); + break; + case Parameter.Modifier.PARAMS: + parameterDeclarationExpression.ParameterModifier = ParameterModifier.Params; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "params".Length), ParameterDeclaration.Roles.Keyword); + break; + default: + if (p.HasExtensionMethodModifier) { + parameterDeclarationExpression.ParameterModifier = ParameterModifier.This; + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "this".Length), ParameterDeclaration.Roles.Keyword); + } + break; + } + if (p.TypeExpression != null) // lambdas may have no types (a, b) => ... + parameterDeclarationExpression.AddChild (ConvertToType (p.TypeExpression), ParameterDeclaration.Roles.Type); + if (p.Name != null) + parameterDeclarationExpression.AddChild (Identifier.Create (p.Name, Convert (p.Location)), ParameterDeclaration.Roles.Identifier); + if (p.HasDefaultValue) { + if (location != null) + parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [1]), 1), ParameterDeclaration.Roles.Assign); + parameterDeclarationExpression.AddChild ((Expression)p.DefaultValue.Accept (this), ParameterDeclaration.Roles.Expression); + } + parent.AddChild (parameterDeclarationExpression, InvocationExpression.Roles.Parameter); + } + } + + void AddTypeParameters (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) + { + if (typeArguments == null || typeArguments.IsEmpty) + return; + for (int i = 0; i < typeArguments.Count; i++) { + if (location != null && i > 0 && i - 1 < location.Count) + parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + var arg = (TypeParameterName)typeArguments.Args[i]; + if (arg == null) + continue; + TypeParameterDeclaration tp = new TypeParameterDeclaration(); + // TODO: attributes +// if (arg.Variance != Variance.None) +// throw new NotImplementedException(); // TODO: variance + tp.AddChild (Identifier.Create (arg.Name, Convert (arg.Location)), InvocationExpression.Roles.Identifier); + parent.AddChild (tp, InvocationExpression.Roles.TypeParameter); + } + } + + void AddTypeArguments (AstNode parent, LocationsBag.MemberLocations location, Mono.CSharp.TypeArguments typeArguments) + { + if (typeArguments == null || typeArguments.IsEmpty) + return; + for (int i = 0; i < typeArguments.Count; i++) { + if (location != null && i > 0 && i - 1 < location.Count) + parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + var arg = typeArguments.Args[i]; + if (arg == null) + continue; + parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); + } + } + + void AddTypeArguments (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) + { + if (typeArguments == null || typeArguments.IsEmpty) + return; + for (int i = 0; i < typeArguments.Count; i++) { + if (location != null && i > 0 && i - 1 < location.Count) + parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + var arg = typeArguments.Args[i]; + if (arg == null) + continue; + parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); + } + } + + void AddConstraints (AstNode parent, DeclSpace d) + { + if (d == null || d.Constraints == null) + return; + for (int i = 0; i < d.PlainConstraints.Count; i++) { + Constraints c = d.PlainConstraints [i]; + var location = LocationsBag.GetLocations (c); + var constraint = new Constraint (); + if (location != null) + constraint.AddChild (new CSharpTokenNode (Convert (location [0]), "where".Length), InvocationExpression.Roles.Keyword); + constraint.AddChild (Identifier.Create (c.TypeParameter.Value, Convert (c.TypeParameter.Location)), InvocationExpression.Roles.Identifier); + if (location != null && location.Count > 1) + constraint.AddChild (new CSharpTokenNode (Convert (location [1]), 1), Constraint.ColonRole); + foreach (var expr in c.ConstraintExpressions) + constraint.AddChild (ConvertToType (expr), Constraint.BaseTypeRole); + parent.AddChild (constraint, AstNode.Roles.Constraint); + } + } + + Expression ConvertArgument (Argument arg) + { + if (arg is NamedArgument) { + var na = (NamedArgument)arg; + NamedArgumentExpression newArg = new NamedArgumentExpression(); + newArg.AddChild (Identifier.Create (na.Name, Convert (na.Location)), NamedArgumentExpression.Roles.Identifier); + + var loc = LocationsBag.GetLocations (na); + if (loc != null) + newArg.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), NamedArgumentExpression.Roles.Assign); + + if (arg.ArgType == Argument.AType.Out || arg.ArgType == Argument.AType.Ref) { + DirectionExpression direction = new DirectionExpression (); + direction.FieldDirection = arg.ArgType == Argument.AType.Out ? FieldDirection.Out : FieldDirection.Ref; + var argLocation = LocationsBag.GetLocations (arg); + if (argLocation != null) + direction.AddChild (new CSharpTokenNode (Convert (argLocation[0]), "123".Length), InvocationExpression.Roles.Keyword); + direction.AddChild ((Expression)arg.Expr.Accept (this), InvocationExpression.Roles.Expression); + newArg.AddChild (direction, NamedArgumentExpression.Roles.Expression); + } else { + newArg.AddChild ((Expression)na.Expr.Accept (this), NamedArgumentExpression.Roles.Expression); + } + return newArg; + } + + if (arg.ArgType == Argument.AType.Out || arg.ArgType == Argument.AType.Ref) { + DirectionExpression direction = new DirectionExpression (); + direction.FieldDirection = arg.ArgType == Argument.AType.Out ? FieldDirection.Out : FieldDirection.Ref; + var argLocation = LocationsBag.GetLocations (arg); + if (argLocation != null) + direction.AddChild (new CSharpTokenNode (Convert (argLocation[0]), "123".Length), InvocationExpression.Roles.Keyword); + direction.AddChild ((Expression)arg.Expr.Accept (this), InvocationExpression.Roles.Expression); + return direction; + } + + return (Expression)arg.Expr.Accept (this); + } + + void AddArguments (AstNode parent, object location, Mono.CSharp.Arguments args) + { + if (args == null) + return; + + var commaLocations = LocationsBag.GetLocations (args); + + for (int i = 0; i < args.Count; i++) { + parent.AddChild (ConvertArgument (args[i]), InvocationExpression.Roles.Argument); + if (commaLocations != null && i > 0) { + int idx = commaLocations.Count - i; + if (idx >= 0) + parent.AddChild (new CSharpTokenNode (Convert (commaLocations[idx]), 1), InvocationExpression.Roles.Comma); + } + } + if (commaLocations != null && commaLocations.Count > args.Count) + parent.AddChild (new CSharpTokenNode (Convert (commaLocations[0]), 1), InvocationExpression.Roles.Comma); + } + + public override object Visit (Invocation invocationExpression) + { + var result = new InvocationExpression (); + var location = LocationsBag.GetLocations (invocationExpression); + result.AddChild ((Expression)invocationExpression.Expression.Accept (this), InvocationExpression.Roles.TargetExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), InvocationExpression.Roles.LPar); + AddArguments (result, location, invocationExpression.Arguments); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), InvocationExpression.Roles.RPar); + return result; + } + + public override object Visit (New newExpression) + { + var result = new ObjectCreateExpression (); + + var location = LocationsBag.GetLocations (newExpression); + result.AddChild (new CSharpTokenNode (Convert (newExpression.Location), "new".Length), ObjectCreateExpression.Roles.Keyword); + + if (newExpression.TypeRequested != null) + result.AddChild (ConvertToType (newExpression.TypeRequested), ObjectCreateExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ObjectCreateExpression.Roles.LPar); + AddArguments (result, location, newExpression.Arguments); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); + + return result; + } + + public override object Visit (NewAnonymousType newAnonymousType) + { + var result = new AnonymousTypeCreateExpression (); + if (newAnonymousType.Parameters == null) + return result; + foreach (var par in newAnonymousType.Parameters) { + var location = LocationsBag.GetLocations (par); + + if (location == null) { + result.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + } else { + var namedArgument = new NamedArgumentExpression (); + namedArgument.AddChild (Identifier.Create (par.Name, Convert (par.Location)), AnonymousTypeCreateExpression.Roles.Identifier); + namedArgument.AddChild (new CSharpTokenNode (Convert (location[0]), 1), AnonymousTypeCreateExpression.Roles.Assign); + namedArgument.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + result.AddChild (namedArgument, AnonymousTypeCreateExpression.Roles.Expression); + } + } + return result; + } + + + public override object Visit (NewInitialize newInitializeExpression) + { + var result = new ObjectCreateExpression (); + result.AddChild (new CSharpTokenNode (Convert (newInitializeExpression.Location), "new".Length), ObjectCreateExpression.Roles.Keyword); + + if (newInitializeExpression.TypeRequested != null) + result.AddChild (ConvertToType (newInitializeExpression.TypeRequested), ObjectCreateExpression.Roles.Type); + + var location = LocationsBag.GetLocations (newInitializeExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ObjectCreateExpression.Roles.LPar); + AddArguments (result, location, newInitializeExpression.Arguments); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); + + return result; + } + + + public override object Visit (ArrayCreation arrayCreationExpression) + { + var result = new ArrayCreateExpression (); + + var location = LocationsBag.GetLocations (arrayCreationExpression); + if (arrayCreationExpression.NewType != null) + result.AddChild (ConvertToType (arrayCreationExpression.NewType), ArrayCreateExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ArrayCreateExpression.Roles.LBracket); + if (arrayCreationExpression.Arguments != null) { + var commaLocations = LocationsBag.GetLocations (arrayCreationExpression.Arguments); + for (int i = 0 ;i < arrayCreationExpression.Arguments.Count; i++) { + result.AddChild ((Expression)arrayCreationExpression.Arguments[i].Accept (this), ArrayCreateExpression.Roles.Argument); + if (commaLocations != null && i > 0) + result.AddChild (new CSharpTokenNode (Convert (commaLocations [commaLocations.Count - i]), 1), ArrayCreateExpression.Roles.Comma); + } + } + var next = arrayCreationExpression.Rank.Next; + while (next != null) { + ArraySpecifier spec = new ArraySpecifier (next.Dimension); + var loc = LocationsBag.GetLocations (next); + spec.AddChild (new CSharpTokenNode (Convert (next.Location), 1), ArraySpecifier.Roles.LBracket); + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), ArraySpecifier.Roles.RBracket); + result.AddChild (spec, ArrayCreateExpression.AdditionalArraySpecifierRole); + next = next.Next; + } + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ArrayCreateExpression.Roles.RBracket); + + if (arrayCreationExpression.Initializers != null && arrayCreationExpression.Initializers.Count != 0) { + var initLocation = LocationsBag.GetLocations (arrayCreationExpression.Initializers); + ArrayInitializerExpression initializer = new ArrayInitializerExpression(); + + 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); + if (commaLocations != null && i > 0) { + initializer.AddChild (new CSharpTokenNode (Convert (commaLocations [commaLocations.Count - i]), 1), IndexerExpression.Roles.Comma); + } + } + + if (initLocation != null) + initializer.AddChild (new CSharpTokenNode (Convert (initLocation[initLocation.Count - 1]), 1), ArrayCreateExpression.Roles.RBrace); + result.AddChild (initializer, ArrayCreateExpression.InitializerRole); + } + + return result; + } + + public override object Visit (This thisExpression) + { + var result = new ThisReferenceExpression (); + result.Location = Convert (thisExpression.Location); + return result; + } + + public override object Visit (ArglistAccess argListAccessExpression) + { + var result = new UndocumentedExpression () { + UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess + }; + result.AddChild (new CSharpTokenNode (Convert (argListAccessExpression.Location), "__arglist".Length), UndocumentedExpression.Roles.Keyword); + return result; + } + + #region Undocumented expressions + public override object Visit (Arglist argListExpression) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }; + result.AddChild (new CSharpTokenNode (Convert (argListExpression.Location), "__arglist".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (argListExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + + AddArguments (result, location, argListExpression.Arguments); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + + public override object Visit (MakeRefExpr makeRefExpr) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.RefValue }; + result.AddChild (new CSharpTokenNode (Convert (makeRefExpr.Location), "__makeref".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (makeRefExpr); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + if (makeRefExpr.Expr != null) + result.AddChild ((Expression)makeRefExpr.Expr.Accept (this), UndocumentedExpression.Roles.Argument); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + + public override object Visit (RefTypeExpr refTypeExpr) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.RefValue }; + result.AddChild (new CSharpTokenNode (Convert (refTypeExpr.Location), "__reftype".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (refTypeExpr); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + + if (refTypeExpr.Expr != null) + result.AddChild ((Expression)refTypeExpr.Expr.Accept (this), UndocumentedExpression.Roles.Argument); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + + public override object Visit (RefValueExpr refValueExpr) + { + var result = new UndocumentedExpression () { UndocumentedExpressionType = UndocumentedExpressionType.RefValue }; + result.AddChild (new CSharpTokenNode (Convert (refValueExpr.Location), "__refvalue".Length), UndocumentedExpression.Roles.Keyword); + var location = LocationsBag.GetLocations (refValueExpr); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), UndocumentedExpression.Roles.LPar); + + + if (refValueExpr.Expr != null) + result.AddChild ((Expression)refValueExpr.Expr.Accept (this), UndocumentedExpression.Roles.Argument); + + if (refValueExpr.FullNamedExpression != null) + result.AddChild ((Expression)refValueExpr.FullNamedExpression.Accept (this), UndocumentedExpression.Roles.Argument); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), UndocumentedExpression.Roles.RPar); + return result; + } + #endregion + + public override object Visit (TypeOf typeOfExpression) + { + var result = new TypeOfExpression (); + var location = LocationsBag.GetLocations (typeOfExpression); + result.AddChild (new CSharpTokenNode (Convert (typeOfExpression.Location), "typeof".Length), TypeOfExpression.Roles.Keyword); + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild (ConvertToType (typeOfExpression.TypeExpression), TypeOfExpression.Roles.Type); + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (SizeOf sizeOfExpression) + { + var result = new SizeOfExpression (); + var location = LocationsBag.GetLocations (sizeOfExpression); + result.AddChild (new CSharpTokenNode (Convert (sizeOfExpression.Location), "sizeof".Length), TypeOfExpression.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild (ConvertToType (sizeOfExpression.QueriedType), TypeOfExpression.Roles.Type); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (CheckedExpr checkedExpression) + { + var result = new CheckedExpression (); + var location = LocationsBag.GetLocations (checkedExpression); + result.AddChild (new CSharpTokenNode (Convert (checkedExpression.Location), "checked".Length), TypeOfExpression.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild ((Expression)checkedExpression.Expr.Accept (this), TypeOfExpression.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (UnCheckedExpr uncheckedExpression) + { + var result = new UncheckedExpression (); + var location = LocationsBag.GetLocations (uncheckedExpression); + result.AddChild (new CSharpTokenNode (Convert (uncheckedExpression.Location), "unchecked".Length), TypeOfExpression.Roles.Keyword); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.LPar); + result.AddChild ((Expression)uncheckedExpression.Expr.Accept (this), TypeOfExpression.Roles.Expression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), TypeOfExpression.Roles.RPar); + return result; + } + + public override object Visit (ElementAccess elementAccessExpression) + { + IndexerExpression result = new IndexerExpression (); + var location = LocationsBag.GetLocations (elementAccessExpression); + + result.AddChild ((Expression)elementAccessExpression.Expr.Accept (this), IndexerExpression.Roles.TargetExpression); + result.AddChild (new CSharpTokenNode (Convert (elementAccessExpression.Location), 1), TypeOfExpression.Roles.LBracket); + AddArguments (result, location, elementAccessExpression.Arguments); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), TypeOfExpression.Roles.RBracket); + return result; + } + + public override object Visit (BaseThis baseAccessExpression) + { + var result = new BaseReferenceExpression (); + result.Location = Convert (baseAccessExpression.Location); + return result; + } + + public override object Visit (StackAlloc stackAllocExpression) + { + var result = new StackAllocExpression (); + + var location = LocationsBag.GetLocations (stackAllocExpression); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "stackalloc".Length), StackAllocExpression.Roles.Keyword); + result.AddChild (ConvertToType (stackAllocExpression.TypeExpression), StackAllocExpression.Roles.Type); + if (location != null && location.Count > 1) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), StackAllocExpression.Roles.LBracket); + result.AddChild ((Expression)stackAllocExpression.CountExpression.Accept (this), StackAllocExpression.Roles.Expression); + if (location != null && location.Count > 2) + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), StackAllocExpression.Roles.RBracket); + return result; + } + + public override object Visit (SimpleAssign simpleAssign) + { + var result = new AssignmentExpression (); + + result.Operator = AssignmentOperatorType.Assign; + if (simpleAssign.Target != null) + result.AddChild ((Expression)simpleAssign.Target.Accept (this), AssignmentExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (simpleAssign.Location), 1), AssignmentExpression.OperatorRole); + if (simpleAssign.Source != null) { + result.AddChild ((Expression)simpleAssign.Source.Accept (this), AssignmentExpression.RightRole); + } + return result; + } + + public override object Visit (CompoundAssign compoundAssign) + { + var result = new AssignmentExpression (); + int opLength = 2; + switch (compoundAssign.Op) { + case Binary.Operator.Multiply: + result.Operator = AssignmentOperatorType.Multiply; + break; + case Binary.Operator.Division: + result.Operator = AssignmentOperatorType.Divide; + break; + case Binary.Operator.Modulus: + result.Operator = AssignmentOperatorType.Modulus; + break; + case Binary.Operator.Addition: + result.Operator = AssignmentOperatorType.Add; + break; + case Binary.Operator.Subtraction: + result.Operator = AssignmentOperatorType.Subtract; + break; + case Binary.Operator.LeftShift: + result.Operator = AssignmentOperatorType.ShiftLeft; + opLength = 3; + break; + case Binary.Operator.RightShift: + result.Operator = AssignmentOperatorType.ShiftRight; + opLength = 3; + break; + case Binary.Operator.BitwiseAnd: + result.Operator = AssignmentOperatorType.BitwiseAnd; + break; + case Binary.Operator.BitwiseOr: + result.Operator = AssignmentOperatorType.BitwiseOr; + break; + case Binary.Operator.ExclusiveOr: + result.Operator = AssignmentOperatorType.ExclusiveOr; + break; + } + + result.AddChild ((Expression)compoundAssign.Target.Accept (this), AssignmentExpression.LeftRole); + result.AddChild (new CSharpTokenNode (Convert (compoundAssign.Location), opLength), AssignmentExpression.OperatorRole); + result.AddChild ((Expression)compoundAssign.Source.Accept (this), AssignmentExpression.RightRole); + return result; + } + + public override object Visit (Mono.CSharp.AnonymousMethodExpression anonymousMethodExpression) + { + var result = new AnonymousMethodExpression (); + var location = LocationsBag.GetLocations (anonymousMethodExpression); + if (location != null) { + result.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), AnonymousMethodExpression.Roles.Keyword); + + if (location.Count > 1) { + result.HasParameterList = true; + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AnonymousMethodExpression.Roles.LPar); + AddParameter (result, anonymousMethodExpression.Parameters); + result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AnonymousMethodExpression.Roles.RPar); + } + } + result.AddChild ((BlockStatement)anonymousMethodExpression.Block.Accept (this), AnonymousMethodExpression.Roles.Body); + return result; + } + + public override object Visit (Mono.CSharp.LambdaExpression lambdaExpression) + { + var result = new LambdaExpression (); + var location = LocationsBag.GetLocations (lambdaExpression); + + if (location == null || location.Count == 1) { + AddParameter (result, lambdaExpression.Parameters); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), "=>".Length), LambdaExpression.ArrowRole); + } else { + result.AddChild (new CSharpTokenNode (Convert (lambdaExpression.Location), 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); + } + } + 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; + } + + public override object Visit (ConstInitializer constInitializer) + { + return constInitializer.Expr.Accept (this); + } + + public override object Visit (ArrayInitializer arrayInitializer) + { + var result = new ArrayInitializerExpression (); + var location = LocationsBag.GetLocations (arrayInitializer); + 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); + if (commaLocations != null && i < commaLocations.Count) + result.AddChild (new CSharpTokenNode (Convert (commaLocations[i]), ",".Length), ArrayInitializerExpression.Roles.Comma); + } + + if (location != null) { + if (location.Count == 2) // optional comma + result.AddChild (new CSharpTokenNode (Convert (location[1]), ",".Length), ArrayInitializerExpression.Roles.Comma); + result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), "}".Length), ArrayInitializerExpression.Roles.RBrace); + } + return result; + } + + #endregion + + #region LINQ expressions + public override object Visit (Mono.CSharp.Linq.QueryExpression queryExpression) + { + var result = new QueryExpression (); + + var currentClause = queryExpression.next; + + while (currentClause != null) { + QueryClause clause = (QueryClause)currentClause.Accept (this); + if (clause is QueryContinuationClause) { + // insert preceding query at beginning of QueryContinuationClause + clause.InsertChildAfter(null, result, QueryContinuationClause.PrecedingQueryRole); + // create a new QueryExpression for the remaining query + result = new QueryExpression(); + } + result.AddChild (clause, QueryExpression.ClauseRole); + currentClause = currentClause.next; + } + + return result; + } + + public override object Visit (Mono.CSharp.Linq.QueryStartClause queryStart) + { + if (queryStart.Expr == null) { + var intoClause = new QueryContinuationClause (); + intoClause.AddChild (new CSharpTokenNode (Convert (queryStart.Location), "into".Length), QueryContinuationClause.IntoKeywordRole); + intoClause.AddChild (Identifier.Create (queryStart.IntoVariable.Name, Convert(queryStart.IntoVariable.Location)), QueryContinuationClause.Roles.Identifier); + return intoClause; + } + + var fromClause = new QueryFromClause (); + var location = LocationsBag.GetLocations (queryStart); + + fromClause.AddChild (new CSharpTokenNode (Convert (queryStart.Location), "from".Length), QueryFromClause.FromKeywordRole); + + if (queryStart.IdentifierType != null) + fromClause.AddChild (ConvertToType (queryStart.IdentifierType), QueryFromClause.Roles.Type); + + fromClause.AddChild (Identifier.Create (queryStart.IntoVariable.Name, Convert(queryStart.IntoVariable.Location)), QueryFromClause.Roles.Identifier); + + if (location != null) + fromClause.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryFromClause.InKeywordRole); + fromClause.AddChild ((Expression)queryStart.Expr.Accept (this), QueryFromClause.Roles.Expression); + return fromClause; + } + + public override object Visit (Mono.CSharp.Linq.SelectMany queryStart) + { + var fromClause = new QueryFromClause (); + var location = LocationsBag.GetLocations (queryStart); + + fromClause.AddChild (new CSharpTokenNode (Convert (queryStart.Location), "from".Length), QueryFromClause.FromKeywordRole); + + if (queryStart.IdentifierType != null) + fromClause.AddChild (ConvertToType (queryStart.IdentifierType), QueryFromClause.Roles.Type); + + fromClause.AddChild (Identifier.Create (queryStart.IntoVariable.Name, Convert(queryStart.IntoVariable.Location)), QueryFromClause.Roles.Identifier); + + if (location != null) + fromClause.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryFromClause.InKeywordRole); + fromClause.AddChild ((Expression)queryStart.Expr.Accept (this), QueryFromClause.Roles.Expression); + return fromClause; + } + + public override object Visit (Mono.CSharp.Linq.Select sel) + { + var result = new QuerySelectClause (); + result.AddChild (new CSharpTokenNode (Convert (sel.Location), "select".Length), QueryWhereClause.Roles.Keyword); + result.AddChild ((Expression)sel.Expr.Accept (this), QueryWhereClause.Roles.Expression); + return result; + } + + public override object Visit (Mono.CSharp.Linq.GroupBy groupBy) + { + var result = new QueryGroupClause (); + var location = LocationsBag.GetLocations (groupBy); + result.AddChild (new CSharpTokenNode (Convert (groupBy.Location), "group".Length), QueryGroupClause.GroupKeywordRole); + result.AddChild ((Expression)groupBy.ElementSelector.Accept (this), QueryGroupClause.KeyRole); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "by".Length), QueryGroupClause.ByKeywordRole); + result.AddChild ((Expression)groupBy.Expr.Accept (this), QueryGroupClause.ProjectionRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.Let l) + { + var result = new QueryLetClause (); + var location = LocationsBag.GetLocations (l); + + result.AddChild (new CSharpTokenNode (Convert (l.Location), "let".Length), QueryLetClause.Roles.Keyword); + result.AddChild (Identifier.Create (l.IntoVariable.Name, Convert (l.IntoVariable.Location)), Identifier.Roles.Identifier); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), QueryLetClause.Roles.Assign); + result.AddChild ((Expression)l.Expr.Accept (this), QueryLetClause.Roles.Expression); + return result; + } + + public override object Visit (Mono.CSharp.Linq.Where w) + { + var result = new QueryWhereClause (); + var location = LocationsBag.GetLocations (w); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "where".Length), QueryWhereClause.Roles.Keyword); + result.AddChild ((Expression)w.Expr.Accept (this), QueryWhereClause.Roles.Condition); + return result; + } + + public override object Visit (Mono.CSharp.Linq.Join join) + { + var result = new QueryJoinClause (); + var location = LocationsBag.GetLocations (join); + result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); + + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); + + result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), "on".Length), QueryJoinClause.OnKeywordRole); + // TODO: on expression + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), "equals".Length), QueryJoinClause.EqualsKeywordRole); + // TODO: equals expression + + return result; + } + + public override object Visit (Mono.CSharp.Linq.GroupJoin join) + { + var result = new QueryJoinClause (); + var location = LocationsBag.GetLocations (join); + result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); + + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); + + result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.Roles.Expression); + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), "on".Length), QueryJoinClause.OnKeywordRole); + + // TODO: on expression + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[2]), "equals".Length), QueryJoinClause.EqualsKeywordRole); + // TODO: equals expression + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[3]), "into".Length), QueryJoinClause.IntoKeywordRole); + + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + return result; + } + + public override object Visit (Mono.CSharp.Linq.OrderByAscending orderByAscending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)orderByAscending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (orderByAscending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Ascending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.OrderByDescending orderByDescending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)orderByDescending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (orderByDescending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Descending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.ThenByAscending thenByAscending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)thenByAscending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (thenByAscending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Ascending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + + public override object Visit (Mono.CSharp.Linq.ThenByDescending thenByDescending) + { + var result = new QueryOrderClause (); + + var ordering = new QueryOrdering (); + + ordering.AddChild ((Expression)thenByDescending.Expr.Accept (this), QueryWhereClause.Roles.Expression); + var location = LocationsBag.GetLocations (thenByDescending); + if (location != null) { + ordering.Direction = QueryOrderingDirection.Descending; + ordering.AddChild (new CSharpTokenNode (Convert (location[0]), "ascending".Length), QueryWhereClause.Roles.Keyword); + } + result.AddChild (ordering, QueryOrderClause.OrderingRole); + return result; + } + #endregion + } + + public CSharpParser () + { + CompilerArguments = new string[] { "-v", "-unsafe"}; + } + + public CSharpParser (string[] args) + { + CompilerArguments = args; + } + + static AstNode GetOuterLeft (AstNode node) + { + var outerLeft = node; + while (outerLeft.FirstChild != null) + outerLeft = outerLeft.FirstChild; + return outerLeft; + } + + static AstNode NextLeaf (AstNode node) + { + if (node == null) + return null; + var next = node.NextSibling; + if (next == null) + return node.Parent; + return GetOuterLeft(next); + } + + static void InsertComments (CompilerCompilationUnit top, ConversionVisitor conversionVisitor) + { + var leaf = GetOuterLeft(conversionVisitor.Unit); + + foreach (var special in top.SpecialsBag.Specials) { + var comment = special as SpecialsBag.Comment; + if (comment == null) + continue; + if (conversionVisitor.convertTypeSystemMode && (comment.CommentType != SpecialsBag.CommentType.Documentation)) + continue; + var type = (CommentType)comment.CommentType; + var start = new AstLocation (comment.Line, comment.Col); + var end = new AstLocation (comment.EndLine, comment.EndCol); + var domComment = new Comment (type, start, end); + domComment.StartsLine = comment.StartsLine; + domComment.Content = comment.Content; + + while (true) { + var nextLeaf = NextLeaf(leaf); + // instert comment at the end + if (nextLeaf == null) { + var node = leaf.Parent ?? conversionVisitor.Unit; + node.AddChild(domComment, AstNode.Roles.Comment); + leaf = domComment; + break; + } + + // comment is between 2 nodes + if (leaf.EndLocation <= domComment.StartLocation && domComment.StartLocation <= nextLeaf.StartLocation) { + var node = leaf.Parent ?? conversionVisitor.Unit; + node.InsertChildAfter(leaf, domComment, AstNode.Roles.Comment); + leaf = domComment; + break; + } + leaf = nextLeaf; + } + } + } + + internal static CompilationUnit Parse (bool convertTypeSystemMode, CompilerCompilationUnit top) + { + if (top == null) + return null; + CSharpParser.ConversionVisitor conversionVisitor = new ConversionVisitor (convertTypeSystemMode, top.LocationsBag); + conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); + top.UsingsBag.Global.Accept (conversionVisitor); + InsertComments (top, conversionVisitor); + return conversionVisitor.Unit; + } + + public class ErrorReportPrinter : ReportPrinter + { + readonly string fileName; + public readonly List Errors = new List (); + + public ErrorReportPrinter (string fileName) + { + this.fileName = fileName; + } + + public override void Print (AbstractMessage msg) + { + base.Print (msg); + var newError = new Error (msg.IsWarning ? ErrorType.Warning : ErrorType.Error, msg.Text, new DomRegion (fileName, msg.Location.Row, msg.Location.Column)); + Errors.Add (newError); + } + } + ErrorReportPrinter errorReportPrinter = new ErrorReportPrinter (null); + + public ErrorReportPrinter ErrorPrinter { + get { + return errorReportPrinter; + } + } + + public bool HasErrors { + get { + return errorReportPrinter.ErrorsCount + errorReportPrinter.FatalCounter > 0; + } + } + + public bool HasWarnings { + get { + return errorReportPrinter.WarningsCount > 0; + } + } + + public CompilationUnit Parse (TextReader reader, int line = 0) + { + // TODO: can we optimize this to avoid the text->stream->text roundtrip? + using (MemoryStream stream = new MemoryStream ()) { + StreamWriter w = new StreamWriter (stream, Encoding.UTF8); + char[] buffer = new char[2048]; + int read; + while ((read = reader.ReadBlock(buffer, 0, buffer.Length)) > 0) + 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); + } + } + + public static void AdjustLineLocations (AstNode node, int line) + { + if (node is IRelocatable) { + ((IRelocatable)node).SetStartLocation (new AstLocation (node.StartLocation.Line + line, node.StartLocation.Column)); + } + foreach (var child in node.Children) { + AdjustLineLocations (child, line); + } + } + + public CompilationUnit Parse (CompilerCompilationUnit top, int line) + { + if (top == null) + return null; + CSharpParser.ConversionVisitor conversionVisitor = new ConversionVisitor (GenerateTypeSystemMode, top.LocationsBag); + conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); + top.UsingsBag.Global.Accept (conversionVisitor); + InsertComments (top, conversionVisitor); + if (CompilationUnitCallback != null) + 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; + } + + public string[] CompilerArguments { + get; + private set; + } + + public Action CompilationUnitCallback { + get; + set; + } + + public bool GenerateTypeSystemMode { + get; + set; + } + + public CompilationUnit Parse (Stream stream, int line = 0) + { + lock (CompilerCallableEntryPoint.parseLock) { + errorReportPrinter = new ErrorReportPrinter (""); + CompilerCompilationUnit top = CompilerCallableEntryPoint.ParseFile (CompilerArguments, stream, "parsed.cs", errorReportPrinter); + var unit = Parse (top, line); + unit.Errors.AddRange (errorReportPrinter.Errors); + return unit; + } + } + + public IEnumerable ParseTypeMembers (TextReader reader, int lineModifier = 0) + { + string code = "unsafe partial class MyClass { " + Environment.NewLine + reader.ReadToEnd () + "}"; + var cu = Parse (new StringReader (code), -1 + lineModifier); + if (cu == null) + return Enumerable.Empty (); + var td = cu.Children.FirstOrDefault () as TypeDeclaration; + if (td != null) + return td.Members; + return Enumerable.Empty (); + } + + public IEnumerable ParseStatements(TextReader reader, int lineModifier = 0) + { + string code = "void M() { " + Environment.NewLine + reader.ReadToEnd() + "}"; + var members = ParseTypeMembers(new StringReader(code), lineModifier - 1); + var method = members.FirstOrDefault() as MethodDeclaration; + if (method != null && method.Body != null) + return method.Body.Statements; + return Enumerable.Empty (); + } + + public AstType ParseTypeReference(TextReader reader) + { + string code = reader.ReadToEnd() + " a;"; + var members = ParseTypeMembers(new StringReader(code)); + var field = members.FirstOrDefault() as FieldDeclaration; + if (field != null) + return field.ReturnType; + return AstType.Null; + } + + public AstNode ParseExpression(TextReader reader) + { + var es = ParseStatements(new StringReader("tmp = " + Environment.NewLine + reader.ReadToEnd() + ";"), -1).FirstOrDefault() as ExpressionStatement; + if (es != null) { + AssignmentExpression ae = es.Expression as AssignmentExpression; + if (ae != null) + return ae.Right; + } + return null; + } + + /// + /// Parses a file snippet; guessing what the code snippet represents (compilation unit, type members, block, type reference, expression). + /// + public AstNode ParseSnippet(TextReader reader) + { + // TODO: add support for parsing a part of a file + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs new file mode 100644 index 0000000000..9545188427 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs @@ -0,0 +1,125 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a file that was parsed and converted for the type system. + /// + public sealed class ParsedFile : AbstractFreezable, IParsedFile + { + readonly string fileName; + readonly UsingScope rootUsingScope; + IList topLevelTypeDefinitions = new List(); + IList assemblyAttributes = new List(); + IList usingScopes = new List(); + IList errors = new List (); + + protected override void FreezeInternal() + { + base.FreezeInternal(); + rootUsingScope.Freeze(); + topLevelTypeDefinitions = FreezeList(topLevelTypeDefinitions); + assemblyAttributes = FreezeList(assemblyAttributes); + usingScopes = FreezeList(usingScopes); + } + + public ParsedFile(string fileName, UsingScope rootUsingScope) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + if (rootUsingScope == null) + throw new ArgumentNullException("rootUsingScope"); + this.fileName = fileName; + this.rootUsingScope = rootUsingScope; + } + + public string FileName { + get { return fileName; } + } + + DateTime parseTime = DateTime.Now; + public DateTime ParseTime { + get { + return parseTime; + } + } + + public UsingScope RootUsingScope { + get { return rootUsingScope; } + } + + public IList Errors { + get { return errors; } + internal set { errors = (List)value; } + } + + public IList UsingScopes { + get { return usingScopes; } + } + + public IProjectContent ProjectContent { + get { return rootUsingScope.ProjectContent; } + } + + public IList TopLevelTypeDefinitions { + get { return topLevelTypeDefinitions; } + } + + public IList AssemblyAttributes { + get { return assemblyAttributes; } + } + + public UsingScope GetUsingScope(AstLocation location) + { + foreach (UsingScope scope in usingScopes) { + if (scope.Region.IsInside(location.Line, location.Column)) + return scope; + } + return rootUsingScope; + } + + public ITypeDefinition GetTopLevelTypeDefinition(AstLocation location) + { + return FindEntity(topLevelTypeDefinitions, location); + } + + public ITypeDefinition GetTypeDefinition(AstLocation location) + { + ITypeDefinition parent = null; + ITypeDefinition type = GetTopLevelTypeDefinition(location); + while (type != null) { + parent = type; + type = FindEntity(parent.NestedTypes, location); + } + return parent; + } + + public IMember GetMember(AstLocation location) + { + ITypeDefinition type = GetTypeDefinition(location); + if (type == null) + return null; + return FindEntity(type.Methods, location) + ?? FindEntity(type.Fields, location) + ?? FindEntity(type.Properties, location) + ?? (IMember)FindEntity(type.Events, location); + } + + static T FindEntity(IList list, AstLocation location) where T : class, IEntity + { + // This could be improved using a binary search + foreach (T entity in list) { + if (entity.Region.IsInside(location.Line, location.Column)) + return entity; + } + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs new file mode 100644 index 0000000000..ccd273ba51 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs @@ -0,0 +1,1009 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using ICSharpCode.NRefactory.CSharp.Analysis; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Produces type and member definitions from the DOM. + /// + public class TypeSystemConvertVisitor : DepthFirstAstVisitor + { + readonly ParsedFile parsedFile; + UsingScope usingScope; + DefaultTypeDefinition currentTypeDefinition; + DefaultMethod currentMethod; + + /// + /// Creates a new TypeSystemConvertVisitor. + /// + /// The parent project content (used as owner for the types being created). + /// The file name (used for DomRegions). + public TypeSystemConvertVisitor(IProjectContent pc, string fileName) + { + if (pc == null) + throw new ArgumentNullException("pc"); + if (fileName == null) + throw new ArgumentNullException("fileName"); + this.parsedFile = new ParsedFile(fileName, new UsingScope(pc)); + this.usingScope = parsedFile.RootUsingScope; + } + + /// + /// Creates a new TypeSystemConvertVisitor and initializes it with a given context. + /// + /// The parsed file to which members should be added. + /// The current using scope. + /// The current type definition. + public TypeSystemConvertVisitor(ParsedFile parsedFile, UsingScope currentUsingScope = null, DefaultTypeDefinition currentTypeDefinition = null) + { + if (parsedFile == null) + throw new ArgumentNullException("parsedFile"); + this.parsedFile = parsedFile; + this.usingScope = currentUsingScope ?? parsedFile.RootUsingScope; + this.currentTypeDefinition = currentTypeDefinition; + } + + public ParsedFile ParsedFile { + get { return parsedFile; } + } + + DomRegion MakeRegion(AstLocation start, AstLocation end) + { + return new DomRegion(parsedFile.FileName, start.Line, start.Column, end.Line, end.Column); + } + + DomRegion MakeRegion(AstNode node) + { + if (node == null || node.IsNull) + return DomRegion.Empty; + else + return MakeRegion(node.StartLocation, node.EndLocation); + } + + DomRegion MakeBraceRegion(AstNode node) + { + if (node == null || node.IsNull) + return DomRegion.Empty; + else + return MakeRegion(node.GetChildByRole(AstNode.Roles.LBrace).StartLocation, + node.GetChildByRole(AstNode.Roles.RBrace).EndLocation); + } + + #region Compilation Unit + public override IEntity VisitCompilationUnit (CompilationUnit unit, object data) + { + parsedFile.Errors = unit.Errors; + return base.VisitCompilationUnit (unit, data); + } + #endregion + + #region Using Declarations + public override IEntity VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) + { + usingScope.ExternAliases.Add(externAliasDeclaration.Name); + return null; + } + + public override IEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + { + ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, true) as ITypeOrNamespaceReference; + if (u != null) + usingScope.Usings.Add(u); + return null; + } + + public override IEntity VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) + { + ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, true) as ITypeOrNamespaceReference; + if (u != null) + usingScope.UsingAliases.Add(new KeyValuePair(usingDeclaration.Alias, u)); + return null; + } + #endregion + + #region Namespace Declaration + public override IEntity VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + DomRegion region = MakeRegion(namespaceDeclaration); + UsingScope previousUsingScope = usingScope; + foreach (Identifier ident in namespaceDeclaration.Identifiers) { + usingScope = new UsingScope(usingScope, NamespaceDeclaration.BuildQualifiedName(usingScope.NamespaceName, ident.Name)); + usingScope.Region = region; + } + base.VisitNamespaceDeclaration(namespaceDeclaration, data); + parsedFile.UsingScopes.Add(usingScope); // add after visiting children so that nested scopes come first + usingScope = previousUsingScope; + return null; + } + #endregion + + #region Type Definitions + DefaultTypeDefinition CreateTypeDefinition(string name) + { + DefaultTypeDefinition newType; + if (currentTypeDefinition != null) { + newType = new DefaultTypeDefinition(currentTypeDefinition, name); + newType.TypeParameters.AddRange(currentTypeDefinition.TypeParameters); + currentTypeDefinition.NestedTypes.Add(newType); + } else { + newType = new DefaultTypeDefinition(usingScope.ProjectContent, usingScope.NamespaceName, name); + parsedFile.TopLevelTypeDefinitions.Add(newType); + } + return newType; + } + + public override IEntity VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + var td = currentTypeDefinition = CreateTypeDefinition(typeDeclaration.Name); + td.ClassType = typeDeclaration.ClassType; + td.Region = MakeRegion(typeDeclaration); + td.BodyRegion = MakeBraceRegion(typeDeclaration); + td.AddDefaultConstructorIfRequired = true; + + ConvertAttributes(td.Attributes, typeDeclaration.Attributes); + ApplyModifiers(td, typeDeclaration.Modifiers); + if (td.ClassType == ClassType.Interface) + td.IsAbstract = true; // interfaces are implicitly abstract + else if (td.ClassType == ClassType.Enum || td.ClassType == ClassType.Struct) + td.IsSealed = true; // enums/structs are implicitly sealed + + ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints, EntityType.TypeDefinition); + + foreach (AstType baseType in typeDeclaration.BaseTypes) { + td.BaseTypes.Add(ConvertType(baseType)); + } + + foreach (AttributedNode member in typeDeclaration.Members) { + member.AcceptVisitor(this, data); + } + + td.HasExtensionMethods = td.Methods.Any(m => m.IsExtensionMethod); + + currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; + return td; + } + + public override IEntity VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + { + var td = currentTypeDefinition = CreateTypeDefinition(delegateDeclaration.Name); + td.ClassType = ClassType.Delegate; + td.Region = MakeRegion(delegateDeclaration); + td.BaseTypes.Add(multicastDelegateReference); + + ApplyModifiers(td, delegateDeclaration.Modifiers); + td.IsSealed = true; // delegates are implicitly sealed + + ConvertTypeParameters(td.TypeParameters, delegateDeclaration.TypeParameters, delegateDeclaration.Constraints, EntityType.TypeDefinition); + + ITypeReference returnType = ConvertType(delegateDeclaration.ReturnType); + List parameters = new List(); + ConvertParameters(parameters, delegateDeclaration.Parameters); + AddDefaultMethodsToDelegate(td, returnType, parameters); + + foreach (AttributeSection section in delegateDeclaration.Attributes) { + if (section.AttributeTarget == "return") { + ConvertAttributes(td.Methods.Single(m => m.Name == "Invoke").ReturnTypeAttributes, section); + ConvertAttributes(td.Methods.Single(m => m.Name == "EndInvoke").ReturnTypeAttributes, section); + } else { + ConvertAttributes(td.Attributes, section); + } + } + + currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; + return td; + } + + static readonly ITypeReference multicastDelegateReference = typeof(MulticastDelegate).ToTypeReference(); + static readonly IParameter delegateObjectParameter = MakeParameter(KnownTypeReference.Object, "object"); + static readonly IParameter delegateIntPtrMethodParameter = MakeParameter(typeof(IntPtr).ToTypeReference(), "method"); + static readonly IParameter delegateAsyncCallbackParameter = MakeParameter(typeof(AsyncCallback).ToTypeReference(), "callback"); + static readonly IParameter delegateResultParameter = MakeParameter(typeof(IAsyncResult).ToTypeReference(), "result"); + + static IParameter MakeParameter(ITypeReference type, string name) + { + DefaultParameter p = new DefaultParameter(type, name); + p.Freeze(); + return p; + } + + /// + /// Adds the 'Invoke', 'BeginInvoke', 'EndInvoke' methods, and a constructor, to the . + /// + public static void AddDefaultMethodsToDelegate(DefaultTypeDefinition delegateType, ITypeReference returnType, IEnumerable parameters) + { + if (delegateType == null) + throw new ArgumentNullException("delegateType"); + if (returnType == null) + throw new ArgumentNullException("returnType"); + if (parameters == null) + throw new ArgumentNullException("parameters"); + + DomRegion region = new DomRegion(delegateType.Region.FileName, delegateType.Region.BeginLine, delegateType.Region.BeginColumn); + + DefaultMethod invoke = new DefaultMethod(delegateType, "Invoke"); + invoke.Accessibility = Accessibility.Public; + invoke.IsSynthetic = true; + invoke.Parameters.AddRange(parameters); + invoke.ReturnType = returnType; + invoke.Region = region; + delegateType.Methods.Add(invoke); + + DefaultMethod beginInvoke = new DefaultMethod(delegateType, "BeginInvoke"); + beginInvoke.Accessibility = Accessibility.Public; + beginInvoke.IsSynthetic = true; + beginInvoke.Parameters.AddRange(invoke.Parameters); + beginInvoke.Parameters.Add(delegateAsyncCallbackParameter); + beginInvoke.Parameters.Add(delegateObjectParameter); + beginInvoke.ReturnType = delegateResultParameter.Type; + beginInvoke.Region = region; + delegateType.Methods.Add(beginInvoke); + + DefaultMethod endInvoke = new DefaultMethod(delegateType, "EndInvoke"); + endInvoke.Accessibility = Accessibility.Public; + endInvoke.IsSynthetic = true; + endInvoke.Parameters.Add(delegateResultParameter); + endInvoke.ReturnType = invoke.ReturnType; + endInvoke.Region = region; + delegateType.Methods.Add(endInvoke); + + DefaultMethod ctor = new DefaultMethod(delegateType, ".ctor"); + ctor.EntityType = EntityType.Constructor; + ctor.Accessibility = Accessibility.Public; + ctor.IsSynthetic = true; + ctor.Parameters.Add(delegateObjectParameter); + ctor.Parameters.Add(delegateIntPtrMethodParameter); + ctor.ReturnType = delegateType; + ctor.Region = region; + delegateType.Methods.Add(ctor); + } + #endregion + + #region Fields + public override IEntity VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + bool isSingleField = fieldDeclaration.Variables.Count == 1; + Modifiers modifiers = fieldDeclaration.Modifiers; + DefaultField field = null; + foreach (VariableInitializer vi in fieldDeclaration.Variables) { + field = new DefaultField(currentTypeDefinition, vi.Name); + + field.Region = isSingleField ? MakeRegion(fieldDeclaration) : MakeRegion(vi); + field.BodyRegion = MakeRegion(vi); + ConvertAttributes(field.Attributes, fieldDeclaration.Attributes); + + ApplyModifiers(field, modifiers); + field.IsVolatile = (modifiers & Modifiers.Volatile) != 0; + field.IsReadOnly = (modifiers & Modifiers.Readonly) != 0; + + field.ReturnType = ConvertType(fieldDeclaration.ReturnType); + if ((modifiers & Modifiers.Fixed) != 0) { + field.ReturnType = PointerTypeReference.Create(field.ReturnType); + } + + if ((modifiers & Modifiers.Const) != 0) { + field.ConstantValue = ConvertConstantValue(field.ReturnType, vi.Initializer); + } + + currentTypeDefinition.Fields.Add(field); + } + return isSingleField ? field : null; + } + + public override IEntity VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + { + DefaultField field = new DefaultField(currentTypeDefinition, enumMemberDeclaration.Name); + field.Region = field.BodyRegion = MakeRegion(enumMemberDeclaration); + ConvertAttributes(field.Attributes, enumMemberDeclaration.Attributes); + + field.ReturnType = currentTypeDefinition; + field.Accessibility = Accessibility.Public; + field.IsStatic = true; + if (!enumMemberDeclaration.Initializer.IsNull) { + field.ConstantValue = ConvertConstantValue(currentTypeDefinition, enumMemberDeclaration.Initializer); + } else { + IField prevField = currentTypeDefinition.Fields.LastOrDefault(); + if (prevField == null || prevField.ConstantValue == null) { + field.ConstantValue = ConvertConstantValue(currentTypeDefinition, new PrimitiveExpression(0)); + } else { + field.ConstantValue = new IncrementConstantValue(prevField.ConstantValue); + } + } + + currentTypeDefinition.Fields.Add(field); + return field; + } + #endregion + + #region Methods + public override IEntity VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + DefaultMethod m = new DefaultMethod(currentTypeDefinition, methodDeclaration.Name); + currentMethod = m; // required for resolving type parameters + m.Region = MakeRegion(methodDeclaration); + m.BodyRegion = MakeRegion(methodDeclaration.Body); + + + ConvertTypeParameters(m.TypeParameters, methodDeclaration.TypeParameters, methodDeclaration.Constraints, EntityType.Method); + m.ReturnType = ConvertType(methodDeclaration.ReturnType); + ConvertAttributes(m.Attributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget != "return")); + ConvertAttributes(m.ReturnTypeAttributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget == "return")); + + ApplyModifiers(m, methodDeclaration.Modifiers); + m.IsExtensionMethod = methodDeclaration.IsExtensionMethod; + + ConvertParameters(m.Parameters, methodDeclaration.Parameters); + if (!methodDeclaration.PrivateImplementationType.IsNull) { + m.Accessibility = Accessibility.None; + m.InterfaceImplementations.Add(ConvertInterfaceImplementation(methodDeclaration.PrivateImplementationType, m.Name)); + } + + currentTypeDefinition.Methods.Add(m); + currentMethod = null; + return m; + } + + void ConvertTypeParameters(IList output, AstNodeCollection typeParameters, AstNodeCollection constraints, EntityType ownerType) + { + // output might be non-empty when type parameters were copied from an outer class + int index = output.Count; + List list = new List(); + foreach (TypeParameterDeclaration tpDecl in typeParameters) { + DefaultTypeParameter tp = new DefaultTypeParameter(ownerType, index++, tpDecl.Name); + ConvertAttributes(tp.Attributes, tpDecl.Attributes); + tp.Variance = tpDecl.Variance; + list.Add(tp); + output.Add(tp); // tp must be added to list here so that it can be referenced by constraints + } + foreach (Constraint c in constraints) { + foreach (var tp in list) { + if (tp.Name == c.TypeParameter) { + foreach (AstType type in c.BaseTypes) { + PrimitiveType primType = type as PrimitiveType; + if (primType != null) { + if (primType.Keyword == "new") { + tp.HasDefaultConstructorConstraint = true; + continue; + } else if (primType.Keyword == "class") { + tp.HasReferenceTypeConstraint = true; + continue; + } else if (primType.Keyword == "struct") { + tp.HasValueTypeConstraint = true; + continue; + } + } + tp.Constraints.Add(ConvertType(type)); + } + break; + } + } + } + } + + DefaultExplicitInterfaceImplementation ConvertInterfaceImplementation(AstType interfaceType, string memberName) + { + return new DefaultExplicitInterfaceImplementation(ConvertType(interfaceType), memberName); + } + #endregion + + #region Operators + public override IEntity VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + { + DefaultMethod m = new DefaultMethod(currentTypeDefinition, operatorDeclaration.Name); + m.EntityType = EntityType.Operator; + m.Region = MakeRegion(operatorDeclaration); + m.BodyRegion = MakeRegion(operatorDeclaration.Body); + + m.ReturnType = ConvertType(operatorDeclaration.ReturnType); + ConvertAttributes(m.Attributes, operatorDeclaration.Attributes.Where(s => s.AttributeTarget != "return")); + ConvertAttributes(m.ReturnTypeAttributes, operatorDeclaration.Attributes.Where(s => s.AttributeTarget == "return")); + + ApplyModifiers(m, operatorDeclaration.Modifiers); + + ConvertParameters(m.Parameters, operatorDeclaration.Parameters); + + currentTypeDefinition.Methods.Add(m); + return m; + } + #endregion + + #region Constructors + public override IEntity VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + Modifiers modifiers = constructorDeclaration.Modifiers; + bool isStatic = (modifiers & Modifiers.Static) != 0; + DefaultMethod ctor = new DefaultMethod(currentTypeDefinition, isStatic ? ".cctor" : ".ctor"); + ctor.EntityType = EntityType.Constructor; + ctor.Region = MakeRegion(constructorDeclaration); + if (!constructorDeclaration.Initializer.IsNull) { + ctor.BodyRegion = MakeRegion(constructorDeclaration.Initializer.StartLocation, constructorDeclaration.EndLocation); + } else { + ctor.BodyRegion = MakeRegion(constructorDeclaration.Body); + } + ctor.ReturnType = currentTypeDefinition; + + ConvertAttributes(ctor.Attributes, constructorDeclaration.Attributes); + ConvertParameters(ctor.Parameters, constructorDeclaration.Parameters); + + if (isStatic) + ctor.IsStatic = true; + else + ApplyModifiers(ctor, modifiers); + + currentTypeDefinition.Methods.Add(ctor); + return ctor; + } + #endregion + + #region Destructors + public override IEntity VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) + { + DefaultMethod dtor = new DefaultMethod(currentTypeDefinition, "Finalize"); + dtor.EntityType = EntityType.Destructor; + dtor.Region = MakeRegion(destructorDeclaration); + dtor.BodyRegion = MakeRegion(destructorDeclaration.Body); + dtor.Accessibility = Accessibility.Protected; + dtor.IsOverride = true; + dtor.ReturnType = KnownTypeReference.Void; + + ConvertAttributes(dtor.Attributes, destructorDeclaration.Attributes); + + currentTypeDefinition.Methods.Add(dtor); + return dtor; + } + #endregion + + #region Properties / Indexers + public override IEntity VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + { + DefaultProperty p = new DefaultProperty(currentTypeDefinition, propertyDeclaration.Name); + p.Region = MakeRegion(propertyDeclaration); + p.BodyRegion = MakeBraceRegion(propertyDeclaration); + ApplyModifiers(p, propertyDeclaration.Modifiers); + p.ReturnType = ConvertType(propertyDeclaration.ReturnType); + ConvertAttributes(p.Attributes, propertyDeclaration.Attributes); + if (!propertyDeclaration.PrivateImplementationType.IsNull) { + p.Accessibility = Accessibility.None; + p.InterfaceImplementations.Add(ConvertInterfaceImplementation(propertyDeclaration.PrivateImplementationType, p.Name)); + } + p.Getter = ConvertAccessor(propertyDeclaration.Getter, p.Accessibility); + p.Setter = ConvertAccessor(propertyDeclaration.Setter, p.Accessibility); + currentTypeDefinition.Properties.Add(p); + return p; + } + + public override IEntity VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) + { + DefaultProperty p = new DefaultProperty(currentTypeDefinition, "Items"); + p.EntityType = EntityType.Indexer; + p.Region = MakeRegion(indexerDeclaration); + p.BodyRegion = MakeBraceRegion(indexerDeclaration); + ApplyModifiers(p, indexerDeclaration.Modifiers); + p.ReturnType = ConvertType(indexerDeclaration.ReturnType); + ConvertAttributes(p.Attributes, indexerDeclaration.Attributes); + if (!indexerDeclaration.PrivateImplementationType.IsNull) { + p.Accessibility = Accessibility.None; + p.InterfaceImplementations.Add(ConvertInterfaceImplementation(indexerDeclaration.PrivateImplementationType, p.Name)); + } + p.Getter = ConvertAccessor(indexerDeclaration.Getter, p.Accessibility); + p.Setter = ConvertAccessor(indexerDeclaration.Setter, p.Accessibility); + ConvertParameters(p.Parameters, indexerDeclaration.Parameters); + currentTypeDefinition.Properties.Add(p); + return p; + } + + IAccessor ConvertAccessor(Accessor accessor, Accessibility defaultAccessibility) + { + if (accessor.IsNull) + return null; + DefaultAccessor a = new DefaultAccessor(); + a.Accessibility = GetAccessibility(accessor.Modifiers) ?? defaultAccessibility; + a.Region = MakeRegion(accessor); + foreach (AttributeSection section in accessor.Attributes) { + if (section.AttributeTarget == "return") { + ConvertAttributes(a.ReturnTypeAttributes, section); + } else if (section.AttributeTarget != "param") { + ConvertAttributes(a.Attributes, section); + } + } + return a; + } + #endregion + + #region Events + public override IEntity VisitEventDeclaration(EventDeclaration eventDeclaration, object data) + { + bool isSingleEvent = eventDeclaration.Variables.Count == 1; + Modifiers modifiers = eventDeclaration.Modifiers; + DefaultEvent ev = null; + foreach (VariableInitializer vi in eventDeclaration.Variables) { + ev = new DefaultEvent(currentTypeDefinition, vi.Name); + + ev.Region = isSingleEvent ? MakeRegion(eventDeclaration) : MakeRegion(vi); + ev.BodyRegion = MakeRegion(vi); + + ApplyModifiers(ev, modifiers); + + ev.ReturnType = ConvertType(eventDeclaration.ReturnType); + + if (eventDeclaration.Attributes.Any(a => a.AttributeTarget == "method")) { + ev.AddAccessor = ev.RemoveAccessor = new DefaultAccessor { Accessibility = ev.Accessibility }; + } else { + // if there's no attributes on the accessors, we can re-use the shared accessor instance + ev.AddAccessor = ev.RemoveAccessor = DefaultAccessor.GetFromAccessibility(ev.Accessibility); + } + foreach (AttributeSection section in eventDeclaration.Attributes) { + if (section.AttributeTarget == "method") { + // as we use the same instance for AddAccessor and RemoveAccessor, we only need to add the attribute once + ConvertAttributes(ev.AddAccessor.Attributes, section); + } else if (section.AttributeTarget != "field") { + ConvertAttributes(ev.Attributes, section); + } + } + + currentTypeDefinition.Events.Add(ev); + } + return isSingleEvent ? ev : null; + } + + public override IEntity VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) + { + DefaultEvent e = new DefaultEvent(currentTypeDefinition, eventDeclaration.Name); + e.Region = MakeRegion(eventDeclaration); + e.BodyRegion = MakeBraceRegion(eventDeclaration); + ApplyModifiers(e, eventDeclaration.Modifiers); + e.ReturnType = ConvertType(eventDeclaration.ReturnType); + ConvertAttributes(e.Attributes, eventDeclaration.Attributes); + + if (!eventDeclaration.PrivateImplementationType.IsNull) { + e.Accessibility = Accessibility.None; + e.InterfaceImplementations.Add(ConvertInterfaceImplementation(eventDeclaration.PrivateImplementationType, e.Name)); + } + + e.AddAccessor = ConvertAccessor(eventDeclaration.AddAccessor, e.Accessibility); + e.RemoveAccessor = ConvertAccessor(eventDeclaration.RemoveAccessor, e.Accessibility); + + currentTypeDefinition.Events.Add(e); + return e; + } + #endregion + + #region Modifiers + static void ApplyModifiers(DefaultTypeDefinition td, Modifiers modifiers) + { + td.Accessibility = GetAccessibility(modifiers) ?? (td.DeclaringTypeDefinition != null ? Accessibility.Private : Accessibility.Internal); + td.IsAbstract = (modifiers & (Modifiers.Abstract | Modifiers.Static)) != 0; + td.IsSealed = (modifiers & (Modifiers.Sealed | Modifiers.Static)) != 0; + td.IsShadowing = (modifiers & Modifiers.New) != 0; + } + + static void ApplyModifiers(TypeSystem.Implementation.AbstractMember m, Modifiers modifiers) + { + // members from interfaces are always Public. + if (m.DeclaringTypeDefinition.ClassType == ClassType.Interface) { + m.Accessibility = Accessibility.Public; + return; + } + m.Accessibility = GetAccessibility(modifiers) ?? Accessibility.Private; + m.IsAbstract = (modifiers & Modifiers.Abstract) != 0; + m.IsOverride = (modifiers & Modifiers.Override) != 0; + m.IsSealed = (modifiers & Modifiers.Sealed) != 0; + m.IsShadowing = (modifiers & Modifiers.New) != 0; + m.IsStatic = (modifiers & Modifiers.Static) != 0; + m.IsVirtual = (modifiers & Modifiers.Virtual) != 0; + } + + static Accessibility? GetAccessibility(Modifiers modifiers) + { + switch (modifiers & Modifiers.VisibilityMask) { + case Modifiers.Private: + return Accessibility.Private; + case Modifiers.Internal: + return Accessibility.Internal; + case Modifiers.Protected | Modifiers.Internal: + return Accessibility.ProtectedOrInternal; + case Modifiers.Protected: + return Accessibility.Protected; + case Modifiers.Public: + return Accessibility.Public; + default: + return null; + } + } + #endregion + + #region Attributes + public override IEntity VisitAttributeSection(AttributeSection attributeSection, object data) + { + // non-assembly attributes are handled by their parent entity + if (attributeSection.AttributeTarget == "assembly") { + ConvertAttributes(parsedFile.AssemblyAttributes, attributeSection); + } + return null; + } + + void ConvertAttributes(IList outputList, IEnumerable attributes) + { + foreach (AttributeSection section in attributes) { + ConvertAttributes(outputList, section); + } + } + + void ConvertAttributes(IList outputList, AttributeSection attributeSection) + { + foreach (CSharp.Attribute attr in attributeSection.Attributes) { + outputList.Add(ConvertAttribute(attr)); + } + } + + IAttribute ConvertAttribute(CSharp.Attribute attr) + { + DomRegion region = MakeRegion(attr); + ITypeReference type = ConvertType(attr.Type); + if (!attr.Type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) { + // Try to add "Attribute" suffix, but only if the identifier + // (=last identifier in fully qualified name) isn't a verbatim identifier. + SimpleTypeOrNamespaceReference st = type as SimpleTypeOrNamespaceReference; + MemberTypeOrNamespaceReference mt = type as MemberTypeOrNamespaceReference; + if (st != null) + type = new AttributeTypeReference(st, st.AddSuffix("Attribute")); + else if (mt != null) + type = new AttributeTypeReference(mt, mt.AddSuffix("Attribute")); + } + List positionalArguments = null; + List> namedCtorArguments = null; + List> namedArguments = null; + foreach (Expression expr in attr.Arguments) { + NamedArgumentExpression nae = expr as NamedArgumentExpression; + if (nae != null) { + if (namedCtorArguments == null) + namedCtorArguments = new List>(); + namedCtorArguments.Add(new KeyValuePair(nae.Identifier, ConvertAttributeArgument(nae.Expression))); + } else { + AssignmentExpression ae = expr as AssignmentExpression; + if (ae != null && ae.Left is IdentifierExpression && ae.Operator == AssignmentOperatorType.Assign) { + string name = ((IdentifierExpression)ae.Left).Identifier; + if (namedArguments == null) + namedArguments = new List>(); + namedArguments.Add(new KeyValuePair(name, ConvertAttributeArgument(ae.Right))); + } else { + if (positionalArguments == null) + positionalArguments = new List(); + positionalArguments.Add(ConvertAttributeArgument(expr)); + } + } + } + return new CSharpAttribute(type, region, positionalArguments, namedCtorArguments, namedArguments); + } + #endregion + + #region Types + ITypeReference ConvertType(AstType type, bool isInUsingDeclaration = false) + { + return ConvertType(type, currentTypeDefinition, currentMethod, usingScope, isInUsingDeclaration); + } + + internal static ITypeReference ConvertType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration) + { + SimpleType s = type as SimpleType; + if (s != null) { + List typeArguments = new List(); + foreach (var ta in s.TypeArguments) { + typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); + } + if (typeArguments.Count == 0 && parentMethodDefinition != null) { + // SimpleTypeOrNamespaceReference doesn't support method type parameters, + // so we directly handle them here. + foreach (ITypeParameter tp in parentMethodDefinition.TypeParameters) { + if (tp.Name == s.Identifier) + return tp; + } + } + return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); + } + + PrimitiveType p = type as PrimitiveType; + if (p != null) { + switch (p.Keyword) { + case "string": + return KnownTypeReference.String; + case "int": + return KnownTypeReference.Int32; + case "uint": + return KnownTypeReference.UInt32; + case "object": + return KnownTypeReference.Object; + case "bool": + return KnownTypeReference.Boolean; + case "sbyte": + return KnownTypeReference.SByte; + case "byte": + return KnownTypeReference.Byte; + case "short": + return KnownTypeReference.Int16; + case "ushort": + return KnownTypeReference.UInt16; + case "long": + return KnownTypeReference.Int64; + case "ulong": + return KnownTypeReference.UInt64; + case "float": + return KnownTypeReference.Single; + case "double": + return KnownTypeReference.Double; + case "decimal": + return ReflectionHelper.ToTypeReference(TypeCode.Decimal); + case "char": + return KnownTypeReference.Char; + case "void": + return KnownTypeReference.Void; + default: + return SharedTypes.UnknownType; + } + } + MemberType m = type as MemberType; + if (m != null) { + ITypeOrNamespaceReference t; + if (m.IsDoubleColon) { + SimpleType st = m.Target as SimpleType; + if (st != null) { + t = new AliasNamespaceReference(st.Identifier, parentUsingScope); + } else { + t = null; + } + } else { + t = ConvertType(m.Target, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration) as ITypeOrNamespaceReference; + } + if (t == null) + return SharedTypes.UnknownType; + List typeArguments = new List(); + foreach (var ta in m.TypeArguments) { + typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); + } + return new MemberTypeOrNamespaceReference(t, m.MemberName, typeArguments, parentTypeDefinition, parentUsingScope); + } + ComposedType c = type as ComposedType; + if (c != null) { + ITypeReference t = ConvertType(c.BaseType, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration); + if (c.HasNullableSpecifier) { + t = NullableType.Create(t); + } + for (int i = 0; i < c.PointerRank; i++) { + t = PointerTypeReference.Create(t); + } + foreach (var a in c.ArraySpecifiers.Reverse()) { + t = ArrayTypeReference.Create(t, a.Dimensions); + } + return t; + } + Debug.WriteLine("Unknown node used as type: " + type); + return SharedTypes.UnknownType; + } + #endregion + + #region Constant Values + IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression) + { + ConstantValueBuilder b = new ConstantValueBuilder(); + b.convertVisitor = this; + ConstantExpression c = expression.AcceptVisitor(b, null); + if (c == null) + return null; + PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; + if (pc != null && pc.Type == targetType) { + // Save memory by directly using a SimpleConstantValue. + return new SimpleConstantValue(targetType, pc.Value); + } + // cast to the desired type + return new CSharpConstantValue(new ConstantCast(targetType, c), usingScope, currentTypeDefinition); + } + + IConstantValue ConvertAttributeArgument(Expression expression) + { + ConstantValueBuilder b = new ConstantValueBuilder(); + b.convertVisitor = this; + b.isAttributeArgument = true; + ConstantExpression c = expression.AcceptVisitor(b, null); + if (c == null) + return null; + PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; + if (pc != null) { + // Save memory by directly using a SimpleConstantValue. + return new SimpleConstantValue(pc.Type, pc.Value); + } else { + return new CSharpConstantValue(c, usingScope, currentTypeDefinition); + } + } + + sealed class ConstantValueBuilder : DepthFirstAstVisitor + { + internal TypeSystemConvertVisitor convertVisitor; + internal bool isAttributeArgument; + + protected override ConstantExpression VisitChildren(AstNode node, object data) + { + return null; + } + + public override ConstantExpression VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) + { + return new PrimitiveConstantExpression(KnownTypeReference.Object, null); + } + + public override ConstantExpression VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + TypeCode typeCode = Type.GetTypeCode(primitiveExpression.Value.GetType()); + return new PrimitiveConstantExpression(typeCode.ToTypeReference(), primitiveExpression.Value); + } + + IList ConvertTypeArguments(AstNodeCollection types) + { + int count = types.Count; + if (count == 0) + return null; + ITypeReference[] result = new ITypeReference[count]; + int pos = 0; + foreach (AstType type in types) { + result[pos++] = convertVisitor.ConvertType(type); + } + return result; + } + + public override ConstantExpression VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + return new ConstantIdentifierReference(identifierExpression.Identifier, ConvertTypeArguments(identifierExpression.TypeArguments)); + } + + public override ConstantExpression VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + { + TypeReferenceExpression tre = memberReferenceExpression.Target as TypeReferenceExpression; + if (tre != null) { + // handle "int.MaxValue" + return new ConstantMemberReference( + convertVisitor.ConvertType(tre.Type), + memberReferenceExpression.MemberName, + ConvertTypeArguments(memberReferenceExpression.TypeArguments)); + } + ConstantExpression v = memberReferenceExpression.Target.AcceptVisitor(this, data); + if (v == null) + return null; + return new ConstantMemberReference( + v, memberReferenceExpression.MemberName, + ConvertTypeArguments(memberReferenceExpression.TypeArguments)); + } + + public override ConstantExpression VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + { + return parenthesizedExpression.Expression.AcceptVisitor(this, data); + } + + public override ConstantExpression VisitCastExpression(CastExpression castExpression, object data) + { + ConstantExpression v = castExpression.Expression.AcceptVisitor(this, data); + if (v == null) + return null; + return new ConstantCast(convertVisitor.ConvertType(castExpression.Type), v); + } + + public override ConstantExpression VisitCheckedExpression(CheckedExpression checkedExpression, object data) + { + ConstantExpression v = checkedExpression.Expression.AcceptVisitor(this, data); + if (v != null) + return new ConstantCheckedExpression(true, v); + else + return null; + } + + public override ConstantExpression VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) + { + ConstantExpression v = uncheckedExpression.Expression.AcceptVisitor(this, data); + if (v != null) + return new ConstantCheckedExpression(false, v); + else + return null; + } + + public override ConstantExpression VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) + { + return new ConstantDefaultValue(convertVisitor.ConvertType(defaultValueExpression.Type)); + } + + public override ConstantExpression VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + ConstantExpression v = unaryOperatorExpression.Expression.AcceptVisitor(this, data); + if (v == null) + return null; + switch (unaryOperatorExpression.Operator) { + case UnaryOperatorType.Not: + case UnaryOperatorType.BitNot: + case UnaryOperatorType.Minus: + case UnaryOperatorType.Plus: + return new ConstantUnaryOperator(unaryOperatorExpression.Operator, v); + default: + return null; + } + } + + public override ConstantExpression VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + ConstantExpression left = binaryOperatorExpression.Left.AcceptVisitor(this, data); + ConstantExpression right = binaryOperatorExpression.Right.AcceptVisitor(this, data); + if (left == null || right == null) + return null; + return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right); + } + + static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0); + + public override ConstantExpression VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) + { + if (isAttributeArgument) { + return new PrimitiveConstantExpression(systemType, convertVisitor.ConvertType(typeOfExpression.Type)); + } else { + return null; + } + } + + public override ConstantExpression VisitArrayCreateExpression(ArrayCreateExpression arrayObjectCreateExpression, object data) + { + var initializer = arrayObjectCreateExpression.Initializer; + if (isAttributeArgument && !initializer.IsNull) { + ITypeReference type; + if (arrayObjectCreateExpression.Type.IsNull) + type = null; + else + type = convertVisitor.ConvertType(arrayObjectCreateExpression.Type); + ConstantExpression[] elements = new ConstantExpression[initializer.Elements.Count]; + int pos = 0; + foreach (Expression expr in initializer.Elements) { + ConstantExpression c = expr.AcceptVisitor(this, data); + if (c == null) + return null; + elements[pos++] = c; + } + return new ConstantArrayCreation(type, elements); + } else { + return null; + } + } + } + #endregion + + #region Parameters + void ConvertParameters(IList outputList, IEnumerable parameters) + { + foreach (ParameterDeclaration pd in parameters) { + DefaultParameter p = new DefaultParameter(ConvertType(pd.Type), pd.Name); + p.Region = MakeRegion(pd); + ConvertAttributes(p.Attributes, pd.Attributes); + switch (pd.ParameterModifier) { + case ParameterModifier.Ref: + p.IsRef = true; + p.Type = ByReferenceTypeReference.Create(p.Type); + break; + case ParameterModifier.Out: + p.IsOut = true; + p.Type = ByReferenceTypeReference.Create(p.Type); + break; + case ParameterModifier.Params: + p.IsParams = true; + break; + } + if (!pd.DefaultExpression.IsNull) + p.DefaultValue = ConvertConstantValue(p.Type, pd.DefaultExpression); + outputList.Add(p); + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs new file mode 100644 index 0000000000..252e3fb1e5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs @@ -0,0 +1,43 @@ +// +// AssemblyInfo.cs +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// +// Copyright (C) 2007 Novell, Inc (http://www.novell.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.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle ("Mono C# Compiler")] +[assembly: AssemblyProduct ("Mono C# Compiler")] +[assembly: AssemblyCopyright ("2001 - 2009 Novell, Inc.")] +[assembly: AssemblyCompany ("Novell, Inc.")] +[assembly: AssemblyCulture ("")] +[assembly: AssemblyConfiguration ("")] + +[assembly: AssemblyVersion ("1.0")] +[assembly: AssemblyFileVersion ("1.0")] + +[assembly: AssemblyDescription ("Mono C# Compiler")] + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog new file mode 100644 index 0000000000..bb00893065 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog @@ -0,0 +1,34100 @@ +2010-07-28 Marek Safar + + * anonymous.cs, assign.cs, attribute.cs, decl.cs, delegate.cs, + doc.cs, dynamic.cs, ecore.cs, expression.cs, generic.cs, import.cs, + iterators.cs, linq.cs, membercache.cs, method.cs, report.cs, + statement.cs, typemanager.cs: Major name lookup fixes to deal with + C# 3.0 invocable members, correctly handle accessibility hidding and + property-like different get/set base accessors. + + Also fixes bugs #624870, #618522, #616068, #444180, #333891 + +2010-07-14 Marek Safar + + * namespace.cs, import.cs: When importing nested type via type + arguments set their parent type correctly (Fixes #622051). + +2010-07-14 Marek Safar + + A fix for bug #622104 + * attribute.cs: Add default lookup flags. + +2010-07-12 Marek Safar + + * generic.cs: Don't use Report directly. + + * expression.cs, ecore.cs: UserOperatorCall uses MethodSpec without + MethodGroupExpr, will be simplified later. + +2010-07-09 Marek Safar + + * property.cs, parameters.cs: Inflated IndexerSpec parameters. + + * import.cs: Don't build unused parameters. + +2010-07-08 Marek Safar + + * expression.cs (Invocation): Don't recreate simple-name expression. + +2010-07-07 Marek Safar + + * ecore.cs: Don't report NRE warning for lifted null. + +2010-07-07 Marek Safar + + * typemanager.cs, convert.cs, expression.cs: Another reference + equality implementation attack (Fixes #620025, #579058). + +2010-07-05 Marek Safar + + * context.cs, expression.cs, ecore.cs: BaseThis is fully based on + this expression (Fixes #619904). + +2010-07-05 Marek Safar + + * membercache.cs, class.cs: Don't use base member to check for + property or indexer base implementation. + +2010-07-03 Marek Safar + + * membercache.cs: Copy Membercache member state flags for 2 stage + inflate (Fixes #619555). + + * ecore.cs: Use resolved accessors everywhere. + +2010-07-02 Marek Safar + + A fix for bug #360820 + * membercache.cs, property.cs: Check accessors of base property and + not the closest one. + +2010-07-02 Marek Safar + + * modifiers.cs, membercache.cs, import.cs, class.cs: Moved imported + override method checks into import. + + * expression.cs: Removed redundant check. + +2010-06-30 Marek Safar + + * nullable.cs, expression.cs, statement.cs, method.cs, ecore.cs, + delegate.cs, cs-parser.jay, visit.cs: Use MemberAccess to resolve + base access expression, it has all bits done correctly. + +2010-06-30 Marek Safar + + * support.cs: Removed unused code. + + * ecore.cs: Don't use memberlookup for operators. + +2010-06-30 Marek Safar + + * typemanager.cs, membercache.cs, convert.cs, expression.cs, + ecore.cs: Replace remaining MethodLookup with correct user operator + lookup (to do correct deep lookup). Clean up most of outstanding + quirks in binary operator overload resolution. + +2010-06-29 Marek Safar + + * import.cs: Operators must have between 1 and 2 parameters. + + * method.cs: Switch destructor to direct membercache lookup + +2010-06-29 Marek Safar + + * driver.cs, expression.cs: Use Membercache for StringConcat when + it got all what is needed. + +2010-06-29 Marek Safar + + * membercache.cs, expression.cs, statement.cs, doc.cs, ecore.cs: + Changed FindMembers to allocate a new list only when a filter is + used. Saves decent chunk of memory and should save even more in the + future when the filter is not used that often. + +2010-06-28 Marek Safar + + * field.cs, property.cs, assign.cs, const.cs, expression.cs, + ecore.cs, class.cs, cs-parser.jay, enum.cs: Don't use intermediate + structure for simple type fields (saves memory and makes few things + simpler). Clean up some hacks mostly for events. + +2010-06-25 Marek Safar + + * statement.cs, cs-parser.jay: Don't create expensive block for + simple statements. + +2010-06-24 Marek Safar + + * statement.cs, report.cs: Rethrow internal error when reporting is + disabled. + + * ecore.cs: Check for identical name only when simple name is set. + Fixes #616667 + +2010-06-24 Marek Safar + + A fix for bug #616809 + * generic.cs, expression.cs, ecore.cs: Added a new type expression + for open generic type to pass unbound type arguments to typeof + expression. + +2010-06-24 Marek Safar + + * statement.cs: Foreach collection implementation refactoring to + search for GetEnumerator more preciselly. Fixes #431453 and more + unreported bugs. + + * linq.cs, decl.cs, ecore.cs, delegate.cs: Update methodgroup api. + +2010-06-23 Marek Safar + + * cs-parser.jay: Track more locations. + +2010-06-22 Marek Safar + + * cs-tokenizer.cs, location.cs, cs-parser.jay: Track more locations. + +2010-06-18 Marek Safar + + * cs-tokenizer.cs, anonymous.cs, expression.cs, statement.cs, + support.cs, location.cs, cs-parser.jay: Some work on full ast mode. + +2010-06-18 Marek Safar + + * convert.cs, typespec.cs, method.cs: Fixed few more dynamic + conversion. + +2010-06-18 Marek Safar + + * typemanager.cs, namespace.cs: Report more predefined types and + imported types collision types as a warning. + Fixes #537414, #601157 + +2010-06-18 Marek Safar + + * generic.cs: Overrides base method constraint can use method type + parameter. + + * import.cs: Removed redundant cache. + +2010-06-17 Marek Safar + + * generic.cs: Propagate type only inflate downwards. + +2010-06-17 Marek Safar + + A fix for bug #614955 + * method.cs: Do not reject binary dynamic operators. + +2010-06-17 Marek Safar + + * typespec.cs: Internal types have no generic parameters. + Fixes #615022. + +2010-06-17 Marek Safar + + A fix for bug #614955 + * cs-parser.jay: Correctly set expression mode for default parameter + values. + +2010-06-17 Marek Safar + + A fix for bug #615023 + * ecore.cs: Resolve dynamic namespace and keyword collision in the + favour of the keyword. + +2010-06-17 Marek Safar + + A fix for bug #614917 + * convert.cs: Allow more undocumented 0 like values to enum type + conversions. + +2010-06-17 Marek Safar + + * generic.cs, method.cs: Inflate copied type parameters from base + class or explicit interfaces. + + * convert.cs: Fixed conversion between two type parameters. + Fixes #614471 + +2010-06-16 Marek Safar + + * membercache.cs, convert.cs: Correctly resize an array used by + GetUserOperator. + +2010-06-15 Marek Safar + + A fix for bug #599601 + * dynamic.cs, ecore.cs: A new flag for dynamic resolver to ignore + generated member access left expression. + +2010-06-16 Marek Safar + + * expression.cs: Dispatch dynamic invocation solely on left + expression type. + +2010-06-16 Marek Safar + + * expression.cs, statement.cs: Always persist explicit cast + semantic at expression level. + +2010-06-15 Marek Safar + + * expression.cs, attribute.cs: Enable generic type parameters + attribute check. + +2010-06-15 Marek Safar + + A fix for bug #612146 + * generic.cs: Don't use fixed array for inflated type parameter + interface constraints. + +2010-06-15 Marek Safar + + * typespec.cs: ElementTypeSpec has to use its own ITypeDefinition. + + * report.cs: Unwrap elements for related symbols reporting. + +2010-06-15 Marek Safar + + A fix for bug #612796 + * cs-tokenizer.cs: Offset correctly keywords the first character + comparison. + +2010-06-15 Marek Safar + + A fix for bug #613397 + * expression.cs: Removed too aggressive object initializers + optimization. + +2010-06-15 Marek Safar + + * parameter.cs, property.cs, membercache.cs, decl.cs, iterators.cs, + anonymous.cs, expression.cs, support.cs, method.cs, pending.cs, + class.cs, cs-parser.jay: Simplify parsing of accessors by removing + any intermediate steps and fake nodes, also saves few MBs of memory. + +2010-06-11 Marek Safar + + * modifiers.cs, rootcontext.cs, location.cs, cs-parser.jay: More + precise modifiers parsing. + +2010-06-09 Marek Safar + + * cs-tokenizer.cs, anonymous.cs, expression.cs, cs-parser.jay: + Fixed few shift/reduce conflicts. + +2010-06-09 Marek Safar + + * typemanager.cs, parameter.cs, dynamic.cs, typespec.cs, + expression.cs, ecore.cs, cs-parser.jay: Fully parse composed type + specifiers and stop using string in AST. + +2010-06-07 Marek Safar + + * typemanager.cs, eval.cs, iterators.cs, anonymous.cs, expression.cs + method.cs, class.cs, delegate.cs, cs-parser.jay, driver.cs, visit.cs + enum.cs: Hold location of predefined types. + +2010-06-07 Marek Safar + + A fix for bug #610878 + * pending.cs: Clone cached list before modifying. + +2010-06-04 Marek Safar + + * convert.cs, typespec.cs, expression.cs: Start using array member + kind for better conversion checks. + + * import.cs, report.cs: Report better error message for runtime + reflection bugs. + +2010-06-04 Marek Safar + + * membercache.cs, convert.cs, nullable.cs, expression.cs: Optimize + user defined conversion probing and simplify user conversion for + nullabe types. Fixes #610940. + +2010-06-03 Marek Safar + + A fix for bug #610919 + * parameter.cs, property.cs, cs-parser.jay: Use independent implicit + parameters for explicit event accessors. Anonymous method capturing + won't otherwise work for event implicit parameter. + +2010-06-02 Marek Safar + + A fix for bug #610088 + * nullable.cs, expression.cs, statement.cs, method.cs, ecore.cs: + Ignore overrides for base overload resolution as for non-base + expressions and convert the best candidate to closest override + afterwards. + +2010-06-01 Marek Safar + + A fix for bug #610139 + * generic.cs, convert.cs: Recursively check effective base interface + +2010-06-01 Marek Safar + + * statement.cs: Handle nullable types and type parameters in using + statement, avoid boxing value types. Also fixes #571010 + +2010-06-01 Marek Safar + + * convert.cs, expression.cs: Emit unbox for underlying nullable + type boxing cast. + +2010-05-29 Marek Safar + + A fix for bug #610126 + * expression.cs: Don't use branch optimization for types bigger than + int. + +2010-05-28 Marek Safar + + A fix for bug #609088 + * import.cs: Check private modifier correctly. + +2010-05-28 Marek Safar + + A fix for bug #609049 + * ecore.cs: Don't ignore override methods when looking for base + member. + +2010-05-27 Marek Safar + + A fix for bugs #608007, #572540, #566130, #476358 + + * generic.cs, linq.cs, expression.cs, statement.cs, cs-parser.jay: + More tricky refactoring of implicit linq blocks. + +2010-05-25 Marek Safar + + * linq.cs, cs-parser.jay: Keep location for all linq clauses. + +2010-05-25 Marek Safar + + * context.cs, expression.cs, cs-parser.jay: Don't store current + block in This expression (it's too early for linq blocks). + +2010-05-21 Marek Safar + + * expression.cs: Use constrained prefix more broadly to avoid boxing. + +2010-05-20 Marek Safar + + A fix for bug #591149 + * nullable.cs: Don't double wrap same expression. + +2010-05-20 Marek Safar + + A fix for bug #569827 + * anonymous.cs: Any issued error in probing mode means no match. + +2010-05-20 Marek Safar + + * expression.cs: Search for base indexer using the closest match + rule. + +2010-05-20 Marek Safar + + A fix for bug #572071 + * method.cs: Set override constraints using unexpanded interface + list. + +2010-05-20 Marek Safar + + A fix for bug #572071 + * ecore.cs: Include secondary extension method lookup in probing + mode. + +2010-05-19 Marek Safar + + A fix for bug #515801 + * typespec.cs (MayBecomeEqualGenericTypes): Recursively check + type arguments. + +2010-05-19 Marek Safar + + A fix for bug #515801 + * pending.cs: Advance counter correctly. + +2010-05-19 Marek Safar + + A fix for bug #480139 + * method.cs, pending.cs: Indexer override uses base name. + +2010-05-19 Marek Safar + + A fix for bug #424064 + * generic.cs: Replace original with inflated type parameter on + failure. + +2010-05-19 Marek Safar + + A fix for bug #359733 + * parameter.cs: Extension attribute can be defined in each assembly. + +2010-05-18 Marek Safar + + A fix for bug #446507 + * method.cs: Only one method can implement an interface. + +2010-05-18 Marek Safar + + A fix for bug #594905 + * convert.cs, constant.cs, expression.cs, literal.cs, ecore.cs: + Typed null can be used as a source for expression methods. + +2010-05-18 Marek Safar + + A fix for bug #606551 + * namespace.cs: Using directive imports only types and not nested + namespaces. + +2010-05-17 Marek Safar + + * typespec.cs, expression.cs, statement.cs, ecore.cs, complete.cs, + delegate.cs: Member instance is resolved after member overload + definitely resolves static/instance property of member expression. + Fixes #545047, #358848, #456605, #460016, #603299 + +2010-05-12 Marek Safar + + A fix for bug #604981 + * generic.cs, decl.cs, anonymous.cs: Reset more type arguments + details for nested anonymous methods stories. + +2010-05-11 Marek Safar + + A fix for bug #604735 + * namespace.cs: Don't report namespace collision. + +2010-05-11 Marek Safar + + A fix for bug #604748 + * class.cs, typespec.cs: Search full imported attribute hierarchy + for AttributeUsage. + +2010-05-11 Marek Safar + + * namespace.cs: Ignore missing dependencies failure at + initialization. + +2010-05-11 Marek Safar + + A fix for bug #604640 + * namespace.cs: Don't resolve using constraints too early. + +2010-05-11 Marek Safar + + A fix for bug #604239 + * generic.cs: Copy partial type constraints to partial container. + +2010-05-10 Marek Safar + + A fix for bug #557210 + * import.cs: Relax underlying enum field rules. + +2010-05-10 Marek Safar + + A fix for bug #603476 + * property.cs: Implement IParametersMember for indexer accessors. + +2010-05-07 Marek Safar + + A fix for bug #601141 + * class.cs: Update all partial modifiers. + +2010-05-06 Marek Safar + + A fix for bug #601708 + * method.cs, membercache.cs: Destructors cannot be hidden. + +2010-05-06 Marek Safar + + A fix for bug #602551 + * class.cs: Resursive reference of type definition is allowed. + +2010-05-06 Marek Safar + + * anonymous.cs: Mutate cached storey instance types too. + +2010-05-06 Marek Safar + + A fix for bug #602443 + * convert.cs: Explicit enum conversion cannot involve user operators + +2010-05-05 Miguel de Icaza + + * class.cs (TypeContainer.DefineBaseTypes) + (TypeContainer.CheckRecursiveDefinition): check for the iface not + being null, as we could have failed resolution and crashed; + Fixes #442144 + + * cs-parser.jay: Productions to catch common mistakes when other + punctuation operators are used instead of comma. Fixes 571702 + +2010-05-05 Marek Safar + + * anonymous.cs: Mutate correct set of constraints. + +2010-05-05 Marek Safar + + A fix for bug #602842 + * expression.cs: Resolve all array bound arguments. + +2010-05-05 Marek Safar + + * import.cs: Don't import private fields. + +2010-04-30 Marek Safar + + Partially based on patch by + + * eval.cs, ecore.cs: Fixed eval show methods. + +2010-04-30 Marek Safar + + * generic.cs, delegate.cs: Implement output type inference of + methodgroup now when the specification was cleared at least little + bit. + +2010-04-29 Marek Safar + + A fix for bug #575611 + * class.cs: Fix recursive unmanaged recursice sruct check. + +2010-04-29 Marek Safar + + A fix for bug #479776 + * expression.cs: Implement typeof unbounded nested generic types. + +2010-04-29 Marek Safar + + A fix for bug #474953 + * class.cs: Fix valid recursive base type definition. + +2010-04-29 Marek Safar + + A fix for bug #421737 + * convert.cs, expression.cs: A boxing conversion exists from a + nullable-type to a reference type, if a boxing conversion exists + from the underlying non-nullable-value-type to the reference type. + +2010-04-29 Marek Safar + + A fix for bug #376875 + * import.cs: Import volatile modifier. + +2010-04-29 Marek Safar + + A fix for bug #372412 + * typespec.cs, expression.cs, codegen.cs: Emit readonly prefix for + generic arrays. + +2010-04-29 Marek Safar + + A fix for bug #568955 + * statements.cs: Handle recursive scope initializers. + +2010-04-28 Marek Safar + + A fix for bug #566511 + * anonymous.cs: Always get inflated version of hoisted variable + on generic type definition. + +2010-04-28 Marek Safar + + * import.cs, membercache.cs: Relax rules for valid properties. + +2010-04-28 Marek Safar + + * import.cs: Intern arrays used in generic arguments. + +2010-04-28 Marek Safar + + A fix for bug #600398 + * convert.cs: Actually use effective base type for the comparison. + +2010-04-28 Marek Safar + + A fix for bug #600326 + * ecore.cs: Pass arity to base member lookup. + +2010-04-28 Marek Safar + + A fix for bug #573385 + * expression.cs: MemberAccess is of generic type based on right + arity length only. + +2010-05-28 Marek Safar + + * cs-tokenizer.cs: Made tab size configurable. + +2010-05-27 Marek Safar + + * attribute.cs: Ensure Obsolete members are defined before doing + ctor look-up. + +2010-05-27 Marek Safar + + * visit.cs: Add DOM visitor skeleton. + + * *.cs: Updated. + +2010-05-27 Marek Safar + + * attribute.cs, codegen.cs: Drop COMPILER_ACCESS hack. + +2010-05-27 Marek Safar + + * *.cs: Major rewrite of compiler internals to better work with + unmodified System.Reflection.Emit. Some of the key changes are + - TypeSpec replaces reflection specific System.Type. + - All Type(TypeSpec) operations are now done in compiler therefore + no dependency on SRE to inflate generic members and types or to + query unclosed types. + - MemberCache is now the only and full hierarchical topology. + - Generic constraints are implemented properly. + - And as a bonus compilation is on average 30% faster. + +2010-04-15 Jb Evain + + * dmcs.exe.config: update the runtime version to .net 4.0 RTM. + +2010-04-12 Marek Safar + + * expression.cs, attribute.cs, parameter.cs: More attribute type + checks. + +2010-04-12 Marek Safar + + A fix for bug #593342 + + * generic.cs, parameter.cs, argument.cs, field.cs, property.cs, + decl.cs, roottypes.cs, constant.cs, nullable.cs, expression.cs, + method.cs, ecore.cs, class.cs, delegate.cs, attribute.cs, + codegen.cs: Add custom attribute encoder to deal with unfinished + types and easier corlib bootstrap from its own types. + +2010-03-26 Marek Safar + + * cs-parser.jay: Report invalid constraint types. + +2010-03-16 Jb Evain + + * Makefile: rename the net_2_1 profile to moonlight. + +2010-03-11 Marek Safar + + * statement.cs, cs-parser.jay: Use correct location for empty + statements. + +2010-03-11 Marek Safar + + * cs-parser.jay: Disable Location from expression. + + * generic.cs: Check constraints for overrides in the parser. + +2010-03-09 Marek Safar + + * cs-parser.jay (GetLocation): Use an expression when available. + +2010-03-04 Marek Safar + + A fix for bug #582579 + * ecore.cs (FieldExpr): Don't optimize cross reference loads. + +2010-03-04 Marek Safar + + A patch by kornelpal@gmail.com + + * dynamic.cs, anonymous.cs, rootcontext.cs, class.cs: Don't make + compiler generated classes sealed by default. Emit and close top + level compiler generated classes as well. + + * support.cs: Use RuntimeHelpers.GetHashCode. + +2010-03-03 Rolf Bjarne Kvinge + + * Makefile: We need to use the internal bootstrapping gmcs for + net_2_1_bootstrap too now. + +2010-03-02 Raja R Harinath + + * expression.cs (IndexerAccess.ResolveAccessor): Add CS1540 check. + +2010-03-02 Marek Safar + + * cs-tokenizer.cs: Missed few locations in previous fix. + +2010-03-02 Marek Safar + + * cs-tokenizer.cs, argument.cs, dynamic.cs, assign.cs, anonymous.cs, + nullable.cs, expression.cs, statement.cs, cs-parser.jay, cfold.cs: + Report correct location for operator errors. + +2010-03-02 Marek Safar + + * typemanager.cs (IsDynamicType): Don't check external types when + the attribute is not external. + +2010-02-24 Marek Safar + + A fix for bug #582579 + * decl.cs (IsExposedFromAssembly): Use PartialContainer for parent + modifiers. + +2010-02-24 Marek Safar + + A fix for bug #581804 + * ecore.cs: Fixed type comparison. + +2010-02-08 Miguel de Icaza + + * namespace.cs (CompletionGetTypesStartingWith): Do not include + private types in the completion results. + + * cs-parser.jay: Bubble completions after "from x in ?" and "from x + ... let ?" + +2010-02-17 Marek Safar + + * generic.cs, field.cs, decl.cs, cs-parser.jay: Simplify special + constraint parsing. + +2010-02-14 Miguel de Icaza + + * eval.cs: Do not do the report printer dance unless the user has + set the DescribeTypes feature. + +2010-02-10 Marek Safar + + * argument.cs, dynamic.cs, expression.cs: Track RC API changes. + +2010-02-08 Marek Safar + + A fix for bug #577029 + * anonymous.cs: Fixed TypeBuilder* check. + +2010-02-06 Miguel de Icaza + + * eval.cs (CompileBlock): Also undo if there are problems during + semantic analysis, fixes various cases where invalid C# code would + be reported, but the internal changes would not be undone. + +2010-02-03 Miguel de Icaza + + * driver.cs: Change the --fatal flag to allow a number to be + passed, this ignores the first N fatal errors. Useful to debug + errors that do not happen on the first hit. + + * cs-parser.jay (invocation_expression): accept both the + CLOSE_PARENS and COMPLETE_COMPLETION, this allows completions + inside an invocation. + + * driver.cs: Expose FatalErrors. + + * eval.cs: Initialize the printer's Fatal property from the + Driver's FatalError flag, this allows csharp --fatal to work + again. + + Add support for calling Describe (typeof (TYPE)) if the expression + entered is a TYPE. + +2010-02-02 Marek Safar + + A fix for bug #574991 + * rootcontext.cs, class.cs, driver.cs: Hide enhanced warnings behind + --lint. + +2010-02-02 Marek Safar + + A fix for bug #575986 + * expression.cs: Don't mutate typeof type definitions. + +2010-01-28 Marek Safar + + * decl.cs: Use only one set of modifiers. + +2010-01-26 Marek Safar + + A fix for bug #573329 + * eval.cs: Don't disable error reporting completely on silent mode. + +2010-01-25 Marek Safar + + A fix for bug #573312 + * constant.cs, expression.cs, ecore.cs: Emit correct offset for + pointer index of unknown size types greater than 2. + +2010-01-15 Marek Safar + + * *.cs: Use only 1 member kind enum. + +2010-01-15 Marek Safar + + * *.cs: Add event specification. + +2010-01-14 Marek Safar + + * membercache.cs: Extracted from decl.cs. + + * *.cs: Put more infrastructure in place. + +2010-01-13 Marek Safar + + * *.cs: Add property specification, unused yet. + +2010-01-13 Marek Safar + + * property.cs: Move all property based declarations into a new file. + +2010-01-13 Marek Safar + + * expression.cs (Conditional): Resolve reduced expression. + +2010-01-13 Marek Safar + + * *.cs: Introduced non-generic method specification. + +2010-01-07 Marek Safar + + * method.cs: Move all method based declarations into a new file. + +2010-01-07 Marek Safar + + * *.cs: Extract field specification. + +2009-12-17 Marek Safar + + * field.cs: Extracted from class.cs + +2009-12-15 Marek Safar + + * attribute.cs (GetFixedBuffer): Work on field definition only. + +2009-12-15 Marek Safar + + * *.cs: Clean up NET_4_0 conditional where possible. + +2009-12-14 Rodrigo Kumpera + + support.cs (DynamicType): Assembly property returns the assembly builder. + This is required due to how compiler context works in corlib. + +2009-12-14 Marek Safar + + A fix for bug #564376 + * assign.cs (LocalTemporary): Removed no longer needed special + by-ref handling. + +2009-12-11 Marek Safar + + * modifiers.cs, decl.cs, iterators.cs, const.cs, anonymous.cs, + class.cs, delegate.cs, cs-parser.jay, enum.cs: Turn modifiers into + enum for easier debugging. + +2009-12-10 Marek Safar + + * decl.cs, anonymous.cs, class.cs: Sealed Define it's now main entry + point. + + * parameter.cs, delegate.cs, dynamic.cs: Don't use builder methods + directly. + +2009-12-10 Marek Safar + + * cs-parser.jay, statement.cs: Handle parser error in code + completition. + +2009-12-10 Marek Safar + + * ecore.cs: Ignore base imported methods when they are already + in method bag. + + * eval.cs: Handle non-existent keys. + + * report.cs, driver.cs: Make fatal work with console printer only. + +2009-12-08 Rodrigo Kumpera + + * typemanager.cs (MakeGenericMethod): Fix stupid mistake. + +2009-12-08 Rodrigo Kumpera + + * typemanager.cs: Add MakeGenericMethod that checks if the method + is really the generic method definition. + + ecore.cs (MethodGroupExpr:IsApplicable): Use new TypeManager function + to inflate generic methods. + +2009-12-08 Marek Safar + + A fix for bug #561149 + * anonymous.cs: Use actual type parameters when checking for generic + method host. + +2009-12-08 Marek Safar + + A fix for bug #561369 + * expression.cs (DoNumericPromotion): Fixed typo. + +2009-12-08 Marek Safar + + *.cs: Moving to generics world. + + cs-parser.jay: Removed current_array_type. + +2009-12-07 Marek Safar + + *.cs: Moving to generics world. + +2009-12-04 Marek Safar + + *.cs: Moving to generics world (day 2). + +2009-12-03 Marek Safar + + *.cs: Moving to generics world. + +2009-12-02 Marek Safar + + * typemanager.cs, parameter.cs, class.cs, delegate.cs, attribute.cs: + Encode dynamic type attribute for elements where attributes cannot + be used. + +2009-12-01 Marek Safar + + argument.cs, assign.cs, expression.cs, cs-parser.jay: Named + arguments by ref. + +2009-12-01 Marek Safar + + A fix for bug #360455 + * class.cs: Never report a unused warning for generic events to + workaround wrong expression type. + +2009-11-30 Marek Safar + + A fix for bug #558305 + * decl.cs, class.cs: Check partial method definitions using correct + flag. + +2009-11-30 Marek Safar + + * argument.cs: Don't cache rarely used dynamic flag. + +2009-11-27 Marek Safar + + * cs-parser.jay: Use jay global stacks (saves over 3MB for corlib). + +2009-11-27 Marek Safar + + * ecore.cs (SimpleName): Removed no longer needed in_transit as + Resolve is now non-reentrant (saves ~0.6MB for corlib). + +2009-11-26 Marek Safar + + A fix for bug #545081 + * decl.cs: Check private nested types of nested types recursively. + +2009-11-26 Marek Safar + + A fix for bug #558305 + * location.cs: Ignore self referencing #line directive + +2009-11-26 Marek Safar + + A fix for bug #558292 + * class.cs: Allow single unsafe fixed buffer fields. + +2009-11-26 Marek Safar + + * expression: Optimize few more zero-based operations. + +2009-11-26 Marek Safar + + * cs-tokenizer.cs, cs-parser.jay: Simplify literal parsing, also + avoids boxing of literal values. + +2009-11-26 Marek Safar + + * cs-tokenizer.cs, argument.cs, eval.cs, linq.cs, decl.cs, + expression.cs, ecore.cs, location.cs, cs-parser.jay, attribute.cs, + codegen.cs: LocatedToken redesing to avoid excessive allocation and + boxing (saves ~7MB for corlib). Also fixes presise token location. + +2009-11-25 Marek Safar + + * ecore.cs, cs-parser.jay: Keep parser structures local. Share + common data buckers. + +2009-11-24 Marek Safar + + * expression.cs: Lower static array initializer barrier. + + * support.cs, driver.cs: Share reader buffer. + +2009-11-23 Marek Safar + + * cs-tokenizer.cs, support.cs: Some tokenizer optimizations. + +2009-11-23 Marek Safar + + * cs-tokenizer.cs, support.cs: Use Dictionary instead of Hashtable, + cleanup some obsolete code. + +2009-11-20 Marek Safar + + * context.cs, expression.cs, ecore.cs, complete.cs: Cleaned up + Expression.Resolve. + +2009-11-20 Marek Safar + + * *.cs: Resolved expressions are never resolved again, this helps to + uncover some not easy to find bugs and improve the performance. + +2009-11-19 Marek Safar + + * *.cs: Made constant expressions fully compatible with any other + expression. + +2009-11-19 Marek Safar + + * *.cs: DoResolve is a worker method and has to be protected. + +2009-11-18 Marek Safar + + * *.cs: More context specific handling. + +2009-11-17 Marek Safar + + * *.cs: More context specific handling. + +2009-11-16 Marek Safar + + * dynamic.cs, class.cs: Removed few fixed user types conversions. + + * symbolwriter.cs: Uses public ILOffset. + +2009-11-13 Marek Safar + + A fix for bug #553650 + * generic.cs: Another missing TypeToCoreType, still too many to fix. + +2009-11-13 Marek Safar + + A fix for bug #555170 + + * class.cs, delegate.cs, enum.cs: Constants have to be available + for parameters resolve. + +2009-11-12 Marek Safar + + * typemanager.cs, argument.cs, support.cs, delegate.cs: Dynamic + arrays. + +2009-11-12 Marek Safar + + * argument.cs, context.cs, expression.cs, ecore.cs: Dynamic binding + with a statically known candidate set. + +2009-11-11 Scott Peterson + + * generic.cs: Made type inflation for generic constraint checks + recursive. This fixes BGO #553655. + +2009-11-11 Marek Safar + + * dynamic.cs, decl.cs, expression.cs, ecore.cs: More dynamic type + checks. + +2009-11-10 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, argument.cs, dynamic.cs, + linq.cs, rootcontext.cs, ecore.cs, class.cs, delegate.cs, + attribute.cs: Add some dynamic error checking. + +2009-11-07 Marek Safar + + A fix for bug #553465 + + * expression.cs: Fixed mixed version of expression tree anonymous + type. + +2009-11-06 Marek Safar + + A fix for bug #553031 + + * linq.cs, expression.cs, class.cs, cs-parser.jay: Initialize + expression tree version of anonymous type with members declaration. + +2009-11-05 Marek Safar + + * parameter.cs: Handle nullable parameter default expression. + + * argument.cs, dynamic.cs, expression.cs, support.cs, ecore.cs, + class.cs, attribute.cs: Check for wrong dynamic arguments. + +2009-11-05 Marek Safar + + * statement.cs: Dynamic statements. + +2009-11-04 Marek Safar + + * dynamic.cs, assign.cs, context.cs, expression.cs, ecore.cs: + Compound assignments over dynamic type. + +2009-11-03 Marek Safar + + * argument.cs, dynamic.cs, expression.cs, delegate.cs: Dynamic + constructor arguments. + +2009-10-30 Marek Safar + + * dynamic.cs, convert.cs, assign.cs, constant.cs, expression.cs, + codegen.cs: Unary mutator on dynamic member access expression. + +2009-10-29 Marek Safar + + A fix for bug #550580 + * convert.cs: Don't eliminate explicit precission casts. + +2009-10-28 Marek Safar + + A fix for bug #550404 + + * parameter.cs, iterators.cs, context.cs, anonymous.cs, + expression.cs, statement.cs, ecore.cs: Quote any nested expression + tree. + +2009-10-27 Marek Safar + + * constant.cs, nullable.cs: Create nullable-null as LiftedNull + constant. + + * class.cs: Allow nullable binary user operators. + +2009-10-26 Marek Safar + + * expression.cs: Move binary expression optimization at the end of + resolve. + +2009-10-23 Marek Safar + + * constant.cs, nullable.cs, expression.cs, literal.cs, cfold.cs: + Separate NullConstant from NullLiteral. + +2009-10-23 Marek Safar + + * typemanager.cs, eval.cs, decl.cs, roottypes.cs, context.cs, + anonymous.cs, expression.cs, rootcontext.cs, ecore.cs, class.cs, + flowanalysis.cs, cs-parser.jay, driver.cs, codegen.cs: Split + ModuleContainer. Add common unclosed member check routine. + +2009-10-22 Marek Safar + + * argument.cs: Use literal flag for real literals only. + + * dynamic.cs: Use correct return type for custom delegates. + +2009-10-22 Marek Safar + + * dynamic.cs, expression.cs: Pass logical binary flag to dynamic + resolver. + +2009-10-22 Marek Safar + + * dynamic.cs, ecore.cs: Dynamic invocation with void return type. + +2009-10-21 Marek Safar + + * dynamic.cs, convert.cs, expression.cs, ecore.cs: Wrap array index + conversion. + +2009-10-21 Marek Safar + + * typemanager.cs, dynamic.cs, expression.cs: Don't resolve runtime + binder flags. + +2009-10-20 Marek Safar + + * argument.cs, dynamic.cs, expression.cs: Latest API update. + +2009-10-19 Marek Safar + + * typemanager.cs, expression.cs: Dynamic array initializer. + +2009-10-16 Marek Safar + + * typemanager.cs, rootcontext.cs: Clear -nostdlib flag when object + is imported. + +2009-10-16 Marek Safar + + A fix for bug #493523, #507067 + * convert.cs, nullable.cs, expression.cs: Do implicit and explicit + standard nullable conversion using underlying standard conversion + and not full conversion. + +2009-10-15 Marek Safar + + * dynamic.cs, expression.cs, ecore.cs, delegate.cs: Check return + type in VerifyArgumentsCompat. + +2009-10-15 Marek Safar + + * nullable.cs, expression.cs, statement.cs, namespace.cs, ecore.cs: + Reject variable used with type arguments. + +2009-10-14 Marek Safar + + * argument.cs, dynamic.cs, assign.cs, expression.cs, ecore.cs: + Implement dynamic expressions assignment. + +2009-10-14 Marek Safar + + * expression.cs: Build underlying expression when resolving unary + mutators. + +2009-10-14 Marek Safar + + * expression.cs: Emit enum array initializer using binary blob. + +2009-10-08 Marek Safar + + * typemanager.cs, constant.cs: Optimize decimal constants which fit + to long range. + +2009-10-07 Marek Safar + + * typemanager.cs: Reset object_type. + + * assign: Made SimpleAssign public. + +2009-10-06 Marek Safar + + * typemanager.cs, decl.cs, namespace.cs, ecore.cs, class.cs: Pass + invocation assembly to IsThisOrFriendAssembly. + +2009-10-05 Marek Safar + + * expression.cs: Equality comparison of generic parameter with + class constraint. + +2009-10-05 Marek Safar + + A fix for bug #543570 + * generic.cs: Import predefined constraints correctly. + +2009-10-02 Marek Safar + + * ecore.cs: Don't crash on overloads with optional paremeters where + arguments count overflows. + + * parameter.cs: Import optional parameter constants using optional + value type. + +2009-10-01 Marek Safar + + * Makefile: Default is gmcs compiler. + +2009-10-01 Marek Safar + + * cs-parser.jay: Fixed few NRE. + +2009-10-01 Marek Safar + + * cs-parser.jay, driver.cs: Expose parser exception in verbose mode. + +2009-09-30 Marek Safar + + * linq.cs, convert.cs, assign.cs, expression.cs, ecore.cs: Add + ShimExpression, ImplicitCast. + +2009-09-30 Marek Safar + + A fix for bug #542959 + * delegate.cs: Emit correct delegate instance variable when there + are static and non-static overloads. + +2009-09-29 Marek Safar + + * dynamic.cs, linq.cs, anonymous.cs, expression.cs, statement.cs, + ecore.cs, cs-parser.jay: Unary expression dynamic compiler. + +2009-09-28 Marek Safar + + A fix for bug #542487 + * ecore.cs: Resolve extension methods hidden by properties. + +2009-09-25 Marek Safar + + * expression.cs, ecore.cs: More dynamic binary expressions. + +2009-09-22 Marek Safar + + * nullable.cs, expression.cs: Fixed null lifted conversion for + bitwise enum operations. + +2009-09-22 Marek Safar + + * convert.cs, ecore.cs: Fixed explicit unsafe coversion of long + values in checked context. + +2009-09-22 Marek Safar + + * expression.cs, ecore.cs: Fixed array index constant conversion. + +2009-09-20 Miguel de Icaza + + * expression.cs: Do not crash when MemberLookup returns something + that is not a MemberExpr here. Report error 582 instead. + + Fixes #499988. + +2009-09-18 Marek Safar + + * decl.cs, class.cs: Check protected property accessors. + +2009-09-18 Marek Safar + + * dynamic.cs, assign.cs: Dynamic compound assignment. + +2009-09-17 Marek Safar + + * expression.cs: Fixed compound assignment explicit conversion. + +2009-09-17 Marek Safar + + * expression.cs, ecore.cs: Cannot infer variables from method group. + +2009-09-16 Marek Safar + + * argument.cs, dynamic.cs, convert.cs, context.cs, anonymous.cs, + constant.cs, nullable.cs, expression.cs, literal.cs, ecore.cs, + codegen.cs: Dynamic binary operations scaffolding. + +2009-09-15 Marek Safar + + * expression.cs: Fixes nullable promotion for enum type variables. + +2009-09-11 Marek Safar + + * driver.cs, dynamic.cs: Reset more static variables. + +2009-09-11 Marek Safar + + * dynamic.cs, expression.cs, rootcontext.cs, namespace.cs, ecore.cs, + driver.cs: Introduced Expression::MakeExpression. + +2009-09-11 Marek Safar + + * eval.cs: Exposed MessageOutput instead of cleaning up eval API. + +2009-09-09 Marek Safar + + * eval.cs, report.cs: Use Console.Out for all eval error or warning + output. + +2009-09-09 Marek Safar + + A fix for bug #518707 + * expression.cs (Is): Optimize only generic parameter type + expression probing value type generic parameter. + +2009-09-09 Marek Safar + + A fix for bug #532571 + * ecore.cs: Check for simple name type arguments used with + non-generic type. + +2009-09-08 Marek Safar + + A fix for bug #497421 + * generic.cs (CheckConstraint): Don't use buildin types to check for + parameterless constructor. + +2009-09-08 Marek Safar + + A fix for bug #537402 + * generic.cs (CheckConstraint): Correctly inflate generic type + arguments when checking generic method. + +2009-09-08 Marek Safar + + A fix for bug #536463 + * decl.cs (AddToContainer): Don't report collision between explicit + and parameterless non-explicit members. + +2009-09-08 Marek Safar + + * eval.cs: Reset more static stuff. + +2009-09-07 Marek Safar + + A fix for bug #324625 + * expression.cs, ecore.cs: Create nested generic type expression + using declaring and not current type. + +2009-09-07 Marek Safar + + * *.cs: Changed Report class to accept various output printers and + be an instance class. An expression resolver can now use different + message reporter for each call and Report.Error can safely throw + an exception. Part of ongoing work to turn mcs into proper library. + +2009-09-04 Marek Safar + + * statement.cs, ecore.cs: Removed error reporting from emit code. + +2009-09-04 Marek Safar + + * cs-parser.jay, parameter.cs: Moved parser check out of constructor + +2009-09-03 Marek Safar + + * anonymous.cs, expression.cs, statement.cs, cs-parser.jay: Moved + parser checks out of constructors. + +2009-09-02 Marek Safar + + * expression.cs, statement.cs, ecore.cs: Use common Report.Error. + +2009-09-02 Marek Safar + + A fix for bug #535448 + * anonymous.cs, class.cs: Copy return label between all contexts. + +2009-09-02 Marek Safar + + A fix for bug #535395 + * namespace.cs: Resolve context can be null. + +2009-08-25 Marek Safar + + A fix for bug #533912 + * generic.cs: Use correct context for constraints resolving. + +2009-08-25 Marek Safar + + A fix for bug #532630 + * driver.cs: Trim conditional symbols. + +2009-08-25 Marek Safar + + * context.cs: New file. + + * *.exe.sources, *.csproj: Updated. + +2009-08-25 Marek Safar + + * generic.cs, parameter.cs, decl.cs, statement.cs, namespace.cs, + class.cs, generic-mcs.cs, codegen.cs: Add GetSignatureForError to + IMembercontext, some small cleanups. + +2009-08-24 Marek Safar + + * *.cs: Split ResolveContext and EmitContext. + +2009-08-24 Marek Safar + + * *.cs: Only ResolveContext implements IMemberContext. + +2009-08-21 Marek Safar + + * *.cs: Renamed IResolveContext to IMemberContext. + +2009-08-21 Marek Safar + + * *.cs: Detached ResolveContext from EmitContext. + +2009-08-21 Marek Safar + + * codegen.cs: Moved flow-analysis to BlockContext. + +2009-08-21 Marek Safar + + * *.cs: Detached BlockContext from EmitContext. + +2009-08-20 Gonzalo Paniagua Javier + + * statement.cs: avoid nullref when the return value of GetEnumerator() + does not contain any MoveNext() method. + +2009-08-19 Marek Safar + + * *.cs: Removed IResolveContext::GenericDeclContainer. + +2009-08-19 Marek Safar + + * class.cs, delegate.cs: Changed Delegate to be TypeContainer based. + +2009-08-19 Marek Safar + + * generic.cs, iterators.cs, expression.cs, statement.cs, ecore.cs, + cs-parser.jay, attribute.cs, codegen.cs: Better error reports. + +2009-08-18 Marek Safar + + * *.cs: Removed boolean fields from EmitContext. + +2009-08-18 Marek Safar + + * *.cs: Add IResolveContext::IsStatic. + +2009-08-18 Marek Safar + + * *.cs: Moved TopBlock's methods from EmitContext to TopBlock. + +2009-08-17 Marek Safar + + * *.cs: Removed DeclContainer from EmitContext. + +2009-08-17 Marek Safar + + * *.cs: Add IResolveContext::CurrentTypeParameters. + +2009-08-14 Marek Safar + + * *.cs: Removed TypeContainer and ContainerType from EmitContext. + +2009-08-14 Marek Safar + + * decl.cs, expression.cs, namespace.cs, ecore.cs, class.cs, + codegen.cs: Add IResolveContext::LookupExtensionMethod. + +2009-08-13 Marek Safar + + * decl.cs: Look in PartialContainer for parent type parameters. + +2009-08-13 Marek Safar + + * decl.cs, namespace.cs, ecore.cs, class.cs, attribute.cs, + codegen.cs: Add IResolveContext::LookupTypeParameter. + +2009-08-13 Marek Safar + + * lambda.cs, expression.cs, statement.cs, namespace.cs, ecore.cs: + Moved resolved logic from Emit to Resolve. + +2009-08-13 Marek Safar + + * parameter.cs, decl.cs, roottypes.cs, class.cs, attribute.cs, + codegen.cs: Reworked atttributes handling of ResolveContext. + +2009-08-12 Marek Safar + + * decl.cs, ecore.cs, class.cs, attribute.cs, codegen.cs: Pushed + LookupNamespaceOrType to ResolveContext. + +2009-08-12 Marek Safar + + * typemanager.cs, decl.cs, expression.cs, namespace.cs, ecore.cs, + class.cs: Removed unused parameters and methods. + +2009-08-11 Marek Safar + + * generic.cs, lambda.cs, anonymous.cs, statement.cs, generic-mcs.cs, + codegen.cs: Finding the best common type of a set of expressions for + lambda statements. + +2009-08-07 Marek Safar + + * dynamic.cs, expression.cs: More dynamic conversions. + +2009-08-06 Miguel de Icaza + + * generic.cs: This loop was incorrect, it was increment ii, but + checking for `i'. This was a change introduced to fix #327497, + now we fix #424012. + + * class.cs: Catch another case for cs0533 error, fixes #324782. + +2009-08-06 Rodrigo Kumpera + + * typemanager.cs (GetGenericArguments): SRE returns null for + generic methods on type builder instances if they are not generic + themselves. For example, for Foo::Bar() it returns null, but + not for Foo::Bar<>() or Foo::Bar(). + +2009-08-05 Marek Safar + + * argument.cs, dynamic.cs, expression.cs, ecore.cs, class.cs, + delegate.cs: Work on dynamic binding. + +2009-08-04 Marek Safar + + A second fix for bug #525342 + * class.cs: Attach partial method attributes to method + implementation. + +2009-08-03 Marek Safar + + * typemanager.cs, parameter.cs, support.cs, class.cs: Dynamic type + restrictions. + + * rootcontext.cs: Default to langversion v4. + +2009-08-03 Marek Safar + + * pending.cs: Check return type before member info is set. + +2009-08-03 Marek Safar + + * anonymous.cs: Fully initialize generic hoisted field expression. + +2009-08-02 Miguel de Icaza + + * cs-parser.jay: Flag variables declared on the interactive shell + as used to prevent the 168 warning about local variable not being + used. + +2009-07-31 Marek Safar + + * parameter.cs, dynamic.cs, support.cs, class.cs, delegate.cs, + attribute.cs: Emit dynamic export attribute. + +2009-07-30 Marek Safar + + * expression.cs: More verifier work. + +2009-07-29 Marek Safar + + * nullable.cs: Fixed SRE crash during corlib compilation. + +2009-07-29 Marek Safar + + * generic.cs, typemanager.cs, decl.cs, iterators.cs, convert.cs, + nullable.cs, expression.cs, ecore.cs, class.cs, attribute.cs: + More TypeManager.TypeToCoreType needed. + +2009-07-29 Marek Safar + + * anonymous.cs: Update after recent SRE fixes. + +2009-07-28 Marek Safar + + * typemanager.cs, expression.cs, ecore.cs, delegate.cs: Use correct + version of GetFieldHandle for fields of generic types. + +2009-07-27 Marek Safar + + * typemanager.cs, argument.cs, convert.cs, assign.cs, expression.cs, + ecore.cs: Add TypeManager.IsDynamicType, + PredefinedAttributes.Dynamic. + +2009-07-27 Marek Safar + + A fix for bug #415375 + * expression.cs: Fixed object and reference type parameter + comparison. + +2009-07-27 Marek Safar + + A fix for bug #525342 + * class.cs: Attach partial method attributes to method + implementation. + +2009-07-24 Marek Safar + + * argument.cs, dynamic.cs, expression.cs, class.cs, attribute.cs: + Dynamic arguments. + +2009-07-24 Marek Safar + + * anonymous.cs (MutateField): Add imported types handling. + +2009-07-23 Marek Safar + + * expression.cs, delegate.cs: Moved arguments resolve into their + counterparts expressions. Removed argument resolve from + CollectionElementInitializer. + +2009-07-23 Marek Safar + + A fix for bug #523683 + * convert.cs, delegate.cs: Use common overload mechanism for method + group conversion check. + +2009-07-22 Marek Safar + + A fix for bug #523899 + * generics.cs: Exact type inference with other bound types. + +2009-07-22 Raja R Harinath + + Don't complain when the same type is implemented by the output + assembly as well as multiple referenced assemblies + * namespace.cs (RootNamespace.LookupTypeReflection): Add + 'must_be_unique' flag. + (GlobalRootNamespace): Update to changes. + (Namespace.LookupType): Pass 'must_be_unique' only when we don't + already have a type in hand. + +2009-07-22 Marek Safar + + * expression.cs: More verifier instrumentation. + + * statement.cs: Do proper throw expression conversion. + +2009-07-22 Marek Safar + + A fix for bug #522789 + * expression.cs: Mutate invocation return type. + +2009-07-16 Marek Safar + + * anonymous.cs: Split assignable and readonly generated variable + references. + +2009-07-16 Marek Safar + + A fix for bug #521671 + * statement.cs: Fixed crash when checking missing type. + +2009-07-16 Marek Safar + + * typemanager.cs, generic.cs, argument.cs, linq.cs, convert.cs, + assign.cs, expression.cs, statement.cs, support.cs, ecore.cs, + class.cs, driver.cs: Work on dynamic binding. + + * dynamic.cs: New file. + + * *.sources, *.proj: Updated. + +2009-07-15 Marek Safar + + * expression.cs (Conditional): Avoid double Resolve. + +2009-07-13 Marcus Griep + + * ecore.cs: Fix obscure bug with resolving members of interfaces + that hide parent interface members. Fixes bug #444388 and corrects + bug #323096 + +2009-07-13 Marek Safar + + * expression.cs (LocalVariableReference): Bounce resolve. + +2009-07-10 Marek Safar + + * typemanager.cs, lambda.cs, parameter.cs, convert.cs, anonymous.cs, + expression.cs, literal.cs, ecore.cs, complete.cs: Moved internal + types to new class. + + * support.cs: New dynamic type wrapper. + +2009-07-08 Marek Safar + + * ecore.cs, cs-parser.jay: Better error reporting for implicitly + typed local variable. + +2009-07-06 Marek Safar + + A fix for bug #519005 + * anonymous.cs: Use null_type as no return type placeholder. + +2009-07-02 Marek Safar + + * generic.cs: Handle type inference of identical type parameters + with different bounds. + +2009-07-01 Marek Safar + + * expression.cs, class.cs: Events variance. + + * cs-parser.jay: Interface events error messages. + +2009-07-01 Marek Safar + + * generic.cs, argument.cs: Updated type inference logic to C# 4.0. + +2009-06-29 Marek Safar + + * parameter.cs, convert.cs, expression.cs, class.cs: Default + parameter expression can be value-type New. + + * cs-parser.jay: Clean up too many parameter modifier boolean flags. + +2009-06-26 Marek Safar + + * generic.cs, argument.cs, expression.cs, ecore.cs, cs-parser.jay: + Implemented C# 4.0 named arguments. + +2009-06-24 Marek Safar + + * typemanager.cs, parameter.cs, iterators.cs, convert.cs, + expression.cs, ecore.cs, delegate.cs: Removed unnecessary ArgList + parameter modifier. Also fixes bug #515497. + +2009-06-24 Marek Safar + + * *.cs: Replaced ArrayList with Arguments in need of a nonsequential + arguments expression to be implemented. + + *.sources: Add argument.cs + +2009-06-23 Marek Safar + + * parameter.cs: Moved GetParameterIndexByName to base class. + + * expression.cs, statement.cs, ecore.cs, delegate.cs: Removed + unused AType. Use argument's version of GetExpressionTree. + +2009-06-22 Marek Safar + + * expression.cs, cs-parser.jay, attribute.cs, codegen.cs: Named + arguments grammar. + +2009-06-17 Marek Safar + + A fix for bug #514096 + * class.cs: Allow IntPtr/UIntPtr fields to be volatile. + +2009-06-17 Marek Safar + + * expression.cs: The first multi-dimensional array nested array + initializers was not checked. + + * statement.cs (Switch): Fixed error message to reflect 2.0 changes. + +2009-06-17 Marek Safar + + A fix for bug #513400 + * nullable.cs (EmitEquality): Operands emit could be simplified for + built-in types when we now emit user operators differently. + +2009-06-16 Marek Safar + + * ecore.cs: Report inaccessible delegate methods correctly. + +2009-06-16 Marek Safar + + * parameter.cs, expression.cs, ecore.cs, class.cs, delegate.cs, + cs-parser.jay: Implemented C# 4.0 optional parameters. + +2009-06-16 Marek Safar + + * driver.cs: Removed broken DefineManifestResource. + +2009-06-16 Raja R Harinath + + * Makefile [net_2_0_bootstrap]: Don't explicitly mention net_1_1. + Use $(BOOTSTRAP_PROFILE) instead. + +2009-06-12 Jb Evain + + * rootcontext.cs: add a Platform field. + * driver.cs: handle /platform. + * codegen.cs: pass the proper flags according to + the platform when saving the assembly. + +2009-06-11 Marek Safar + + * parameter.cs, const.cs, report.cs, cs-parser.jay, attribute.cs: + Add optional parameters grammar. + +2009-06-10 Marek Safar + + * eval.cs, anonymous.cs, report.cs, rootcontext.cs, cs-parser.jay, + driver.cs: Split lang version and metadata version. + +2009-06-10 Marek Safar + + * decl.cs: Better overload ctor collision error message. + +2009-06-05 Jb Evain + + * driver.cs (EmbededResource): avoid using an internal method + in gmcs to embed manifest resources. + +2009-06-04 Sebastien Pouliot + + * generic.cs, parameter.cs: Avoid using 'var' so we can bootstrap + the compiler from older mono versions (like moon's bots) + +2009-06-04 Marek Safar + + * namespace.cs (LookupTypeReflection): Ignore collisions between + forwarded types. + +2009-06-04 Marek Safar + + * codegen.cs: Enabled generic type forwarders. + +2009-06-04 Marek Safar + + * dmcs.*: Add another version of SRE compiler. + +2009-06-03 Marek Safar + + * generic.cs, typemanager.cs, parameter.cs, convert.cs, + generic-mcs.cs: Fixed variant type conversions. + +2009-06-02 Marek Safar + + A fix for bug #507863 + * codegen.cs: Fixes a crash on invalid string value attribute. + +2009-06-01 Marek Safar + + A fix for bug #508334 + * typemanager.cs, parameter.cs, convert.cs, expression.cs, ecore.cs, + cs-parser.jay: Fully import __arglist modifier. + +2009-05-29 Marek Safar + + * generic.cs, typemanager.cs, parameter.cs, ecore.cs, class.cs, + delegate.cs, generic-mcs.cs: Rewrote type variance checks to + actually work with closed generic types. + +2009-05-27 Alan McGovern + + * class.cs, decl.cs, delegate.cs, parameter.cs: + Fix the build by replacing the use of 'var' with the actual type. + +2009-05-27 Marek Safar + + * generic.cs, parameter.cs, decl.cs, ecore.cs, class.cs, delegate.cs + cs-parser.jay, generic-mcs.cs: Report wrong variant types + declarations. + + * driver.cs, rootcontext.cs, report.cs: Add 3.0 language version + filter. + +2009-05-26 Rodrigo Kumpera + Marek Safar + + A fix for bug #377509 + * parameter.cs: Use predefined and not empty name for implicit + setters. + +2009-05-21 Marek Safar + + * class.cs: Don't report wrong warnings for event fields. + +2009-05-21 Marek Safar + + A fix for bug #504667 + * class.cs: Check for static class using parent container instead of + parent type. + +2009-05-08 Marek Safar + + A fix for bug #496922 + * expression.cs: Always use temporary variable when using object + initializer. + +2009-04-28 Marek Safar + + A fix for bug #495112 + * class.cs (IsUnmanagedType): Handle recursive unmanaged types using + local cache. + +2009-04-27 Miguel de Icaza + + * driver.cs: Add a flag to work as a replacement for CSC in VS. + +2009-04-24 Miguel de Icaza + + * complete.cs: No idea how gonzalo got a null in the list, but + avoid crashing. + +2009-04-24 Miguel de Icaza + + * complete.cs (CompletionElementInitializer): New completion class + to support completing inside a C# 3 element initializer, so this + allows completion for Silverlight situations where it is very + common to do: + + new TextBlock () { Fo + + (CompletionSimpleName): Expose the prefix that was + passed to the simple name. + + * cs-parser.jay (object_or_collection_initializer): Add support + for element_initializers. + + * expression.cs (CollectionOrObjectInitializers.DoResolve): + special case completion expressions as this method aggressively + collects data before it operates, and errors were being thrown + earlier than we were able to complete. + +2009-04-23 Miguel de Icaza + + * eval.cs: Make getcompletions silent and enable debugging output + if the -v option is passed. + + * namespace.cs (NamespaceEntry.CompletionGetTypesStartingWith): + Consider looking up the namespace that matches the prefix being + used. + + This is part of the support for allowing completions like: + `System.Co' to complete to System.Console. + + * complete.cs (CompletionSimpleName.AppendResults): Make this + routine reusable. + +2009-04-21 Raja R Harinath + + * cs-parser.jay (GetTokenName): Mark GENERATE_COMPLETION and + COMPLETE_COMPLETION as internal. + +2009-04-17 Miguel de Icaza + + * complete.cs: Include namespace resolution in simple names as + well as global types and types in the using scope in the + resolution. + + * namespace.cs: Supporting infrastrcture to provide completions + based on the current using scope. + + * eval.cs: Introduce an entry point that allows for initialization + to return a list of the files passed on the command line. + +2009-04-14 Marek Safar + + A fix for bug #494243 + * report.cs (SymbolRelatedToPreviousError): Fixed NRE. + +2009-04-13 Marek Safar + + A fix for bug #493887 + * statement.cs: Don't skip string multi-section with default or + null label when populating string hashtable. + +2009-04-06 Marek Safar + + A fix for bug #492329 + * expression.cs (New): Load variable when assigning type parameter + to ref variable. + +2009-04-06 Marek Safar + + A fix for bug #488960 + * decl.cs: Compare MVAR types using non-null values. + +2009-03-27 Marek Safar + + * typemanager.cs, expression.cs: Removed unused nullable checks. + +2009-03-27 Marek Safar + + * *.cs: Removed some gmcs conditionals. + +2009-03-26 Marek Safar + + * generic.cs, support.cs: Moved generics stuff out of support.cs + +2009-03-24 Marek Safar + + * ecore.cs, expression.cs: Use queried type for MethodGroupExpr + DeclaringType. + +2009-03-23 Marek Safar + + * attribute.cs: Consider all members for error reporting when + checking named arguments. + +2009-03-23 Marek Safar + + A fix for bug #487625 + * namespace.cs: Use a warning for all predefined type conflicts. + +2009-03-23 Marek Safar + + A fix for bug #485706 + * statement.cs: Explicitly type catch type argument to pass verifier + check. + +2009-03-22 Miguel de Icaza + + Initial support to provide code completion facilities to consumers + of the evaluator API. + + * cs-tokenizer.cs (CompleteOnEOF): this new property is used to + support the completion engine. When we reach the end of the + input stream instead of returning EOF, when this flag is true the + tokenizer instead produces: + + One GENERATE_COMPLETION token: this token then must be + handled in the grammar at every point where the user + would likely request a completion. + + As many COMPLETE_COMPLETION tokens as necessary. These + tokens are generated to assist the parser in unwinding and + producing a valid parse tree. + + The parser rules do not have to be perfect, the parser needs to be + augmented with judicious use of GENERATE_COMPLETION tokens to + improve the areas where we can provide completion and the parser + needs to add support for COMPLETE_COMPLETION tokens in productions + to make them work. + + It is common to not have enough support for COMPLETE_COMPLETION + under certain rules and that even if we generated the + GENERATE_COMPLETION token that the resulting tree will be invalid + due to the missing rules that support COMPLETE_COMPLETION. + + The final EOF token is produced by having the parser notify the + tokenizer when it reaches the root production that the next token + should be EOF. + + * support.cs (CompletionResult): New Exception. This exception + is thrown to return the completion results when one of the special + completion expressions is reached. + + This exception is thrown by the completing ExpressionStatements + classes that live in complete.cs + + * complete.cs (CompletingExpression): a new base class for + completing expressions. This derives from the + ExpressionStatement class and not from Expression as it allows + completion to happen not only where expressions are expected in + the grammar, but also where statements are expected. + + (CompletionSimpleName): A new class used to provide completions + for SimpleNames. This currently only resolves to local + variables from the evaluator context (GetVars call). + + (CompletionMemberAccess): Implements support for completing member + access patterns. + + * cs-parser.jay: Add support for completion in a few places. + + * eval.cs (GetCompletions): New public API for the evaluator that + returns a list of possible completions given the input. The + return value is an array of completions + + * anonymous.cs (Compatible): If the exception thrown from the + resolved expression is a CompletionResult exception let that one + through instead of printing a diagnostic error in the try/catch. +< +2009-03-22 Miguel de Icaza + + * + + * driver.cs (Main): Use Environment.Exit to quit quickly and + prevent the compiler from doing the usual wait for helper thread + to terminate. + + This is to prevent a slowdown that was reported by Gonzalo on + ASP.NET + +2009-03-19 Marek Safar + + * ecore.cs: Load build-in types directly instead of accessing + an internal field. + +2009-03-18 Marek Safar + + * ecore.cs: Always use unbox.any when available. + +2009-03-18 Marek Safar + + * class.cs: Always set TypeAttributes.BeforeFieldInit conditionally. + +2009-03-17 Marek Safar + + * generic.cs: Removed obsolete version of type inference. + +2009-03-16 Marek Safar + + * typemanager.cs, decl.cs, roottypes.cs, anonymous.cs, nullable.cs, + expression.cs, rootcontext.cs, namespace.cs, ecore.cs, class.cs, + delegate.cs, flowanalysis.cs, cs-parser.jay, driver.cs, + attribute.cs, codegen.cs: Changed RootTypes to be ModuleContainer. + +2009-03-11 Marek Safar + + A fix for bug #482996 + * anonymous.cs: Make sure we are not infering return type when + checking type compatibility. + +2009-03-11 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, decl.cs, const.cs, + rootcontext.cs, namespace.cs, class.cs, delegate.cs, driver.cs, + generic-mcs.cs, attribute.cs, codegen.cs: Maintain predefined + attributes in their own structure. Needed when accessing their + properties before they are resolved. + +2009-03-09 Marek Safar + + * cs-tokenizer.cs: Optimized GetKeyword using an array instead of + hashtable (~10x faster). + + * driver.cs: Removed wrong Reset. + +2009-03-08 Marek Safar + + * class.cs: Use correct common base type for unmanaged delayed + check. + + * rootcontext.cs: Wrap unhandled exception. + +2009-03-06 Raja R Harinath + + Make SeekableStreamReader self-tuning and arbitrarily seekable + * support.cs (SeekableStreamReader.ResetStream): New. Allocates + the buffer. + (SeekableStreamReader.Position.set): Use it. Simplify logic + which, as a side-effect, makes it arbitrarily-seekable. Tune the + buffer size when the stream needs to be re-read from the beginning. + +2009-03-05 Marek Safar + + A fix for bug #480100 + * parameter.cs: A parameter is not hoisted when used directly as ET. + +2009-03-04 Marek Safar + + * statement.cs: Fixed an issue when using variable is of interface + type. + +2009-03-03 Marek Safar + + A fix for bug #480319 + * report.cs, driver.cs: Support -warnaserror-: option. + +2009-03-03 Marek Safar + + A fix for bug #480867 + * typemanager.cs, expression.cs, ecore.cs: Changed method group + expression to have no valid type. + +2009-03-03 Marek Safar + + A fix for bug #481258 + * class.cs: Set extension method flag in partial container. + +2009-03-03 Marek Safar + + * statement.cs, typemanager.cs: Use expression for StringEmitter. + + * attribute.cs: Add sanity check. + +2009-02-27 Marek Safar + + * class.cs: Add external constructor error. + +2009-02-26 Marek Safar + + A fix for bug #475354 + * convert.cs, nullable.cs, expression.cs, statement.cs: Emit + correctly user defined nullable equality operators. + +2009-02-25 Marek Safar + + A fix for bug #479532 + * expression.cs: Implement NewInitialize::AddressOf. + +2009-02-25 Marek Safar + + A fix for bug #413633 + * expression.cs: Iterate all base class-constraint types. + +2009-02-24 Marek Safar + + A fix for bug #479209 + * literal.cs: Mutate null underlying type. + +2009-02-24 Marek Safar + + A fix for bug #476295 + * convert.cs: Avoid wrapping implicitly convertible reference type. + +2009-02-23 Marek Safar + + * iterators.cs: Create MemberName correctly. + +2009-02-23 Marek Safar + + A fix for bug #478655 + * literal.cs: Check also underlying null type conversion. + +2009-02-21 Marek Safar + + * generic.cs, ecore.cs, class.cs: Removed redundant AsAccessible. + +2009-02-20 Marek Safar + + A fix for bug #477447 + * statement.cs: Add reference to correct parent storey when this + is accessible from deep children storey (more than 1 level). + +2009-02-19 Marek Safar + + A fix for bug #475860 by David Mitchell + * class.cs: Define base type members before setting up member cache. + +2009-02-18 Marek Safar + + A fix for bug #477378 + * nullable.cs, expression.cs, statement.cs: More precise null type + sanity checks. + +2009-02-18 Marek Safar + + A fix for bug #472805 + * typemanager.cs, namespace.cs: Import only visible extension method + types. + +2009-02-18 Marek Safar + + A fix for bug #476895 + * attribute.cs: Use correct resolve context for attribute type. + +2009-02-18 Marek Safar + + A fix for bug #476266 + * anonymous.cs: Mutate multi-dimensional arrays. + +2009-02-18 Marek Safar + + A fix for bug #476400 + * statement.cs, expression.cs: Removed wrong Dispose optimization. + +2009-02-18 Marek Safar + + A fix for bug #476811 + * generics.cs: Fixed null-literal check. + +2009-02-17 Marek Safar + + * typemanager.cs, convert.cs, flowanalysis.cs, driver.cs, + expression.cs, ecore.cs, rootcontext.cs, eval.cs, class.cs: More + messing with static variables. + +2009-02-16 Marek Safar + + A fix for bug #475965 + * generics.cs: Check generic parameter type after extracting from + Expression. + +2009-02-16 Marek Safar + + A fix for bug #475823 + * convert.cs, expression.cs, literal.cs, ecore.cs, cfold.cs: Add + typed-null support. + +2009-02-14 Marek Safar + + * modifiers.cs, decl.cs, ecore.cs, class.cs, flowanalysis.cs: + Simplified event field definition using backing field and not + field builder directly. + + * expression.cs (EmitLdArg): Optimize fast paths. + +2009-02-13 Marek Safar + + A fix for bug #475327 + * expression.cs (ArrayCreation): Don't mutate values optimized away. + +2009-02-13 Marek Safar + + A fix for bug #475342 + * cs-parser.jay: Using 'super' instead of 'base' to call base + constructor crashes compiler. + +2009-02-13 Marek Safar + + A fix for bug #475354 + * expression.cs (Constantify): Add nullable types. + + * const.cs (EmitDecimalConstant): Avoid explicit cast. + +2009-02-12 Marek Safar + + A fix for bug #475246 + * expression.cs: More broken flowanalysis hacking needed. + +2009-02-12 Marek Safar + + * attribute.cs: Compare only ref/out array modifiers. + +2009-02-11 Marek Safar + + * statement.cs: Use member cache when looking for foreach members. + +2009-02-11 Marek Safar + + * expression.cs: Don't expose internal initializer types. + + * statement.cs: Check also explicit conversions for goto case. + +2009-02-11 Marek Safar + + * convert.cs, statement.cs: Removed usage of IsAssignableFrom. + +2009-02-10 Marek Safar + + * *.cs: Replace null-type with NullLiteral where appropriate. + +2009-02-09 Marek Safar + + * expression.cs: Initializer of reference argument use temporary + variable to be verifiable. + + * parameter.cs: Share EmitLdArg. + +2009-02-09 Marek Safar + + A fix for bug #473559 + * class.cs: Fixed: Not reporting error about nested class with the + same name. + +2009-02-06 Scott Peterson + + Contributed under the MIT/X11 license. + + * generic.cs: Added VerifyVariantTypeParameters which performs new + variance verification logic. The old logic, based on the spec, was + wrong because the spec is full of LIES! + + * generic-mcs.cs: Stubbed out the VerifyVariantTypeParameters method. + + *typemanager.cs: Moved variance verification logic to GenericTypeExpr. + + * class.cs: + * ecore.cs: Added calls to the new variance verification logic. + + * parameter.cs: + * delegate.cs: Removed calls to the old variance verification logic. + +2009-02-06 Marek Safar + + * delegate.cs: Use cached Invoke method directly. + +2009-02-06 Marek Safar + + * expression.cs: Emit expression tree for hoisted variable access. + +2009-02-04 Marek Safar + + * namespace.cs: Add better extension class check. + +2009-02-05 Scott Peterson + + * generic.cs: Fixed typeo (TypeParameter.Variacne). + +2009-02-04 Scott Peterson + + This patch adds initial generic variance support to the compiler. + It is contributed under the MIT/X11 license. + + * typemanager.cs: Modified ImplementsInterface to check variance. + Added VerifyVariantTypeParameters which checks the specified type to see + if it uses a variant type parameter as a type argument (which is not + allowed). Added IsVariantOf which determins if the first type is a + variant of the second. NOTE: This only supports reference types at + the moment to conform with the current level of VM support. When the + VM supports value types, this will follow step. + + * generic.cs: Added the Variance enum. Added a Variance property to + TypeParameter and added variance support to definition phase. Added a + Variance property to TypeParameterName. Also check to make sure that + no variant types appear in generic method parameters. + + * cs-tokenizer.cs: Modified parse_less_than to tokenize the variance + keywords if the langversion supports it. + + * parameter.cs: Added Parameter.VerifyNoVariantTypeParameters to ensure + that variant types are only used in legal positions. Also added + ParametersCompiled.VerifyNoVariantTypeParameters to check all of its + parameters. + + * decl.cs: Construct TypeParameter with the variance information. + + * convert.cs: Checks variance in ImplicitReferenceConversionExists + and ImplicitConversionStandard. + + * rootcontext.cs: Added new "Future" language version. + + * class.cs: In TypeContainer.DoDefineMembers, ensure that contravariant + type parameters are not used as type arguments in interface inheritance. + In MemberBase.DoMemberDependentChecks, ensure that contravariant type + parameters are not used as method return types. In MemberBase. + ResolveMemberType, ensure that variant type parameters are not used + as type arguments. Also call VerifyNoVariantTypeParameters on every + set of parameters which are resolved. + + * delegate.cs: Modified Delegate.Define to ensure that variant + parameters are not used as type arguments and that a contravariant + parameter is not used as the return type. Also call + VerifyNoVariantTypeParameters on the delegate parameters. + + * cs-parser.jay: Modified grammar to support "in" and "out" keywords + to specify generic variance. + + * driver.cs: Added support for LanguageVersion.Future in the form of + "-langversion:future". + + * generic-mcs.cs: Stubbed out new members in generic.cs. + +2009-02-03 Marek Safar + + * class.cs, generic.cs: Emit type parameter constraints for nested + types. + +2009-02-02 Marek Safar + + A fix for bug #471213 + * class.cs: Avoid emitting backing field for abstract event fields. + +2009-02-01 Marek Safar + + A fix for bug #359731 + * cs-tokenizer.cs, cs-parser.jay: Correctly parse nested query + expressions. + +2009-01-30 Marek Safar + + A fix for bug #470767 + * statement.cs: Introduced BlockScopeExpression, needed when + expression tree conversion has to emit scope variables. + +2009-01-29 Marek Safar + + * class.cs: Remove duplicate CallingConvention. + +2009-01-29 Marek Safar + + *.cs: Rename Parameters to ParametersCompiled and ParametersImported + when I finally found the right naming convention. + +2009-01-29 Marek Safar + + * cs-tokenizer.cs: Put back different open parens optimization. + +2009-01-28 Marek Safar + + A fix for bug #470227 + * cs-tokenizer.cs: Remove too agressive parser optimization. + +2009-01-28 Marek Safar + + A fix for bug #324319 + * class.cs: Remove too early base type resolve. + +2009-01-27 Marek Safar + + A fix for bug #324319 + * ecore.cs: Explicitly type null when assigning to type argument to + make pass verifier check. + +2009-01-27 Marek Safar + + * anonymous.cs: Fixed recent regression when initializing captured + this. + +2009-01-26 Marek Safar + + A fix for bug #469019 + * anonymous.cs: Use all parent type parameters when instantiating + nested generic storey. + +2009-01-26 Marek Safar + + * expression.cs: Check for null instance methodgroup expression. + +2009-01-26 Marek Safar + + A fix for bug #469244 + * cs-tokenizer.cs, cs-parser.jay: Fixed parsing of nullable type + instance inside a conditional expression. + +2009-01-23 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, decl.cs, anonymous.cs, + expression.cs, report.cs, ecore.cs, attribute.cs: Use common + GetElementType and HasElementType. IsValueType clean up. + +2009-01-23 Marek Safar + + * nullable.cs: Use common EmitCall. + + * expression.cs: Emit constraint. for virtual calls only. + +2009-01-23 Marek Safar + + * typemanager.cs, generic.cs, eval.cs, convert.cs, const.cs, + expression.cs, statement.cs, rootcontext.cs, ecore.cs, class.cs, + driver.cs, attribute.cs, enum.cs: Split IsValueType and IsStruct + checks. + +2009-01-22 Jb Evain + + * anonymous.cs: make anonymous types' ToString implementation + match what csc outputs. + +2009-01-21 Marek Safar + + * typemanager.cs, ecore.cs, iterator.cs: TypeLookupExpression clean + up. + +2009-01-17 Marek Safar + + * convert.cs, ecore.cs: Explicitly casts type arguments to pass + verifier checks. + +2009-01-16 Marek Safar + + * nullable.cs (LiftedBinaryOperator): Check for all possible null + expressions. + +2009-01-15 Marek Safar + + A fix for bug #466634 + * statement.cs: Add reference for nested storey when only this + is captured. + +2009-01-15 Marek Safar + + A fix for bug #466474 + * codegen.cs: Emit SecurityPermissionAttribute when -unsafe option + was specified. + +2009-01-15 Marek Safar + + * iterators.cs, anonymous.cs, expression.cs, statement.cs, ecore.cs: + Fixed nested stories parent referencing process. Also fixes #463985. + +2009-01-06 Marek Safar + + * decl.cs, iterators.cs, expression.cs, statement.cs, doc.cs, + class.cs, cs-parser.jay, codegen.cs: Clean up destructor + implementation. Also fixes #463108. + +2009-01-05 Marek Safar + + A fix for bug #416109 + * decl.cs: Issue correct CLSAttribute warning location. + +2009-01-05 Marek Safar + + A fix for bug #456775 + * attribute.cs: Use attribute owner scope when resolving attribute + arguments. + +2009-01-05 Marek Safar + + A fix for bug #457257 + * decl.cs: Fixed incorrect member declaring type comparison. + +2009-01-05 Marek Safar + + A fix for bug #460896 + * driver.cs: Handle /RES resources as embeddable. + +2009-01-05 Marek Safar + + A fix for bug #462515 + * ecore.cs: Report inacessible members upwards. + +2009-01-05 Marek Safar + + A fix for bug #463190, #463192 + * decl.cs, namespace.cs: Also import internal extension classes. + +2009-01-04 Marek Safar + + A fix for bug #463415 + * generic.cs: Use right index for RemoveDependentTypes. + +2009-01-02 Marek Safar + + A fix for bug #463196 + * expression.cs: Fixed enum to null comparison. + +2009-01-02 Marek Safar + + A fix for bug #463121 + * nullable.cs: Fixed nullable user equality operator comparison. + +2009-01-02 Marek Safar + + A fix for bug #462950 + * class.cs, decl.cs: Use full explicit name when defining automatic + property backing field. + +2009-01-02 Marek Safar + + A fix for bug #462592 + * pending.cs: Emit type arguments for generic proxy method. + +2008-12-30 Marek Safar + + * expression.cs (As): Mutate all type arguments. + +2008-12-29 Marek Safar + + A fix for bug #462622 + * anonymous.cs: Resolve anonymous type GetHashCode in unchecked + context. + +2008-12-29 Marek Safar + + A fix for bug #450782 + * ecore.cs: Consider more variables of form V.I to be fixed. + +2008-12-29 Marek Safar + + A fix for bug #460712 + * typemanager.cs: Core types could be imported. + +2008-12-28 Marek Safar + + A fix for bugs #460847, #460772, #458049, #457339, #447807 + * generic.cs, parameter.cs, lambda.cs, linq.cs, anonymous.cs + statement.cs, ecore.cs, class.cs, delegate.cs, flowanalysis.cs + cs-parser.jay, driver.cs: LINQ implementation upgrade to deal with + user lambdas used inside query clauses. + +2008-12-18 Marek Safar + + A fix for bug #460229 + * cs-tokenizer.cs: Ignore wrongly placed BOM markers. + +2008-12-18 Marek Safar + + A fix for bug #459952 + * decl.cs, namespace.cs: Use common CheckAccessLevel. + +2008-12-18 Marek Safar + + A fix for bug #459630 + * convert.cs: Enum to valuetype conversion is not allowed. + +2008-12-18 Marek Safar + + A fix for bug #457087 + * generic.cs: Don't crash when constraint comes from type + declaration. + +2008-12-16 Marek Safar + + A fix for bug #459221 + * anonymous.cs, statement.cs: Delay only captured this + initialization. + +2008-12-12 Marek Safar + + A fix for bug #457489 + * anonymous.cs, statement.cs: Split anonymous storey instantiation + and initialization to capture scope initializers correctly. + +2008-12-11 Marek Safar + + * generic.cs, parameter.cs, expression.cs, statement.cs, doc.cs: + ParameterReference refactoring. + +2008-12-03 Marek Safar + + * typemanager.cs, namespace.cs, driver.cs: Allow ExtensionAttribute + to be imported from any assembly. + +2008-12-03 Marek Safar + + * parameter.cs, lambda.cs, linq.cs, iterators.cs, anonymous.cs + statement.cs, class.cs, cs-parser.jay: Removed duplicate parameters + from anonymous method and lambda expression. + +2008-12-01 Marek Safar + + A fix for bug #448560 + * expression.cs (As): Box any generic type arguments to be + verifiable. + +2008-11-29 Raja R Harinath + + Add tripwire for implicit conversion bugs + * ecore.cs (MethodGroupExpr.Error_ArgumentCountWrong): New helper + for CS1501 error. + (MethodGroupExpr.OverloadResolve): Add sanity check between + IsApplicable and VerifyArgumentsCompat. + (VerifyArgumentsCompat): Report CS1501 where appropriate. + +2008-11-29 Raja R Harinath + + Fix build break in System.Data_test + * convert.cs (ImplicitConversionExists): Move NullLiteral + conversions ... + (ImplicitStandardConversionExists): ... here. + +2008-11-28 Marek Safar + + * literal.cs: Emit correctly explicit null to nullable cast. + +2008-11-28 Marek Safar + + * ecore.cs, generics.cs: Fixed crash when type arguments fail to + resolve. + +2008-11-28 Marek Safar + + A fix for bug #449005 + * convert.cs, nullable.cs: Use only one implicit nullable + conversion. + +2008-11-27 Marek Safar + + * convert.cs, literal.cs: More Convert cleanup is needed. + +2008-11-27 Marek Safar + + * decl.cs, class.cs: Fixed misleading error message. + +2008-11-26 Marek Safar + + A fix for bug #449005 + * nullable.cs (EmitEquality): Disable optimization for user operator + operands. + +2008-11-25 Marek Safar + + A fix for bug #447027 + * anonymous.cs (HoistedVariable): Cache also outer access to deal + with context variables stored as expression instances. + +2008-11-25 Marek Safar + + A fix for bug #447027 + * delegate.cs: Fixed delegate VerifyMethod logic. + +2008-11-24 Marek Safar + + * ecore.cs, delegate.cs: MethodGroup expressions can be applicable + but not verifiable. + +2008-11-21 Marek Safar + + * typemanager.cs, decl.cs, anonymous.cs, class.cs, enum.cs: Rewrote + member type resolve to follow normal flow, instead of random + property access. + +2008-11-21 Marek Safar + + * iterators.cs (GetEnumeratorStatement): Re-use already resolved + type. + +2008-11-21 Marek Safar + + * const.cs: Emit decimal array constant as literal. + +2008-11-20 Marek Safar + + * iterators.cs, ecore.cs: Removed CurrentBlock statement. + +2008-11-19 Marek Safar + + * eval.cs, location.cs, driver.cs (Location.SourceFiles): Turned + into real property (saves 8 MB for corlib compilation). + +2008-11-19 Marek Safar + + * generic.cs, lambda.cs, linq.cs, iterators.cs, anonymous.cs, + nullable.cs, expression.cs, statement.cs, ecore.cs, cs-parser.jay + generic-mcs.cs: Small cleanup of TypeArguments. + +2008-11-18 Marek Safar + + * generic.cs, iterators.cs, anonymous.cs, nullable.cs, ecore.cs, + expression.cs, namespace.cs, generic-mcs.cs, class.cs: Small cleanup + of ConstructedType expression, renamed to GenericTypeExpr. + +2008-11-17 Marek Safar + + A fix for bug #445303 + * location.cs (IsConditionalDefined): Handle undefined global + defines. + +2008-11-17 Marek Safar + + A fix for bug #444678 + * expression.cs (TryReduceConstant): Always create new constant + instance. + +2008-11-17 Marek Safar + + A fix for bug #444673 + * ecore.cs: Ignore open generic types when used as generic type + instance fields. + +2008-11-17 Marek Safar + + A fix for bug #445458 + * expression.cs, cs-parser.jay: Don't crash when an expression + statement is null. + +2008-11-17 Marek Safar + + A fix for bug #445464 + * expression.cs, cs-parser.jay: Fixed typeof of non-generic type + inside unbound type. + +2008-11-14 Jb Evain + + * driver.cs: ignore empty -nowarn argument such as + the one in -nowarn:12,13,,. + +2008-11-13 Marek Safar + + A fix for bug #444271 + * anonymous.cs: Rescan parent storeys when best candidate was + undone. + +2008-11-13 Marek Safar + + * generic.cs, expression.cs, ecore.cs, cs-parser.jay: Removed + useless UnboundTypeExpression. + + * attribute.cs: Do check obsolete attribute on generic types. + +2008-11-12 Marek Safar + + A fix for bugs #425680, #400139 + * ecore.cs, expression.cs: Trying to do some almost_matched_members + refactoring. + +2008-11-11 Marek Safar + + A fix for bug #435747 + * assign.cs, expression.cs: Cleanup New assignment to emit correcly + compound value types assignment. Few micro optimizations added. + +2008-11-10 Marek Safar + + A fix for bug #442610 + * anonymous.cs (MutateConstructor): More SRE hacking. + +2008-11-10 Marek Safar + + A fix for bug #442579 + * ecore.cs: Also initialize expanded form of a method with 1 params + parameter. + +2008-11-06 Marek Safar + + * expression.cs (UnaryMutator): Do early l-side check. + +2008-11-05 Miguel de Icaza + + * codegen.cs (InitDynamic): also setup Assembly.Name like we do in + Init, otherwise we would crash later on when checking for friend + assemblies. + + * eval.cs: Do not hide errors from invalid calls to LoadAssembly. + Otherwise we never get any meaningful information as to what + failed. + +2008-11-05 Marek Safar + + A fix for bug #436318 + * driver.cs, report.cs: Add -warnaserror:Wn to command line options. + +2008-11-05 Miguel de Icaza + + * namespace.cs: Turns out that it was a really bad idea to hide + the errors for namespaces not found here in eval mode. + + * eval.cs: When we process using clauses, only enter those into + the list of valid using clauses after they have been validated. + + The above change gives the proper semantics: it does not + senselessly report the same errors with broken using statements by + never storing them in the first place when they are invalid. + +2008-11-05 Marek Safar + + A fix for bug #421839 + * cs-parser.jay: Remove expression from coalesce rule to force lower + priority than the assignment operator. + +2008-11-05 Marek Safar + + A fix for bug #437875 + * nullable.cs: Compile correctly method group operand used with null + coalescing operator. + +2008-11-04 Marek Safar + + A fix for bug #434589 + * expression.cs (Binary): Ignore lifted conversions when at least + one operand is of reference type. + +2008-11-04 Marek Safar + + * cs-parser.jay: Better syntax error report. + +2008-11-03 Marek Safar + + A fix for bug #436792 + * cs-parser.jay: Use GetLocation to access location. + +2008-11-03 Marek Safar + + A fix for bug #440774 + * cs-parser.jay: Also set current_array_type when parsing local + variables types. + +2008-11-03 Marek Safar + + A fix for bug #440785 + * expression.cs (As): Don't resolve self modifing expression + multiple times. + +2008-11-03 Marek Safar + + A fix for bug #439447 + * cs-tokenizer.cs: Tokenize surrogates only where allowed. + +2008-11-03 Marek Safar + + A fix for bug #437571 + * cs-parser.jay: Fixes internal error for invalid expression + statements. + +2008-10-17 Marek Safar + + * ecore.cs: Resolve correctly ambiguous params delegate methods. + +2008-10-17 Marek Safar + + * generic.cs, anonymous.cs: Simplified GetDeclarations. + +2008-10-17 Marek Safar + + * cs-tokenizer.cs: More precise cast parsing. + +2008-10-16 Martin Baulig + + * anonymous.cs (AnonymousMethodStorey): Put back the + `hoisted_locals' hashtable and use it in EmitType(). + +2008-10-15 Marek Safar + + * cs-tokenizer.cs, nullable.cs, expression.cs, statement.cs, + cs-parser.jay: Tokenizer optimizations and memory reduction, saves + ~5MB for corlib. + +2008-10-14 Marek Safar + + * cs-tokenizer.cs: Add bool type to the list of valid cast tokens. + +2008-10-14 Marek Safar + + * statement.cs: Mutate scope initializers. + +2008-10-14 Marek Safar + + * expression.cs: Use typeless value for This constant. + + * ecore.cs: Access FieldInfo via GetConstructedFieldInfo. + +2008-10-14 Marek Safar + + * cs-tokenizer.cs, cs-parser.jay: Unify context sensite keyword + tokenizer. + +2008-10-13 Marek Safar + + * cs-tokenizer.cs: Add missing alias qualifier and dotted generic + type to type cast. + +2008-10-13 Marek Safar + + * cs-tokenizer.cs, expression.cs, cs-parser.jay: Reworked parens + parser and tokenizer. Fixes many ambiguities including #433258. + +2008-10-10 Marek Safar + + * cs-parser.jay: Fixed missing accessor recovery. + +2008-10-10 Marek Safar + + A fix for bug #433701 + * expression.cs: Better error message. + +2008-10-10 Marek Safar + + * cs-parser.jay, expression.cs: Start reporting real parser errors. + + * Makefile: Disabled unused debug symbols. + + Also fixes: #320556, #321097, #321656, #321876, #351316 + +2008-10-09 Miguel de Icaza + + * eval.cs: rename "" to "{interactive}", to work + around a requirement in the compiler that this be a valid + filename, and in Windows it is not (433886). + +2008-10-09 Marek Safar + + * cs-tokenizer.cs, cs-parser.jay: Fixed more subtle parser problems + +2008-10-08 Marek Safar + + * cs-tokenizer.cs, eval.cs, anonymous.cs, statement.cs, class.cs + cs-parser.jay: Generic type declaration and type arguments cleanup. + +2008-10-05 Marek Safar + + * cs-parser.jay: Allow parsing weird array creation construct. + +2008-10-05 Marek Safar + + * cs-parser.jay: Conflicts reduction. + +2008-10-04 Marek Safar + + * cs-parser.jay: Conflicts reduction. + +2008-10-04 Raja R Harinath + + Fix #398325 + * flowanalysis.cs (MyBitvector.MakeShared): Rename from 'Shared' + property. Add a 'count' hint about the use of the shared vector. + Ensure that we don't leak out dirty bits. + (UsageVector.MergeChild): Throw away information about variables + in child vectors. + Based on patch and analysis by Moritz Kroll . + +2008-10-03 Marek Safar + + A fix for bug #431746 + * iterators.cs, anonymous.cs: Re-initialize hoisted iterator + parameters when iterator is created. + +2008-10-03 Marek Safar + + A fix for bug #431827 + * expression.cs: Fixed right based pointer arithmetic operations + emit. + +2008-10-03 Marek Safar + + A fix for bug #353779 + * assign.cs, expression.cs: Fixed compound assignment conversions. + +2008-10-02 Marek Safar + + A fix for bug #375262 + * statement.cs: Refactor ArrayForeach to be usable with string + indexer. Optimized single dimentional arrays foreach. + +2008-10-02 Marek Safar + + A fix for bug #431255 + * anonymous.cs, expression.cs: Removed broken optimization. + +2008-10-01 Marek Safar + + * anonymous.cs: Use full type parameters of parent generic + containers. Removed unnecessary AddParentStoreyReference call. + +2008-10-01 Marek Safar + + A fix for bug #324702 + * class.cs: Use better shorter names for explicit interface member + implementations. + + * ecore.cs, typemanager.cs: Convert only mscorlib predefined names. + +2008-10-01 Marek Safar + + * expression.cs: Use new interface to check fixed expression. + +2008-10-01 Marek Safar + + A fix for bug #421101 + * expression.cs, statement.cs, ecore.cs: Use IFixedExpression + interface to check for fixed fixed-buffers. + +2008-10-01 Marek Safar + + A fix for bug #429264 + * assign.cs, anonymous.cs, ecore.cs: More type mutators added. + + * delegate.cs: Removed unnecessary casts. + +2008-09-30 Marek Safar + + A fix for bug #352151 + * decl.cs, iterators.cs, anonymous.cs, report.cs, namespace.cs, + class.cs: Fixed already defined explicit interface members check. + +2008-09-29 Rodrigo Kumpera + + cs-tokenizer.cs: Fix typo. + +2008-09-28 Miguel de Icaza + + * eval.cs (InteractiveBase): The quit command now just sets a + flag, instead of calling Environment.Exit(), it is milder on + embedded hosts. + + CompiledMethod is now in Mono.CSharp, not nested inside + the Evaluator, it was inconvenient to use. + +2008-09-27 Miguel de Icaza + + * eval.cs (Evaluator): Introduce Compile method, to allow compiled + code to be invoked without having to reparse. + +2008-09-27 Miguel de Icaza + + * ecore.cs: The recent changes to FieldExpr broke this as well. + Fixes LINQ queries in the interactive shell. + + * Multiple files: indentation fixing for the Mono coding + guidelines for the switch statement. + + * eval.cs: Make the Evaluator API thread safe. + +2008-09-26 Marek Safar + + * anonymous.cs, statement.cs, class.cs, cs-parser.jay: Simplified + constructor parsing. + +2008-09-26 Marek Safar + + A fix for bug #325326 + * statement.cs: Check possible mistaken empty statement using + explicit blocks only. + +2008-09-25 Miguel de Icaza + + * eval.cs (LoadAssembly, ReferenceAssembly): Call + RootNamespace.ComputeNamespaces to update the internal list of + namespaces, this is no longer done for us. + + (InteractiveBase): Use the Evaluator APIs instead of calling into + Driver directly + +2008-09-25 Marek Safar + + A fix for bug #429264 + * expression.cs: Missing mutator for access to multidimensional + arrays. + +2008-09-25 Marek Safar + + * class.cs, statement: Emit DebuggerHidden attribute for iterator + entry wrapper. + + * driver.cs: Missing input argument check. + +2008-09-25 Marek Safar + + * typemanager.cs, generic.cs, eval.cs, decl.cs, anonymous.cs, + expression.cs, statement.cs, rootcontext.cs, class.cs, + cs-parser.jay, driver.cs, generic-mcs.cs, enum.cs: Removed obsolete + DefineMembers. + +2008-09-24 Miguel de Icaza + + * ecore.cs (FieldExpr): Only initialize eclass when we return a + fully constructed FieldExpr, fixes the regression introduced in + the last commit. + + * ecore.cs, expression.cs: Plug back the eclass initialization as + otherwise it regresses `csharp'. + +2008-09-24 Marek Safar + + * typemanager.cs, decl.cs, convert.cs, assign.cs, expression.cs, + ecore.cs, attribute.cs: Moved obsolete method checks from emit + phase to resolve phase. It resolves problems with expression trees + and fixes bugs #323796, #325156. + +2008-09-23 Marek Safar + + * codegen.cs: Report better error when symbol writer is missing. + +2008-09-23 Marek Safar + + * codegen.cs: Set .NET symbol writer. + + * decl.cs: Guard against null generic arguments. + + * report.cs: Don't report exactly same additional details. + +2008-09-22 Marek Safar + + A fix for bug #324917 + * cs-parser.jay: Add missing multidimensional non-expression type + ranks. + +2008-09-22 Marek Safar + + A fix for bug #428191 + * anonymous.cs: Create an outer generic fields also for non-storey + anonymous methods. + +2008-09-22 Marek Safar + + A fix for bug #378294 + * class.cs: Make fixed size buffers gmcs feature only. + +2008-09-22 Marek Safar + + A fix for bug #355622, #324993 + * assign.cs, const.cs, class.cs: Create new EmitContext for each + field initializer. + +2008-09-19 Marek Safar + + * nullable.cs, expression.cs, namespace.cs, delegate.cs: Duplicate + error reporting. + +2008-09-19 Marek Safar + + A fix for bug #416110 + * generic.cs: Struct constraint results in default ctor and + ValueType base type constraint to be set. + +2008-09-19 Marek Safar + + A fix for bug #423791 + * generic.cs: Fixed params output type type-inference. + +2008-09-19 Marek Safar + + * cs-parser.jay, expression.cs: Fixed few expression crashes. + +2008-09-19 Marek Safar + + * cs-tokenizer.cs: Don't break on extra partial modifier. + +2008-09-19 Marek Safar + + A fix for bug #427592 + * generic.cs: Use common parameter resolve method. + +2008-09-18 Marek Safar + + A fix for bug #414758 + * expression.cs, ecore.cs: Fixed crash when accessing non-static + property. + +2008-09-18 Marek Safar + + * driver.cs, namespace.cs: Read types and namespaces after all + requested assemblies are loaded, fixes issues with System.Core + auto-reference, and #419888. + +2008-09-18 Marek Safar + + A fix for bug #417705 + * cs-parser.jay: Fixed as/is operator expression split. + +2008-09-18 Marek Safar + + * const.cs, expression.cs, statement.cs, ecore.cs, cs-parser.jay: + Fixed expression tree representation of empty new expression and + new initializer expression. + +2008-09-18 Miguel de Icaza + + * eval.cs: Remove warning, keep reference to driver around. + + * Hide fields that do not need to be public. + +2008-09-17 Marek Safar + + A fix for bug #426385 + * expression.cs (ImplicitlyTypedArrayCreation): Use full implicit + conversion for array elements. + +2008-09-17 Marek Safar + + * expression.cs, statement.cs, class.cs, cs-parser.jay: Fixed + void parsing conflicts. + +2008-09-15 Marek Safar + + A fix for bug #425601 + * driver.cs, typemanager.cs, namespace.cs: Automatically reference + System.Core only when there is no custom ExtensionAttribute + implementation. + +2008-09-15 Miguel de Icaza + + * namespace.cs: Do not report CS0246 (name + +2008-09-12 Marek Safar + + A fix for bug #425669 + * generic.cs: Don't cache generic static anonymous method + containers. + +2008-09-12 Marek Safar + + * generic.cs, class.cs, delegate.cs: Check recursive inherited + conflicting constraints. + +2008-09-12 Raja R Harinath + + * cs-tokenizer.cs (consume_identifier): Allow partial methods in + mcs too. + +2008-09-12 Marek Safar + + * literal.cs, convert.cs, expression.cs, statement.cs: More null + to null pointer conversion fixes. + +2008-09-11 Marek Safar + + * cs-parser.jay, expression.cs: An implicitly typed local variable + declarator cannot use an array initializer. + +2008-09-11 Marek Safar + + * cs-parser.jay: Reduced number of printed tokens, add sorting. + +2008-09-11 Marek Safar + + * generic.cs (InflatedConstraints): Don't crash when constraints + are different. + + * cs-parser.jay: const_declarator is a block. + + * constant.cs: Check for not allowed NaN conversions. + +2008-09-10 Miguel de Icaza + + * driver.cs: Drop --shell argument, the compiler is no longer a + REPL. + + * eval.cs: Move most of the code that deals with evaluation into + this file and document the public API from repl.cs + + * repl.cs: Remove from here. + +2008-09-10 Marek Safar + + A fix for bug #424684 + * generic.cs: Generic class constraints must come first. + +2008-09-09 Miguel de Icaza + + * cs-parser.jay: Improve error reporting for syntax errors in + statements and expressions, we now report the expected tokens + instead of reporting the useless "; expected". + + Drop the strings from the token declaration, it turns out that + they did not do what I thought they did. Instead they were adding + two sets of tokens to the tables. + +2008-09-09 Marek Safar + + * typemanager.cs, generic.cs, parameter.cs, expression.cs, class.cs, + delegate.cs: Share special type check. + +2008-09-09 Marek Safar + + A fix for bug #423981 + * expression.cs (EmitBranchable): Correctly emit inverted float conditions. + +2008-09-09 Marek Safar + + * ecore.cs (ReducedConstantExpression): Implemented ConvertExplicitly and + ConvertImplicitly. + +2008-09-09 Marek Safar + + A fix for bugs: #324750, #335946 + * cs-tokenizer.cs, cs-parser.jay, expression.cs: Use a custom + lookup rule to determine ?-based tokens. + +2008-09-08 Miguel de Icaza + + * repl.cs (OptionalAssign.EmitStatement): It is possible that some + expressions (like event adding or removing) end up here, so we + need to treat those as statements. + + Add LoadAssembly method. + +2008-09-04 Miguel de Icaza + + * repl.cs: Add Time method. + +2008-09-05 Marek Safar + + * cs-tokenizer.cs: Fixed swaped UTF-16 surrogates parsing. + +2008-09-05 Miguel de Icaza + + * repl.cs: Add workaround for old compilers. + +2008-09-04 Jb Evain + + * repl.cs (PrettyPrint): pretty print everything that + implements IDictionary, as well as IEnumerables. Also, + add a quit helper property. + +2008-09-04 Marek Safar + + * constant.cs: Better error reporting for decimal literals. + + * class.cs, attribute.cs, typemanager.cs: Emit more fixed buffer + field attributes. + +2008-09-04 Marek Safar + Miguel de Icaza + + A fix for bug #422951 + * assign.cs (Assign.DoResolve): Perform the type conversions + checks before we attempt to initialize `New' initializers. + +2008-09-04 Marek Safar + + A fix for bug #422853 + * delegate.cs (DelegateCreation): Add special handling for + EmptyExpression.Null instance expression which is just another + hack for undecided member instance exression. + +2008-09-04 Marek Safar + + * expression.cs, ecore.cs: Emit full expression tree for reduced + binary expressions. + +2008-09-04 Marek Safar + + * expression.cs (This): Guard against multi-resolving. + + * ecore.cs, statement.cs (Throw): Simplified. + + * flowanalysis.cs: Also verify event fields. + +2008-09-04 Miguel de Icaza + + * assign.cs (Assign.DoResolve): Perform the type conversions + checks before we attempt to initialize `New' initializers. + + * repl.cs (PrettyPrint): Add Hashtable prettyprint + + * anonymous.cs (AnonymousTypeClass): On EvalMode make the class + public. + + * repl.cs: Update help. + +2008-09-03 Miguel de Icaza + + * driver.cs (ProcessDefaultConfig): Now it encapsulates all the + handling of the default config handling, including the special + treatment of System.Core assembly. + + Fixes the REPL processing for LINQ. + +2008-09-03 Marek Safar + + A fix for bug #422507 + * expression.cs (UnboxCast): Add missing child expression mutator. + +2008-09-03 Marek Safar + + * driver.cs: Don't self reference System.Core assembly. + +2008-09-03 Marek Safar + + A fix for bug #422507 + * expression.cs (StringConcat): Add missing type mutator. + +2008-09-03 Marek Safar + + * generic.cs (TypeInferenceContext): Follow equality rule for + constructed type lower bound type inference. + +2008-09-02 Miguel de Icaza + + * getline.cs (CmdRefresh): Apply patch from Douglas S. Blank + which updates the cursor position on + refresh. + +2008-09-02 Marek Safar + + A fix for bug #367145 + * driver.cs: Fixed import of extension methods when using -noconfig + option. + +2008-09-02 Marek Safar + + * iterator.cs: Don't emit GetEnumerator method twice but call a generic + version from non-generic implementation instead. + +2008-09-01 Marek Safar + + A fix for bug #418908 + * class.cs: Use AddScopeStatement for field initializers. + +2008-09-01 Marek Safar + + A fix for bug #415385 + * ecore.cs, convert.cs: Do method group conversion for equal group types. + +2008-09-01 Marek Safar + + A fix for bug #421736 + * iterators.cs: Don't crash on unreachable iterators. + +2008-09-01 Marek Safar + + A fix for bug #421628 + * parameter.cs, attribute.cs: Clone also parameter attributes. + +2008-08-30 Miguel de Icaza + + * namespace.cs (LookupType): In EvalMode, try to replace + the TypeBuilder from our cache with a Type as Reflection.Emit does + not like to mix code from older assemblies emitted and new + assemblies emitted. + + This sounds like a serious Mono bug that prevents multiple + assemblies to be generated and consumed at the same time. + + * cs-parser.jay (push_current_class): Do not make interactive + classes internal or private, make them public as we currently + generate each new class in a new assembly. + +2008-08-29 Miguel de Icaza + + * decl.cs, roottypes.cs, class.cs:: Add an infrastructure to + remove types that are entered into the global namespace during + parsing so that we can remove them on failure. + + * cs-parser.jay: Parsing: we now keep track of types that are + entered into global variables and queue those in case the parsing + or resolution fail. + + This happens in a few situations: during partial-input, we invoke + the parser repeatedly for example with the string "class X", this + would cause X to be registed, and we need to remove this + registration so that another parse attempt later with say "class X {" + would actually work. + + Additionally, if there is an error in the resolution phase, for + example: "class X : NonExistant {}" th + + * cs-parser.jay: Be more precise with the errors being raised, + instead of flagging all exceptions during parsing to be attributed + to the parsing process, distinguish those from errors happening in + the actions and hint that using -v would produce the actual + exception. + + * repl.cs: Do not load all compiler references on each reset, + doing the partial reset takes care of this. + +2008-08-28 Miguel de Icaza + + * repl.cs: Add support for loading all the files from + ~/.config/csharp/*cs as startup scripts and ~/.config/csharp/*.dll + as shell libraries. + + Introduce a micro-parser that is able to deambiguate on its input + whether we are dealing with a compilation unit (namespace, class, + interface, struct, delegate) declaration or a statement. This + allows both declarations and statements to be entered. + + Set history size by default to 300 lines. + + Instead of distinguishing based on the parser.InteractiveResult, + have only two cases: statements were parsed, or a compilation unit + was. Always pull the Using statement additions from the + compilation unit parse. + + * cs-tokenizer.cs: Rename tokens to better describe their intent + (EvalStatementParserCharacter and EvalCompilationUnitParserCharacter). + + * rootcontext.cs: Split EvalMode into EvalMode and StatementMode. + EvalMode is used to trigger the lookup of global variables while + StatementMode is used turn variable declarations into static + fields. + + * getline.cs: Allow history size to be set. + +2008-08-29 Marek Safar + + A fix for bug #360755 + * ecore.cs (SimpleName): Exclude indexers from simple name resolve. + +2008-08-29 Marek Safar + + * generic.cs, iterators.cs, codegen.cs: Removed unused variable. + + * typemanager.cs, statement.cs, ecore.cs, enum.cs: Don't reconstruct enum + member name, it is too confusing + + * decl.cs, class.cs: Don't report unused fields with attached attribute. + + * rootcontext.cs: Finally default to warning level 4. + +2008-08-28 Marek Safar + + * class.cs (CheckBase): Ignore overloaded operators. + +2008-08-28 Marek Safar + + A fix for bug #420830 + * expression.cs, cs-parser.jay: Put back InvocationOrCast expression. + +2008-08-28 Marek Safar + + A fix for bug #420832 + * anonymous.cs, iterators.cs: Also clone hoisted this iterator variable. + +2008-08-28 Marek Safar + + A fix for bug #420386 + * nullables.cs: Fixed logic of nullable user comparison operators involving + null values. + +2008-08-28 Marek Safar + + * attribute (IsClsCompliant): Use FALSE value for pointer types. + +2008-08-27 Miguel de Icaza + + * repl.cs: Add support for aborting the running code with C-c. + +2008-08-27 Raja R Harinath + + * cs-parser.jay (CS1002): Dump 'yyToken' with Report.ExtraInformation. + +2008-08-27 Miguel de Icaza + + * cs-parser.jay (interactive_statement_list): A new set of rules + for hosting statements that uses the "interactive_" prefix. + + * repl.cs: Add support for parsing `using' as a statement or as a + directive. Deambiguating before passing this to the parser. + + We need to distinguish statement_expressions that occur at the + toplevel vs those that occur embedded into expressions. + + * getline.cs: Applied patch from Stuart Carnie + that fixes the cursor key handling, and a history bug. + +2008-08-26 Miguel de Icaza + + * Makefile: Drop BOOTSTRAP_COMPILER as that was masking the + limitations in Console, instead the 2.0 bootstrap libraries now + include the Console bits. + + Also, remove the use of Nullables from getline.cs + + ------------ + + Interactive support for the C# compiler. Use gmcs --shell to + enter a read-eval-print loop shell. + + Docs: http://www.mono-project.com/CsharpRepl + + * sources: include repl.cs here and getline.cs for gmcs.exe, + everything else is getline.cs impaired. + + * Makefile: when bootstrapping pass a special flag + BOOTSTRAP_COMPILER which we use to prevent failures in compilation + as we use NET_2_0 define to pull 2.0 APIs from System.Console. + This distinguishes those two cases. + + * repl.cs: Support for a read-eval-print loop. Will be soon + refactored into eval support and then REPL on top of it. + + * ecore.cs: If a simplename lookup fails, before erroring out, + if we are in EvalMode to resolve the name to a declaration in the + Eval-land. + + This means that variable declarations that happened in previous + classes (as repl puts every statement in a separate class) are + made visible in this way. + + * cs-parser.jay: UnexpectedEOF, a new flag that is set if we + triggered an error due to the end of file being reached. This is + used to do multi-line input, and notify the caller that the user + needs to provide more text before a successful parse. + + Add new grammar rules after the INTERACTIVE_PARSER token is seen + to drive the evaluation with a custom wrapper. + + * driver.cs: Add support for --shell, and refactor some code to be + reused from repl.cs + + * namespace.cs: Add support for serializing the contents of the + namespaces and reloading them. + + * getline.cs: A managed implementation of ReadLine under + X11/Apache2 license terms. Easy to embed in other applications as + well. + + * namespace.cs: Add some functions to save and restore the + namespace state. + + * rootcontext.cs: New public field. + + * cs-tokenizer.cs: Add support for one of the possible characters + we introduce into the token stream. + + This patch does not affect the regular tokenization process, the + only performance hit would happen if there is an invalid character + on the input string. + + * support.cs: Move isatty helper routine here. + + * codegen.cs: Small cleanup, and add a mechanism to initialize the + code generator for in-memory assemblies. + +2008-08-26 Marek Safar + + * generic.cs, ecore.cs, delegate.cs, cs-parser.jay, expression.cs: A type + parameter cannot be always used as a type. + +2008-08-21 Marek Safar + + * convert.cs, expression.cs: Use single ExplicitReferenceConversion routine. + +2008-08-21 Marek Safar + + * convert.cs: Implement explicit array to IList conversion. + +2008-08-20 Marek Safar + + A fix for bug #362740 + * cs-tokenizer.cs: Handle UTF-16 surrogates. + +2008-08-20 Marek Safar + + * generic.cs, support.cs, typemanager.cs, lambda.cs, parameter.cs, + pending.cs, ecore.cs, linq.cs, class.cs, decl.cs, delegate.cs, + flowanalysis.cs, iterators.cs, cs-parser.jay, convert.cs, anonymous.cs, + expression.cs, attribute.cs, statement.cs, doc.cs: Refactored parameters + handling to use just one type of infrastructure and deal with generics + more effectivelly. + +2008-07-23 Martin Baulig + + *** Merged this from trunk revision 108527 *** + + * statement.cs + (ExplicitBlock.EmitSymbolInfo): Moved to `ToplevelBlock'. + (ToplevelBlock.EmitSymbolInfo): Tell the symbol writer about the + scope variable. + +2008-08-15 Marek Safar + + * ecore.cs, linq.cs, const.cs, expression.cs, statement.cs: More robust + error checks. + +2008-08-15 Marek Safar + + * delegate.cs: Fixed compiler crash when creating delegate using partial + method. + + * typemanager.cs: MulticastDelegate is not a delegate. + +2008-08-14 Marek Safar + + * expression.cs, ecore.cs, anonymous.cs, class.cs: Fixed missing error + checks. + +2008-08-14 Raja R Harinath + + * cs-parser.jay (type): Allow 'var' in mcs too. + (local_variable_type): Likewise. + +2008-08-14 Marek Safar + + * driver.cs: Removed broken -noconfig variants. + +2008-08-14 Marek Safar + + A fix for bug #417078 + * expression.cs: Emit correctly left side pointer operators. + +2008-08-13 Marek Safar + + * generic.cs, lambda.cs: Inflate method generic arguments only. + +2008-08-12 Marek Safar + + * class.cs: Fixed struct layout check regression. + +2008-08-12 Marek Safar + + * cs-parser.jay, enum.cs: Simplified enum parsing. + + * decl.cs: Check all type parameters conflicts. + + * expression.cs, statement.cs, attribute.cs: More expression checks. + +2008-08-11 Marek Safar + + * generic.cs: Add type inference types restriction. + + * parameter.cs, class.cs, delegate.cs, iterators.cs, cs-parser.jay, + anonymous.cs, expression.cs: Allocate less accessor parameters. + +2008-08-08 Marek Safar + + * typemanager.cs, ecore.cs: Ambiguous operators can come from different + classes. + +2008-08-08 Marek Safar + + * convert.cs, delegate.cs: Fixed delegate compatibility conversion. + +2008-08-07 Marek Safar + + * class.cs, decl.cs, iterator.cs, ecore.cs: Refactor base type resolving. + Also fixes #362146 and #381592. + +2008-08-07 Marek Safar + + * ecore.cs: Reduced constant cannot be used as an attribute value. + + * cs-parser.jay: Base expression has to be a type. + + * expression.cs (Conditional): Uses ReducedExpression. + +2008-08-06 Marek Safar + + A fix for bug #376826 + * parameter.cs, ecore.cs, anonymous.cs, expression.cs, statement.cs: An + address of hoisted local variable or parameter cannot be taken. + +2008-08-05 Marek Safar + + * ecore.cs, constant.cs, expression.cs, statement.cs: Resolve correctly + anonymous method inside checked/unchecked expression. + +2008-08-05 Marek Safar + + * typemanager.cs (IsEqual): Guard against null. + + * ecore.cs, class.cs, convert.cs, const.cs, constant.cs, expression.cs, + attribute.cs, enum.cs, statement.cs: Pass EmitContext to constant conversion + routine. Fixed few misleading conversion errors. + +2008-08-04 Marek Safar + + * class.cs: Consider generics when checking cycles in struct layout. + +2008-08-04 Raja R Harinath + + * cs-tokenizer.cs (get_cmd_arg): Simplify. Don't be too pedantic. + +2008-08-04 Marek Safar + + A fix for bug #414165 + * anonymous.cs: Use same anonymous implementation method for all anonymous + method emits. + +2008-08-04 Marek Safar + + * generic.cs, anonymous.cs, statement.cs: Emit inherited anonymous method + constraints. + +2008-08-04 Marek Safar + + * cs-parser.jay: Typeof argument has to be a type expression. + + * namespace.cs: Check alias and namespace definitions collisions. + + * class.cs, pending.cs: Moved explicit interface accessor implementation + check. + + * delegate.cs, expression.cs: Verify special name invocations. + +2008-08-01 Marek Safar + + * cs-parser.jay: Don't choke on empty generic type arguments. + + * cs-tokenizer.cs: Handle escaped preprocessor directives. + + * expression.cs, ecore.cs: Minor expressions bugs. + +2008-08-01 Marek Safar + + * cs-parser.jay: Removed duplicate interface declaration (fixes 2 conflicts) + and added more error handling. + + * class.cs, iterators.cs, anonymous.cs: Removed useless interface parameter. + + * modifiers.cs, enum.cs: Fixed. + +2008-07-31 Jb Evain + + * driver.cs: remove -pkg ability of smcs. + +2008-07-30 Marek Safar + + * statement.cs (Switch): Correctly set empty default target for single + blocks. + +2008-07-30 Marek Safar + + * typemanager.cs, assign.cs, driver.cs, expression.cs, statement.cs: Rewrote + string switch statement implementation to use string dictionary which + significantly (2-8x) improves performance of generated code. + +2008-07-29 Marek Safar + + A fix for bug #412880 by Atsushi Enomoto + * modifiers.cs (GetDescription): Fixed FamANDAssem case. + +2008-07-29 Marek Safar + + A fix for bug #412595 + * typemanager.cs, convert.cs, expression.cs: Some types are never + convertible to each other. + +2008-07-29 Marek Safar + + * nullable.cs (CreateNullConstant): An error messages update. + +2008-07-29 Marek Safar + + A fix for bug #412595 + * cfold.cs: Don't cast undefined bool constant. + +2008-07-29 Martin Baulig + + * symbolwriter.cs + (SymbolWriter.Reset): New public static method. + + * driver.cs + (CompilerCallableEntryPoint.Reset): Call SymbolWriter.Reset(). + +2008-07-28 Marek Safar + + * cs-tokenizer.cs (IsLambdaOpenParens): Optimized using more stop tokens. + + * expression.cs (ElementAccess): Exact size allocation. + +2008-07-26 Marek Safar + + * driver.cs: Replaced outdated UnixParseOption with CSCParseOption. + +2008-07-25 Marek Safar + + * flowanalysis.cs (StructInfo): Fixed detection of dynamic types. + + * class.cs: Removed $PRIVATE$ field hack which caused problems during + flow analysis. + +2008-07-25 Marek Safar + + A fix for bug #412217 + * assign.cs: Mutate also assignment type. + +2008-07-25 Marek Safar + + A fix for bug #323644 + * typemanager.cs (IsValidProperty): Verify DefaultMemberName when checking + indexers. + +2008-07-25 Marek Safar + + A fix for bug #412134 + * expression.cs (ResolveOperatorEnum): Do implicit conversion of + non-enumerable operands when overloading equality or bitwise operators. + +2008-07-25 Marek Safar + + * anonymous.cs: Cache closed generic anonymous method delegates. + +2008-07-24 Marek Safar + + * lambda.cs, linq.cs, class.cs, iterators.cs, cs-parser.jay, assign.cs, + anonymous.cs, statement.cs: Always emit anonymous method as static method + when is instance free. Use nesting for nested anynomous methods blocks. + +2008-07-23 Marek Safar + + * anonymous.cs (MutateGenericMethod): Added extra code path for imported + types. + +2008-07-23 Marek Safar + + * expression.cs: Removed MakeSimpleCall. + +2008-07-23 Marek Safar + + A fix for bug #323012 + * class.cs, pending.cs: Emit proxy for indexers when they differ in name. + Base method implementing interface has to be public. + +2008-07-23 Marek Safar + + * cs-parser.jay: Don't break on missing argument. + +2008-07-22 Marek Safar + + A fix for bug #320993 + * report.cs, parameter.cs, class.cs, decl.cs, delegate.cs, attribute.cs, + enum.cs, codegen.cs: Report CLS compliance errors as warnings. + +2008-07-22 Marek Safar + + A fix for bug #320748 + * convert.cs: Implicit user operators cannot convert to interfaces + +2008-07-22 Marek Safar + + A fix for bug #312686 + * driver.cs: Ignore empty assembly references. + +2008-07-22 Marek Safar + + A fix for bug #387040 + * ecore.cs: Skip constrains check for an explicit implementation. + +2008-07-21 Marek Safar + + A fix for bug #409045 + * cs-tokenizer.cs, rootcontext.cs, class.cs, location.cs, delegate.cs, + cs-parser.jay, driver.cs, expression.cs, attribute.cs: Conditional + identifiers are file specific unless passed as input arguments. + +2008-07-21 Marek Safar + + * typemanager.cs, parameter.cs, class.cs, attribute.cs: Use an attribute + to emit UnmanagedMarshal data under 2.0 profile. + +2008-07-21 Marek Safar + + A fix for bug #410369 + * parameter.cs: Clone correctly ParamsParameter. + +2008-07-21 Marek Safar + + * expression.cs (Argument): Always report type for type based expressions + errors. + +2008-07-18 Marek Safar + + A fix for bug #410666 + * anonymous.cs: Correctly initialize generic storey reference. + +2008-07-18 Marek Safar + + * convert.cs: Don't box same type arguments. + +2008-07-18 Marek Safar + + * ecore.cs, linq.cs, delegate.cs, constant.cs, nullable.cs, expression.cs: + Finished missing generic type mutators. + +2008-07-18 Marek Safar + + * iterators.cs, statement.cs: Finished statements CloneTo. + +2008-07-18 Marek Safar + + * anonymous.cs: ExpressionTreeProxy is of Value type expression. + + * expression.cs: Emit optimized default value expressions in expression tree + array initializer. + +2008-07-18 Marek Safar + + * ecore.cs, cs-parser.jay, statement.cs: Error reporting fixes. + +2008-07-17 Marek Safar + + A fix for bug #367536 + * cs-parser.jay: Check static constructor of generic types for an access + modifier. + +2008-07-17 Marek Safar + + A fix for bug #353800 + * lambda.cs: Emit ret for contextual statements. + + * codegen.cs: Keep both resolved and unreachable flags, otherwise we end + up emitting redundant ret for all anonymous methods with return. + +2008-07-17 Marek Safar + + A fix for bug #365188 + * ecore.cs, anonymous.cs, expression.cs, codegen.cs, statement.cs: Don't + create anonymous method storey in unreachable block. + +2008-07-17 Marek Safar + + * generic.cs, typemanager.cs, cs-tokenizer.cs, parameter.cs, namespace.cs, + class.cs, delegate.cs, flowanalysis.cs, iterators.cs, anonymous.cs, + driver.cs, nullable.cs, expression.cs, attribute.cs, codegen.cs, + statement.cs: Fixed relevant defects found by Gendarme. + +2008-07-17 Marek Safar + + A fix for bug #325291 + * modifiers.cs, class.cs, cs-parser.jay, anonymous.cs, codegen.cs, + statement.cs: Replaced IAnonymousHost with top level block flag. + +2008-07-17 Marek Safar + + * cs-parser.jay: Clean up unused open_parens. + +2008-07-17 Marek Safar + + * ecore.cs: Custom error message for a range variable assignment. + +2008-07-16 Marek Safar + + * constant.cs, typemanager.cs: Emit empty string ("") as string.Empty field + load. + +2008-07-16 Marek Safar + + * literal.cs: Null literal is of object type. + +2008-07-16 Marek Safar + + * nullable.cs (LiftedBinaryOperator): Always lift unwrapped nullable + expression of nullable equality comparison. + +2008-07-15 Marek Safar + + * expression.cs(PointerArithmetic): Removed redundant assignment. + +2008-07-15 Marek Safar + + * decl.cs (GetSignatureForError): Report full namespace name for containers. + +2008-07-14 Marek Safar + + A fix for bug #408361 + * anonymous.cs (MutateGenericMethod): Store generic type arguments before + they are replaced by GetMethod. + +2008-07-14 Marek Safar + + A fix for bug #408721 by jeremie.laval@gmail.com + * expression.cs (Indirection): Implemented CloneTo. + +2008-07-14 Marek Safar + + * statement.cs (AssignableSlots): Temporary disabled variable initialization + assert check. + +2008-07-14 Marek Safar + + * report.cs (EnableReporting): Don't reinitialize 0-based values. + +2008-07-11 Marek Safar + + * linq.cs: Reset tranparent parameter counter in probing mode. + +2008-07-11 Marek Safar + + * anonymous.cs: Mutate anonymous method type. + +2008-07-11 Marek Safar + + * ecore.cs, anonymous.cs: Mutate field expressions. + +2008-07-10 Marek Safar + + A fix for bug #369670 + * linq.cs, statement.cs: Use explicit block for query expressions variables. + +2008-07-10 Marek Safar + + * report.cs, ecore.cs: Flush recorder only when silent mode is off. + +2008-07-10 Raja R Harinath + + Fix bug #314902 + * cs-tokenizer.cs (is_punct): If a generic lookahead is looking + only one '>', and finds a '>>', abort the generic lookahead. + +2008-07-10 Marek Safar + + A fix for bug #319902 + * cs-tokenizer.cs: Always look-ahed for `>=' when tokenizing `>'. + +2008-07-10 Marek Safar + + A fix for bug #406371 + * statement.cs: Moved EmitSymbolInfo to Block. + +2008-07-09 Marek Safar + + * ecore.cs: Report better error for extension method overload failures. + +2008-07-09 Marek Safar + + * expression.cs (Is): No need to box reference values. + +2008-07-09 Marek Safar + + * class.cs: Use event resolve context when initializing CreateEmitContext. + +2008-07-09 Marek Safar + + A fix for bug #394436 + * anonymous.cs, class.cs, expression.cs, lambda.cs: Emit correctly extension + method used inside expression trees. Added more LINQ to expression tree + conversions. + +2008-07-08 Marek Safar + + A fix for bug #378189, #370577 + * lambda.cs, ecore.cs: Implemented 3.0 enhancement to better conversion + from expression. + +2008-07-08 Marek Safar + + * anonymous.cs, class.cs, decl.cs: Emit CompilerGenerated attribute + hierarchically. + +2008-07-08 Marek Safar + + A fix for bug #406702 + * anonymous.cs: Always park anonymous method in the nearest parent storey. + +2008-07-07 Marek Safar + + A fix for bug #406648 + * cs-parser.jay: Report nullable use in mcs for some cases. + +2008-07-07 Marek Safar + + * ecore.cs: Improved argument mismatch error messages. + +2008-07-07 Marek Safar + + * anonymous.cs: Don't cache generic delegates when reference MVAR argument. + +2008-07-07 Marek Safar + + * expression.cs (TypeOf): Mutate type argument. + +2008-07-04 Marek Safar + + * class.cs: Report missing partial modifier for correct type. + +2008-07-04 Marek Safar + + * ecore.cs, expression.cs (VariableReference): Variable property is + protected. + +2008-07-04 Marek Safar + + * ecore.cs, convert.cs: Made OpcodeCast more memory efficient. + +2008-07-04 Marek Safar + + * anonymous.cs, class.cs, lambda.cs, iterator.cs: Cache static anonymous + method delegates. + +2008-07-04 Marek Safar + + * anonymous.cs, class.cs, expression.cs, iterator.cs, statement.cs: Reduce + anonymous method storey to an instance method when only "this" is hoisted. + +2008-07-03 Marek Safar + + A fix for bug #321615 + * expression.cs: Pointer comparisons use unsigned operator. + +2008-07-03 Marek Safar + + * expression.cs: Fixed native pointer conversions. Also fixes #321615. + +2008-07-02 Marek Safar + + A fix for bug #404905 + * class.cs: Always initialize local unsafe variables. + +2008-06-30 Marek Safar + + A fix for bug #396987 + * expression.cs (NewInitialize): Clear local temporary variable for next run + +2008-06-27 Marek Safar + + A fix for bug #401020 + * ecore.cs: Both types and modifiers have to match for ref and out arguments + +2008-06-27 Marek Safar + + A fix for bug #398319 + * cs-parser.jay: Implemented undocumented base access expression inside + anonymous types. + +2008-06-26 Marek Safar + + A fix for bug #404227 + * cs-parser.jay: Parse namespace declaration using qualified identifier. + +2008-06-26 Marek Safar + + A fix for bug #404227 + * convert.cs: Fixed explicit array to interface cast. + +2008-06-26 Marek Safar + + A fix for bug #403894 + * delegate.cs: Mutate DelegateInvocation type. + +2008-06-26 Marek Safar + + A fix for bug #379348 + * delegate.cs: Box a load of generic parameters. + +2008-06-26 Marek Safar + + * expression.cs: Add an array creation arguments mutate. + +2008-06-26 Marek Safar + + A fix for bug #386068 + * anonymous.cs, expression.cs: Emit correctly hoisted expression tree + parameter. + +2008-06-25 Marek Safar + + * ecore.cs, expression.cs: Fixed broken TypeCast clone, implemented few more + CloneTo. + +2008-06-25 Marek Safar + + A fix for bug #403518 + * delegate.cs: Type correctly anonymous method new invocation. + +2008-06-24 Marek Safar + + A fix for bug #394826 + * anonymous.cs: Fully qualify members when resolving anonymous type internal + calls. + +2008-06-24 Marek Safar + + A fix for bug #394826 + * anonymous.cs, iterators.cs: Construct generic storey only when is really + needed. + +2008-06-24 Marek Safar + + * class.cs: Clone indexer parameters for localized capturing. + +2008-06-24 Marek Safar + + A fix for bug #402379 + * expression.cs: Don't crash when an object initializer resolve fails. + +2008-06-24 Marek Safar + + A fix for bug #402888 + * expression.cs: Mutate conditional expression. + +2008-06-24 Marek Safar + + A fix for bug #401012 + * class.cs: Keep StructLayout in shared container. + +2008-06-24 Marek Safar + + A fix for bug #400438 + * decl.cs, class.cs: Only properties can be automatically implemented. + +2008-06-24 Marek Safar + + * statement.cs (ChangeToIterator): Copy also labels. + +2008-06-23 Marek Safar + + * ecore.cs: Pass type argument details to parent extension method. + +2008-06-23 Marek Safar + + A fix for bug #375966 + * delegate.cs: Fixed IsTypeCovariant generic type conversions. + +2008-06-23 Raja R Harinath + + * Makefile (bootstrap-libs): Pass NO_DIR_CHECK to sub-make. + +2008-06-22 Marek Safar + + A fix for bug #394347 + * anonymous.cs: Cache compatible delegates as compatibility check produces + a new method every time. + +2008-06-20 Marek Safar + + * anonymous.cs: Propagate storey reference for single references. + +2008-06-20 Marek Safar + + A fix for bug #387615 + * assign.cs, expression.cs: Correctly clone compound assignment. + +2008-06-19 Marek Safar + + A fix for bug #359611, #359604 + * anonymous.cs: Mutate all types of hoisted parameters. + +2008-06-19 Marek Safar + + * typemanager.cs, lambda.cs, parameter.cs, ecore.cs, linq.cs, class.cs + delegate.cs, iterators.cs, cs-parser.jay, assign.cs, anonymous.cs, driver.cs + expression.cs, codegen.cs, statement.cs + + Fixes bugs: #318652, #323223, #234779, #325069, #325476, #332532, #334465, + #345907, #349190, #353276, #355256, #359617, #378542, #384584, #396530 + + ** Anonymous methods, lambda expressions rewrite ** + + Anonymous expressions are now resolved when an explicit block is resolved + and they don't require any registration procedure anymore. Further, + anonymous methods are defined when explicit block is emitted which allows + better control of whole process and opens possibilities for more + optimizations as well as alternative to reverse whole process. + + A concept of `MutateHoistedGenericType' was introduced to keep the resolve + process consistent and to correctly emit hoisted generic methods when they + have at least 1 hoisted variable. + +2008-06-17 Martin Baulig + + * class.cs: Also emit the `[DebuggerHidden]' attribute on the main + iterator method. + (AbstractPropertyEventMethod.IsDebuggerHidden): New protected + virtual property; check it in Emit(). + (PropertyMethod.IsDebuggerHidden): Override, check whether we're + an iterator. + (MethodOrOperator.ResolveMethods): Set `DEBUGGER_HIDDEN' if we're + an iterator. + (Indexer.Define): Likewise. + +2008-06-17 Marek Safar + + * convert.cs: Don't use IsInterface on type arguments. + + * delegate.cs: DelegateInvocation uses MethodInfo. + + * parameter.cs: Removed IsTypeParameter. + + * generic-mcs.cs: More missing stuff. + +2008-06-16 Martin Baulig + + * modifiers.cs + (Modifiers.DEBUGGER_HIDDEN): New public const. + + * typemanager.cs + (TypeManager.GetDebuggerHiddenAttribute): New public static method. + + * class.cs + (MethodOrOperator.Emit): Check `Modifiers.DEBUGGER_HIDDEN'. + (AbstractPropertyEventMethod): Likewise. + (Constructor.Emit): Likewise. + (SourceMethod.SetCompilerGenerated): Removed. + + * iterator.cs: Set `Modifiers.DEBUGGER_HIDDEN' everywhere except + on MoveNext(). + + * anonymous.cs + (RootScopeInfo.DoDefineMembers): Set `Modifiers.DEBUGGER_HIDDEN' + if we're an `IteratorHost'. + (AnonymousMethodMethod..ctor): Don't set + `Modifiers.COMPILER_GENERATED'; csc only sets this on the class, + not on the method. + +2008-06-16 Marek Safar + + * statement.cs: Clean-up foreach statements. + +2008-06-12 Marek Safar + + * class.cs: Stop using public method which should not exist + (MethodBuilder.SetGenericMethodSignature). + +2008-06-11 Martin Baulig + + * location.cs + (Location.LookupFile): Add `CompilationUnit' argument; when given + a relative file name, make it relative to the directory the .cs + file is located in instead of using the current directory. + +2008-06-11 Martin Baulig + + * class.cs + (IMethodData.EmitExtraSymbolInfo): Added `SourceMethod' argument. + (MethodOrOperator.EmitExtraSymbolInfo): Likewise. + (SourceMethod.SetRealMethodName): Moved here from the symbol writer. + (SourceMethod.SetCompilerGenerated): Likewise. + +2008-06-11 Marek Safar + + * codegen.cs, driver: Only write symbol file when it's asked for. + +2008-06-11 Marek Safar + + * codegen.cs: Don't use assembly writer error handling for symbol writer. + +2008-06-10 Martin Baulig + + * symbolwriter.cs: Reflect latest MarkSequencePoint() API changes. + +2008-06-09 Marek Safar + + A fix for bug #316290 + * expression.cs: Include decimal operators in predefined table. + + * parameters.cs: More readonlyness. + +2008-06-09 Marek Safar + + A fix for bug #397213 + * cs-parser.jay: One more missing current_local_parameters reset. + +2008-06-09 Marek Safar + + A fix for bug #396633 + * class.cs: Host backing field in partial container. + +2008-06-09 Marek Safar + + A fix for bug #397068 + * expression.cs: Check both operand types when predefined operator is used. + +2008-06-05 Martin Baulig + + Merged the `debugger-kahalo' branch. + + * class.cs + (MethodData.Emit): Call SymbolWriter.SetCompilerGenerated() if + we're an iterator method. + (SourceMethod): Reflect latest symbol writer changes; + SymbolWriter.OpenMethod() now takes a `ICompileUnit' argument and + now `start_row' and `end_row'. + (Constructor.Emit): Fix the logic whether to emit symbol information. + + * iterator.cs: Call SymbolWriter.SetCompilerGenerated() on all the + generated methods. + + * location.cs + (CompilationUnit): New public class; derives from `SourceFile'. + (SourceFileEntry.DefineSymbolInfo): New public method. + (SourceFileEntry.SetChecksum): New public method. + (Location): Encode hidden line numbers by using `column == 255'; + the .ctor now accepts `column == -1' to mark a hidden line number. + (Location.Hidden): New public property. + (Location.CheckPoint): Add `CompilationUnit'. + (Location.SourceFiles): Change return type to `CompilationUnit[]'. + (Location.Push): Add `CompilationUnit compile_unit' argument. + (Location.CompilationUnit): New public property. + + * statement.cs + (ToplevelBlock.Emit): Add `ec.Mark (EndLocation)'. + + * cs-parser.jay: `SourceFile' -> `CompilationUnit'. + + * driver.cs: `SourceFile' -> `CompilationUnit'. + + * cs-tokenizer.cs: `SourceFile' -> `CompilationUnit'. + + * namespace.cs: `SourceFile' -> `CompilationUnit'. + + * cs-tokenizer.cs: Add support for `#pragma checksum' and + `#line hidden'. + + * symbolwriter.cs + (SymbolWriter.MarkSequencePoint): Take a `Location' and use the + new symbol writer API to also pass the file. + +2008-06-05 Marek Safar + + * statement.cs: Emit catch variable assignment using variable expression. + +2008-06-05 Marek Safar + + * ecore.cs, expression.cs, statement.cs: Make TemporaryVariable compatible + with other variable types. + +2008-06-04 Marek Safar + + * ecore.cs, expression.cs, statement.cs, typemanager.cs: Removed custom + GetLength method emit, it breaks resolve rules. + +2008-06-02 Atsushi Enomoto + Marek Safar + + A fix for bug #395542 + * cs-parser.jay: The trailing comma is allowed in anonymous type member + declaration. + +2008-06-02 Marek Safar + + A fix for bug #395287 + * class.cs, modifiers.cs: Automatic properties method base modifiers checks. + +2008-05-31 Marek Safar + + A fix for bug #395845 + * class.cs, nullable.cs: User unary operator is allowed to have nullable and + non-nullable parameter type. + +2008-05-31 Marek Safar + + * class.cs: Handle contructor initializer as a statement in top-level block. + +2008-05-30 Marek Safar + + * attribute.cs: Don't mix old and new corlib types when emitting corlib + security attributes. + +2008-05-24 Marek Safar + + * ecore.cs, expression.cs: Small IVariable refactoring. + +2008-05-22 Marek Safar + + * assign.cs (LocalTemporary): Implemented CreateExpressionTree. + +2008-05-21 Marek Safar + + * cs-parser.jay: Removed redundant catch type check. + +2008-05-21 Marek Safar + + A fix for bug #390372 + * nullable.cs: Set correct return type. + +2008-05-21 Marek Safar + + A fix for bug #391062 + * typemanager.cs: Fixed crash when comparing null types. + +2008-05-21 Marek Safar + + A fix for bug #391871 + * cs-parser.jay: Better error handling for invalid catch type. + +2008-05-20 Marek Safar + + A fix for bug #392155 + * cs-tokenizer.cs: Fixed casting of byte and decimal expression. + +2008-05-15 Marek Safar + + A fix for bug #390666 + * ecore.cs (BetterExpressionConversion): Unwrap each Expression + expressions. + +2008-05-15 Marek Safar + + * class.cs, expression.cs, statement.cs: Removed a hack, setting block flag + in getter. + +2008-05-13 Marek Safar + + A fix for bug #389625 + * delegate.cs, generic.cs: Some progress on method group return type + inference. + +2008-05-13 Marek Safar + + A fix for bug #378419 + * namespace.cs: Inspect also parent namespaces not only namespace entries. + +2008-05-12 Marek Safar + + * class.cs (Constructor): Added IsCompilerGenerated. + +2008-05-12 Marek Safar + + * expression.cs: Enum binary operators can accept non-enum operand only when + is implicitly convertible to underlying type. + +2008-05-12 Marek Safar + + A fix for bug #389272 + * support.cs: Workaround System.InvalidOperationException for enums. + +2008-05-12 Marek Safar + + A fix for bug #389073 + * convert.cs: More undocumented explicit IntPtr/UIntPtr conversions. + +2008-05-10 Marek Safar + + * driver.cs: Split Parse. + + * location.cs (LookupFile): Uses string.Empty. + +2008-05-07 Marek Safar + + * expression.cs, parameter.cs: Small ParameterReference clean up. + +2008-05-07 Marek Safar + + * anonymous.cs, codegen.cs, convert.cs, ecore.cs: Removed uber ugly TempEc + hack. Fixes #387502. + +2008-05-06 Martin Baulig + + * class.cs (Constructor.Emit): Fix the logic whether to emit + symbol information. + +2008-05-06 Raja R Harinath + + Fix #385503 + * iterators.cs (Iterator.CurrentBlock.DoEmit): Don't emit + InvalidOperationException when the iterator is before the start or + after the end. + +2008-05-06 Marek Safar + + * nullable.cs (NullCoalescingOperator): Result is underlying type of left, + when left is nullable type. + +2008-05-06 Marek Safar + + A fix for bug #386628 + * expression.cs (LocalVariableReference): Continue in resolving when + variable is not assigned. + +2008-05-05 Marek Safar + + * nullable.cs, statement.cs (Unwrap): Store non-variable expression in all + nullable operations. + +2008-05-04 Marek Safar + + * nullable.cs, statement.cs (Unwrap): Don't duplicate variable expressions, + it saves many redundant temporary variables for nullable operations. + +2008-05-03 Marek Safar + + * assign.cs: EventAddOrRemove is a statement and cannot have a type. + + * cfold.cs, constant.cs, expression.cs: Share Error_OperatorCannotBeApplied + method. + + * nullable.cs: Constant coalescing operator optimizations. + +2008-05-03 Marek Safar + + * constant.cs: Use unsigned conversion for values which are unsigned only. + +2008-05-03 Marek Safar + + * convert.cs, literal.cs, nullabel.cs, typemanager.cs: Implemeted null + coalescing operator as it should be. + +2008-05-02 Marek Safar + + A fix for bug #371016 + * expression.cs: All predefined delegate operators require implicit method + group conversion. + +2008-05-02 Marek Safar + + * constant.cs: Emit long constant as uint when fits the range. + + * convert.cs, expression.cs: Fixed few unsafe conversions. + +2008-05-02 Marek Safar + + * convert.cs, literal.cs: Don't wrap implicit reference conversion to object + +2008-05-02 Raja R Harinath + + Fix #385758 + * convert.cs (ImplicitNumericConversion): Don't modify the type of + 'expr'. + * ecore.cs (EmptyCast.Create): Flatten nested EmptyCasts. + +2008-05-01 Marek Safar + + * constant.cs, literal.cs: IsLiteral property for error reporting. + + * ecore.cs, expression.cs: Implemented Property expression. + +2008-05-01 Marek Safar + + * class.cs, modifiers.cs, flowanalysis.cs: New BACKING_FIELD flag. + + * nullable.cs: Implemented nullable coalescing null operator. + + * ecore.cs, expression.cs: Expression trees work. + +2008-05-01 Marek Safar + + * ecore.cs: CreateExpressionTree is finally abstract. + + * expression.cs, linq.cs: Updated. + +2008-05-01 Marek Safar + + * expression.cs, ecore.cs: Block base access expression inside expression + tree. + +2008-05-01 Marek Safar + + A fix for bug #385058 + * expression.cs: User-defined operator implementations always take + precedence over predefined operator implementations. + +2008-04-30 Marek Safar + + * assign.cs, anonymous.cs, lambda.cs, nullable.cs, ecore.cs, linq.cs, + class.cs, iterators.cs, expression.cs, attribute.cs: Filled a few more + expression tree conversions. + +2008-04-30 Marek Safar + + * typemanager.cs, ecore.cs, class.cs, expression.cs, doc.cs: Merged all + operators method details to Operator class. + +2008-04-30 Marek Safar + + * anonymous.cs: Pass unsafe flags to anonymous container. + + * ecore.cs, expression.cs, statement.cs: Block unsafe pointer operations + inside expression tree. + +2008-04-29 Martin Baulig + + * cs-tokenizer.cs (Tokenizer.Position): Added `line'. + (Tokenizer.PopPosition): Also restore the `line'. + +2008-04-29 Marek Safar + + * delegate.cs: Implemented Invoke expression. + +2008-04-29 Marek Safar + + * expression.cs: Fixed equality reference comparison regression. + +2008-04-29 Marek Safar + + * ecore.cs: Clean up EmptyCast hack. + + * expression.cs, nullable.cs: Implemented enum binary and unary operations + using correct conversion rules. Also fixes #383993. + +2008-04-28 Martin Baulig + + * class.cs (Constructor.Emit): Don't emit debugging information + for generated default .ctor's. + +2008-04-28 Marek Safar + + * convert.cs: Empty-cast ushort to int conversion. + +2008-04-28 Marek Safar + + A fix for bug #384191 + * ecore.cs, expression.cs: Fixed expression cloning. + +2008-04-28 Marek Safar + + * ecore.cs, delegate.cs, assign.cs: Few tweaks for recent changes. + +2008-04-28 Raja R Harinath + + Fix #381559, test-638.cs, test-639.cs + * assign.cs (CompoundAssign.Helper): New wrapper. + (CompoundAssign.DoResolve): Use it to wrap the nested 'target' + access. + * ecore.cs (MethodGroupExpr.VerifyArgumentsCompat) : + Pass unconverted expressions to the params array creation expression. + (FieldExpr.EmitAssign): Don't special-case StringConcat. + (PropertyExpr.EmitAssign): Likewise. + * expression.cs (ArrayCreation.ResolveArrayElement): Keep track of the + element if it is of kind CompoundAssign.Helper. + (ArrayCreation.Emit): If we saw a CompoundAssign.Helper, emit it + first before anything else. + (ArrayAccess.EmitAssign): Don't special-case StringConcat. + (ArrayAccess.LoadArrayAndArguments): Simplify. + +2008-04-27 Marek Safar + + * expression.cs: Fixed cloning of typeof(void). + +2008-04-27 Raja R Harinath + + * assign.cs (Assign.DoResolve): Remove support for EventExprs. + (Assign.Emit): Likewise. Move it to ... + (CompoundAssign.DoResolve): ... here and ... + (CompoundAssign.Emit): ... here. + (EventAddOrRemove): New helper to handle += and -= on events, and + avoid the use of BinaryDelegates. + * ecore.cs (EventExpr.DoResolveLValue): Emit CS0070 unconditionally. + (EventExpr.EmitAddOrRemove): Improve. + * delegate.cs (DelegateInvocation.DoResolve): Simplify slightly. + + * cs-parser.jay (type) : Don't + create VarExprs for 'foo.bar.var'. + * ecore.cs (VarExpr.InferType): Rename from DoResolveLValue, which + is a highly inappropriate name for its functionality. + +2008-04-26 Raja R Harinath + + Simplify handling of multiple assignments + * assign.cs (Assign): Clear out all 'embedded assign' gunk. Make + inheritable-only. + (SimpleAssign): New. Class to be used for normal assignments. + * anonymous.cs, class.cs, cs-parser.jay: Update to changes. + * expression.cs, parameter.cs, statement.cs: Likewise. + +2008-04-25 Marek Safar + + * ecore.cs, expression.cs, nullable.cs: Implemeted enum binary add operation + for incompatible underlying types, more to come, uff. + +2008-04-26 Raja R Harinath + + Fix gtest-388.cs + * expression.cs (VariableReference.EmitAssign) : + Handle 'leave_copy'. + +2008-04-25 Marek Safar + + * expression.cs, nullable.cs: Implemented UnaryPlus expression. + +2008-04-24 Raja R Harinath + + Fix test-636.cs. Sprinkle a few more 'EmitSideEffect's around + * expression.cs (Unary.TryReduceConstant): Unwrap SideEffectConstant. + * statement.cs (While, Do, For): Allow test to have side effects. + (For.DoEmit): Always emit InitStatement. + + Fix test-635.cs + * expression.cs (Binary.DoResolve) : + Always create SideEffectConstant. + (Binary.EnumLiftUp): Don't assume that the enumeration constant is + of type EnumConstant. + + * expression.cs (Binary.EmitBranchable) : + Handle 'right' being SideEffectConstant of type 'bool'. + + * expression.cs (Binary.EmitBranchable) : + Use left.EmitBranchable instead of open coding it, so as to + improve optimization opportunities. + + * constant.cs (SideEffectConstant.EmitSideEffect): Simplify slightly. + + * ecore.cs (Expression.EmitBranchable): Document some non-obvious + assumptions. + (Expression.EmitSideEffect): Document. + +2008-04-23 Marek Safar + + * expression.cs: Implemented NewArrayBounds, TypeIs, and TypeAs expressions. + +2008-04-23 Marek Safar + + * constant.cs, statement.cs: Use EmitSideEffect for constant if statement. + +2008-04-23 Marek Safar + + * ecore.cs, expression.cs, delegate.cs: Implemeted delegate instantiation + conversion to expression tree. + +2008-04-23 Marek Safar + + * ecore.cs: Removed unused expression. + +2008-04-22 Marek Safar + + * expression.cs: Implemented NegateChecked and New expressions. + +2008-04-22 Marek Safar + + * convert.cs, nullable.cs, expression.cs: Implemented Negate expression. + +2008-04-22 Raja R Harinath + + Fix #351102 + * anonymous.cs (AnonymousMethodExpression.DoResolve): Mark as + needing final 'ret' instruction. + +2008-04-22 Marek Safar + + * expression.cs: Disabled lifted binary conversion on ISO-1 profiles. + +2008-04-21 Marek Safar + + * expression.cs: Emit ldnull and not null expression as an instance argument + of static method expression calls. + +2008-04-21 Marek Safar + + A fix for bug #378200 + * expression.cs: Fixed crash when creating parameterless expression tree + method call. + +2008-04-21 Marek Safar + + A fix for bug #375297 + * anonymous.cs: Fixed crash when inferring from null argument anonymous + method. + +2008-04-21 Marek Safar + + A fix for bug #377596 + * decl.cs, class.cs: Emit delegate type argument attributes. + +2008-04-21 Marek Safar + + A fix for bug #365314 + * generic.cs, ecore.cs: Type parameter declaration cannot be of generic type + +2008-04-21 Marek Safar + + * cs-parser.jay, expression.cs: ComposedCast can work with type expressions + only. + +2008-04-21 Marek Safar + + * generic.cs (TypeParameter): Removed redundant location. + +2008-04-19 Marek Safar + + * generic.cs, parameter.cs, namespace.cs, ecore.cs, class.cs, decl.cs, + delegate.cs, iterators.cs, cs-parser.jay, const.cs, enum.cs: Use + FullNamedExpression in all declaration type expression, statements will come + later. + +2008-04-18 Marek Safar + + * generic.cs, namespace.cs, ecore.cs, class.cs, decl.cs, generic-mcs.cs, + nullable.cs, expression.cs, enum.cs, doc.cs: Cleaning up type expressions. + +2008-04-18 Marek Safar + + * parameter.cs, delegate.cs, cs-parser.jay, expression.cs: Removed unused + code. + +2008-04-17 Marek Safar + + * decl.cs, class.cs, generic.cs: Verify partial parts type parameters and + constraints. + +2008-04-17 Marek Safar + + * decl.cs, class.cs, cs-parser.jay, ecore.cs, expression.cs: Unify all type + name expressions. + Also fixes #340463. + +2008-04-17 Raja R Harinath + + Hook up 'EmitSideEffect' + * constant.cs (Constant.EmitSideEffect): New. + (SideEffectConstant.Emit): Simplify. Use EmitSideEffect. + (SideEffectConstant.EmitSideEffect): New. + * ecore.cs (BoxedCast.EmitBranchable): Remove. We can't use an + unconditional branch in EmitBranchable. + (FieldExpr.EmitBranchable): New. + * expression.cs (Unary.EmitSideEffect): New. + (Binary.EmitSideEffect): New. + (VariableReference.EmitSideEffect): New. Do nothing. + +2008-04-16 Raja R Harinath + + Introduce 'EmitSideEffect' + * ecore.cs (Expression.EmitSideEffect): New. + (TypeCast): Rename from EmptyCast. + (EmptyCast): New. + (EmptyCast.EmitBranchable, EmptyCast.EmitSideEffect): Implement. + (BoxedCast.EmitBranchable, BoxedCast.EmitSideEffect): Implement. + * convert.cs, nullable.cs: Update to changes. + +2008-04-16 Marek Safar + + * class.cs, cs-parser.jay: Early check for base types expression. + +2008-04-16 Marek Safar + + * decl.cs (MemberName): Declare PrettyName as obsolete. + +2008-04-16 Marek Safar + + * namespace.cs: Use MemberName comparison. + +2008-04-16 Raja R Harinath + + Fix build break + * decl.cs (MemberName.PrettyName): New. Replaces the misnamed + FullName. + (MemberName.MethodName, MemberName.GetSignatureForError): Improve. + (MemberName.FullyQualifiedName): New. Provides the functionality + that users assume FullName would have. + * ecore.cs, namespace.cs: Update to changes. + + * statement.cs (Using.assign): Make into ExpressionStatement. + (Using.EmitPreTryBody): Simplify. + +2008-04-16 Marek Safar + + * report.cs: ColorFormat is protected. + + * rootcontext.cs: Unused fields clean-up. + + * namespace.cs: Made UsingEntry name private. + +2008-04-16 Marek Safar + + * cs-tokenizer.cs, location.cs: Removed unused field. + +2008-04-16 Jan Oravec + Raja R Harinath + + Fix #379822 + * constant.cs (SideEffectConstant.value): Rename from 'left'. + (SideEffectConstant.side_effect): Rename from 'right'. + (SideEffectConstant..ctor): Normalize 'side_effect'. + (SideEffectConstant.Emit): Emit 'value', not 'side_effect' as the + value of this constant. + * cfold.cs: Update to changes. + +2008-04-15 Marek Safar + + * cs-paser.jay: Removed unused variable. + + * driver.cs: Made Compile instance method. + +2008-04-15 Raja R Harinath + + * flowanalysis.cs (FlowBranching.MergeChild): Simplify. + +2008-04-15 Marek Safar + + * cs-paser.jay, namespace.cs: Simplified handling of namespace imports. + +2008-04-13 Jb Evain + + * namespace.cs: update the System.Core fullname for 2.1 + * driver.cs: update the list of required assemblies for 2.1. + Merged from the Moonlight 2 branch. + +2008-04-11 Marek Safar + + * assign.cs, ecore.cs, expression.cs, nullable.cs: More work on nullable + types and user defined operators. User operators arguments has to be checked + for null value before invocation, which also means no operator is called + when any argument is not convertible to unwrapped nullable type. + +2008-04-09 Marek Safar + + * convert.cs, ecore.cs, expression.cs, nullable.cs: Initial refactoring + of Unary expressions to follow operator overloading rules precisely. + Also fixes #321794, #323794 + +2008-04-08 Marek Safar + + * cs-parser.jay, expression.cs: Don't wrap Indirection expression in Unary + expression. + +2008-04-08 Marek Safar + + * expression.cs, ecore.cs: Implemented MemberInit expression. + +2008-04-08 Raja R Harinath + + Fix mono/tests/exception4.cs + * statement.cs (ExceptionStatement, TryCatch): Revert to using + ec.NeedReturnLabel () rather emitting a 'nop'. + + * statement.cs (ExceptionStatement.SomeCodeFollows): A hook for a + simple heuristic. + (TryCatch.SomeCodeFollows): Likewise. + * flowanalysis.cs (FlowBranchingException): Call 'SomeCodeFollows' + for 'break', 'continue' and 'return' statements inside a try. + We're fairly sure that the generated IL stream will have more + instructions textually following the try. + (FlowBranchingTryCatch): Likewise. + + * statement.cs (Throw.Resolve): Move CS0156 and CS0724 testing ... + * flowanalysis.cs (FlowBranching.CheckRethrow): ... here and to its + overrides. + + * statement.cs (CollectionForeach.DisposableWrapper): Make a true + wrapper -- forward everything to CollectionForeach. + (CollectionForeach.NonDisposableWrapper): New. + (CollectionForeach.EmitFinallyBody): Use 'endfinally' instruction + instead of a pop + branch to end. + +2008-04-07 Marek Safar + + A fix for bug #377485 + * assign.cs, expression.cs, decl.cs, class.cs, ecore.cs, namespace.cs: + Propagate location for extension method groups. Report conversion failure at + right place. + +2008-04-07 Marek Safar + + * anonymous.cs, expression.cs, ecore.cs, typemanager.cs: Implemented + ListInit and Field expressions. + +2008-04-06 Raja R Harinath + + * iterators.cs (Iterator.EmitMoveNext): Remove try/fault wrapper. + Since $PC is always -1 inside the body of MoveNext, the fault + handler is a no-op. + * flowanalysis.cs (FlowBranchingException.EmitFinally): Kill. + * statement.cs (ExceptionStatement.emit_finally): Likewise. + (ExceptionStatement.ResolveFinally): Drop 'branching' argument. + + The denouement! Fix #324708 + * iterators.cs (Iterator.EmitMoveNext): Reset $PC to -1 on entry. + (Iterator.EmitYieldBreak): We no longer need to reset $PC. + * statement.cs (ExceptionStatement.DoEmit): Actually emit the + 'finally' inside the finally clause. + + * statement.cs (ExceptionStatement.DoEmit): Emit try/finally block + inside an iterator. Don't emit the body of the 'finally' inside + the finally clause yet. + + Use the ResumableStatement infrastructure for MoveNext () + * iterators.cs (Iterator.EmitMoveNext_NoResumePoints): New. + (Iterator.EmitMoveNext): Use 'resume_points'. Get rid of + 'old_resume_points'. Move dispatcher upfront. + (Iterator.MarkYield): Mark the 'resume_point' of a Yield. + * statement.cs (ExceptionStatement.DoEmit): Emit a dispatcher if + in an enumerator. This encodes the main fix in this patch series + -- we can only jump into the first instruction of a try from the + outside, but we want to emit try/finally regions in iterators and + resume in the middle of them. + +2008-04-05 Raja R Harinath + + * statement.cs (ExceptionStatement.ResolveFinally): Move setting + of NeedReturnLabel here. + + Introduce a common point for emitting try/finally to IL + * statement.cs (ExceptionStatement.DoEmit): New. Combines all the + features of the various subclasses, which are now driven by ... + (ExceptionStatement.EmitPreTryBody): ... this and ... + (ExceptionStatement.EmitTryBody): ... this and the original + EmitFinallyBody. + (TryFinally, Lock, Using, UsingTemporary, DisposableWrapper): + Remove DoEmit and update to follow above protocol. + + * statement.cs (ExceptionStatement.EmitForDispose): If all labels + of the dispatcher are the same, skip emitting the 'switch'. + * iterator.cs (Iterator.EmitDispose): Update to changes. + + Clean up handling of 'using' statement + * statement.cs (UsingTemporary): New. Carved out of ... + (Using): ... this. Simplify drastically. Handle exactly + one variable. + * cs-parser.jay (using_statement): Split. Create UsingTemporary + or Using as appropriate. If there are multiple variable declared, + create nested Using statements. + (resource_acquisition): Kill. + + * statement.cs (ExceptionStatement.EmitForDispose): Use + EmitFinallyBody, not EmitFinally. + + * flowanalysis.cs (FlowBranching.StealFinallyClauses): Remove. + * iterator.cs: Update to changes. + + Start using the ResumableStatement infrastructure + * statement.cs (ResumeableStatement.PrepareForDispose): New. + (ResumableStatement.EmitForDispose): New. + (ExceptionStatement): Override them. + * iterators.cs (Iterator.EmitDispose): Use PrepareForDispose and + EmitForDispose to create the body of the Dispose method. Don't + use OldResumePoint. + + * iterator.cs (Iterator.AddResumePoint): Move here from ... + * statement.cs (Toplevel.AddResumePoint): ... here. + (Toplevel.MoveNextStatement.Resolve): Create FlowBranchingIterator. + * flowanalysis.cs (FlowBranchingIterator): New. + * codegen.cs (EmitContext): Update to changes. + + * iterators.cs (Iterator.OldResumePoint): Rename from ResumePoint. + (Iterator.old_resume_points): Rename from 'resume_points'. + (Iterator.MoveNextStatement): Remove unused class. + + New infrastructure for try/finally in iterators (still unused) + * flowanalysis.cs (FlowBranching.AddResumePoint): New. + (FlowBranchingToplevel.AddResumePoint): Hook into + ToplevelBlock.AddResumePoint. + (FlowBranchingTryCatch): Move CS01626 and CS01631 checks here. + (FlowBranchingException): Hook into ExceptionBlock.AddResumePoint. + * statement.cs (ToplevelBlock.AddResumePoint): New. Collect + resume points and assign program-counter values. + (ExceptionBlock.AddResumePoint): Collect resume points for + de-muxer at the top of try block. + * iterators.cs (Yield.CheckContext): Simplify. + (Yield.Resolve): Use FlowBranching.AddResumePoint. + +2008-04-04 Raja R Harinath + + * flowanalysis.cs (FlowBranching.AddReturnOrigin): Change Location + argument to an ExitStatement. + (FlowBranchingException): Refactor saved origins code. + * statement.cs (ExitStatement): Update to cahges. + * iterator.cs (YieldBreak): Likewise. + + * statement.cs (ResumableStatement): New. Common base class for + YieldReturn and ExceptionStatement. + (ExitStatement): New. Common base class for Return and YieldBreak. + (Return): Update to changes. + * iterator.cs (YieldBreak): Likewise. + * lambda.cs (ContextualReturn): Likewise. + + Fix #377028 + * ecore.cs (Expression.ResolveAsTypeStep): If '!silent' attempt to + emit a meaningful error message. + + Fix #324765, #319508 + * flowanalysis.cs (VariableInfo.IsEverAssigned): New. + (VariableInfo.SetAssigned): Set it. + * statement.cs (Block.UsageWarning): Use 'IsEverAssigned' to + determine if CS0219 or CS0168 is appropriate. Don't use + flow-analysis information. + (Block.Resolve): Use ec.EndFlowBranching, not ec.DoEndFlowBranching. + * codegen.cs (EmitContext.DoEndFlowBranching): Kill. Inline into ... + (EmitContext.EndFlowBranching): ... this. + +2008-04-03 Marek Safar + + * class.cs, typemanager.cs: Emit volatile field with IsVolatile modifier. + +2008-04-03 Marek Safar + + A fix for bug #376508 + * convert.cs, expression.cs: Fixed difference between ImplicitConversion and + ImplicitConversionExists. + +2008-04-03 Marek Safar + + * expression.cs (Binary): Added remaining binary operators to expression + tree builder. + + * nullable.cs: Optimize shift with null argument. + +2008-04-03 Raja R Harinath + + Fix minor IL regression + * statement.cs (TryCatch..ctor): Add 'inside_try_finally' argument. + (TryCatch.DoEmit): Use it to avoid creating another ExceptionBlock. + * cs-parser.jay (try_statement): Update to changes. + + * statement.cs (TryFinally.need_exc_block): Delete. + (TryFinally): Update to changes. + + Now all ExceptionStatements are unconditional + * statement.cs (CollectionForeach.DisposableWrapper): New. + Extract out the try/finally code into a new wrapper. + (CollectionForeach.Resolve): Use it to simplify the code. + +2008-04-02 Raja R Harinath + + Start at simplifying ExceptionStatement semantics a bit + * statement.cs (TryCatch, TryFinally): Split 'Try' into two pieces. + * cs-parser.jay (try_statement): Update to changes. + (opt_catch_clauses): Remove. + * flowanalysis.cs: Update to changes. + (FlowBranching.BranchingType.TryCatch): New. + (FlowBranchingTryCatch): New. + + * flowanalysis.cs (FlowBranching.BranchingType.SwitchSection): Kill. + (FlowBranching.CreateBranching): Update to changes. + (FlowBranchingBlock.AddSibling): Add sanity check. + * codegen.cs (EmitContext.StartFlowBranching) : + Update to changes. + + * iterators.cs (Iterator.MarkFinally): Remove. + * statement.cs (ExceptionStatement): Update to changes. + + Add support for skipping over finally blocks at runtime. First + in a series to fix #324708 + * iterators.cs (Iterator.SkipFinally): New LocalBuilder. + (Iterator.EmitMoveNext): Initialize it. + * statement.cs (ExceptionStatement.EmitFinally): Use it to emit a + branch over the body of the 'finally' clause. + +2008-03-31 Raja R Harinath + + Avoid lopsided use of Foo/DoFoo names + * statement.cs (ExpressionStatement.EmitFinallyBody): + Rename from EmitFinally. + (ExpressionStatement.EmitFinally): Rename from DoEmitFinally. + * iterator.cs: Update to changes. + +2008-04-02 Marek Safar + + * ecore.cs, expression.cs, nullable.cs: ConditionalLogicalOperator is now + based on UserOperatorCall. More binary nullable operators clean up. + +2008-04-02 Martin Baulig + + * symbolwriter.cs: Remove the `#if !DISABLE_TERRANIA_CHANGES' conditionals. + +2008-04-02 Marek Safar + + * nullable.cs: Merge user and empty conversions when lifting expression + trees. + + * expression.cs (StringConcat): Implemented expression tree representation. + +2008-04-01 Marek Safar + + * nullable.cs: When lifting null literal and a user operator exists, no call + is made. + +2008-04-01 Marek Safar + + * nullable.cs, ecore.cs, expression.cs: Convert null arithmetic to lifted + null. + +2008-04-01 Marek Safar + + * nullable.cs, expression.cs: Use namespace instead heavily nested + monster abstract class. + +2008-04-01 Marek Safar + + * ecore.cs, convert.cs, constant.cs, nullable.cs, expression.cs: Implemented + lifting of null literal and user operators. Clean up of some temporary + nullable hacks. + +2008-03-30 Raja R Harinath + + Fix #368224, test-629.cs + * flowanalysis.cs (FlowBranching.StealFinallyClauses): Return true + if it crossed an unwind-protect boundary. + * iterators.cs (Yield.CheckContext): Relax check for 'yield break'. + (Yield.Resolve, Yield.DoEmit): Track whether the yield occurs + inside an unwind-protected region. + (YieldBreak.Resolve, YieldBreak.DoEmit): Likewise. + (Iterator.MarkYield): Add 'unwind_protect' parameter. Emit a + 'leave' instead of a 'br' if unwind-protected. + (Iterator.EmitYieldBreak): Likewise. + +2008-03-29 Gert Driesen + + * driver.cs: Only define versioninfo resources if no win32 resource + file was specified. + +2008-03-28 Marek Safar + + A fix for bug #372375 + * convert.cs: Fixed boxing of nullable types. + +2008-03-28 Marek Safar + + * typemanager.cs: Initialize InternalsVisibleTo as the very first optional + type. + +2008-03-28 Marek Safar + + A fix for bug #374619 + * nullable.cs: Fixed guarding of EmitBitwiseBoolean. + +2008-03-27 Marek Safar + + * lambda.cs: Check return type only for invocation. + +2008-03-27 Marek Safar + + A fix for bug #374214 + * ecore.cs: Correctly report argument type mismatch. + +2008-03-27 Marek Safar + + * convert.cs (ImplicitReferenceConversionCore): Correctly compare enum type + and not rely on broken IsEnum. + +2008-03-27 Marek Safar + + * nullable.cs: New file, extracted from generic.cs. + + * generic.cs, generic-mcs.cs, *.csproj, *.sources: Updated. + +2008-03-27 Marek Safar + + * generic.cs, convert.cs, generic-mcs.cs, expression.cs: Added lifting of + predefined comparison operators and null literals. + + * report.cs: New warning ID. + +2008-03-25 Marek Safar + + A fix for bug #370577 + * lambda.cs: Check return type too. + +2008-03-25 Marek Safar + + A fix for bug #372846 + * class.cs: Automatic properties can be declared as unsafe. + +2008-03-20 Marek Safar + + * location.cs: Use string based concatenation. + + * expression.cs: LiftedBinaryOperator is gmcs only. + +2008-03-20 Marek Safar + + * generic.cs, literal.cs, ecore.cs, expression.cs: Ongoing work on nullable + conversions rules and expression trees. + +2008-03-19 Marek Safar + + * delegate.cs: Use extension method source as delegate target. + +2008-03-19 Marek Safar + + * generic.cs, generic-mcs.cs, expression.cs, ecore.cs: Rewrote nullable + binary operations to be purely based on binary operations and optimized + emitted code (30% less in some cases). Introduced ReducedExpression for ETs + and other ET refactoring. + + * typemanager.cs: Fixed warning. + +2008-03-17 Marek Safar + + * class.cs, decl.cs, delegate.cs: Do protected modifier check on each member + + * symbolwriter.cs: Fixed. + +2008-03-17 Marek Safar + + * anonymous.cs, driver.cs: Reset anonymous types counters. + +2008-03-17 Marek Safar + + * ecore.cs (MethodGroupExpr): Skip first candidate, it's already the best. + + * class.cs: Use fullname for all type member definitions. + +2008-02-19 Martin Baulig + + * class.cs + (IMethodData.EmitExtraSymbolInfo): New interface method. + (MethodData.Emit): Call method.EmitExtraSymbolInfo(). + (MethodOrOperator.EmitExtraSymbolInfo): Implement this new + interface method here as an empty public virtual method. + + * anonymous.cs + (AnonymousMethodMethod.ctor): Added `string real_name' argument. + (AnonymousMethodMethod.EmitExtraSymbolInfo): Override and call + CodeGen.SymbolWriter.SetRealMethodName(). + +2008-02-18 Martin Baulig + + * anonymous.cs + (ScopeInfo.EmitType): Override this and emit debugging + information for captured variables. + (RootScopeInfo.EmitType): Override this and emit symbol + information for a captured `this'. + +2008-02-15 Martin Baulig + + * iterators.cs: Emit debugging info. + + * codegen.cs + (EmitContext.Flags): Add `OmitDebuggingInfo'. + (EmitContext.OmitDebuggingInfo): New public property. + + * statement.cs + (While): Override Emit() and don't emit symbol info there; do it + inside DoEmit() instead. + (Block.Emit): Omit symbol information while emitting the scope + initializers; don't ec.Mark() the `EndLocation'. Fix the lexical + block logic. + (ExplicitBlock.IsIterator): Moved here from `ToplevelBlock'. + (ToplevelBlock.MakeIterator): Pass the `flags' to `ExplicitBlock's + .ctor to make `IsIterator' work. + +2008-03-14 Martin Baulig + + * symbolwriter.cs: Added the new symbol writer function from the + debugger's `terrania' branch; temporarily enclose them inside + `#if !DISABLE_TERRANIA_CHANGES' conditionals until I'm back from + my vacations. + +2008-03-14 Martin Baulig + + * symbolwriter.cs + (SymbolWriter): Make this a public static class. + + * codegen.cs + (CodeGen.SymbolWriter): Removed; use the new static `SymbolWriter' + class instead of using `if (CodeGen.SymbolWriter != null)' everywhere. + +2008-03-14 Marek Safar + + A fix for bug #370577 + * statement.cs, lambda.cs: Added extra limitations when dealing with void + return type. + +2008-03-14 Marek Safar + + * typemanager.cs (CSharpName): Made 250 times faster. + +2008-03-13 Marek Safar + + * ecore.cs, expression.cs: Emit conversion for ET shift argument. + +2008-03-12 Marek Safar + + * generic.cs, typemanager.cs, enum.cs, codegen.cs, statement.cs: Try not to + crash when predefined field does not exist. + +2008-03-12 Marek Safar + + * ecore.cs (PropertyExpr): Fixed IsSingleDimensionalArrayLength regression. + +2008-03-12 Marek Safar + + * class.cs (FixedField): Don't crash when contructors are missing. + +2008-03-11 Marek Safar + + * typemanager.cs, namespace.cs, literal.cs, ecore.cs, class.cs, decl.cs, + convert.cs, constant.cs, expression.cs, statement.cs: Use same method to + check internal types accessibility for internal and external types. + Replaced EnumToUnderlying by GetEnumUnderlyingType. + +2008-03-11 Marek Safar + + * support.cs, typemanager.cs, pending.cs, ecore.cs, class.cs, delegate.cs + convert.cs, const.cs, anonymous.cs, constant.cs, expression.cs, + attribute.cs, statement: Use corect instance of predefined types (work + related to #364674). + +2008-03-07 Marek Safar + + * expression.cs (TypeOfVoid): Fixed predefined method initialization. + +2008-03-07 Marek Safar + + * generic.cs, typemanager.cs, parameter.cs, rootcontext.cs, ecore.cs, + class.cs, delegate.cs, iterators.cs, const.cs, constant.cs, driver.cs, + expression.cs, attribute.cs, codegen.cs, statement.cs: TypeManager optional + predefined types clean up, delayed predefined types members initialization + (work related to #364674). + +2008-03-05 Marek Safar + + * typemanager.cs (IsFriendAssembly): InternalsVisibleTo is not mandatory. + +2008-03-05 Marek Safar + + * typemanager.cs, parameter.cs, rootcontext.cs, ecore.cs, class.cs, decl.cs, + delegate.cs, convert.cs, driver.cs, attribute.cs, codegen.cs: TypeManager + predefined types clean up (work related to #364674). + +2008-03-04 Marek Safar + + * ecore.cs: Print an error message instead of throwing exception. + +2008-03-04 Marek Safar + + * generic.cs, typemanager.cs, literal.cs, convert.cs, cfold.cs, constant.cs, + expression.cs, statement.cs: Unififed null literal representation. + +2008-03-03 Marek Safar + + * anonymous.cs, cfold.cs, convert.cs, delegate.cs, doc.cs, ecore.cs, + expression.cs: Refactored binary operators resolve phase and improved speed. + The nullable code is still missing and won't work correctly, more fixes + required. + + It also fixes #323726, #324312, #324248, and many other unreported issues. + +2008-02-29 Zoltan Varga + + * report.cs (FeatureIsNotAvailable): Use 'mcs1' instead of 'mcs', and 'mcs' + instead of 'gmcs'. + +2008-02-27 Marek Safar + + * ecore.cs: Clean-up and split BetterConversion. + +2008-02-25 Raja R Harinath + + Fix #363791 + * enum.cs (EnumMember.Value): Only access 'value' if + ResolveValue says it's ok. + (EnumMember.DoResolveValue): Don't set prev_member.value. + (Enum.GetDefinition): Reverse arguments of Equals -- + EnumMember.Value can return 'null'. + + * statement.cs (Switch.Error_AlreadyOccurs): Fix typo in name. + +2008-02-22 Marek Safar + + * generic.cs, expression.cs: More ongoing work on expression trees. + +2008-02-21 Marek Safar + + * class.cs, typemanager.cs: Rewrote operator matching logic to correctly + handle missing matches when mutiple operators exist. + +2008-02-20 Marek Safar + + A fix for bug #363218 + * expression.cs (ArrayCreation.Clone): Deal with multi-dimensional + initializers. + +2008-02-20 Marek Safar + + * expression.cs, constant.cs, cfold.cs: Yet another side-effect constant + update. This time to deal correctly with SideEffectConstant expression used + as an argument for another constant folding. + +2008-02-20 Raja R Harinath + + * typemanager.cs (DropGenericMethodArguments): Ensure we get an underlying + MethodBuilder. + +2008-02-19 Marek Safar + + * constant.cs, cfold.cs: SideEffectConstant results can apply for folding. + +2008-02-19 Marek Safar + + A fix for bug #328136 + * expression.cs: Do not fold immediately LogicalAnd operators when the left + side is a false constant, because we still need to evaluate the right-hand + side. + + * statement.cs (If): Emit two types of boolean constants (simple constant, + side-effect constant). + +2008-02-19 Marek Safar + + * constant.cs (SideEffectConstant): Don't emit boolean constant. + + * expression.cs: Fold immediately LogicalAnd operators when both sides are + constants. + +2008-02-18 Marek Safar + + A fix for bug #361457 + * ecore.cs (IsApplicable): Params methods have lower priority. + + * support.cs: Return correct parameter modifier for params types. + +2008-02-18 Marek Safar + + * generic.cs (TypeParameter): Cache attribute target name. + + * support.cs: Removed unused variable. + + * typemanager.cs: Removed debugging leftover. + + * ecore.cs: Use local type instead of a property; + + * class.cs (VerifyMembers): Consider also parent to test whether type member + is local or public. + + * expression.cs (FullMethodDesc): Removed. + + * attribute.cs (IsValidArgumentType): Made static. + +2008-02-17 Raja R Harinath + + Cleanup to be more readable. + * Makefile (GMCS_PROFILE): Remove. + (COMPILER_NAME): New helper. + +2008-02-15 Miguel de Icaza + + * cs-tokenizer.cs: if a conditional expression happens inside a + (...) this also means that we do not need to de-ambiguate between + an parenthesized expression and a cast. + + Fixes 346484. + + * constant.cs (SideEffectConstant): a constant value that happens + to have a side effect. + + Fixes the build regressions introduced by the fix for #359789 + +2008-02-14 Rodrigo Kumpera + + * expression.cs (Conditional.Emit): when emitting the ternary + operator, use local variables to generate code verifiable code. + + The verifier cannot infer that the type on stack before the + stloc.0 is executed is of type ParentB. This happens because the + stack merge algorithm uses only parent types when deciding which + is the common type. This is described in Part III 1.8.1.3 of ECMA + 335. + + This code compiled with mcs is not verifiable under MS. The MS + verifier picks the first common interface of Foo and Bar, which is + wrong, but doesn't use a full join type of the 2 interfaces. + + CSC uses a clever hack to compile such code in a verifiable + way. It stores the intermediate values in a local variable with + the expected type. + + Fixes: #358102 + +2008-02-14 Miguel de Icaza + + * expression.cs: Do not fold BitwiseAnd operators when the left + side is a false constant, because we still need to evaluate the + right-hand side. + + Fixes #359789 + + * support.cs: Instead of throwing an InternalErrorException when + the position of the stream is outside the boundary of our buffer, + reset the state of the reader, and restart the reading from the + beginning of the file. + +2008-02-14 Marek Safar + + * generic.cs (TypeParameter.GetMembers): Is not supported operation. + +2008-02-14 Marek Safar + + A fix for bug #361686 + * decl.cs: A protected types used inside a private class which parents + derives from the protected class are accessible. + +2008-02-13 Marek Safar + + * generic.cs (ConstraintChecker): Use cached member lookup when looking for + the parameterless constructor. + +2008-02-13 Marek Safar + + * generic.cs, typemanager.cs, iterators.cs, codegen.cs: Refactored core + lookup methods to use standard member cache when doing member lookup. + +2008-02-12 Marek Safar + + * driver.cs: Don't report full path for referenced module as assembly error. + +2008-02-12 Marek Safar + + * Makefile: Fixed `qh' target to work on all machines. + + * report.cs, typemanager.cs, parameter.cs, ecore.cs, class.cs, anonymous.cs, + expression.cs, codegen.cs, statement.cs, doc.cs: Replaced type IsSubclassOf + and HasElementType with TypeManager implementation. + +2008-02-08 Marek Safar + + A fix for bugs #325134, #359749 + * expression.cs, ecore.cs: Try to resolve an extension method even if the + first binds point to non-method member expression. + +2008-02-08 Marek Safar + + * cs-parser.jay: Null coalescing operator is not part of ISO-1. + +2008-02-08 Marek Safar + + A fix for bugs #321394, #323028 + * generic.cs, parameter.cs, ecore.cs, class.cs, decl.cs, delegate.cs: + Reworked naive IsAccessibleAs implementation to handle nested types. + +2008-02-05 Jb Evain + + * class.cs: use generic type comparison for parameters + as well. + +2008-02-05 Marek Safar + + A fix for bug #325372 + * class.cs: Use generic type comparison when testing method signatures. + +2008-02-05 Marek Safar + + A fix for bug #357047 + * ecore.cs: Applied C# 3.0 changes to better conversion. + +2008-02-05 Marek Safar + + A fix for bug #358374 + * cs-parser.jay: Correctly set modifiers for all constructor types. + +2008-02-04 Marek Safar + + A fix for bug #355251 + * generic.cs: Added base class constraint based type inference. + +2008-02-01 Marek Safar + + A fix for bug #357255 + * decl.cs: One more missing visibility check. + +2008-02-01 Marek Safar + + * support.cs: Fixed broken return. + +2008-01-25 Marek Safar + + * report.cs: Correctly reset warnings count after probing. + +2008-01-25 Martin Baulig + + * namespace.cs + (NamespaceEntry.SymbolFileID): Make this work again after + MemberName.ToString() is gone. + +2008-01-25 Marek Safar + + * expression.cs: Implemented Divide, Equal, ExclusiveOr, GreaterThanOrEqual + expressions. + +2008-01-25 Marek Safar + + * generic.cs: Use full implicit conversion for type inference fixing. + +2008-01-24 Marek Safar + + * ecore.cs, expression.cs, generic.cs: Implemented Convert, ConvertChecked. + Fixed user operator conversions. + +2008-01-24 Marek Safar + + * generic.cs: Do nullable type to null comparison optimization during + resolve phase. + +2008-01-24 Marek Safar + + A fix for bug #355163 + * generic.cs: Enabled l-value resolve on nullable expressions. + +2008-01-24 Marek Safar + + A fix for bug #353986 + * class.cs: Ingore static ctors with parameters for any further checks. + +2008-01-24 Marek Safar + + A fix for bug #354310 + * namespace.cs: Removed redundant check. + +2008-01-24 Marek Safar + + A fix for bug #354928 + * expression.cs: ElementInitializers can be resolved only once. + +2008-01-24 Marek Safar + + * convert.cs, ecore.cs, expression.cs, generic.cs: Implemented Coalesce and + Condition expressions. + +2008-01-23 Marek Safar + + * codegen.cs: Fixed AssemblyBuilder initialization on other platforms. + +2008-01-22 Marek Safar + + * ecore.cs, expression.cs, generic.cs: Implicit bool? to bool conversion is + not allowed. + + * generic.cs: Implemented coalesce expression. + +2008-01-22 Marek Safar + + A fix for bug #355145 + * anonymous.cs, convert.cs, ecore.cs, generic.cs, lambda.cs: Implemented + expression tree type inference. + +2008-01-22 Raja R Harinath + + Fix #354663 + * expression.cs (Binary.IsUnsignedType): Fix typo. + +2008-01-22 Marek Safar + + * ecore.cs, expression.cs, generic.cs: Implemented NewArrayInit expression. + +2008-01-22 Marek Safar + + A fix for bug #355161 + * ecore.cs, expression.cs: Wider range of extension method supported + expressions. + +2008-01-22 Gert Driesen + + * codegen.cs: Use magic value for AssemblyBuilderAccess to instruct + AssemblyBuilder to operate in compiler context. Fixes mcs part of + bug #354970. + +2008-01-22 Marek Safar + + A fix for bug #355148 + * ecore.cs, expression.cs: Correctly report misused ref and out modifiers. + +2008-01-22 Miguel de Icaza + + * expression.cs (CreateExpressionTree): Add support for or and + logical or, and indent following the coding conventions. + + * typemanager.cs (LinqExpression): renamed from + ExpressionTreeManager, for a shorter name. + + Use TypeManager.CoreLookupType to lookup types from our core + assemblies and turn those into "Type" variables. + + Consumers that previously used "Namespace" and "Type" from this + class should instead use the TypeExpression which is a type that + is fully resolved (without involving the regular C# resolution + rules). + + This typically looks like this: + + TypeExpression texpr = new TypeExpression (LinqExpression.expression_type, loc); + new MemberAccess (texpr, name, type_arguments, loc) + + This avoids the problem in: #355178 + +2008-01-21 Marek Safar + + * cs-parser.jay, expression.cs: Check `namespace alias qualifier' language + feature in parser only as we do in other cases. + +2008-01-21 Marek Safar + + * attribute.cs, ecore.cs, class.cs, delegate.cs, expression.cs, linq.cs, + typemanager.cs: A refactoring of params arguments to reuse existing + expressions (params -> array initializer) to emit params argument instead + of specialized handling. + It was required by expression tree implementation and it has other benefits + as well, we now apply same optimization for params arguments as we do for + array initializers. + +2008-01-18 Marek Safar + + A fix for bug #353526 + * generic.cs: A type inference of params arguments may not required any + temporary array creation. + +2008-01-18 Marek Safar + + A fix for bug #353534 + * generic.cs, ecore.cs, expression.cs: A method group type inference is + supported for delegates only. + +2008-01-18 Marek Safar + + * generic.cs: Fixed 3.0 type inference fixing phase to determine a unique + type for more than 1 candidates. + +2008-01-18 Marek Safar + + * typemanager.cs, ecore.cs, expression.cs: Implemented ArrayLength and Call + expressions. + +2008-01-16 Marek Safar + + * generic.cs, typemanager.cs, lambda.cs, parameter.cs, ecore.cs, constant.cs, + expression.cs: Implemented Add, And, AndAlso, and ArrayIndex (without unary + operator) expressions. + +2008-01-16 Zoltan Varga + + * statement.cs: Avoid declaring an IL variable for this_variable since it is + not accessed from the generated IL. + +2008-01-14 Marek Safar + + * typemanager.cs, lambda.cs, parameter.cs, ecore.cs, class.cs, delegate.cs, + iterators.cs, convert.cs, assign.cs, anonymous.cs, expression.cs, + statement.cs: The first expression tree implementation drop, mostly + infrastructure work. + +2008-01-14 Marek Safar + + * ecore.cs (IsNestedChild): Refactored. + +2008-01-11 Marek Safar + + * lambda.cs: Don't use a cast on unknown expression statement. + +2008-01-10 Geoff Norton + + * cs-tokenizer.cs: One more token to distinguish between method and lambda + arguments + +2008-01-09 Marek Safar + + * doc.cs: Report better /doc crash details. + +2008-01-09 Marek Safar + + A fix for bug #352536 + * ecore.cs, assign.cs, codegen.cs: Check event assignments. + +2008-01-08 Marek Safar + + A fix for bug #352287 + * ecore.cs, expression.cs: Do `this' access checking in all member access + expressions. + +2008-01-08 Marek Safar + + * rootcontext.cs, driver.cs: Switch to linq mode by default. + + * report.cs: Reset message stacks. + +2008-01-08 Marek Safar + + * generic.cs (InferInPhases): Correctly calculate params position. + +2008-01-08 Marek Safar + + * cs-tokenizer.cs: No need to parse full string when parsing lambda + arguments. + +2008-01-07 Marek Safar + + * cs-tokenizer.cs: Enabled lambda arguments micro-parser for all profiles. + + * decl.cs (LookupNamespaceOrType): Don't cache names which caused an error. + + * driver.cs: Updated --help option. + +2008-01-07 Marek Safar + + * generic.cs (InferParamsTypeArguments): Removed. + (InferInPhases): Add params type inference. + (LowerBoundInference): Fixed scoring mechanism. + + * cs-tokenizer.cs (PreProcessPragma): Use Location instead of line. + +2008-01-06 Gert Driesen + + * typemanager.cs: On 2.0 profile, GetPublicKeyToken returns an empty + byte array for unsigned "baked" assemblies. + +2008-01-05 Gert Driesen + + * codegen.cs: AssemblyName.GetPublicKey returns a zero-length byte + array for assemblies that are not strongnamed. + +2008-01-04 Marek Safar + + A fix for bug #351481 + * expression.cs (MemberAccess.ResolveNamespaceOrType): Use correct + declaring type for nested generic types. + +2008-01-04 Marek Safar + + * namespace.cs, class.cs, decl.cs, cs-parser.jay: Use GetSignatureForError + instead of ToString. + +2008-01-03 Marek Safar + + A fix for bug #351047 + * expression.cs (Binary.ResolveOperator): Allow equality operators between + null and structs only when equality and inequality operators are defined + either as an user-operators or predefined operators. + +2008-01-03 Marek Safar + + A fix for bug #351047 + * generic.cs, typemanager.cs, class.cs: New IsReferenceType helper method. + +2008-01-03 Marek Safar + + A fix for bug #351257 + * cs-tokenizer.cs: Advance line number for '\r' correctly. + +2008-01-03 Marek Safar + + A fix for bug #351157 + * class.cs (Using): Fixed yet another broken cloning. + + (Block): Put back more sensible default value for statements. + +2008-01-01 Gert Driesen + + * codegen.cs: Allow AssemblyVersion with only major version component. + Fixes bug #351055. + +2007-12-29 Marek Safar + + A fix for bug #324654 + * class.cs: Use FullName property as member name. + +2007-12-28 Marek Safar + + A fix for bug #342117 + * generic.cs (ConstraintChecker): Struct constraint also satisfies default + constructor constraint. + +2007-12-28 Marek Safar + + A fix for bug #338273 + * class.cs (ProbertyBase): Access modifier checks are required for overrides + only. + +2007-12-28 Marek Safar + + A fix for bug #350839 + * ecore.cs (MethodroupExpr): Probing hacks are no longer required. + +2007-12-27 AdTsai (http://code.google.com/u/AdTsai/) + + Reviewed by Ben Maurer, Miguel de Icaza, patches from Google's + GHOP: + + http://code.google.com/p/google-highly-open-participation-mono/issues/detail?id=4 + + * statement.cs: Changed some Hashtables to use HybridDictionaries + instead. It was observed that some HashTables only contained a few + items in the vast majority of cases. Since HybridDictionary is + more efficient on small sets (<10 elements), "known_variables" + from class ExplicitBlock as well as "labels" and "constants " from + class Block were changed to HybridDictionaries. + + Atsai results: (56216kb->54987kb) + + Miguel results (bootstrap of mcs): 59819kb -> 59290kb + + +2007-12-27 AdTsai (http://code.google.com/u/AdTsai/) + + Reviewed by Ben Maurer, Miguel de Icaza, patches from Google's + GHOP: + + http://code.google.com/p/google-highly-open-participation-mono/issues/detail?id=4 + + * expression.cs: foreach loop to for loop, saved on allocation of + enumerator (59333kb->59141kb) + + * statement.cs. Changed foreach loops to for loops, saved on + allocation of enumerator (59141kb->59006kb) + + * decl.cs: ArrayLists in .NET 1.1 allocate 16 elements by default + when constructed with no specified capacity. This was causing a + few ArrayLists to allocate more memory than they would potentially + need in the Block class and MemberCache class. Setting the + ArrayLists to construct with a capacity of 1 saves some + memory. (56216kb->55585kb) + +2007-12-27 Marek Safar + + A fix for bug #347189 (2nd issue) + * expression.cs (MemberAccess): Nested type can be found in base non-generic + type. + +2007-12-27 Miguel de Icaza + + * report.cs: Do not use colors if stdout and stderr are not a + terminal. + +2007-12-27 Marek Safar + + A fix for bug #346998 + * ecore.cs (MethodGroupExpr): Implemented override filter for generic + overloads. + +2007-12-27 Marek Safar + + A fix for bug #343465 + * class.cs: Explicit method name for nested types uses dots only. + +2007-12-27 Marek Safar + + A fix for bug #343707 + * cs-tokenizer.cs: Advance line number for mixed CR/LF files correctly. + +2007-12-27 Marek Safar + + * ecore.cs: Report type inference errors only when arguments count matches + parameter count. + + * generic.cs (NullCoalescingOperator): Cannot be applied to null. + + * expression.cs, report.cs: New warning. + + * typemanager.cs: Catch anonymous method type too. + +2007-12-23 Marek Safar + + A fix for bug #346379 + * expression.cs (UnaryMutator): Emit size of type for pointer mutator. + +2007-12-23 Marek Safar + + A fix for bug #347359 + * expression.cs (Invocation): Don't resolve already resolved expression. + +2007-12-23 Marek Safar + + A fix for bug #347189 + * class.cs (FixedField): Use non-dependent code only in the define phase. + +2007-12-23 Marek Safar + + A fix for bug #348076 + * ecore.cs (FieldExpr.DoResolve): Allow any variable based expression. + +2007-12-22 Marek Safar + + * ecore.cs (MethodGroupExpr.OverloadResolve): Set type arguments for + discovered extension methods. + +2007-12-22 Marek Safar + + * ecore.cs, namespace.cs, expression.cs: Removed broken ResolveGeneric + method. + +2007-12-21 Miguel de Icaza + + * report.cs (ErrorMessage): Add support for using colors on + terminals that support it. + +2007-12-21 Marek Safar + + * ecore.cs: Use information about expanded params for error reporting. + +2007-12-21 Marek Safar + + * ecore.cs, generic.cs, delegate.cs: Refactoring of method overloading code + and logic for params overloads. + +2007-12-15 Miguel de Icaza + + * generic.cs (NullCoalescingOperator.CloneTo): implement this one, + as this is also created from the parser. Fixes #349034 + +2007-12-12 Miguel de Icaza + + * statement.cs (Throw.CloneTo): it is valid to have empty + expressions for throw. + +2007-12-03 Marek Safar + + * cs-parser.jay: Set delegate constraint parsing region correctly. + +2007-12-03 Marek Safar + + A fix for bug #345467 + * typemanager.cs (IsEqual): Compare generic parameters position only. + +2007-11-28 Marek Safar + + * expression.cs (BaseAccess): Type arguments can be null. + +2007-11-27 Raja R Harinath + + * statement.cs (Block.Resolve): Ensure flow-branching tree is + consistent even when an error has occured. + (Switch.Resolve): Likewise. + +2007-11-22 Marek Safar + + A fix for bug #334505 + * class.cs: Don't ignore InternalsVisibleTo attribute for internal + overrides. + +2007-11-22 Marek Safar + + * ecore.cs, typemanager.cs, delegate.cs, expression.cs: The first of + refactorings required to resolve extension methods correctly when mixing + generics and non-generics members. + +2007-11-20 Marek Safar + + A fix for bug #342584 + * convert.cs: Added not documented explicit IntPtr/UIntPtr to enum + conversion. + +2007-11-19 Marek Safar + + A fix for bug #342512 + * delegate.cs: Use delegate argument expression when is available. Don't + emit virtual call when class is sealed. + +2007-11-16 Marek Safar + + A fix for bug #325423 + * assign.cs (FieldInitializer): Use resolved expression for emit. + + * class.cs: Print less confusing error message. + +2007-11-16 Marek Safar + + * cs-tokenizer.cs: Removed GMCS ifdefs. + + * rootcontext.cs, report.cs: Report unavailable gmcs features used by + mcs. + + * cs-parser.jay: Disabled nullable check. + + * generic-mcs: Copied more generic stuff. + +2007-11-16 Marek Safar + + * gcs-parser.jay: Merged to cs-parser.jay. + + * generic.cs, typemanager.cs, cs-tokenizer.cs, linq.cs, Makefile + * *.csproj, *.sources: Updated to use only jay parser file. + +2007-11-16 Marek Safar + + * gcs-parser.jay: Added nullable and default expression feature checks. + +2007-11-16 Marek Safar + + * gcs-parser.jay, cs-parser.jay, class.cs: Unified parameters parsing, + it fixes many TODOs and hidden bugs. + + * expression: Removed duplicate error check. + +2007-11-15 Marek Safar + + * gcs-parser.jay, statement.cs, decl.cs, ecore.cs: Try to resolve an + implicitly type local variable only when it is used in a declaration. + +2007-11-15 Marek Safar + + * attribute.cs: Use CS0612 for empty strings. + +2007-11-14 Marek Safar + + * lambda.cs, statement.cs: Contextual return may act as a statement. + +2007-11-14 Marek Safar + + A fix for a regression cause by #324222 + * class.cs: Don't report unused even when it implements an interface. + +2007-11-13 Marek Safar + + A fix for bug #341205 + * ecore.cs, expression.cs: Method group expression cannot do static + method access with an instance reference check before overloading takes + a place. + +2007-11-13 Marek Safar + + A fix for bug #325359 + * class.cs: Use predictable name for automatically generated property. + +2007-11-12 Marek Safar + + A fix for bug #324996 + * expression.cs (Is): Handle case where D is nullable and T is not + correctly. + + * generics.cs (Nullable.HasValue): Nullable HasValue expression. + +2007-11-12 Marek Safar + + * generic.cs, literal.cs, ecore.cs, class.cs, delegate.cs, const.cs, + anonymous.cs, expression.cs, attribute.cs, codegen.cs, statement.cs: + Flush small error reporting changes. + +2007-11-09 Marek Safar + + A fix for bug #324996 + * expression.cs: Rewrote Is expression implementation to work with + generics, nullable types, anonymous method. A const result expression + uses existing infrastructure instead of custom not fully-featured one. + +2007-11-08 Marek Safar + + A fix for bug #340202 + * class.cs: Consider generics for volatile field. + +2007-11-08 Marek Safar + + A fix for bug #335594 + * expression.cs: Use conversion rules when handling string addition. + +2007-11-07 Marek Safar + + A fix for bug #336651 + * expression.cs: Fixed a crash when probing is on. + +2007-11-07 Marek Safar + + A fix for bug #324242 + * covert.cs: Added a conversion from any nullable-type with an + underlying enum-type to the type System.Enum. + +2007-11-07 Marek Safar + + A fix for bug #324222 + * class.cs: Report all non-used event fields. + +2007-11-07 Marek Safar + + A fix for bug #325161 + * cs-parser.jay, gcs-parser.jay, decl.cs: Implemented namespace alias + qualifier for generic types. + +2007-11-07 Marek Safar + + A fix for bug #322971 + * expression.cs, ecore.cs: Added intermediate result value check for + indexers. + +2007-11-07 Marek Safar + + A fix for bug #324754 + * cs-parser.jay, gcs-parser.jay, class.cs: Try to create an interator + when it was requested. + +2007-11-07 Marek Safar + + A fix for bug #325101 + * expression.cs: Do type not value comparison for `is' expression. + +2007-11-07 Marek Safar + + A fix for bug #320236 + * convert.cs: Don't apply user conversion on underlying target type. + +2007-11-06 Marek Safar + + * expression.cs: Don't use unresolved expression for error reporting. + +2007-11-06 Marek Safar + + A fix for bugs #337712, #324490 + * ecore.cs (MethodGroupExpr): Refactored to handle delegate method + overloading resolution too. + + * delegate.cs: Uses MethodGroupExpr for overloading resolution. It makes + the process consistent and more robust. + + * expression.cs, linq.cs, report.cs: Update. + +2007-11-02 Marek Safar + + A fix for bug #332909 + * attribute.cs: Resolve attributes in correct context using error + handling procedure. + + * rootcontext.cs: Define Obsolete attribute members as core members. + +2007-11-02 Marek Safar + + * statement.cs: Removed unused methods. + +2007-10-31 Wade Berrier + + * Makefile: reenable copy of gmcs.exe.config, but include it in EXTRA + DIST (it doesn't get included because PROGRAM isn't defined to be gmcs + during 'make dist') + +2007-10-31 Marek Safar + + A fix for bug #338102 + * decl.cs (CheckExistingMembersOverloads): Workaround issue with generic + methods registered as non-generics. + +2007-10-31 Marek Safar + + A fix for bugs #337712, #324490 + * delegate.cs: Delegate covariance and contravariance is not allowed for + value types. + +2007-10-31 Marek Safar + + A fix for bug #337719 + * cs-tokenizer.cs: Restore identifier buffer when parsing contextual + `from' keyword. + +2007-10-30 Marek Safar + + * Makefile (net_2_0_bootstrap/mcs.exe.config): Reverted copy gmcs.exe.config. + +2007-10-29 Marek Safar + + * cs-tokenizer.cs, gcs-parser.jay, driver.cs: Fixed parsing of nested + query expressions. + +2007-10-29 Raja R Harinath + + * Makefile (net_2_0_bootstrap/mcs.exe.config): Copy gmcs.exe.config. + +2007-10-29 Marek Safar + + A fix for bug #334652 + * ecore.cs (MethodGroupExpr.OverloadResolve): Do also lookup for + extension methods when we have not found the best candidate in normal + container. + +2007-10-27 Marek Safar + + * AssemblyInfo.cs: Keep up-to-date. + +2007-10-27 Marek Safar + + * Makefile: Fixed generics compiler name. + +2007-10-27 Marek Safar + + * lambda.test: removed, lambda parsing is done differently. + + * gen-il.cs, gen-treedump.cs, old-code.cs : Obsolete. + +2007-10-27 Gert Driesen + + * Makefile: Removed dependency on gmcs.exe.config. Fixes build. + +2007-10-27 Marek Safar + + * Makefile, *.sources : All C# compilers are in mcs folder. + + * *.cs: Use existing 2_1 define for smcs. + +2007-10-26 Marek Safar + + A fix for bug #335847 + * assign.cs, expression.cs: Couple of changes to avoid creating a + temporary variable for each object initializer assignment statement. It + simplifies struct initialization too, otherwise two temporary variables + would be required. + Implemented optimization of redundant default element initializers. + +2007-10-25 Marek Safar + + A fix for bug #336766 + * expression.cs (Class.CheckBase): Use generic name when method is + generic. + +2007-10-25 Marek Safar + + A fix for bug #334737 + * expression.cs (IndexerAccess.EmitAssign): Emit local temporary + variable and not variable argument for prepared copies. + +2007-10-24 Marek Safar + + A fix for bug #325110 + * class.cs, expression.cs, attribute.cs: Use open generic method when + checking conditional attribute. + +2007-10-24 Marek Safar + + * report.cs, cs-tokenizer.cs, class.cs, cs-parser.jay, anonymous.cs, + expression.cs, statement.cs: Renamed method FeatureIsNotISO to + FeatureIsNotAvailable. + +2007-10-24 Marek Safar + + ** C# 3.0 Partial methods + + * cs-tokenizer.cs, support.cs, class.cs, decl.cs: Implemented partial + methods support. Because of member cache issue with generics only + non-generics partial methods are fully supported. + +2007-10-23 Marek Safar + + * class.cs, decl.cs: Rewrote member overloads check to cope with + generics and to use member cache for member checking. It also improves + performance and fixes remaining overloads issues. + +2007-10-20 Marek Safar + + * class.cs, const.cs, decl.cs, delegate.cs, enum.cs, generic.cs, + roottypes.cs, typemanager.cs: + + A member cache creation logic changed to add members immediately and + not rely on fallback. The member cache is now only prefered way + how to access and find type declaration members. It saves 5 MB of memory + during MWF compilation and makes code ready for more optimizations and + clean-ups, it's also a pre-requirement for partial methods. + +2007-10-18 Raja R Harinath + + * ecore.cs (Expression.Error_ValueCannotBeConverted): Add special + handling for generic parameters. + +2007-10-15 Marek Safar + + * class.cs (FixedField): Removed redundant volatile check. + +2007-10-15 Marek Safar + + * class.cs, decl.cs: Fixed overload members verification to do only one + check per possible collision. + +2007-10-13 Marek Safar + + A fix for bug #325478 + * anonymous.cs (AnonymousContainer.Compatible): Merge are flags together + and create only one disposable flags container. + +2007-10-12 Marek Safar + + A fix for bug #332442 by Alexandre Gomes + * statement.cs (Fixed): Fixed variables cloning. + +2007-10-12 Marek Safar + + A fix for bug #333342 + * class.cs (EventField): Don't mark value type event as synchronized. + +2007-10-12 Marek Safar + + * ecore.cs, anonymous.cs (MethodGroupExpr): Use score from type + inference to identify best candidate method correctly. + (ProperyExpr): A range variable is read only and cannot be modified. + +2007-10-11 Marek Safar + + * ecore.cs, delegate.cs (MethodGroupExpr): Refactored best candidate + logic to identify best candidate method correctly. + +2007-10-11 Marek Safar + + * location.cs (Equals, GetHashCode): Removed. + +2007-10-11 Marek Safar + + * report.cs: Implemented message recorder. It is used mainly for lambda + expressions to capture otherwise swallowed error messages. + + * anonymous.cs, lambda.cs.cs: Do full parameters check. + + * ecore.cs (ExtensionMethodGroup): Report binding failure at the botton + and not at the top. + (MethodGroupExpr.DoResolve): Use message recorder for error handling. + + * expression.cs (MemberAccess): Always report lookup failure. + + * location.cs: Implemented Equals, GetHashCode. + + * statement.cs (Return.DoResolve): Fixed hardcoded error argument. + +2007-10-10 Jb Evain + + * codegen.cs: re-enable assembly version check. + +2007-10-09 Marek Safar + + * report.cs, anonymous.cs, driver.cs, expression.cs: Added few ISO-2 + checks. + + * namespace.cs (UsingAlias): Do correct version check. + +2007-10-08 Marek Safar + + * expresison.cs, ecore.cs: Issue extension method error message when + appropriate. + + * rootcontext.cs: Added ISO_2 compiler mode option. + +2007-10-08 Marek Safar + + * expresison.cs (UnaryMutator.ResolveOperator): Print more useful error + message. + +2007-10-08 Marek Safar + + * attribute.cs (GetString, GetBoolean): Work with both literal and + constant. + + * ecore.cs, expresison.cs, delegate.cs (Invocation, MethodGroupExpr): + Moved method overload specific methods to MethodGroupExpr. + + (IndexerAccess): Re-wrote resolving mechanism, fixed many issues and + it should be less memory consuming. + +Mon Oct 8 09:29:15 CEST 2007 Paolo Molaro + + * codegen.cs: remove the assembly version check until the buildbot is + fixed. + +2007-10-07 Jb Evain + + * attribute.cs (Attribute.GetString): if the value + expression is a StringConstant, return its string value. + +2007-10-07 Jb Evain + + * typemanager.cs: add `assembly_version_attribute_type`. + * codegen.cs: on attribute emission, check that the + AssemblyVersionAttribute doesn't overflow. + +2007-10-05 Marek Safar + + A fix for bug #324677 + * anonymous.cs, decl.cs: Yes another anonymous container hack. Overwrite + parent container of a scope container with currently resolved one. + +2007-10-05 Marek Safar + + A fix for bug #325534 + * class.cs (Invocation.DoResolve): Check invocation of object finalizer + only. + +2007-10-05 Marek Safar + + A fix for bug #327504 + * class.cs (Operator.Define): Refactored implicit and explicit user + operator conversion rules. + +2007-10-05 Marek Safar + + A fix for bug #327520 + * ecore.cs (ExtensionMethodGroupExpr): Emit resolved extension argument. + +2007-10-04 Marek Safar + + A fix for bug #328022 + * class.cs (MethodData.Define): Use correct method to check whether + a method implementents an accessor. + +2007-10-04 Marek Safar + + A fix for bug #330069 + * statement.cs (Fixed.Resolve): Read the first array element only when + an array is instantiated. + +2007-10-04 Marek Safar + + * expression.cs, assign.cs, generics.cs: Print correct operator when + compound assignment is used. + +2007-10-04 Marek Safar + + A fix for bug #325841 + * expression.cs (ArrayAccess): Use full argument cloning only for + string compound concatenation. + +2007-10-03 Marek Safar + + A fix for bug #328774 + * ecore.cs (FieldExpr.EmitAssign): Fixed string concatenation compound + assignment. + (PropertyExpr.EmitAssign): Fixed string concatenation compound + assignment. + +2007-10-03 Raja R Harinath + + Fix #328490 + * ecore.cs (SimpleName.DoSimpleNameResolve): Handle Property and + Event accessibility checks here. Remove some bogus code that + accidently made GenericMethods work. + (PropertyExpr.IsAccessibleFrom, EventExpr.IsAccessibleFrom): New. + +2007-09-25 Marek Safar + + * expression.cs (ArrayCreation): Fixed cloning of an implicit types. + + * statement.cs (Block): Refactored AddVariable to allow error handling + customization. + + * generic.cs: New stub. + +2007-09-23 Marek Safar + + * anonymous.cs, codegen.cs: Changed InferReturnType to be EmitContext + flag. + +2007-09-17 Marek Safar + + * class.cs: Use partial container to record whether any partial part + contains static field initializer and therefore default contructor has + to be defined. + +2007-09-14 Marek Safar + + * class.cs (TypeContainer.AddPartial): Fixed an issue reported on + mono-list when only one of two partial parts has defined accessibility + modifier. + +2007-09-14 Marek Safar + + A fix for bug #82845 + + * class.cs (TypeContainer): Set correct resolve context for all field + initializers. + +2007-09-13 Marek Safar + + * assign.cs: Fixed a crash when field is resolved twice with an error. + + * codegen.cs: Changed InFieldInitializer to be flag. + + * anonymous.cs, ecore.cs, expression.cs: Update after + IsInFieldInitializer rename. + + * const.cs: Removed unused parameter. + + * class.cs: Changed the way how we resolve and emit field initializers. + The field initilizers have to have access to contructor block to emit + compiler generated code. + +2007-09-13 Marek Safar + + * expression.cs (MemberAccess.DoResolve): DeclSpace is broken by + generics use TypeContainer instead. + +2007-09-12 Marek Safar + + * generic.cs (TypeInferenceContext.InflateGenericArgument): Stub. + + * lambda.cs (ResolveParameters): Use more powerful + InflateGenericArgument. + + * parameters.cs: Better exception message. + +2007-09-10 Marek Safar + + * anonymous.cs (AnonymousMethodExpression.CompatibleChecks): Report + correct expression block type. + + * ecore.cs (Expression.Error_MemberLookupFailed): Made virtual. + + * expression.cs (Invocation): Extracted method group resolve to + DoResolveOverload. + +2007-09-07 Marek Safar + + * ecore.cs (Expression.MemberLookupFinal): Removed unused loc parameter. + (MethodGroupExpr.ResolveGeneric): Use existing method group instance. + + * expression.cs (MemberAccess.DoResolve): Uses generic resolver for + generic extension methods. + +2007-09-06 Marek Safar + + A fix for bug #82676 (Do I get it right now?) + * convert.cs (Binary.ResolveOperator): An interface is converted to the + object before a standard conversion is applied. + +2007-09-06 Marek Safar + + * convert.cs (ImplicitReferenceConversionCore): Reverted wrong fix of + #82676. + +2007-09-05 Marek Safar + + A fix for bug #82676 + * convert.cs (ImplicitReferenceConversionCore): Check both sides for + non-generic interface types. + +2007-09-05 Marek Safar + + A fix for bug #82690 + * ecore.cs (PropertyExpr.EmitAssign): Leave a copy does just that. + +2007-09-05 Marek Safar + + A fix for bug #82571 + * anonymous.cs (AnonymousMethod.DoCreateMethodHost): Use internal + modifier for container based methods. + +2007-09-05 Marek Safar + + A fix for bug #82676 + * convert.cs (ImplicitReferenceConversionCore): From any class-type S to + any interface-type T means to any of interface type T. + +2007-09-04 Marek Safar + + * namespace.cs: We have 2 versions of System.Core assembly. + +2007-09-04 Marek Safar + + A fix for bug #82652 + * class.cs (Class.GetClassBases): Compare types and not expressions. + +2007-09-04 Marek Safar + + A fix for bug #82620 + * expression.cs (Invocation.EmitArguments): Duplicate params arguments + actually never worked before. + (IndexerAccess): Emit prepared arguments before they are modified. + +2007-09-04 Marek Safar + + A fix for bug #82563 + * assign.cs: Revert wrong fix. + + * expression.cs (VariableReference.EmitAssign): Handle ref reference + correctly. + (ArrayAccess): Changed the way we emit compound (prepared) assignments. + Instead of ldelema/stdind we have to use temporary variables to handle + cases like String.Concat (params string[]). + +2007-08-31 Marek Safar + + * class.cs: EmitAttributes to Emit rename. + + * decl.cs (MemberCore.GetClsCompliantAttributeValue): Parent can be + null. + (MemberCore.HasClsCompliantAttribute): Don't depend on + GetClsCompliantAttributeValue execution. + +2007-08-31 Marek Safar + + * anonymous.cs: Use shorter type prefix. + + * ecore.cs (SimpleName.DoSimpleNameResolve): Use transparent identifiers + when exist. + + * expression.cs (LocalVariableReference.DoResolveBase): Don't capture + variables when probing is on. + + * statement.cs (LocaLInfo.Clone): Clone correctly resolved and + unresolved variables. + (TopLevelBlock.GetTransparentIdentifier): Default implementation doesn't + handle transparent identifiers. + +2007-08-26 Marek Safar + + * attribute.cs (IsClsCompliant): Add nullable types test. + +2007-08-24 Atsushi Enomoto + + * doc.cs : catch other types of exception than XmlException to + report CS1570. Fixed bug #82565. + +2007-08-23 Marek Safar + + * anonymous.cs (AnonymousMethodExpressin.ExplicitTypeInference): + The number of delegate parameters has to match. + (AnonymousMethodExpressin.VerifyParameterCompatibility): Handles generic + arrays. + +2007-08-21 Marek Safar + + * anonymous.cs (AnonymousMethod): Generate private anonymous method + to fix problem with private arguments. + +2007-08-20 Marek Safar + + * anonymous.cs (AnonymousTypeClass): An anonymous type can be empty. + + * decl.cs (MemberName): Ignore generic type with no generic arguments. + + * expression.cs (AnonymousTypeDeclaration): An anonymous type can be + empty. Add cloning suport. + + * roottypes.cs (GetAnonymousType): Fixed argument comparison logic. + +2007-08-20 Marek Safar + + * convert.cs, ecore.cs, expression.cs, literal.cs: Use factory method + to create EmptyCast. It handles EmptyConstantCast specialization for + constants. + +2007-08-18 Marek Safar + + * expression.cs (Binary.is_unsigned): Handle unsafe types too. + (EmitArrayArgument): One routine for array arguments. + (ArrayCreation.MakeByteBlob): Fixed an array alignment. + +2007-08-17 Marek Safar + + * cs-tokenizer.cs (GetKeyword): Handle from keyword in a different way. + +2007-08-17 Marek Safar + + * anonymous.cs: MemberLookupFinal update. + + * class.cs (ConstructorInitializer): Is expression based. + + * delegate.cs: MethodGroupExpr update. + + * ecore.cs (Error_MemberLookupFailed): Improved to report better error + messages. + (Error_MemberLookupFailed): Customizable error override. + (MethodGroupExpr): Keep queried type for later usage. + (MethodGroupExpr.OverloadResolve): Catch errors related to overload + resolve. + + * expression.cs: Error_MemberLookupFailed refactoring. + (New.DoResolve): Resolve as much as possible. + (ElementInitializer.Error_MemberLookupFailed): Object initializer + customization for invalid member types. + + * statement.cs: MethodGroupExpr update. + +2007-08-16 Marek Safar + + * modifier.cs (Check): Check all modifiers and not only accessibility + ones. + +2007-08-16 Marek Safar + + * ecore.cs (Expression.Error_ValueCannotBeConverted): Report always a + type and not an expression. + +2007-08-16 Marek Safar + + * statement.cs (Catch.Clone): Type and variable can be null. + +2007-08-16 Marek Safar + + A fix for bug #81979 + * assign.cs (Assign.Emit): Prepare arguments for string concatenation. + I am really not sure whether this is the best fix. + + * expression.cs (VariableReference.EmitAssign): Do prepare_load test + only once. + +2007-08-14 Marek Safar + + ** C# 3.0 Object and collection initializers (major re-write) + + * assign.cs (DoResolve): Initializers are not assign related. + + * codegen.cs (EmitContext.CurrentInitializerVariable): Holds a varible + used during collection or object initialization. + + * expression.cs (Error_InvalidArguments): Add initializers specific + messages. More will come later because it requires some general + refactoring. + (New.DoResolve): Better error handling for unsafe types. + (EmptyExpressionStatement): New class. + (ElementInitializer): An object initializer expression. + (CollectionElementInitializer): A collection initializer expression. + (CollectionOrObjectInitializers): A block of object or collection + initializers. + (NewInitialize): New expression with element/object initializers. + + * statement.cs: Reverted object/collection initializer hacks. + + * typemanager.cs (CSharpName): Filter __arglist type. + +2007-08-09 Marek Safar + + ** C# 3.0 Anonymous Types (update to the latest standard) + + * expression.cs (Binary.ResolveOperator): Threat all null based types + same. + (AnonymousTypeDeclaration): Renamed from AnonymousType and simplified. + (AnonymousTypeParameter): Updated. + + * anonymous.cs (CompilerGeneratedClass): Add custom name overload. + (AnonymousTypeClass): New anonymous type container. + + * class.cs (AddField): Return operation result. + + * generic.cs: Another empty TypeArguments overload. + + * roottypes.cs (AddAnonymousType, GetAnonymousType): Anonymous types + are stored at top of normal hierarchy. + + * typemanager.cs (CSharpName): Filter anonymous types. + +2007-08-09 Marek Safar + + * expression.cs (StringConcat.Append): Handle 3 and more concatenation + as single Concat call. How could we miss that :-( + +2007-08-08 Marek Safar + + * expression.cs (ArrayCreation.CloneTo): Allocate exact size. + +2007-08-07 Miguel de Icaza + + * expression.cs: Fix the previous commit, the creation of the + arguments array list needs also to be conditional on the arguments + not being null. + + * class.cs: Add a little bit of help to help narrow down problems. + + * expression.cs (ArrayCreation.CloneTo): Argument can be null, do + not try to copy in that case. + + * driver.cs: When building SMCS, include a new different set of + default assemblies here. Do this here so we can control whether + to include the default assemblies with /noconfig. + +2007-08-03 Marek Safar + + A fix for bug #81979 + * expression.cs (TypeOf.GetAttributableValue): Check for type arguments + only. + +2007-08-03 Marek Safar + + A fix for bug #82300 + + * anonymous.cs (AnonymousContainer.Define): Don't define anything when + we are in probing scope. + +2007-08-03 Marek Safar + + A fix for bug #82301 + + * statement.cs (Catch.CloneTo): Clone blocks in the right order. + (Statement.CloneTo): Clone and not map children blocks. + +2007-08-03 Marek Safar + + A fix for bug #82299 + + * expression.cs (LocalVariableReference.CloneTo): Remap local info + variable too. + + * statement.cs (Statement.CloneTo): Clone variables before statements + to allow remaping of local variables. + +2007-08-03 Marek Safar + + A fix for bug #82296 + + * anonymous.cs, + * report.cs: Log crash details for future clone problems. + + * statement.cs (Return.Clone): Don't clone non-existent expression. + +2007-08-03 Raja R Harinath + + * class.cs (TypeContainer.AddBasesForPart): Make virtual. + (Class.AddBasesForPart): Move CS0537 check here from ... + * cs-parser.jay (class_declaration): ... here. Move calling of + 'AddBasesForPart' to ... + (class_bases): ... here. + (struct_declaration, interface_declaration): Update to changes. + +2007-08-02 Marek Safar + + A fix for bug #81923 + + * statement.cs (Using.ResolveLocalVariableDecls): Only non-user implicit + conversion is allowed. + +2007-08-02 Marek Safar + + A fix for bug #81564 + + * ecore.cs (EventExpr): Add IsBase handling. + + * expression.cs (BaseAccess.CommonResolve): Events can use base accessor + too. + +2007-08-02 Raja R Harinath + + Reduce some differences between cs-parser.jay in mcs/ and gmcs/. + * cs-parser.jay: Some whitespace cleanups. + (current_delegate): New. + (type_name): New. + (struct_declaration): Make similar to gmcs/cs-parser.jay -- add + a dummy code block, and use 'type_name' instead of 'member_name'. + (interface_declaration, class_declaration): Likewise. + (delegate_declaration): Likewise. Rearrange slightly and use + 'current_delegate'. + * cs-tokenizer.cs (handle_where): Rename from handle_constraints. + (GetKeyword): Update to change. Use '!foo' instead of 'foo == false'. + +2007-08-02 Marek Safar + + A fix for bug #82039 + + * ecore.cs (TypeLookup.GetSignatureForError): Use name when type is not + available. + + * typemanager.cs (CSharpName): Split to string overload. + +2007-08-02 Marek Safar + + * expression.cs, + * report.cs: Updated warning CS0472. + +2007-08-01 Marek Safar + + A fix for bug #82181 + * cs-parser.jay, + * cs-tokenizer.cs: Ignore partial keyword inside block expression. + +2007-08-01 Marek Safar + + A fix for bug #82277 + * statememnt.cs (Block.Clone): Don't clone explicit blocks twice. + +2007-08-01 Marek Safar + + ** C# 3.0 Type Inference (major bits are working) + + * anonymous.cs (AnonymousMethodExpression): Removed refactored fields. + (.ImplicitStandardConversionExists): Uses compatible. + (.ExplicitTypeInference): Infers type arguments based on explicit arguments + (.InferReturnType): New method. + (.Compatible): Refactored. + (.ResolveParameters): Uses factory to create resolved parameters. + (.CompatibleMethod): Add probing mode support. + (AnonymousContainer): Removed unused fields. Split Define and Resolve to + clearly distinguish between 2 different operations. + (LambdaMethod): Moved to lambda.cs. + (AnonymousMethod): Removed unused fields and methods. + (AnonymousDelegate): Simplified. + + * codegen.cs (ResolveTopBlock): Updated renamed Resolve to Define. + + * convert. cs (ImplicitConversionStandard): Compatible works differently. + + * delegate.cs (Delegate): New mehods to reduce code duplication. + (.GetConstructor): New method. + (.GetInvokeMethod): New method. + (DelegateCreation): Updated. + + * ecore.cs (ResolveOverloadExtensions): Don't crash when extension method + does not exist. + (OverloadResolve): Made probing little bit faster. + + * expression.cs (ParameterReference.DoResolveLValue): Reference can be null + when probing is on. + + * generic.cs (TypeInferenceContext): Dummy implementation. + + * iterators.cs: Updated after Resolve/Define rename. + + * lambda.cs (LambdaExpression) + (.ResolveParameters): Handles both type of arguments and type inference too. + + * parameter.cs (ImplicitLambdaParameter.Resolve): Sanity check. + (InflateTypes): Updated. + + * support.cs (InflateTypes): Changed signature and updated. + + * typemanager.cs (LookupMemberCache): Better dynamic type check. + (MemberLookup_FindMembers): More MS tricks. + (GetParameterData): Ditto. + (GetDelegateParameters): Uses quick path for dynamic types. + +2007-08-01 Marek Safar + + * class.cs (MethodData.Define): EmitContext is required for generic stuff + only. + +2007-07-31 Marek Safar + + * statement.cs (ProcessParameters): Don't crash when parameters have wrong + syntax. + +2007-07-26 Jb Evain + + * typemanager.cs (TypeManager.GetConstructor): Add a method overload + which takes a boolean 'report_errors', similar to the GetMethod. + (InitCodeHelpers): StructLayoutAttribute.ctor(int16) is not visible + in .net 2.1, do not report errors here. + + * typemanager.cs (TypeManager.InitCoreTypes): System.ArgIterator, + System.Runtime.CompilerServices.RequiredAttributeAttribute and + System.Runtime.CompilerServices.TypeForwardedToAttribute are internal + in .net 2.1. + + * typemanager.cs (TypeManager.InitCoreTypes): Move the resolution + of the type InternalsVisibleToAttribute before the first call + to CoreLookupType which is allowed to fail (third boolean parameter + to true). Because, during the resolution for a type that is not + immediately found, we try to check if the type is not defined in + a friend assembly, and to do so, we need the + InternalVisibleToAttribute. + +2007-07-23 Miguel de Icaza + + * expression.cs (Binary): Add support for the brain-dead CSC 2.x + feature that allows structs to be compared against null and inline + the result as true or false. + + Notice that the same code is not permitted inside a generic block + of code that would do: + + class Foo where T : struct { + bool Eval (T x) + { + return x == null; + } + } + + It is only allowed if the type of T is not bound (no where + clause). In my opinion, this CSC 2 behavior is broken but people + seem to be using it (IronRuby does, a few bug reports on bugzilla + have it and some people have complained about it). + + All of the users that depend on this behavior have code that is + very likely broken. + + * report.cs (Warning, Error): make these take object arguments, + not strings, as that allows us to take advantage of Format. + +2007-07-20 William Holmes + + * decl.cs: Changed MemberName.CountTypeArguments to also check the + Left member variable for the Count. + * doc.cs: Changed DocUtil.GetMethodDocCommentName to call + MemberName.CountTypeArguments to avoid a NRE. + + This code is contributed under the MIT X11 license + +2007-07-18 Marek Safar + + * cs-tokenizer.cs: Improved lambda parsing and removed old code. + +2007-07-18 Atsushi Enomoto + + * doc.cs : generic method arguments are written as ``x while generic + type arguments are `x. Combined with the previous change, fixed bug + #79706. + +2007-07-18 Raja R Harinath + + Fix #82120 + * expression.cs (Binary.ResolveOperator): When converting + 'a + (- b)' to 'a - b', ensure that the unary '-' is discarded. + +2007-07-18 Atsushi Enomoto + + * doc.cs : when T: or whatever x: is specified, it does not really + check the doc comment's syntax correctness. Fixed bug #82006. + +2007-07-18 Marek Safar + + * anonymous.cs (AnonymouseMethodExpression): Refactored to work with + LambdaExpression better. + + * cs-tokenizer.cs: Changed a way how we detect lambda parameters. + + * driver.cs (LambdaTypeParseTest): Removed, tested method is gone. + + * ecore.cs (Expression.MemberLookupFailed): Don't show currect context + as it can be generated. + + * expression.cs (Invocation.Error_InvalidArguments): Show correct + modifiers. + + * lambda.cs (LambdaExpression): Refactored to share same code with + AnonymousMethodExpression. + +2007-07-17 Marek Safar + + * anonymous.cs (MakeName): Include host name for easier debugging. + (LambdaMethod): New class for lambda spcecific stuff. + + * attribute.cs: Set EmitContext return type. + + * class.cs: Set EmitContext return type. + + * codegen.cs (EmitContext): Return type cannot be null to stop messing + with null/void meaning. + + * iterators.cs (ContainerType): Implemented. + + * rootcontext.cs: Set value of TypeManager.bool_type at early stage. + + * statement.cs (Return): Updated to lambda expressions. + (Block.CloneTo): Parent can be null. + +2007-07-13 Marek Safar + + A fix for bug #81917 + * attribute.cs (AttributeTester.GetFixedBuffer): More robust testing. + + * class.cs (FixedField): Check whether field is in unsafe scope. + + * ecore.cs (FieldExpr.DoResolve): Create fixed buffer expression here. + (FieldExpr.Emit): Fixed buffers cannot be volatile. + + * expression.cs (ElementAccess.Resolve): Move fixed buffers resolve to + FieldExpr. + + * statement.cs (Fixed.Resolve): Simplified fixed buffers. + +2007-07-13 Marek Safar + + * cs-tokenizer.cs, class.cs, decl.cs, driver.cs, namespace.cs, + rootcontext.cs, expression.cs, statement.cs: Updated to use WarningLevel + from Report class. + +2007-07-13 Marek Safar + + * ecore.cs (FieldExpr.AddressOf): Less confusing warning message. + +2007-07-13 Marek Safar + + * anonymous.cs (AnonymousMethodExpression): Parameters are r/o. + (AnonymousContainer.ResolveNoDefine): Another ec to aec flag conversion. + + * codegen.cs(EmitContext): Add ProbingMode flag. + + * delegate.cs (DelegateInvocation): Set few instance variables as r/o. + + * driver.cs: For now set both warning values. + + * ecore.cs (SimpleName): Name is readonly. + (MethodGroup.OverloadResolve): One quick path for probing. + + * expression.cs (Unary): Set Oper r/o. + (Binary): Set Oper r/o. + (ParameterReference): Set few instance variables as r/o. + (ParameterReference.DoResolveBase): Don't capture aruments when + the probing is on. + (Invocation.CloneTo): Fixed typo, looks easy, yeah. + (Arglist): arguments are private. + (SizeOf): type is private and r/o. + (MemberAccess): arguments are private. + + * report.cs: Enhanced reporting on/off capabilities. + + * lambda.cs: Uses ec.IsInProbingMode. + (ContextualReturn): Derives from return. + + * rootcontext.cs: For now set both warning values. + + * statement.cs (CloneContext.RemapBlockCopy): Remaps block to cloned + copy if one exists. + (Return.Resolve): Don't die immediately. + (Block.Resolve): Speed-up probing. + (Block.CloneTo): Clone only child blocks. + +Fri Jul 13 11:19:28 CEST 2007 Paolo Molaro + + * iterators.cs: reverted Miguel's latest change (r81925) as it + breaks the build in System. + +2007-07-13 Miguel de Icaza + + * iterators.cs (Yield.CheckContext): Check for the iterator type + also here as we can call into Yield even in codepaths that are not + directly checked by + (MethodOrOperator is the only path that was checked). + + In addition to the standard check, use a more specific check for + constructors to report a more verbose error. + +2007-07-12 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): Do not stop processing here, + report the warning and continue + + * statement.cs (Using.EmitLocalVariableDecls): We were leaving + values on the stack on the call to Emit. Use EmitStatement if + possible, or using Emit + Pop if not possible. Fixes #82064 + +2007-07-12 Raja R Harinath + + * expression.cs (Invocation.IsApplicable): Reorganize slightly to + avoid try...finally in some cases. + +2007-07-10 Marek Safar + + * attribute.cs (Attribute.ResolveConstructor): Uses method group. + + * class.cs (ConstructorInitializer.Resolve): Use and keep method group + instead of method. Re-use standard error handling. + (ConstructorInitializer.Emit): Simplified. + + * delegate.cs: Updated after Invocation.EmitCall change. + + * ecore.cs (GetOperatorTrueOrFalse): Uses MethodGroupExpr only. + (SimpleName.SimpleNameResolve): Set and reset in_transit flag correctly. + (ExtensionMethodGroupExpr): Refactored to use same OverloadResolve + method and don't permanently changing input arguments. + (MethodGroupExpr): Introduced resolved best_candidate, when method group + is resolved it has one of the candidates is the best one which is later + used to emit. Removed a few unused method. + (MethodGroupExpr.MakeUnionSet): Moved from Invocation, it belongs here. + + * expression.cs (StaticCallExpr.MakeSimpleCall): Uses method group. + (Binary.ResolveOperator): Ditto. + (ConditionalLogicalOperator.DoResolve): Ditto. + (Invocation): Uses method group. + (Invocation.DoResolve): Simplified. + (Invocation.EmitCall): Removed useless is_static. + (Invocation.Emit): Delegate to method group. + (Invocation.EmitStatement): Simplified. + (New): Uses method group. + (MemberAccess.DoResolve): Don't destroy original expression. + + * statement.cs (ForEach.Resolve): Use null for no method arguments. + +2007-07-04 Marek Safar + + * ecore.cs (VarExpr.DoResolveLValue): More restriction checks. + + * anonymous.cs, + * lambda.cs: Add custom error message type. + +2007-07-03 Marek Safar + + * lambda.cs: Simplified little bit. + + * parameter.cs: Introduced ImplicitLambdaParameter. + (Parameters.CreateFullyResolved): New factory instead of ctor. + + * anonymous.cs, + * class.cs, + * delegate.cs: Updated parameter creation. + +2007-07-03 Marek Safar + + * ecore.cs (SimpleName.GetSignatureForError): Display correctly generic + arguments. + + * generic.cs: Synchronized with gmcs. + +2007-07-03 Marek Safar + + * class.cs (Indexer): Check return type as soon as possible. + + * cs-parser.jay: Initialize implicit_value_parameter_type for interface + members too. + + * ecore.cs (VarExpr.DoResolveLValue): Set eclass value. + + * expression.cs (Invocation.Error_InvalidArguments): Show type only. + + * parameter.cs (Parameter): Use expression type when it is available. + + * support.cs (ReflectionParameters.ParameterDesc): Show an extension + method modifier for the first parameter only. + +2007-06-24 Marek Safar + + A fix for bug #81938 + * typemanager.cs (ChangeType): Fixed couple of char conversions. + + * constant.cs: Tide up an exception message. + +2007-06-22 Marek Safar + + * ecore.cs (SimpleName.DoSimpleNameResolve): Better error reporting when + an uninitialized variable is used. + + * expression.cs (LocalVariableReference.DoResolve): Ditto. + +2007-06-22 Marek Safar + + * ecore.cs (SimpleName.TypeOrNamespaceNotFound): Allow to override type + not found error handling. + + * expression.cs (ArrayCreation): Removed redundant fields and little bit + simplified. + (ArrayCreation.ResolveArrayElement): To be ready to customization. + (ArrayCreation.DoResolve): Simplified. + (ImplicitlyTypedArrayCreation.DoResolve): Implicitly typed arrays have + its own resolve process. + (ImplicitlyTypedArrayCreation.ResolveArrayElement): Conversion magic. + +2007-06-20 Marek Safar + + * namespace.cs (NamespaceEntry.Error_AmbiguousTypeReference): Print + more error details. + +2007-06-20 Marek Safar + + * cs-tokenizer.cs: Removed var related stuff. + + * ecore.cs (Expression.ResolveAsContextualType): Introduced new method. + (VarExpr): Changed to derive from SimpleName. VarExpr now behaves as + a type and a keyword at same time. + + * decl.cs (MembeName.GetTypeExpression): Create VarExpr when type name + matches to "var". + + * expression.cs (ImplicitlyTypedArrayCreation): New empty class for + implicitly typed arrays, more changes will follow. + + * statement.cs (LocalInfo.Resolve): Resolve type as contextual type. + +2007-06-19 Marek Safar + + * ecore.cs (VarExpr): Removed Handled field. + + * statement.cs (Using.ResolveLocalVariableDecls): Refactored to use + build-in assign functionality. + (ForEach.Resolve): Removed all implicitly typed local variable code and + simplified. + (ArrayForeach.Resolve): Infer implicitly typed local variable here. + (CollectionForeach.Resolve): Infer implicitly typed local variable here. + +2007-06-18 Marek Safar + + * assign.cs: Removed implicitly typed local variable check. + + * expression.cs (LocalVariableReference.DoResolve): Add check for self + referencing implicitly typed local variable. + (LocalVariableReference.DoResolveLValue): Infer implicitly typed local + variable here. + + * statement.cs (Fixed): Removed unsupported implicitly typed local + variable code. + +2007-06-15 Marek Safar + + * decl.cs (MemberName): Moved all Unbound stuff to parser. + +2007-06-14 Marek Safar + + A fix for bugs #81855 and #76274 + * attribute.cs (AttachTo): Always set owner for global attributes to + prefined owner. + + * ecore.cs (Error_TypeDoesNotContainDefinition): A type location can be + usefull too. + + * cs-parser.jay: Assembly and module attributes must precede all other + elements except using clauses and extern alias declarations. + +2007-06-13 Marek Safar + + A fix for bug #81748 + * cs-tokenizer.cs, + * expression.cs: More checks for non ISO-1 features. + +2007-06-12 Marek Safar + + A fix for bug #81807 + * statement.cs(Switch.TableSwitchEmit): Define null label when it's not + present inside switch statement and it is required by nullable check. + +2007-06-12 Marek Safar + + A fix for bug #81840 + * ecore.cs (SimpleName.ResolveAsTypeStep): Look for non-generic type + when type matching fails. + + * namespace.cs: Tiny error message change. + +2007-06-12 Marek Safar + + * decl.cs (CheckAbstractAndExtern): Moved to MemberCore for easier error + reporting. Added automatic property check. + + * class.cs: Updated after CheckAbstractAndExtern relocation. + (AEventPropertyAccessor.GetSignatureForError): Customized. + +2007-06-11 Marek Safar + + * class.cs (DefineBaseTypes): Base type can be undefined. + + * ecore.cs (TypeLookup): Minor refactoring. + (DoResolveAsTypeStep): Removed redundant check. + + * namespace.cs (Lookup): Removed redundant check. + + * rootcontext.cs (BootstrapCorlib_ResolveType): Uses normal + ResolveAsTypeTerminal step. + (BootstrapCorlib_*): Simplified. + (PopulateCoreType): Core types can be now external. + +2007-06-07 Marek Safar + + * anonymous.cs (VerifyExplicitParameterCompatibility): Add flag to do + verification only. + (InferTypeArguments): Infers anonymous expression type arguments. + (Compatible): Split to Compatible and InferTypeArguments. + + * lambda.cs: Updated. + +2007-06-08 Marek Safar + + * anonymous.cs (AnonymousContainer): Marked as compiler generated. + +2007-06-07 Raja R Harinath + + Fix #80477, cs0135-2.cs, cs0135-3.cs + * statement.cs (ToplevelBlock.ProcessParameters): Add parameter + names to the "known" variables list. + (Block.CheckInvariantMeaningInBlock): Handle the fact the + parameter names are also "known". + (Block.CheckError136): Remove. + (ExplicitBlock.CloneTo): New. Set 'known_variables' in target to + null. + +2007-06-07 Marek Safar + + * ecore.cs (MethodGroupExpr.OverloadResolve): Print full method definition. + +2007-06-06 Marek Safar + + * ecore.cs (SimpleName.Emit): Emitting unresolved simple name is + internal error not an user error. + + * expression.cs (IsApplicable): Refactored to make debugging easier. + + * support.cs: More tricks for non-mono runtimes. + + * typemanager.cs (CoreLookupType): Made public. + (InitSystemCore): All linq specific stuff moved to linq.cs + +2007-06-05 Marek Safar + + * typemanager.cs (CSharpSignature): One more missing build-in types + replacement. + More tricks for non-mono runtime. + +2007-06-05 Raja R Harinath + + * statement.cs (Block.CheckError136_InParents): Remove. + (Block.AddVariable): Use GetParameterInfo instead. + (ToplevelBlock.ProcessArguments): Likewise. + +2007-06-04 Raja R Harinath + + * statement.cs (ToplevelBlock.CloneTo): New. Copy over parameter + information too. + (ToplevelBlock.GetParameterInfo): Split out of ... + (ToplevelBlock.GetParameterRefernce): ... this. + (ToplevelBlock.ParameterMap): Remove. + * expression.cs (ParameterReference): Update to use + ToplevelParameterInfo. + + * statement.cs (ToplevelBlock.ProcessParameters): Workaround some + regression. + + * flowanalysis.cs (FlowBranching.CheckOutParameters): Move ... + * statement.cs (ToplevelBlock.CheckOutParameters): ... here. + + * statement.cs (ToplevelBlock.ResolveMeta): Move CS0136 checks ... + (ToplevelBlock.ProcessParameters) ... here. + (ToplevelBlock..ctor): Invoke it. + + * statement.cs (ToplevelBlock.ResolveMeta): Add sanity checks for + new parameters. + + * statement.cs (IKnownVariable): New interface. + (LocalInfo): Implement it. + (ToplevelParameterInfo): New class. + (ExplicitBlock.AddKnownVariable): Use IKnownVariable. + (ExplicitBlock.GetKnownVariable): Likewise. Rename from + GetKnownVariableInfo. + +2007-06-03 Raja R Harinath + + Partly speed up CS0136 error checks. + * statement.cs (ExplicitBlock.GetKnownVariableInfo): Remove + 'recurse' parameter. + (Block.DoCheckError136): Only check errors in parameters. Move + local variable checks ... + (Block.AddVariable): ... here, and ... + (ToplevelBlock.ResolveMeta): ... here. + +2007-06-02 Raja R Harinath + + * statement.cs (Block.IsChildOf): Remove. + + * statement.cs (Statement.Clone): Move special case code ... + (Block.CloneTo): ... here. + +2007-05-29 Raja R Harinath + + * statement.cs (ToplevelBlock.container): Remove field. It's + redundant with 'Parent'. + (ToplevelBlock.ContainerBlock): Remove accessor. + (ToplevelBlock..ctor): Update to changes. Register anonymous + child with parent here, ... + * cs-parser.jay (end_anonymous): ... not here. Don't modify + current_block. + (start_anonymous): Don't save current_block. + (top_current_block): Remove. + + * statement.cs (Block.Flags): Remove IsExplicit and IsToplevel flags. + (Block.Resolve): Update to changes. + (Block..ctor): Move setting of "correct" 'Toplevel' + and 'Explicit' fields to ... + (ExplicitBlock..ctor, ToplevelBlock..ctor): ... here. + +2007-05-27 Raja R Harinath + + Kill Block.Implicit + * statement.cs (Block.Implicit): Remove. + (Block): Update to changes. + * flowanalysis.cs: Likewise. + + Mildly speed up CheckInvariantMeaningInBlock + * statement.cs (ExplicitBlock.AddKnownVariable): Move here from Block. + Recursively call AddKnownVariable to all enclosing blocks. + (ExplicitBlock.GetKnownVariableInfo): Move here from Block. + Remove recursive calls. + (Block): Update to changes. + + New ExplicitBlock invariants + * statement.cs (Block.Explicit): New field. It points to the + immediately enclosing non-implicit block. + (Block..ctor): Maintain the invariant. + * cs-parser.jay: Take advantage of invariant. + + Introduce ExplicitBlock + * statement.cs (ExplicitBlock): New. + (ToplevelBlock): Derive from it. + (Block.Flags.IsExplicit): Rename from '...Implicit' and invert + sense of flag. + (Block.Implicit): Update to changes. + * cs-parser.jay: Update to changes. + + Remove unused field + * codegen.cs (EmitContext.IsLastStatement): Remove. + * statement.cs (Block.DoEmit): Update to changes. + +2007-05-25 Raja R Harinath + + * cs-parser.jay: Use 'start_block' and 'end_block' rather than + modifying current_block directly. + +2007-05-23 Scott Peterson + + * class.cs: Implemented automatic properties (C# 3.0) + Thanks to Marek for the help. + +2007-05-23 Raja R Harinath + + * flowanalysis.cs (VariableInfo.SetAssigned): When noting a + variable as assigned, note also that all its components are + assigned too. + (MyBitVector.SetRange): New. Function to set multiple bits to true. + +2007-05-19 Marek Safar + + * anonymous.cs, class.cs: Emit Compiler generated attribute when + member is marked as compiler generated. + + * decl.cs (MemberCore): Refactored ModFlags into property. + + * modifiers.cs: Add new modifier (COMPILER_GENERATED). + (Check): Check only accessibility modifiers. + +2007-05-18 Raja R Harinath + + Track all assignable slots in one bit array + * statement.cs (ToplevelBlock.ParameterMap): Convert into array. + (ToplevelBlock.ResolveMeta): Don't create a VariableMap. Move + logic from VariableMap constructor here. Use the same 'offset' + variable that's later used for computing offsets of local + variables. + * flowanalysis.cs (UsageVector.parameters): Remove. + (UsageVector): Update to changes. + (VariableMap): Remove. + + Avoid creating ParameterMap in every block + * statement.cs (Block.ParameterMap): Move ... + (ToplevelBlock.ParameterMap): ... here. + (ToplevelBlock.ResolveMeta): Create VariableMap for parameters + only once. + * flowanalysis.cs (FlowBranching.param_map): Remove. + (FlowBranching.UsageVector): Update to changes. + (FlowBranchingToplevel.CheckOutParameters): Likewise. + + * statement.cs (Block.CloneTo): Clone Toplevel field too. + + * expression.cs (ParameterReference): Distinguish between block + where parameter was referenced and declared. + +2007-05-18 Marek Safar + + * flowanalysis.cs, statement.cs: Put back improved error handling. + +2007-05-15 Scott Peterson + + * assign.cs: + * expression.cs: + Imporved object and collection initialization (C# 3.0). + +2007-05-15 Marek Safar + + A fix for bug #81380 + * expression.cs (Is.DoResolve): Only value types have constant `is' + behaviour. + +2007-05-15 Raja R Harinath + + * statement.cs (ToplevelBlock.child): Remove. + +2007-05-15 Raja R Harinath + + Rationalize ResolveMeta: refactoring + (Block.ResolveMeta): Remove wrong or superfluous comments. Carve + out constant handling code into ... + (Block.DoResolveConstants): ... this. + + Rationalize ResolveMeta: kill local_map + * statement.cs (Block.local_map, Block.LocalMap): Remove. + (Block.AssignableSlots): New. + (Block.ResolveMeta): Make protected. Don't create a VariableMap + for locals -- move code from VariableMap here. Avoid unnecessary + allocations. + * flowanalysis.cs (FlowBranching.local_map): Remove. + (FlowBranching..ctor): Use Block.AssignableSlots. + (VariableMap): Remove unused constructors. + +2007-05-11 Raja R Harinath + + * Makefile [PROFILE=net_2_0_bootstrap]: Add special-case rules. + +2007-05-11 Marek Safar + + * typemanager.cs (IsFriendAssembly): Should not be called for building + assembly. + +2007-05-09 Marek Safar + + * literal.cs (NullConstant): Print null in all cases. + + * expression.cs (Binary.ResolveOperator): Implemented delegate + comparison based on C# 2.0 changes. + +2007-04-28 Scott Peterson + + This code is contributed under the MIT X11 license + + The following enables support for several C# 3.0 language features: + + * cs-tokenizer.cs: Added support for the "var" keyword. + + * ecore.cs: Refactored TypeLookupExpression.DoResolveAsTypeStep(). + Added VarExpr class to facilitate type inferencing. + + * class.cs: Added IDictionary field AnonymousTypes to TypeContainer + to support anonymous types. + + * assign.cs: Added support for type inferencing and initialization. + + * anonymous.cs: Added AnonymousClass class to enable anonymous types. + + * expression.cs: Added implicit array support to ArrayCreation. + Added 5 types and 1 interface: + + IInitializable Implementing classes can inject initializing + statements after object instantiation. + + Initializer Stores data for object initialization. + + AnonymousType An expression for anonymous types. + + AnonymousTypeParameter Stores data about an anonymous type's field. + + NewInitialize An expression for object initialization. + + CollectionInitialize An expression for collection initialization. + + * statement.cs: Added "var" keyword support to the foreach, using, and fixed + statements. + +2007-05-06 Marek Safar + + A fix for bug #81500 + * cs-tokenizer.cs: Add special handling for coalescing operator. + +2007-05-06 Marek Safar + + A fix for bug #81529 + * attribute.cs (GetAttributeUsage): AttributeUsage attribute inherits + its value from base class until it is redefined. + +2007-05-02 Raja R Harinath + + Fix regression in cs0631-3.cs + * cs-parser.jay (operator_declarator): Add opt_attributes to error + fallback. Make error fallback catch more cases. + +2007-05-01 Miguel de Icaza + + * cs-parser.jay: Allow parameters in operator declarations to have + attributes. + +2007-04-27 Miguel de Icaza + + * statement.cs (If.CloneTo): Only clone the FalseStatement if it + exists. + + * lambda.cs (ContextualReturn.Resolve): An expression is valid + inside the ContextualReturn, it does not have to be an + ExpressionStatement. + +2007-04-24 Miguel de Icaza + + * lambda.cs (ContextualReturn.Resolve): if the return type is not + set, set it. + +2007-04-23 Miguel de Icaza + + * anonymous.cs (AnonymousContainer): split the virtual Resolve + method in two methods: ResolveNoDefine and Resolve. + + ResolveNoDefine will stop just after ResolveTopBlock has been + called. + + Resolve will then continue by creating a method and issuing the + call to method.Define (). + + (AnonymousMethod): Split and implement the new Resolve and + ResolveNoDefine as well. + + * lambda.cs (LambdaExpression): Split the anonymous method + resolution code into a separate routine (CoreCompatibilityTest) + from DoCompatibleTest. + + (LambdaExpression.TryBuild): New method, this method tries to + build the LambdaExpression with the given set of types to be used + as the types for the various parameters of the lambda expression. + + If the compilation succeed with the given types, the infered type + of the Anonymous method is returned, otherwise null is returned. + +2007-04-23 Marek Safar + + A fix for bug #81414 + * delegate.cs: Better fix, moved ApplyAttributes from Define to Emit. + +2007-04-22 Miguel de Icaza + + * cs-tokenizer.cs: Change various identifiers here from the + camelCasing to the recommended Linux-like style for instance + variables from the Coding Guidelines. + +2007-04-19 Martin Baulig + + * convert.cs + (Convert.ImplicitReferenceConversionCore): Allow conversions from + System.Enum to System.ValueType. + +2007-04-13 Martin Baulig + + Rewrote implicit reference conversions. We need to distinguish + between implicit reference conversions (13.1.4) and implicit + boxing conversions (13.1.5). + + According to the spec, there's an an implicit conversion + "From a one-dimensional array-type S[] to IList and base + interfaces of this interface, provided there is an implicit + reference conversion from S to T." Note that this does not + include boxing conversions. + + * convert.cs + (Convert.ImplicitTypeParameterBoxingConversion): New method. + (Convert.ImplicitReferenceConversion): Split into + ImplicitReferenceConversionCore() and + ImplicitBoxingConversionExist(). + (Convert.ImplicitReferenceConversionExists): Use the new + ImplicitReferenceConversionCore() and ImplicitBoxingConversionExists(). + +2007-04-12 Martin Baulig + + * convert.cs (Convert.ImplicitReferenceConversion): Move the + `TypeManager.null_type' checks up to the top of the method. + +2007-04-11 Marek Safar + + A fix for bug #81350 + * class.cs, decl.cs, ecore.cs, namespace.cs: The optimization for private + extension methods. + +2007-04-11 Martin Baulig + + * statement.cs (Foreach.CollectionForeach.ProbeCollectionType): + Use `TypeManager.GetInterfaces(t)' rather than `t.GetInterfaces()' + to make this work for generic classes; fixes #79561. + +2007-04-11 Martin Baulig + + * expression.cs (As): Add support for nullable types; fixes #79371. + +2007-04-11 Martin Baulig + + * doc.cs (DocUtil.GetSignatureForDoc): Don't crash if + `type.FullName' is null; fixes #80243. + +2007-04-11 Martin Baulig + + * expression.cs (Invocation.IsApplicable): Don't modify the method + if type inference succeeded, but the method was not applicable. + Fixes #81250. + +2007-04-10 Marek Safar + + A fix for bug #81324 + * namespace.cs (Namespace.LookupExtensionMethod): Always inspect both + internal and external namespaces containers. + +2007-04-10 Martin Baulig + + * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Use + TypeManager.DropGenericMethodArguments() so we also call + IMethodData.SetMemberIsUsed() for generic methods. Fixes #80357. + +2007-04-10 Martin Baulig + + * iterators.cs (Iterator.CreateIterator): Don't crash if + `method.ReturnType' is null. This happens if something went wrong + while resolving that typ (we already reported an error in this case). + +2007-04-10 Martin Baulig + + * expression.cs (New.DoResolve): Don't call CheckComImport() on + generic interfaces; report the CS0144 directly. + +2007-04-10 Martin Baulig + + * ecore.cs (MemberExpr.ResolveMemberExpr): If `left' is a + `TypeExpr', call ResolveAsTypeTerminal() on it; fixes #81180. + +2007-04-10 Martin Baulig + + * expression.cs (New.DoEmitTypeParameter): Fix #81109. + +2007-04-09 Raja R Harinath + + A better fix + * flowanalysis.cs (UsageVector.MergeChild): Handle child.Block == null. + * statement.cs: Use KillFlowBranching only in ResolveUnreachable. + + Fix #81338 + * statement.cs (For.Resolve): If resolution fails, use + KillFlowBranching. + +2007-04-08 Marek Safar + + * anonymous.cs (MakeName): Make faster and zero-based. + (VerifyExplicitParameterCompatibility): Back to mode where generic + parameter is ignored. + (AnonymousMethodMethod.Emit): Decorate method as compiler generated. + + * class.cs (EmitType): Method can emit another new method. + + * cs-tokenizer.cs (IsLinqEnabled): Fixes static cctor race. + + * driver.cs: Updated. + + * lambda.cs: Reuse predefined empty parameters. + + * parameter.cs: Updated + + * support.cs: Implemented InflateTypes. + + * typemanager.cs (GetFullName): Don't use FullName as it can be null. + (InitSystemCore): Introduced to isolate 3.0 dependencies. + +2007-04-03 Martin Baulig + + Fix #80632. + + * statement.cs (Foreach.CollectionForeach.TryType): Use a custom + version of TypeManager.IsOverride() which also works with generic + types. + +2007-04-03 Martin Baulig + + Fix #81044. + + * convert.cs + (Convert.ExplicitReferenceConversion): We need to cast when + converting from IList to S[]. + +2007-04-01 Marek Safar + + * decl.cs (FindExtensionMethods): Consider all candidates with same name + at this level. + + * expression.cs (MemberAccess.DoResolve): Cache resolved expression. + +2007-03-31 Marek Safar + + * anonymous.cs (AnonymousMethodExpression.Compatible): Handles both + argument and return type inferring. + + * codegen.cs (InferReturnType): Flag whether return can be inferred. + (ReturnType): Turned to property. + + * statement.cs (Return): Implemented return type inferring. + + * support.cs (ReflectionParameters): Use local types if possible. + +2007-03-30 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Remove. + (FlowBranching.UsageVector): Update to changes. + + Prepare to kill 'Reachability' + * flowanalysis.cs (UsageVector): Remove 'Reachability' from + argument of constructor. + +2007-03-29 Raja R Harinath + + Prepare to kill 'Reachability' + * flowanalysis.cs (UsageVector.is_unreachable): New. + (UsageVector): Update to maintain 'is_unreachable' in parallel to + 'reachability', and verify they're consistent. + + Fix #81121 + * expression.cs (New.EmitStatement): Handle type parameters here too. + +2007-03-29 Martin Baulig + + Fix #79148. + + * anonymous.cs + (ScopeInfo.ctor): Use `Modifiers.PUBLIC' if we're a nested + CompilerGeneratedClass. + (ScopeInfo.EmitScopeInstance): Make this protected. + (CapturedVariable.EmitInstance): Use `Ldarg_0' if + `ec.CurrentAnonymousMethod.Scope == Scope'. + + * statement.cs (Block.ScopeInfo): Make this a property. + +2007-03-27 Raja R Harinath + + Prepare to kill 'Reachability' + * flowanalysis.cs (FlowBranching.Reachability): Make class private. + (FlowBranching.UsageVector.Reachability): Remove property. + (FlowBranching.UsageVector.IsUnreachable): New property. + (FlowBranching.UsageVector.ResetBarrier): New. + (FlowBranching.UsageVector, FlowBranchingLabeled): Update to changes. + * codegen.cs, statement.cs: Update to changes. + +2007-03-27 Martin Baulig + + Fix #81209. + + * decl.cs + (DeclSpace.LookupNestedTypeInHierarchy): Correctly handle nested + generic types. + +2007-03-26 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Use a boolean + instead of TriState. Remove all mention of TriState. + + * flowanalysis.cs (FlowBranching.Reachability): Prepare to be + replaced by a boolean. Add boolean 'is_unreachable' field, check + and maintain invariants. + +2007-03-25 Marek Safar + + * anonymous.cs: Restored checks disabled for uninflated anonymous methods. + +2007-03-25 Marek Safar + + * expression.cs: Stop using obsolete 2.0 opcodes. + +2007-03-25 Marek Safar + + * enum.cs (EnumMember.Define): Fixed regression and slowdown caused by + one of the latests Martin's fixes. + +2007-03-23 Miguel de Icaza + + * expression.cs: On BigEndian systems, swap the bytes, temporary + solution until we get a new bitconverter class. + +2007-03-23 Martin Baulig + + Fix #81158. + + * decl.cs (MemberCache.AddMembers): Add generic methods both as + "Method" and "Method`1". Normally, a cache lookup is done on the + "Method" form (ie. without the generic arity), but this one makes + lookups on the full form work as well. + +2007-03-22 Raja R Harinath + + * flowanalysis.cs (Reachability): Reorganize slightly, and remove + unused properties. + +2007-03-20 Bill Holmes + * class.cs: + Added 2 MemberCoreArrayList objects, ordered_explicit_member_list and + ordered_member_list, to TypeBuilder to store members to be defined + in the order they were parsed in. + - ordered_explicit_member_list contains all properties indexers + and methods that are defined as explicit implementation of an + interface or base class. + - ordered_member_list contains all properties indexers and methods + that are not defined as explicit implementation of an interface + or base class. + + Removed MethodArrayList and IndexerArrayList from TypeBuilder. The + functionality in these removed classes has been replaced with + ComputeIndexerName, EmitIndexerName, HasEqualss, HasGetHashCode, and + CheckEqualsAndGetHashCode members defined and called in the TypeBuilderClass. + + Adding CheckForDuplications to PropertyBase.PropertyMethod and calls + to CheckForDuplications inside GetMethod and SetMethod Define Method + to handle method property and indexer name conflicts. + + Fixes #79434 + + All code is contributed under the MIT/X11 license. + +2007-03-20 Martin Baulig + + * class.cs (TypeContainer.Interfaces): Removed; they're now + included in `TypeContainer.Types'. + +2007-03-20 Martin Baulig + + Fix #77963, #80314 and #81019. Added gtest-317, ..., gtest-320. + + * class.cs (TypeContainer.CreateType): New public method. This is + now called before DefineType() to create the TypeBuilders. + (TypeContainer.DefineType): Don't create the TypeBuilder here; it + has already been created by CreateType(). + (TypeContainer.DefineTypeBuilder): Renamed into CreateTypeBuilder(); + don't resolve our base classes here; this has been moved into + DefineBaseTypes(). We're now called from CreateType(). + (TypeContainer.DefineBaseTypes): New private method; resolve our + base classes here. We're now called from DefineType(). + + * rootcontext.cs + (RootContext.ResolveTree): Call TypeContainer.CreateType() on all + our types first to create all the TypeBuilders. After that, call + TypeContainer.DefineType() on all the types which'll resolve their + base classes and setup the resolve order. + +2007-03-20 Martin Baulig + + * class.cs (TypeContainer.Enums): Removed; they're now included in + `TypeContainer.Types'. + +2007-03-20 Martin Baulig + + * class.cs + (TypeContainer.DefineType): Don't call ResolveMembers() here. + (TypeContainer.DoResolveMembers): Call DefineType() on our + `compiler_generated' classes; moved here from DefineNestedTypes(). + + * rootcontext.cs + (RootContext.ResolveTree): Call ResolveMembers() on all + TypeContainer's in the `type_container_resolve_order'. + +2007-03-19 Marek Safar + + * class.cs: Use corlib to handle InternalMethodImplAttribute. + +2007-03-17 Marek Safar + + * class.cs (EventFieldAccessor.EmitMethod): Don't override existing + implementation flags. + +2007-03-17 Marek Safar + + * class.cs: More optimizations for type parameters. + +2007-03-15 Marek Safar + + * anonymous.cs (AnomymousMethod): Can be now hosted in generic container. + + * ecore.cs, parameter.cs: More common code for both corlibs. + + * typemanager.cs (IsGenericMethod): Simplified. + +2007-03-15 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Remove handling of + 'returns'. + * statement.cs, iterators.cs, lambda.cs: Update to changes. + + * statement.cs (Lock.Resolve): Invoke 'ec.NeedReturnLabel' + unconditionally. Simplify explanation. + (Try.Resolve, Using.Resolve): Likewise. + +2007-03-15 Martin Baulig + + Fix #80731. + + * decl.cs (DeclSpace): If we're a partial class, use our + `PartialContainer's `TypeParameters' and `CurrentTypeParameters'. + +2007-03-15 Raja R Harinath + + * flowanalysis.cs (FlowBranching.Reachability): Remove handling of + 'throws'. + (FlowBranching.UsageVector): Update to changes. + (FlowBranching.MergeSiblings): Likewise. + * statement.cs: Likewise. + +2007-03-15 Martin Baulig + + Fix #79302. + + * decl.cs + (MemberCache): Added a special .ctor for type parameters. + + * typemanager.cs + (TypeManager.MemberLookup_FindMembers): `TypeParameter' now has a + `MemberCache'. + +2007-03-09 Martin Baulig + + * enum.cs (Enum): Make this a TypeContainer. + (EnumMember): Derive from `Const'. + + * const.cs + (Const.DoResolveValue): New protected virtual method; move most of + the functionality of ResolveValue() here so we can override it in + `EnumMember'. + (Const.CreateConstantReference): Make this virtual. + + * class.cs (Kind): Add `Kind.Enum'. + (TypeContainer.Emit): Don't emit the enums here; they're already + in the `RootContext.typecontainer_resolve_order'. + + * rootcontext.cs (RootContext.EmitCode): Don't emit the enums + here; they're already in the `typecontainer_resolve_order'. + + * ecore.cs (EnumConstant.ConvertImplicitly): Add + TypeManager.DropGenericTypeArguments(). + + * typemanager.cs + (TypeManager.CSharpEnumValue): Add DropGenericTypeArguments(). + (TypeManager.IsEnumType): Likewise. + (TypeManager.EnumToUnderlying): Likewise. + (TypeManager.IsEqual): Add support for enums. + +2007-03-12 Raja R Harinath + + * typemanager.cs (InitCoreTypes) [NET_2_0]: Allow + DefaultParameterValueAttribute to be undefined, say if System.dll + is not referenced. + +2007-03-11 Marek Safar + + * ecore.cs, parameter.cs, typemanager.cs: Another gmcs fix to work with + any mscorlib. + +2007-03-10 Marek Safar + + * class.cs, parameter.cs: Unified parameters verification. + +2007-03-08 Martin Baulig + + * cs-parser.jay (constructor_header): Pass the location to the + newly created TopLevelBlock. + +2007-03-07 Martin Baulig + + * statement.cs (Block.Resolve): Don't crash on error; bug #80715. + +2007-03-06 Miguel de Icaza + + * convert.cs (ExplicitReferenceConversionExists): Sync this method + with the changes from David, fixes the build. + +2007-03-05 David Mitchell + + * convert.cs: Implement From System.Collecitons.Generic.IList + and its base interfaces to a one-dimensional array type S[], + provided there is an implicit or explicit reference conversion + from S to T. + +2007-03-03 Marek Safar + + * cs-tokenizer.cs: Implemented basic linq grammar. + + * driver.cs: Set linq lang version on demand. + +2007-02-26 Marek Safar + + * cs-parser.jay, expression.cs: Compile empty __arglist correctly. + +2007-02-25 Marek Safar + + * attribute.cs: Replaced DefinePInvoke in favor of S.R.E implementation + (Fixes #80455) + + * class.cs (InterfaceMemberBase): Share common `extern' modifier checks + here. + Check property and event extern attributes. + + * codegen.cs (ModuleClass): HasDefaultCharSet when module defined global + charset. + +2007-02-24 Marek Safar + + A fix for bug #80407 + * ecore.cs: Don't report ambiguity error when methods have same parent. + +2007-02-23 Marek Safar + + A fix for bug #80878 + * class.cs, cs-parser.jay: Event property can host anonymous methods. + +2007-02-22 Marek Safar + + * attribute.cs: Enable ExtensionAttribute presence test. + +2007-02-22 Marek Safar + + * class.cs: Warn about missing GetHashCode only when Equals is override. + + * decl.cs: Check accessibility of type arguments. + + * typemanager.cs: Correctly report nullable array. + +2007-02-20 Marek Safar + + * class.cs, report.cs: Capture more details when things go wrong. + +2007-02-20 Marek Safar + + A fix for bug #80650 + * cs-parser.jay: Anonymous container starts at constructor declaration + and not at block beginning because it has to be usable in constructor + initializer. + + * statement.cs: Use context location and not block one for error reporting. + +2007-02-18 Marek Safar + + A fix for bug #78712 + * class.cs.cs, decl.cs, ecore.cs: LookupAnyGeneric inspects nested types + too. + +2007-02-18 Marek Safar + + A fix for bug #80493 by Atsushi Enomoto + * cs-parser.jay: Ignore invalid attribute target. + +2007-02-18 Marek Safar + + * cs-tokenizer.cs: Ignore '\0' as white space character. + +2007-02-17 Miguel de Icaza + + * cs-parser.jay: Add support for lambda expressions to the mcs + compiler as well. + + * lambda.cs: Only clone when we are probing, not on the final call + (Compatible is the final call). + + * statement.cs (CloneContext): Introduce class to provide block + remapping during clone. + + All statements Clone themselves now. + + (Clone): special handling for blocks, when we clone a block, we + register the block inside this routine, as children of the block + might trigger a lookup. + + * expression.cs: Add support for CloneContext in all expressions. + +2007-02-17 Marek Safar + + A fix for bug #80493 + * statement.cs: Report ambiguous warning when interfaces are not related. + +2007-02-15 Marek Safar + + C# 3.0 extension methods. + + * attribute.cs (Error_MisusedExtensionAttribute): Extension attribute + cannot be used directly. + + * class.cs (Class.Emit): Emit extension attribute if any class method + is extension method. + (Method.Define): Add basic extension method validation conditions. + (Method.Emit): Emit extension attribute for method. + + * codegen.cs (AssemblyClass): Emit extension attribute if at least one + extension method exists. Currently we follow same approach as Microsoft + does, emit even if a method or a class are private but this can change + later. + + * cs-parser.jay: Add handling of `this' keyword in method parameters + context. + + * decl.cs (DeclSpace.IsStaticClass): New property. + (MemberCache.FindExtensionMethods): Looks for extension methods with + defined name and extension type. + + * doc.cs: Updated after OverloadResolve changes. + + * driver.cs: Add new soft reference to System.Core.dll. + + * ecore.cs (MethodLookup): Can return only MethodGroupExpr. + (ExtensionMethodGroupExpr): Represents group of extension methods. + + * expression.cs (Invocation): Moved methods BetterConversion, MoreSpecific, + BetterFunction, IsOverride, IsAncestralType, OverloadResolve + to MethodGroupExpr and made non-static for easier customization. + (Invocation.DoResolve): Add extension method lookup when no standard + method was found. + (MemberAccess.DoResolve): Try extension methods if no member exists. + + * modifiers.cs: Add METHOD_EXTENSION modifier. + + * namespace.cs (RegisterExtensionMethodClass): Register class namespace + as well as candidate extension type. + (ComputeNamespaces): When assembly constains extension methods registers + them. + (Namespace.RegisterExternalExtensionMethodClass): Register type for later + extension method lookup. + (Namespace.LookupExtensionMethod): Looks for extension method in this + namespace. + (NamespaceEntry.LookupExtensionMethod): Does extension methods lookup to + find a method which matches name and extensionType. + + * parameter.cs (Parameter): Add This modifer. + (HasExtensionMethodModifier): New property. + (Resolve): Add extension parameter check. + (ModFlags): turned to property to exclude this modifier as it is not real + parameter modifier. + (Parameters): Implemented ExtensionMethodType and HasExtensionMethodType. + + * support.cs (ParameterData): Add ExtensionMethodType. + (ReflectionParameters): Implemented ExtensionMethodType interface property. + + * typemanager.cs: Add type and ctor extension attribute type. + +2007-02-15 Miguel de Icaza + + * report.cs (DisableErrors, EnableErrors): used to prevent error + output when we are "trying" to compile various methods with + different types. + + * ecore.cs (Expression): Add Clone method that calls the virtual + CloneTo method. The current CloneTo method in Expression throws + an exception so we can track down all the places where this must + be implemented (not using abstract, because that would be a lot of + up-front-work before we can start testing the implementation + idea). + + Important: we only need Clone capabilities for expressions created + by the parser, as the expressions we will be cloning are + expressions in the pre-resolved state. This vastly simplifies + the work required. + + (SimpleName): Add CloneTo that does nothing. + (EmptyCast): Add CloneTo. + + * expression.cs (Binary): Implement CloneTo. + (Invocation.IsApplicable): Store the current ec in + EmitContext.TempEc and restore it on return. This is used so we + do not have to sprinkle hundres of methods with an extra + EmitContext, we know that the only user is the lambda expression + ImplicitConversionExists code. + + (Argument): Add Cloning capabilities. + (LocalVariableReference, ParenthesizedExpression, Unary, Probe, + Cast, Conditional, ArrayCreation, InvocationOrCast, Invocation, + ArglistAccess, ArgList, TypeOf, SizeOf, CheckedExpr, + UnCheckedExpr, ElementAccess, BaseAccess, BaseIndexerAccess, + IndexerAccess): Add Clone capability. + + (LocalVariableReference, This): TODO: needs cloned Block mapping. + + (Argument): Add cloning capability. + + * assign.cs (Assign): Implement CloneTo. + + * anonymous.cs (ImplicitStandardConversionExists): Make virtual. + + * lambda.cs (ImplicitStandardConversionExists): Implement lambda + version by calling Convert with the EmitContext (that we are + currently storing in ec, this is not great, but will do for now, + to avoid passing EmitContext parameters to hundreds of functions + that do not need them now). + + (SetExpression): Remove, it is not needed. + + (ContextualReturn): Implement CloneTo. + + * statement.cs (Statement): Implement cloning infrastructure, + similar to expressions. + + (Block): Partial implementation of Clone for statements. + + (Return): Implement clone. + + * constant.cs (Constant.CloneTo): New method, does nothing. + + * codegen.cs (TempEc): Add a static EmitContext as a temporary + solution, until we decide how to exactly do this. + +2007-02-14 Marek Safar + + A fix for bug #80493 + * class.cs (FindOutBaseMethod): When the base accessor does not exist and + a property is override we need to use second accessor. + +2007-02-13 Marek Safar + + A fix for bug #80418 + * attribute.cs, class.cs: Use correct calling conventions for pinvoke + methods. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + Another fix for bug #80749 + * pending.cs: Abstract class has priority over interfaces. + +2007-02-13 Marek Safar + + * class.cs Better error message. + + * driver.cs: Add shorter versions of -optimize option. + +2007-02-13 Martin Baulig + + * class.cs (Constructor.Emit): Check the return value of + ec.ResolveTopBlock() and return on error. + +2007-02-13 Raja R Harinath + + * ecore.cs (Error_InvalidExpressionStatement): Add a comma to error + message to fix error message regression. + +2007-02-12 Marek Safar + + * delegate.cs: Delegate creation expression cannot be of Nullable type. + +2007-02-12 Marek Safar + + A fix for bug #80749 + * assign.cs (FieldInitializer): FieldInitializer has to keep track of + its parent container. + + * class.cs (DefineFieldInitializers): Each initializer can has different + resolve context. + + * const.cs: Updated. + +2007-02-11 Miguel de Icaza + + * lambda.cs (LambdaExpression.Compatible): Remove some early code, + now all the heavy lifting to check that embedded statements or + expressions have the right form is done in the ContextualReturn. + + (ContextualReturn): New class. + + * ecore.cs (Error_InvalidExpressionStatement): Make a helper + method that can be invoked to report 201, so we do not replicate + this everywhere. + + * cs-parser.jay: Reuse Error_InvalidExpressionStatement. + + * cs-tokenizer.cs (xtoken): Correctly compute the column, it was + treating tabs as spaces. + +2007-02-09 Marek Safar + + A fix for bug #80315 by martin.voelkle@gmail.com (Martin Voelkle) + * assign.cs: Use full implicit conversion for right side check. + +2007-02-09 Marek Safar + + * statement.cs (Switch): Switch over boolean type is not standardized. + +2007-02-08 Marek Safar + + A fix for bug #80755 + * decl.cs (FindBaseEvent): Don't use method cache for events. + +2007-02-07 Marek Safar + + * cs-parser.jay: Better syntax error handling. + + * ecore.cs, enum.cs, statement.cs, typemanager.cs: Print enum member name + instead of underlying type value. + +2007-02-06 Marek Safar + + * driver.cs: Check define identifier before is registered. + + * namespace.cs: Use existing error message. + + * report.cs: New warning. + +2007-02-06 Marek Safar + + A fix for bug #80742 + * expression.cs: Delegate Invoke method can be called directly. + +2007-02-06 Marek Safar + + A fix for bug #80676 + * class.cs (IsEntryPoint): The Main method can have params modifier. + +2007-02-04 Miguel de Icaza + + * parameter.cs (Parameter, Parameters): Add Clone method. + + * anonymous.cs (Compatible): Turn method into virtual method, so + LambdaExpression can implement a different behavior. + + (CompatibleChecks, VerifyExplicitParameterCompatibility): Factor + out the basic checking here, so it can be used by + LambdaExpressions. + + * lambda.cs: Introduce "Compatible" function that will do the + heavy lifting. + +2007-02-02 Marek Safar + + * attribute.cs: Unified one error message. + + * class.cs (Class): Use type attributes and not properties to test static + class. + (IsEntryPoint): Don's pass local variable. + + * convert.cs: Removed duplicate check. + + * decl.cs, doc.cs, ecore.cs (LookupType): Renamed to LookupNamespaceOrType. + + * driver.cs: Don't crash when soft reference does not exist. + + * namespace.cs (EnsureNamespace): Renamed to RegisterNamespace. + (UsingEntry): Removed redundant allocation. + + * parameter.cs: Add fast path for type parameters. + + * support.cs: Don't allocate attribute when it's not used. + +2007-01-30 Miguel de Icaza + + * anonymous.cs + (AnonymousMethodExpression.ImplicitStandardConversionExists): turn + this into a virtual method, so we can override it in LambdaExpression. + + * driver.cs: Improve diagnostics in case of failure. + + * cs-tokenizer.cs: Instead of trying to parse a type and a name, + write a function that is slightly more complex and that parses: + + type identifier [, type identifier]* ) + + The old function would return incorrectly a OPEN_PARENS_LAMBDA for + this expression: + + (canEmpty ? i >= 0 : i > 0) + +2007-01-30 Raja R Harinath + + * cs-tokenizer.cs (parse_namespace_or_typename): Don't throw an + exception on possibly valid code. + +2007-01-29 Raja R Harinath + + * cs-tokenizer.cs (is_punct) ['<']: Update to changes in + Push/PopPosition. + (parse_opt_type_arguments): Remove. It's almost the same as + parse_less_than. + (parse_namespace_or_typename): Use parse_less_than. + +2007-01-28 Miguel de Icaza + + * cs-tokenizer.cs: Typo fix, its not GMCS_SOURCES but GMCS_SOURCE, + this bug took a few hours to find, because the state saved and + restored by PushPosition and PopPosition was ignoring the state of + parse_generic_less_than. + + I can also now remove the handling of OP_LT and OP_GT, this solves + the big mistery. + + * cs-tokenizer.cs: store the location for the ARROW token, we use + that in the parser. + + (PushPosition, PopPosition): save/restore also `current_token', + restore `parse_generic_less_than' (was missing). + + (parse_opt_type_arguments): use parse_type, not + parse_namespace_or_typename to parse types. + + * lambda.cs: Empty new file, will eventually have the lambda + expression implementation. + + * lambda.test: used to test the internal tokenizer. + + * report.cs (FeatureIsNotISO1): Rename from + FeatureIsNotStandardized, because it was about the language level + (1 vs 2) it was not about standarization. + + (FeatureRequiresLINQ): New. + + * support.cs (SeekableStreamReader): Only require that the reader + is a TextReader, not a StreamReader, so we can plug StringReader. + + * cs-tokenizer.cs (parse_type_and_parameter): Returns true if at a + given position in the input stream the following tokens can be + parsed as a type followed by an identifier. + + (is_punct): after a '(' if parse_type_and_parameter returns true, + then return a special token OPEN_PARENS_LAMBDA which is used to + avoid reduce/reduce errors in the grammar for the + lambda_expression rules. + + (parse_type): implement a type parser inside the + tokenizer, the parser only returns true or false depending on + whether the input at a given position can be parsed as a type. + + (peek_token): new method used during type parsing. + +2007-01-28 Raja R Harinath + + Fix #80531 + * anonymous.cs (ScopeInfo.InflateParameters): New. + (AnonymousContainer.Resolve): Use it to redirect types of + delegate parameters. + +2007-01-27 Raja R Harinath + + Fix #80530 + * expression.cs (Error_InvalidArguments): Don't use two different + messages for CS1503. Use ExtraInformation and + SymbolRelatedToPreviousError instead. + + Fix #80358 + * decl.cs (DeclSpace.initialize_type_params): Don't access + 'type_params' of a partial class directly. + +2007-01-26 Miguel de Icaza + + * constant.cs: Removed a handful of out-of-range checks that were + not necessary. + +2007-01-25 Marek Safar + + * expression.cs (CheckUselessComparison): Add additional check for char + constants. + + * namespace.cs: Fixed typo. + +2007-01-23 Miguel de Icaza + + * constant.cs: Bloat removal, CheckRange and CheckUnsigned are + gone, instead we inline the test, preventing the needless casts to + longs, ulongs and doubles for the parameters, avoiding calls to + methods that overchecked stuff, and instead inlined things + nicely. + +2007-01-20 Marek Safar + + * cs-parser.jay: Better parameter error handling. + +2007-01-17 Marek Safar + + A fix for bug #80368, #80522 + * expression.cs (ArrayCreation.only_constant_initializers): Indicates + whether array initializer contains constants only. + (ArrayCreation.Emit): Use better formula to decide when + are array initializers for static initialization. + (ArrayCreation.EmitDynamicInitializers): When the array is small enough we + have to emit even constants otherwise they are pre-initialized. + +2007-01-17 Bill Holmes + Raja R Harinath + + Fix emit order of 'get' vs. 'set'. + * support.cs (Accessors): New. + * cs-parser.jay (accessor_declarations): Use it instead of 'Pair'. + Note the order in which accessors are declared in the source. + * class.cs (PropertyBase.DefineGet, PropertyBase.DefineSet): New. + Refactored from Property.Define and Indexer.Define. + (PropertyBase.DefineAccessors): New helper that calls the above in + appropriate order as noted by the parser. + (Property.Define, Indexer.Define): Update to changes. + (PropertyBase.SetMethod.PropertyInfo): Don't return a null. + +2007-01-17 Raja R Harinath + + Fix cs0029-6.cs and gcs0029-2.cs (regression) + * ecore.cs (EmptyConstantCast.ConvertImplicitly): Check that + there's an implicit conversion from the current type to the target + type before converting the underlying constant. + +2007-01-16 Marek Safar + + * const.cs (ResolveValue): Updated after constant conversion was made more + generic. + + * constant.cs (GetAttributableValue): constant to object conversion is + used for attributes only. + (IntConstant.ConvertImplicitly): Moved from convert to be used in all + constant conversions. + (LongConstant.ConvertImplicitly): Ditto. + + * convert.cs (ImplicitNumericConversion): Extracted constant bussiness. + (ImplicitConversionStandard): Handle constant conversion as extra step. + It solves the issue when constant conversion was called indirectly like + inside array initializer and constant folding was skipped. + + * literal.cs (NullLiteral.ConvertImplicitly): Fixed an issue exposed by + this change. + + * statement.cs(ImplicitConversionStandard): Updated after constant + conversion was made more generic. + +2007-01-16 Sergey P. Kondratyev + + * expression.cs (As.DoResolve): Use GenericConstraints instead of + Constraints, solves the problem where the compiler incorrectly + reported that a type parameter was not constrained to a class (Bug + 80518) + +2007-01-14 Marek Habersack + + * doc-bootstrap.cs: Fix a compilation problem in the bootstrap phase. + +2007-01-14 Marek Safar + + A fix for bug #80368 + * assign.cs (FieldInitializer): New class implements field + initializer statement. + + * attribute.cs: Update after FieldMember rename. + + * class.cs (PropertyBasedMember): New common class for property based + types. + (InterfaceMemberBase): New base class for all members which can be used as + an interface members. + (MethodCore): Moved really common code to InterfaceMemberBase. + (Method.Define): Equal and GetHasCode detection is relevant for methods + only. + (MethodData.Define): Don't assume that public event implements an + interface automatically. + (MethodData.DefineMethodBuilder): Issue an error even if only extern + modifier is used. + (MemberBase): Moved all interface speficic code to InterfaceMemberBase. + (FieldMember): Merged with FieldBase. + (EventProperty.AEventPropertyAccessor): New specialization to check whether + event extern modifier can be used. + (EventField.EventFieldAccessor): Moved event field specific code here. + (Event.AllowedModifiers): Even event can be extern. + (Event.FindOutBaseMethod): New override specific to events. + (Indexer.parameters): Reintroduce parameters because base class holds + only properties common data. + (Indexer.CheckForDuplications): Indexers are threated as methods so we + need do extra parameters check. + + * const.cs: Update after FieldMember rename. + + * decl.cs (MemberCache.FindBaseEvent): New method. + + * doc.cs (GetMethodDocCommentName): Accept parameters as extra argument + to reflect that indexer is now derived from PropertyBased. + + * ecore.cs (GetMemberType): Made public. + (EventExpr.ResolveMemberAccess): Use right event cache and checks for + obsolete event. + + * flowanalysis.cs, statement.cs: Update after FieldMember rename. + + * typemanager.cs (CSharpSignature): Correctly print event accessors. + (RegisterEvent): Removed. + (RegisterPrivateFieldOfEvent): Renamed to RegisterEventField. + (GetPrivateFieldOfEvent): Renamed to GetEventField. + +2007-01-11 Raja R Harinath + + Fix #80249 + * statement.cs (CollectionForeach.TryType): Prefer generic + GetEnumerator over non-generic variant. Fix code to follow comments. + +2007-01-09 Raja R Harinath + + Fix #80446 + * support.cs (ReflectionParameter): Don't use an invalid index on + the generic parameter data. + +2007-01-08 Miguel de Icaza + + * driver.cs: Just add a tiny bit of infrastructure. + +2007-01-02 Marek Safar + + * class.cs (VerifyMembers): Fixed an crash reported on mono mailing list + where field type is struct from current assembly. + + * ecore.cs (EnumConstant.AsString): Report an enum member name whenever + it is possible. + +2007-01-02 Marek Safar + + A fix for bug #80381 + * attribute.cs (AttributeTester.RegisterNonObsoleteType): Registers + the core types. + + * namespace.cs (GlobalRootNamespace.LookupTypeReflection): Better error + messages. + (Namespace.LookupType): Always use core types from corlib when speficied. + + * report.cs: A new warning. + + * rootcontext.cs (BootstrapCorlib_ResolveInterface, + BootstrapCorlib_ResolveClass): Register type as non-obsolete type. + (ResolveCore): Add missing System.Runtime.InteropServices._Attribute. + + * typemanager.cs (CoreLookupType): Register type as non-obsolete type. + (InitCoreTypes): Set expression type of object_type and value_type + immediately after lookup. + +2007-01-01 Miguel de Icaza + + * cs-tokenizer.cs: Accept Pc class characters (Connector + Punctuation) as valid identifiers. Fixes #78259 + + * expression.cs (Invocation.DoResolve): Moved the check for the + use of `this' for doing method calls to the Invocation resolution + step, after overload resolution has taken place instead of doing + the check at the low-level `This.DoResolve' level. + + The `This.DoResolve'(appens before overload resolution, so it has + no way of knowing if the method that will be called will be + instace or static, triggering an erroneous report for cs0188 (Bug + 78113). + + We now do the check for instance method invocations after we know + what method will be called. + + (This.CheckThisUsage): Move the actual use of this structure + checking into its own method and expose it. + + * Everywhere that called Error_ValueCannotBeConverted: pass a new + EmitContext. + + Exceptions: Null.ConvertImplicitly, + Constant.ImplicitConversionRequired as there are too many call + sites for passing the ec. + + * ecore.cs (Expression.Error_ValueCannotBeConverted): Take an + EmitContext, if the value is null, then we do not try to provide + the extra information from the error (If a userdefined conversion + exists, as UserDefinedConversion requires a non null-EmitContext). + + Fixes: #80347 + +2006-12-30 Raja R Harinath + + * flowanalysis.cs (MyBitVector): Document some invariants. + (MyBitVector.Or, MyBitVector.And): Reimplement the optimizations + introduced below, and add a couple of others, + +2006-12-30 Marek Safar + + * attribute.cs (GetMethodObsoleteAttribute): Uses new + GetPropertyFromAccessor and GetEventFromAccessor. + + * class.cs (MethodCore.CheckBase): A new warning when obsolete member + overrides non-obsolete one. + (Indexer.Define): Error message has been moved to the parser. + + * cs-parser.jay: Better syntax errors handling. + + * delegate.cs (NewDelegate.DoResolve): Issue less confusing error message + when an invocation has no arguments. + + * ecore.cs: Removed not used caching. + + * expression.cs (IsSpecialMethodInvocation): Reuses TypeManager + implementation. + + * report.cs: Add a new warning. + + * support.cs (ReflectionParameters): Implements Equals, GetHashCode. + + * typemanager.cs (enumeration_type): Removed. + (CSharpSignature): Reuses IsSpecialMethod. + (IsEqual): Hack for MS BCL. + (GetPropertyFromAccessor): New method. + (GetEventFromAccessor): New method. + (IsSpecialMethod): Fixed to handle more cases. + +2006-12-30 Marek Safar + + * cs-tokenizer.cs (PreProcessDefinition, handle_preprocessing_directive): + Made white spaces array static. + + * ecore.cs (RemoveGenericArity): Optimized. + + * flowanalysis.cs (MyBitVector.Or, MyBitVector.And): Optimized (up to + 10 times faster). + (MyBitVector.initialize_vector): Simplified. + +2006-12-22 Miguel de Icaza + + * ecore.cs: Am not entirely happy with this hack, but it seems to + address the issue in 80257 (a small test case for + CreativeDocs.NET). + + I set the MethodGroupExpr.Type to an internal compiler type + (itself in this case) to force the resolution to take place. Why + it does not take place with a null is beyond me. + +2006-12-20 Marek Safar + + A fix for bug #80288 + * expression.cs (ResolveOperator): Consider user defined conversion for + logical and operator too. + (EmitBranchable): Optimization for logical and when full constant folding + could not be applied but one operand is constant. + +2006-12-19 Marek Safar + + * class.cs (GetClassBases): Write 5 times every day, will never use + FullName for error reporting. + + * decl.cs (AsAccessible, CheckAccessLevel): Always unpack arrays first. + +2006-12-19 Martin Baulig + + * statement.cs (LocalInfo.EmitSymbolInfo): New public method; emit + the symbol file info here. + +2006-12-18 Marek Safar + + * cs-tokenizer.cs (handle_preprocessing_directive): When previous section + of `elseif' is taking then following sections are not taking. + Fixes an issue reported on mono mailing list. + +2006-12-18 Marek Safar + + A fix for bug #80300 + * cs-tokenizer.cs (PreProcessDefinition): Do no define/undefine when + a caller is not taking. + +2006-12-18 Raja R Harinath + + * anonymous.cs: Change several TypeContainer declarations to DeclSpace. + (CompilerGeneratedClass): Use parent.PartialContainer unconditionally. + (RootScopeInfo, AnonymousMethodMethod): Update to changes. + * iterator.cs: Change several TypeContainer declarations to DeclSpace. + * class.cs: Update to changes. + +2006-12-17 Marek Safar + + A fix for bug #79934 + * anonymous.cs (CompilerGeneratedClass): Register class in a shared + partial container. + + * class.cs (ResolveMembers): Register an iterator in current container and + not in shared one. + +2006-12-16 Raja R Harinath + + Fix test-543.cs + * expression.cs (VerifyArgumentsCompat): Allow zero arguments to + satisfy a params annotated parameter. + +2006-12-16 Marek Safar + + A fix for bug #77014 + * expression.cs (Invocation.BetterFunction): Fixed to cope with dynamic + paramters correctly and not rely on hacks in Parameters class. + (Invocation.IsParamsMethodApplicable): Changed to accept params parameter + at any possition. + (Invocation.VerifyArgumentsCompat): Ditto. + (Invocation.EmitArguments): Changed to correctly emit params arguments at + any possition. + + * parameter.cs (HasParams): Don't assume that params is the last one. + + * support.cs (ReflectionParameters.ctor): Look for params attribute + correctly. + (ReflectionParameters.ParameterType): Removed hack when we returned last + parameter for out of range parameters. + (ParameterName, ParameterModifier): Ditto. + +2006-12-14 Marek Safar + + A fix for bug #79987 + * decl.cs (DeclSpace.VerifyClsCompliance): External names cache is null + when assembly is not CLS compliant but type is. I have no idea why is this + allowed. + + * typemanager.cs (Reset): Invalidate AllClsTopLevelTypes cache. + +2006-12-13 Miguel de Icaza + + * class.cs (ConstructorInitializer.Resolve): Allow for ":this()" + in struct constructors, they are basically no-ops. + +2006-12-12 Marek Safar + + * cs-tokenizer.cs (Position): Save preprocessor status too. + +2006-12-12 Marek Safar + + A fix for bug #77794 + * cs-tokenizer.cs (consume_identifier): Check for correct partial context. + +2006-12-12 Marek Safar + + * cs-tokenizer.cs (get_cmd_arg): Support CR as the line terminator. + Fixes #69299. + (pp_expr): Report error for an invalid expression. + (handle_preprocessing_directive): Simplified; add more error checking. + +2006-12-11 Marek Safar + + A fix for bug #74939 + * cs-tokenizer.cs (is_punct): We cannot simply disable preprocessor + directives handling. + +2006-12-10 Marek Safar + + A fix for bugs #80093, and #75984 + * cs-tokenizer.cs (handle_preprocessing_directive): Fixed #if/#else/#endif + logic, it seems to me as it worked before "by coincidence". + (xtoken): Simplified to use reworked handle_preprocessing_directive. + (cleanup): Enabled endif check. + +2006-12-09 Marek Safar + + A fix for bug #80162 + * statement.cs (CollectionForeach.TryType): Generics and non-generics + enumerators are never ambiguous. + +2006-12-08 Raja R Harinath + + Fix #80060 + * cs-tokenizer.cs (parse_less_than): Recognize double-colons too. + +2006-12-06 Marek Safar + + A fix for bug #80144 + * class.cs (EventProperty.Define): Explicit implementation means + that an even is used. + +2006-12-06 Marek Safar + + Fixes the operators implementation (part II) + + * cfold.cs (DoConstantNumericPromotions): Renamed to + DoBinaryNumericPromotions and simplified. + (BinaryFold): Couple of conversion fixes; simplified. + + * constant.cs, ecore.cs, literal.cs + (ToType): Renamed to ConvertImplicitly. + (Reduce): Renamed to ConvertExplicitly. + + * class.cs, convert.cs: Updated. + + * expression.cs: TryReduce doesn't throw an exception. + +2006-12-01 Marek Safar + + A fix for bug #80108 + * ecore.cs (EventExpr.EmitAddOrRemove): Don't crash when right side is not + compatible. + +2006-11-30 Marek Safar + + Fixes unary operators implementation (part I) + Also fixes #80026 + + * cfold.cs (Error_CompileTimeOverflow): Made internal + + * const.cs (IConstant): Changed to use reference to constant and + not constant itself. + Updated IConstant implementations. + + * constant.cs (CreateConstant): New factory method. + Updated IConstant implementation. + + * convert.cs (ImplicitStandardConversionExists): Uses compiler Equals. + + * ecore.cs: Updated to use CreateConstantReference. + + * enum.cs: Reflects IConstant changes. + + * expression.cs (Unary): Reimplemented +,-,~ to conform C# standard. + + * literal.cs (NullConstant): Change to be independently usable. + +2006-11-29 Martin Baulig + + * class.cs (Constructor.Emit): Correctly handle anonymous methods; + we need to emit the scope initializer before calling the base .ctor. + + * anonymous.cs: Merged back from the new anonymous methods branch. + (AnonymousMethodHost): Renamed to `RootScopeInfo'. + + * expression.cs (ParameterReference.DoResolveBase): Create a + "normal" ScopeInfo when capturing parameters rather than using the + root scope; this makes things work with anonymous methods having + parameters. + + * statement.cs + (ToplevelBlock.AnonymousMethodHost): Renamed into `RootScope'. + +2006-11-22 Marek Safar + + A fix for bug #79987 + * class.cs (VerifyClsCompliance): Move redundant CLS compliance attribute + check to a base class. + * decl.cs (VerifyClsCompliance): Warn that CLS compliance cannot be tested + only when assembly has missing attribute. + * report.cs: Update. + +2006-11-21 Marek Safar + + * cs-tokenizer.cs: Merged with gmcs version. + +2006-11-20 Marek Safar + + * cs-tokenizer.cs, + * cs-parser.jay: Better error message when partial keyword is misplaced. + +2006-11-19 Gert Driesen + + A fix for bug #79810 + report.cs: CS1058 only applies to 2.0 profile (gmcs). + codegen.cs: on 2.0 profile, non-exception throwables are wrapped in + a RuntimeWrappedException by default. + +2006-11-18 Marek Safar + + A fix for bug #79843 + * delegate.cs (Delegate.VerifyMethod): Fixed covariance and contravariance + implementation. + (DelegateCreation.Error_NoMatchingMethodForDelegate): Ditto. + +2006-11-18 Marek Safar + + * driver.cs, namespace.cs: Uses faster IndexOf version. + +2006-11-17 Marek Safar + + A fix for bug #79941 + * class.cs (MemberCore.IsDuplicateImplementation): Add more tricks for + operators. + (Operator.Define): Implicit/Explicit operator of same type is duplicate + even if internal name is different. + * convert.cs (GetConversionOperator): Replaced EmitContext with parentType. + (UserDefinedConversion): Simplified as the operators cannot be internal. + * ecore.cs (Error_ValueCannotBeConverted): Take account of user + conversions. + (MethodLookup): Replaced EmitContext with parentType. + * expression.cs: Updated. + +2006-11-09 Raja R Harinath + + * driver.cs (BadAssembly): Handle all the ugliness of + DefineDynamicAssembly. + +2006-11-08 Raja R Harinath + + Address parts of #58244 -- most of what's left is in the runtime + * driver.cs (LoadAssembly): Simplify slightly. Add CS0009 and + CS1509 error checks, and handle them for all assembly loads, not + just the first invocation. + (LoadModule): Likewise. Move handling of 'adder_method' ... + * codegen.cs (AssemblyClass.AddModule): ... here. + +2006-11-02 Marek Safar + + * statement.cs.cs (CollectionForeach.TryType): Issue a error when + IEnumerable is ambiguous. + +2006-10-31 Marek Safar + + A fix for bug #67689 + * statement.cs.cs (CollectionForeach.TryType): Issue a warning when + GetEnumerator is ambiguous. + + * report.cs: Add new warning. + +2006-10-29 Marek Safar + + A fix for bug #78602 + ecore.cs (PropertyExpr.InstanceResolve): The qualifier for access + to protected member can be nested type. + +2006-10-28 Marek Safar + + A fix for bug #78965 + ecore.cs (PropertyExpr.InstanceResolve): The qualifier for access + to protected member must derive from current type. + +2006-10-27 Marek Safar + + assign.cs: Reuses error method. + + ecore.cs (Expression.Error_ValueCannotBeConverted): Report a value + instead of type for constants. + (Expression.Error_ValueAssignment): Common error method. + + * expression.cs (UnaryMutator.ResolveOperator): Value cannot be used + for any assignment. + +2006-10-27 Marek Safar + + A fix for bug #79081 + * expression.cs (MemberAccess.DoResolve): Check nested type + accessibility. + +2006-10-27 Atsushi Enomoto + + * doc.cs : nested delegates were not handled. Fixed bug #79754. + +2006-10-26 Marek Safar + + A fix for bug #76591 + * cs-tokenizer.cs (IsCastToken): Enable a cast of anonymous method. + +2006-10-26 Marek Safar + + * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Don't allow to have + type forwarder of the same type multiple times. + +2006-10-26 Raja R Harinath + + Fix #78820 + * ecore.cs (PropertyExpr.InstanceResolve): Always resolve the + instance as an rvalue, even when we later resolve as an lvalue. + +2006-10-25 Martin Baulig + + * anonymous.cs: Fix #79673. + +2006-10-24 Marek Safar + + A fix for bug #79666 + expression.cs (ArrayCreation.GetAttributableValue): An initializer can be + ignored when is optimized (= default value) as its value is already set. + +2006-10-23 Marek Safar + + A fix for bug #79724 + * report.cs (SymbolRelatedToPreviousError): Uses DeclSpace instead of + TypeContainer for type lookup. + +2006-10-23 Marek Safar + + A fix for bug #79231 + * ecore.cs (ResolveAsBaseTerminal): Removed redundant error test. + * expression.cs (OverloadResolve): Always convert type name for + an error message. + (ResolveNamespaceOrType): Don't confuse a nested type with any + other member. + +2006-10-18 Martin Baulig + + * anonymous.cs: Propagate the IsStatic state, fixes the crasher in banshee. + +2006-10-17 Miguel de Icaza + + * convert.cs: Fix typo, fixes the test-535.cs, we were casting to + an int32, but requesting an int64 from the conversion + +2006-10-12 Martin Baulig + + * anonymous.cs + (AnonymousContainer.Resolve): Inflate the `ReturnType'. Fixes #79592. + +2006-10-12 Martin Baulig + + * statement.cs + (Using.EmitLocalVariableDeclFinally): Small fix for iterators. + +2006-10-11 Miguel de Icaza + + * convert.cs: Remove broken code: I was doing the "Existance" + tests for Implicit conversions. + +2006-10-10 Miguel de Icaza + + * convert.cs: Added one missing case in + ImplicitStandardConversionExists uint64 to intptr. + + Fixes #59800 + + * typemanager.cs (uintptr_type): another core known type. + + * ecore.cs (OperatorCast): routine used to do cast operations that + depend on op_Explicit. We could change some of the Decimal + conversions to use this. + + This one has a probe mechanism that checks both types for an op_ + which it coudl be used to eliminate two classes: CastToDecimal + and CastFromDecimal. + + * convert.cs: Implement the conversions documented in #59800 + +2006-10-10 Martin Baulig + + * iterators.cs (Iterator.Resolve): Call RootScope.ResolveType() + before RootScope.ResolveMembers(). + + * anonymous.cs (ScopeInfo.CapturedScope.ctor): Use the child's + `CurrentType' if appropriate. + +2006-10-09 Marek Safar + + A fix for bug #78568 + * cs-tokenizer.cs (Deambiguate_CloseParens): Expression cannot be cast + when contains binary operators. + * cs-parser.jay: Updated. + +2006-10-09 Martin Baulig + + * delegate.cs + (Delegate.DefineType): Don't call TypeParameter.Resolve() here; + moved that into Define() and also do the other type parameter + checks there. Fixes #79094. Added gtest-292.cs. + + * expression.cs + (ArrayCreation.EmitDynamicInitializers): Use `etype.IsValueType' + since that doesn't include type parameters; don't use `Ldelema' + for type parameters. Fixes #78980. Added gtest-293.cs. + +2006-10-08 Marek Safar + + A fix for #77796 + * convert.cs (ExplicitReferenceConversion): Only enum to enum value + conversion is allowed. + +2006-10-06 Marek Safar + + * ecore.cs (Expression.MemberLookup): Don't register any symbol for + error reporting when no error occurs. + +2006-10-06 Marek Safar + + * cfold.cs (ConstantFold.BinaryFold): Report an error when the conversion + does not exist. + +2006-10-06 Raja R Harinath + + Fix #79584 + * class.cs (DefineTypeBuilder): Check circular dependencies before + setting the parent of the TypeBuilder. + (CheckRecursiveDefinition): Don't use 'BaseType', since + it may not be valid until after DefineTypeBuilder. Use + 'base_type' instead. + +2006-10-04 Martin Baulig + + Merged the Anonymous Methods patch. + + * anonymous.cs, iterators.cs: The new anonymous methods code. + + * statement.cs (Variable): New public abstract class. + (LocalInfo.Variable): New public property. + (LocalInfo.ResolveVariable): New public method. + (Block.Flags): Add `IsIterator'. + (Block.AddVariable): Improved the CS0136 check. + (Block.AnonymousChildren): New public property. + (Block.AddAnonymousChild): New public method. + (ToplevelBlock): Update to use the new anonymous method framework. + (ToplevelBlock.ctor): `container' is now a `Block' and not a + `ToplevelBlock'; this is required to correctly implement the + CS0136 check. + (Fixed, Using): Use `TemporaryVariable' instead of directly + creating the `LocalBuilder'. + + * parameter.cs (Parameter.ResolveVariable): New public method. + (Parameters.ResolveVariable): Likewise. + + * ecore.cs (TemporaryVariable): Use the new `Variable' framework. + + * class.cs (TypeContainer): Replaced the `iterators' list and + corresponding methods with a list of `CompilerGeneratedClass'es. + (TypeContainer.ResolveMembers): New public method. + (Method): `IIteratorContainer' has been replaced by + `IAnonymousHost'. + + * expression.cs (VariableReference): New public abstract base + class for `LocalVariableReference', `ParameterReference' and + `This'. + + * codegen.cs (EmitContext): Removed `capture_context', + `HaveCaptureInfo', `EmitScopeInitFromBlock()' and `Capture*()'. + (EmitContext.EmitThis): Removed. + + * cs-parser.jay: Replace `iterator_container' with + `anonymous_host'. + +2006-10-04 Martin Baulig + + * generic.cs (GenericMethod): Don't make this abstract. + (Constraints.Clone): Added dummy implementation. + +2006-10-04 Raja R Harinath + + Fix #79577 + * namespace.cs (LookForAnyGenericType): Avoid nullref on + 'declspaces'. Avoid allocating arrays willy-nilly. + + Fix #79553 + * cfold.cs (BinaryFold): Move boolean Equality and Inequality + cases out of the switch. + +2006-09-28 Marek Safar + + * namespace.cs (Namespace.Error_NamespaceDoesNotExist): Better error + message when non-generic type is used with the type arguments. + * expression.cs: Updated. + +2006-09-28 Raja R Harinath + + Fix #79013 + * convert.cs (Convert.ImplicitStandardConversionExists): Avoid infloop. + * expression.cs (EmptyExpression.Grab, EmptyExpression.Release): + Change semantics slightly. Don't insist on having only one + temporary EmptyExpression -- just throttle the creation of new ones. + + Fix #79451 + * ecore.cs (Expression.MemberLookup): Enable CS0229 errors for + non-interfaces too. If no methods are found, don't try to create + a MethodGroupExpr. + +2006-09-28 Marek Safar + + * ecore.cs (ResolveAsTypeStep): Print better error when type can be + generic type. + + * namespace.cs (Namespace.LookForAnyGenericType): New method to help + us produce better error message. + +2006-09-27 Marek Safar + + * expression.cs (Binary.ResolveOperator): Warn about a side effect + of the `|' operator. + + * report.cs: A new warning added. + +2006-09-27 Martin Baulig + + * generic.cs (GenericMethod): Don't make this abstract. + +2006-09-27 Martin Baulig + + * report.cs + (InternalErrorException): Added overloaded ctor taking a params array. + +2006-09-26 Marek Safar + + * class.cs, codegen.cs, const.cs, cs-tokenizer.cs, driver.cs, ecore.cs: + Fixed the cases when same error was reported twice. + + * report.cs (SymbolRelatedToPreviousError): Simplified as all our messages + now report symbol information. + +2006-09-25 Martin Baulig + + * class.cs: Completely unified with the gmcs version. + +2006-09-25 Martin Baulig + + * typemanager.cs (TypeManager.IsNullableType): New public function. + (TypeManager.IsNullableTypeOf): Likewise. + (TypeManager.IsNullableValueType): Likewise. + + * class.cs (MethodCore): Added the `GenericMethod' argument from + gmcs and also unified all classes derived from `MethodCore' with gmcs. + +2006-09-24 Raja R Harinath + + * convert.cs: Unify with gmcs version. + +2006-09-24 Marek Safar + + * decl.cs (DeclSpace.VerifyClsCompliance): When type has type parameters + verify them as well. + + * report.cs: New warning. + +2006-09-24 Marek Safar + + * anonymous.cs (AnonymousMethod.Compatible): Cannot generate arguments + for anonymous block with out argument. + +2006-09-24 Marek Safar + + * class.cs (ClassOrStruct.VerifyMembers): Fixed to report correctly + not used private events only. + +2006-09-23 Marek Safar + + * cfold.cs (BinaryFold): On the guest to unify empty constant cast. + + * const.cs (Const.Define): Check for constant type. + (Const.IsConstantTypeValid): Looks for valid constant types. + + * convert.cs (ImplicitReferenceConversion): NullCast to EmptyConstantCast. + + * ecore.cs (EmptyConstantCast): New common class for all constant based + EmptyCast(s). + + * expression.cs (Is.DoResolve): Handle null constant especially. + (New.DoResolve): Check for new void(). + (MemberAccess.DoResolve): Cope with all kind of nulls. + + * literal.cs (NullConstant): Uses EmptyConstantCast. + (NullDefault): Based on EmptyConstantCast. + (NullLiteral): Uses EmptyConstantCast. + + * statement.cs (Block.ResolveMeta): Check for constant type. + +2006-09-22 Martin Baulig + + * delegate.cs, attribute.cs: Merged with the gmcs versions. + +2006-09-22 Raja R Harinath + + * literal.cs (NullDefault): The type of default(IFoo) is 'IFoo', + not the null type. + + Fix part of #79451 + * typemanager.cs (Closure.Filter): Consider PrivateScope attributes. + * decl.cs (DeclSpace.FindMemberToOverride): Likewise. Reorganize + code slightly. + +2006-09-22 Martin Baulig + + * ecore.cs: Merged with the gmcs version. + + * generic.cs (ConstructedType): New dummy class. + (TypeArguments): Don't make this abstract. + + * typemanager.cs + (TypeManager.IsGenericTypeDefinition): New method. + (TypeManager.GetGenericFieldDefinition): Moved here from gmcs. + +2006-09-22 Raja R Harinath + + * expression.cs (ComposedCast): Check for arrays of TypedReference + before creating the type, not after. + +2006-09-21 Marek Safar + + * cfold.cs, const.cs, enum.cs, statement.cs: Updated + after ToType change. + + * constant.cs (Constant.ImplicitConversionRequired): Designed to used + when constant must be implicitly convertible. + + * convert.cs (ImplicitReferenceConversion): Reuse ToType. + + * ecore.cs (NullCast): Derives from NullConstant. + + * expression.cs (Is.DoResolve): Removed useless variables. + (Conditional.DoResolve): Quick hack for `Foo () ? null : null'. + (New.Constantify): Add enum support. + (MemberAccess.DoResolve): Add warning when accessing null constant or + variable. + + * generic.cs (GenericConstraints.IsReferenceType): Another dummy + property. + + * literal.cs (NullConstant): New abstract class with common + functionality for all null specializations. + (NullDefault): Represents default(X) when result can be + reduced to null. + (NullLiteral): Updated. + + * report.cs: Add new warning. + +2006-09-21 Martin Baulig + + * generic.cs (GenericTypeParameterBuilder): Removed this ugly hack. + +2006-09-21 Martin Baulig + + * generic.cs (GenericConstraints): New dummy class. + (Constraints): Likewise. + (TypeParameter): Likewise. + (TypeParameterName): Likewise. + (GenericMethod): Likewise. + + * typemanager.cs (TypeManager.GetGenericArguments): New method. + + * decl.cs: Merged with the gmcs version. + +2006-09-21 Raja R Harinath + + * generic.cs (TypeParameter): Implement IMemberContainer. + (GenericTypeParameterBuilder): New. An abominable repugnant hack. + + * rootcontext.cs: Unify with gmcs version. + + * report.cs: Unify with gmcs version. + * typemanager.cs (AddTypeParameter, LookupTypeParameter): Move + from gmcs/generics.cs. + * generics.cs (TypeParameter): New dummy class. + + * support.cs: Unify with gmcs version. + +2006-09-20 Raja R Harinath + + * ecore.cs (MethodGroupExpr.ResolveGeneric): New dummy method. + * expression.cs (MemberAccess, BaseAccess): Remove GMCS_SOURCE #ifdef. + + * decl.cs (MemberName): Unify with gmcs, except for GetTypeExpression. + * generic.cs (TypeArguments): New dummy class to help avoid #ifdefs. + * mcs.exe.sources: Add generic.cs. + + * codegen.cs: Unify with gmcs version. + + * codegen.cs (IResolveContent.GenericDeclContainer): Copy from gmcs. + (EmitContext): Add GenericDeclContainer implementation. + * decl.cs (MemberCore, DeclSpace): Likewise. + * namespace.cs: Remove #ifdef GMCS_SOURCE. + + * namespace.cs (GetTypeInAssembly): Remove #ifdef GMCS_SOURCE. + MCS TypeManager has a corresponding dummy method. + +2006-09-19 Martin Baulig + + * expression.cs: Completely merged with the gmcs version. + +2006-09-19 Martin Baulig + + * expression.cs (Invocation): Merged with the gmcs version. + (ArrayAccess.GetStoreOpcode): Likewise. + +2006-09-19 Martin Baulig + + * typemanager.cs + (TypeManager.IsGenericMethod): Moved here from ../gmcs/generic.cs. + (TypeManager.IsGenericMethodDefinition): Likewise. + +2006-09-19 Martin Baulig + + * typemanager.cs + (TypeManager.IsEqual): Moved the gmcs implementation here. + (TypeManager.DropGenericTypeArguments): Likewise. + (TypeManager.DropGenericMethodArguments): Likewise. + (TypeManager.GetTypeArguments): Moved here from gmcs. + (TypeManager.HasGenericArguments): Likewise. + +2006-09-19 Martin Baulig + + * expression.cs (Binary): Merged with the gmcs version. + +2006-09-19 Martin Baulig + + * expression.cs (Probe, As, Is): Merged with the gmcs version. + +2006-09-19 Martin Baulig + + * typemanager.cs: Merged with the gmcs version. + +2006-09-16 Raja R Harinath + + * AssemblyInfo.cs [GMCS_SOURCE]: Unify with gmcs source. + * driver.cs: Likewise. + +2006-09-16 Marek Safar + + A fix for #79401 + * class.cs (MethodCore.VerifyClsCompliance): Do check for abstract members + only if parent type is class. + * decl.cs (MemberCore.GetClsCompliantAttributeValue): Fixed missing cache + update. + +2006-09-15 Marek Safar + + * cs-parser.jay, + * expression.cs(MemberAccess.DoResolve): Don't crash when not allowed + keywords are used. + * typemanager.cs(CSharpName): Converts NullType to null. + +2006-09-15 Martin Baulig + + * typemanager.cs + (TypeManager.GetMethodName): Added mcs implementation. + (TypeManager.IsEqual): Likewise. + + * ecore.cs + (SimpleName.RemoveGenericArity): Added dummy implementation. + + * pending.cs: Merged with the gmcs version. + +2006-09-15 Martin Baulig + + * statement.cs: Merge with the gmcs version. + +2006-09-15 Martin Baulig + + * statement.cs (Switch): Merge with the gmcs implementation + (without nullables), which is newer. + +2006-09-15 Martin Baulig + + * statement.cs (Block.Variables): Make this public. + (ToplevelBlock.Parameters): Make this a property. + (Throw.Resolve): Use `TypeManager.IsSubclassOf ()'. + +2006-09-15 Martin Baulig + + * namespace.cs: Merge with the gmcs version. + +2006-09-15 Martin Baulig + + * decl.cs (MemberName): Minor code cleanups. + +2006-09-15 Martin Baulig + + * parameter.cs: Merge with the gmcs version. + +2006-09-15 Martin Baulig + + * enum.cs: Merge with the gmcs version: 3005 is a warning in gmcs + and an error in mcs. + +2006-09-15 Martin Baulig + + * flowanalysis.cs: Merged from GMCS; added the generics code into + a `GMCS_SOURCE' conditional so we can share this file. + +2006-09-08 Martin Baulig + + * typemanager.cs (TypeManager.interlocked_type): New public field. + (TypeManager.int_interlocked_compare-exchange): New public field. + (TypeManager.InitEnumUnderlyingTypes): Also initialize the + enumerator types here and call InitGenericCoreTypes(). + (TypeManager.InitCoreTypes): Call InitEnumeratorTypes() right + after calling InitEnumUnderlyingTypes(). + + * rootcontext.cs + (RootContext.ResolveCore): Added `System.Threading.Interlocked' to + `classes_second_stage'. + +2006-09-14 Marek Safar + + * assign.cs, ecore.cs, expression.cs: Share error message text. + * class.cs (FieldMember.Define): Check for varible of static type. + * driver.cs (LoadAssembly): Uses error output for errors. + * statement.cs: Updated. + +2006-09-08 Marek Safar + + * expression.cs (Error_OperatorCannotBeApplied): Report type instead of + type instance. + +2006-09-07 Martin Baulig + + * driver.cs + (MainDriver): Revert r62663 from Marek; see #70506 for details. + +2006-08-29 Miguel de Icaza + + * cs-parser.jay: Turn 1522 into a warning, instead of an error #79210 + +2006-08-17 Miguel de Icaza + + * cs-tokenizer.cs: Apply patch from Atsushi Enomoto that fixes + #52019 and #79064, the use of the \uXXXX sequence in source code + to represent unicode characters. + +2006-08-15 Marek Safar + + * expression.cs (SizeOf.DoResolve): Check for void type. Fixed enum types + support. + * class.cs, ecore.cs, statement.cs: Merged to one error message. + +2006-08-13 Miguel de Icaza + + * assign.cs: Catch attempts to assign to a method groups in += and + report as 1656 + +2006-08-13 Marek Safar + + A fix for #79056 + * cs-parser.jay: Don't destroy current array type by typeof of array's. + +2006-08-12 Marek Safar + + * class.cs (Method.Define): Issue a warning when generic method looks like + an entry point. + * decl.cs (MemberCore.GetSignatureForError): Print member type arguments + as well. + +2006-08-09 Marek Safar + + * anonymous.cs(AnonymousDelegate.Emit): Uses Constructor filter when + looking for ctor. + * decl.cs (MemberCache.FindMembers): When container is interface we need to + search all base interfaces as a member can be ambiguous. + * delegate.cs (Delegate.FindMembers): Fixed to return valid data for + Constructor member type filter. + (Delegate.ResolveConstructorMethod) Uses Constructor filter. + * ecore.cs: (Expression.MemberLookup): Implemented ambiguity error/warning + reporting for returned memberinfos. + * report.cs: Updated. + * typemanager.cs (TypeManager.LookupBaseInterfacesCache): Uses TypeManager + version to work on all runtimes. + (TypeManager.RealMemberLookup): Removed members filtering. + +2006-08-08 Raja R Harinath + + * ecore.cs (FieldExpr.EmitAssign): Release temporary. + (PropertyExpr.EmitAssign): Likewise. + * expression.cs (Indirection.EmitAssign): Likewise. + (LocalVariableReference.EmitAssign): Likewise. + (ParameterReference.EmitAssign): Likewise. + (Invocation.EmitArguments): Likewise. + (ArrayAccess.EmitAssign): Likewise. + (IndexerAccess.EmitAssign): Likewise. + (This.EmitAssign): Likewise. + (ConditionalLogicalOperator.Emit): Likewise. + + Fix #79026 + * codegen.cs (EmitContext.GetTemporaryLocal): Simplify. Use Stack + instead of ArrayList. If the hashtable has a LocalBuilder, don't + leave it in after returning it. + (EmitContext.FreeTemporaryLocal): Simplify. Update to changes. + +2006-08-06 Marek Safar + + * expresssion.cs (IndexerAccess.DoResolve): Fixed to report correct error + message. + +2006-08-03 Raja R Harinath + + Fix cs0146-3.cs and cs0146-4.cs. + * class.cs (TypeManager.CheckRecursiveDefinition): Check that + enclosing types don't depend on the current type. + +2006-08-02 Raja R Harinath + + Fix #77963 + * class.cs (TypeContainer.DoDefineMembers): Use + FindBaseMemberWithSameName on Parent, since we're interested in + whether we hide inherited members or not. + (FindBaseMemberWithSameName): Make slightly more robust. + + Fix the non-generic testcase from #77396 + * decl.cs (DeclSpace.DeclContainer): Remove override. + + * namespace.cs (NamespaceEntry.Doppelganger): Create slave + declspaces for doppelgangers too. + (UsingEntry): Implement IResolveContext. + (UsingEntry.Resolve): Don't set ToplevelTypes.Namespace. Use + 'this' as the resolve context. + (LocalAliasEntry): Likewise. + + Implement parts of #77403 + * roottypes.cs (RootDeclSpace): New. Used to represent the + toplevel declaration space. Each namespace declaration introduces + a "partial" root declaretion space. + * namespace.cs (NamespaceEntry.SlaveDeclSpace): New. + (NamespaceEntry.ctor): Create a SlaveDeclSpace if necessary. + * cs-parser.jay (CSharpParser.ctor): Initialize 'current_class' + from 'current_namespace.SlaveDeclSpace'. + (namespace_declaration): Likewise. + * class.cs (TypeContainer.ctor): Remove parent==ToplevelTypes + check. It can't happen now. + * decl.cs (DeclSpace.LookupType): Likewise. + * driver.cs (MainDriver): Sanity check. + +2006-08-01 Raja R Harinath + + * decl.cs (DeclSpace.FindNestedType): Remove. + (DeclSpace.LookupNestedTypeINHierarchy): Use PartialContainer and + LookupTypeContainer to get the container of the nested type. + * class.cs (TypeContainer.FindNestedType): Make non-override. + +2006-07-31 Raja R Harinath + + * decl.cs (DeclSpace.PartialContainer): Move field from ... + * class.cs (TypeContainer.PartialContainer): ... here. + (TypeContainer.AddBasesForPart): New helper. + (MemberBase.ParentContainer): Remove. Use Parent.PartialContainer + instead. + * cs-parser.jay (current_class): Convert to DeclSpace. + (struct_declaration, interface_declaration, class_declaration): + Use AddBasesForPart instead of .Bases directly. + * const.cs, iterators.cs: Update to changes. + +2006-07-28 Raja R Harinath + + * class.cs (TypeContainer.AddMemberType): Rename from + AddToTypeContainer. + (TypeContainer.AddMember): Rename from AddToMemberContainer. + (AddTypeContainer): New. Combine AddClassOrStruct and + AddInterface. + (AddPartial): Update. Add 'is_partial' argument. + * roottypes.cs: Update to changes. + * cs-parser.jay (push_current_class): New helper for handling + current_container and current_class. + (struct_declaration, interface_declaration, class_declaration): + Use it. + +2006-07-26 Raja R Harinath + + * roottypes.cs: Rename from tree.cs. + + Rename RootContext.Tree.Types to RootContext.ToplevelTypes. + * tree.cs (Tree, ITreeDump): Remove types. + * rootcontext.cs (tree, Tree): Remove fields. + (root, ToplevelTypes): New. + * *.cs: Update to rename. + + * tree.cs (Tree.RecordDecl): Remove. + (RootTypes.AddToTypeContainer): Record the toplevel type in its + namespace here. + * class.cs, cs-parser.jay: Remove mention of RecordDecl. + +2006-07-23 Raja R Harinath + + * codegen.cs (EmitContext.Flags): Move InCatch, InFinally, + DoFlowAnalysis and OmitStructFlowAnalysis here. + (ec.With): Rename from WithUnsafe and generalize. + (ec.WithCheckState): Remove. All users can be handled by 'With'. + (ec.WithFlowAnalyis): New. + * ecore.cs, expression.cs, statement.cs: Update. + +2006-07-22 Raja R Harinath + + * statement.cs (Block.ResolveMeta): Simplify slightly. + + * codegen.cs (EmitContext.Flags): New enum. Used to represent the + multiple boolean fields. Convert InUnsafe, constant_check_state, + check_state to flags. + (CheckState, ConstantCheckState): Update. + (InUnsafe): New read-only property. + (FlagsHandle): Rename from CheckStateHandle and convert to handle + arbitrary flags. + (WithUnsafe): New helper similar to WithCheckState. + * statement.cs (Block.ResolveMeta): Use WithUnsafe. + (Unsafe.Resolve, Unsafe.DoEmit): Likewise. + +2006-07-21 Raja R Harinath + + Make comparisons use the same IL irrespective of whether they're + in a 'checked' or 'unchecked' context: one of the issues in #78899 + * codegen.cs (EmitContext.CheckState): Make read-only property. + (EmitContext.ConstantCheckState): Likewise. + (EmitContext.CheckStateHandle, EmitContext.WithCheckState): New + helper that implement a save/restore stack for CheckState + values. This is the only way to change check-state. + * ecore.cs (Expression.ExpressionToArrayArgument): Use WithCheckState. + * expression.cs (CheckedExpr.DoResolve, CheckedExpr.Emit): Likewise. + (CheckedExpr.EmitBranchable): New forwarding method. + (UnCheckedExpr): Likewise. + * statement.cs (Block.ResolveMeta): Use WithCheckState. + (Unchecked.Resolve, Unchecked.DoEmit): Likewise. + (Checked.Resolve, checked.DoEmit): Likewise. + +2006-07-20 Miguel de Icaza + + * anonymous.cs: Cache the resolved anonymous delegate, and return + this so that the ResolveTopBlock is only triggered once, not + twice. + + Currently we trigger ResolvetopBlock twice due to a first pass of + argument check compatibility, and a second pass that does the + actual resolution. + +2006-07-15 Marek Safar + + * annonymous.cs (AnonymousMethod.CreateScopeType): Fixed nested type + modifiers. + * rootcontext.cs (Reset): Add helper_classes. + +2006-07-15 Marek Safar + + A fix for #78860 + * statement.cs (Switch.SimpleSwitchEmit): Handle case null at any position + correctly. + +2006-07-13 Miguel de Icaza + + * statement.cs (Lock): Handle expressions of type + TypeManager.null_type specially. Fixes #78770 + +2006-07-08 Marek Safar + + * expression.cs (Binary.ResolveOperator): Don't crash when null is assigned + to an event. + +2006-07-08 Marek Safar + + * attribute.cs (AttributeTester.GetMethodObsoleteAttribute): Fixed to look + for accessors as well. + * ecore.cs (EventExpr): Add AccessorTable. + +2006-07-01 Marek Safar + + A fix for #78738 + * attribute.cs, class.cs, ecore.cs : Add missing location of related symbol + for CS0122 where appropriate. + * typemanager.cs (IsNestedChildOf): Type can be null in the case of top + level attributes. + (Filter): Assembly can be null in the case of top level attributes. + +2006-06-25 Marek Safar + + A fix for #78690 + + * ecore.cs (Expression.MemberLookupFailed): Don't crash when failed lookup + is done at global level. + +2006-06-24 Marek Safar + + A fix for #77002, Implemented TypeForwarder support. + + * attribute.cs (Attribute.GetArgumentType): Reads type argument. + * expression.cs (TypeOf.TypeArgument): Exposes typeof type. + * typemanager.cs (): Add type_forwarder_attr_type. + +2006-06-24 Marek Safar + + * report.cs: Add CS0469 warning. + +2006-06-21 Martin Baulig + + * codegen.cs (CodeGen.Save): Moved the symbol file generation into + the `try'-block, so we also report CS0016 etc. there. + +2006-06-21 Martin Baulig + + * delegate.cs + (Delegate.VerifyMethod): Allow `params' methods; fixes #78678. + +2006-06-21 Martin Baulig + + * expression.cs (Unary.ResolveOperator): In `Operator.AddressOf', + also report CS1686 for parameters. + +2006-06-21 Martin Baulig + + * statement.cs (GotoCase.Resolve): Report a warning (CS0469) + instead of an error if the value is not implicitly convertible to + the switch types; fixes #77964. + +2006-06-21 Raja R Harinath + + Fix #78673 + * class.cs (FieldBase.ResolveInitializer): Stop resolution if + FieldBuilder is null. + + Fix #78662 + * expression.cs (Binary.CheckShiftArguments): Don't overwrite original + 'left' and 'right' before error-checking. + +2006-06-16 Juraj Skripsky + + * ecore.cs (SimpleName.Error_ObjectRefRequired): Do not truncate the name. + Fixed bug #78601. + (MemberExpr.EmitInstance): Use GetSignatureForError () to get full name. + (FieldExpr.DoResolve): likewise. + (PropertyExpr.InstanceResolve): likewise. + (EventExpr.InstanceResolve): likewise. + +2006-06-04 Marek Safar + + * parameter.cs (Parameter.ApplyAttributeBuilder): More DefaultValue + attribute applicable tests for attribute argument. + +2006-06-02 Raja R Harinath + + Fix #78079 + * expression.cs (Binary.DoNumericPromotions): Remove and rewrite. + (Binary.OverloadResolve_PredefinedIntegral): New. + (Binary.OverloadResolve_PredefinedFloating): New. + (Binary.OverloadResolve_PredefinedString): New. + (Binary.ResolveOperator): Use those instead of DoNumericPromotions. + Follow the standard more closely, and treat numeric promotions in + terms of overload resolution. + (Binary.CheckShiftArguments): Simplify. + +2006-06-01 Raja R Harinath + + * flowanalysis.cs (MyBitVector): Simplify representation. + (MyBitVector.Clone): Avoid allocating BitArray. + (MyBitVector.operator&): Rename from MyBitVector.And and make symmetric. + (MyBitVector.operator|): Likewise, with MyBitVector.Or. + (*): Update. Change all references to MyBitVector.And and + MyBitVector.Or to &= and |=. + +2006-05-29 Raja R Harinath + + Fix cs0231-[34].cs. + * cs-parser.jay (formal_parameter_list): Extend the pattern below + to param arguments too. + +2006-05-26 Miguel de Icaza + + * cs-parser.jay: Catch another parsing form for arglist being + followed by other arguments. Fixes #78313. + +2006-05-24 Raja R Harinath + + * flowanalysis.cs (FlowBranchingToplevel.AddReturnOrigin): Move + checking of out parameters to ... + (FlowBranchingToplevel.Merge): ... here. + (FlowBranchingException.AddBreakOrigin): If 'finally_vector' is + set, propagate the origin upward, and only complain if there was + no other error. + (FlowBranchingException.AddContinueOrigin): Likewise. + (FlowBranchingException.AddReturnOrigin): Likewise. + (FlowBranchingException.AddGotoOrigin): Likewise. + +2006-05-23 Raja R Harinath + + * flowanalysis.cs (UsageVector.MergeOrigins): If an origin is + unreachable, skip it. + (FlowBranchingException.Merge): Always propagate jumps, even if + the finally block renders subsequent code unreachable. + +2006-05-18 Raja R Harinath + + Fix #77601 + * statement.cs (Goto.Resolve): Move responsibility for resolving + 'goto' to FlowBranching.AddGotoOrigin. + (Goto.SetResolvedTarget): New. Callback to set the + LabeledStatement that's the target of the goto. + (Goto.DoEmit): Use Leave instead of Br when crossing an + unwind-protect boundary. + * flowanalysis.cs (FlowBranching.AddGotoOrigin): Rename from + LookupLabel and adjust to new semantics. + (FlowBranchingToplevel.AddGotoOrigin): Likewise. + (FlowBranchingBlock.AddGotoOrigin): Likewise. Use + Goto.SetResolvedTarget to update target. + (FlowBranchingLabeled.AddGotoOrigin): Likewise. + (FlowBranchingException.AddGotoOrigin): Rewrite to be similar to + AddBreakOrigin & co. Delay propagation until ... + (FlowBranchingException.Merge): ... this. + + * statement.cs (Block.Resolve): Always depend on flow-branching to + determine unreachability. Kill workaround that originally emitted + only one statement after an "unreachable" label (see infloop in + test-515.cs). + + Fix #77869, #76148, #77755, #75255 and a host of other bugs. + This is still "wrong", but anything better would probably need a + multi-pass algorithm. + * flowanalysis.cs (FlowBranchingLabeled): Salt away a copy of the + usage vector. Force current usage vector to be reachable, to + optimistically signify backward jumps. + (FlowBranchingLabeled.LookupLabel): Note if a backward jump is + detected. + (FlowBranchingLabeled.Merge): New. If no backward jump was + detected, return the original salted-away usage vector instead, + updated with appropriate changes. Print unreachable warning if + necessary. + * statement.cs (Block.Resolve): Don't print unreachable warning on + a labeled statement. + +2006-05-17 Gert Driesen + + * driver.cs: Pass filename without path to AssemblyBuilder's + AddResourceFile. Fixes bug #78407. + +2006-05-17 Raja R Harinath + + * statement.cs (LabeledStatement.Resolve): Move merging of origins ... + * flowanalysis.cs (FlowBranchingLabeled): ... here. + (FlowBranching.MergeChild): Overwrite + reachability information from Labeled branchings too. + +2006-05-16 Raja R Harinath + + * statement.cs (Goto.Resolve): Merge jump origins here ... + * flowanalysis.cs (FlowBranching.Label): ... rather than here. + + * flowanalysis.cs (FlowBranching.LookupLabel): Move CS0159 check ... + (FlowBranchingToplevel.LookupLabel): ... here. Add CS1632 check. + (FlowBranchingGoto.LookupLabel): New. Handle back jumps. + (FlowBranchingBlock.LookupLabel): Call LabeledStatement.AddReference + here, ... + * statement.cs (Goto.Resolve): ... not here. + (Goto.Emit): Remove CS1632 check. + +2006-05-14 Marek Safar + + * ecore.cs (Expression.ResolveAsTypeTerminal): Fixed type in the obsolete + error message. + +2006-05-11 Raja R Harinath + + * flowanalysis.cs (UsageVector.MergeJumpOrigins): Kill. + (FlowBranchingBlock.Label): Use UsageVector.MergeOrigins. + (FlowBranchingException.Label): Likewise. + + * flowanalysis.cs (MyBitVector.SetAll): New. Sets all bits to the + given value. + (MyBitVector.Or): Use it to avoid losing information (Count). + (FlowBranching.MergeOrigins): Likewise. + + * flowanalysis.cs (UsageVector.IsDirty): Remove. + (UsageVector.Parameters, UsageVector.ParameterVector): Likewise. + (UsageVector.Locals, UsageVector.LocalVector): Likewise. + (UsageVector.ToString): Simplify. + (UsageVector.MergeSiblings): Move here from ... + (FlowBranching.Merge): ... here. + (FlowBranchingToplevel.CheckOutParameters): Take an UsageVector, + not a MyBitVector. + +2006-05-10 Raja R Harinath + + * flowanalysis.cs (UsageVector.MergeOrigins): Simplify, now that a + null bitvector is treated as all-true. + + * flowanalysis.cs (MyBitVector.And, MyBitVector.Or): Make lazier. + (MyBitVector): Rationalize invariants. 'vector != null' implies + that we have our own copy of the bitvector. Otherwise, + 'InheritsFrom == null' implies all inherited bits are true. + +2006-05-09 Marek Safar + + * statement.cs (LocalInfo): Add IsConstant. + (LocalInfo.DeclareLocal): Moved from EmitMeta and changed to don't emit + local variable for constants. + +2006-05-09 Raja R Harinath + + * flowanalysis.cs (MyBitVector.Empty): New. + (MyBitVector): Don't allow InheritedFrom to be null. + (MyBitVector.And, MyBitVector.Or): Treat 'null' as all-ones. + (UsageVector, FlowBranching): Update to changes. + + * flowanalysis.cs (FlowBranching.InTryWithCatch): Don't terminate + recursion. The 'Parent == null' condition isn't sufficient for + anonymous methods. + (FlowBranching.AddBreakOrigin): Likewise. + (FlowBranching.AddContinueOrigin): Likewise. + (FlowBranching.AddReturnOrigin): Likewise. + (FlowBranching.StealFinallyClauses): Likewise. + (FlowBranching.MergeTopBlock): Move to FlowBranchingToplevel. + (FlowBranching.CheckOutParameters): Likewise. + (FlowBranchingToplevel): Terminate all the above recursions here. + (FlowBranchingToplevel.End): Rename from MergeTopBlock. + * codegen.cs (EmitContext.ResolveTopBlock): Update to changes. + + * flowanalysis.cs (BranchingType.Toplevel): New. Represents a + toplevel block. + (FlowBranchingToplevel): New. Empty for now. + (FlowBranching.MergeTopBlock): Update. + * codegen.cs (EmitContext.ResolveTopBlock): Create a Toplevel + branching for the anonymous delegate. + (EmitContext.StartFlowBranching): Add ToplevelBlock variant. + + * flowanalysis.cs (UsageVector.MergeOrigins): Reorganize. + (UsageVector.MergeJumpOrigins): Don't ignore current reachability + information at the start of the merge. Reorganize. + +2006-05-07 Marek Safar + + * class.cs (MethodData.Define): Method cannot implement interface accessor. + +2006-05-07 Marek Safar + + * expression.cs (QualifiedAliasMember.ResolveAsTypeStep): Pass location + to newly introduced ctor. + + * namespace.cs (Namespace.Error_NamespaceDoesNotExist): Moved an error + message to one place. + (GlobalRootNamespace.Error_NamespaceDoesNotExist): Custom message for + global namespace. + +2006-05-07 Marek Safar + + * const.cs (Const.Error_ExpressionMustBeConstant): Better error message. + + * ecore.cs (Expression.ResolveAsConstant): Updated. + + * statement.cs (ResolveMeta): Updated. + +2006-05-06 Marek Safar + + * cs-parser.jay: __arglist cannot be used in initializer. + +2006-05-06 Marek Safar + + A fix for #77879 + * namespace.cs (LocalAliasEntry.DoResolve): Don't allow to access nested + private types. + +2006-05-05 Raja R Harinath + + * statement.cs (EmptyStatement.ResolveUnreachable): Override. + (LabeledStatement): Add 'name' parameter. + (LabeledStatement.Name, LabeledStatement.JumpOrigins): New. + (Block.AddLabel): Update to changes. + * cs-parser.jay (labeled_statement): Likewise. + + * flowanalysis.cs (BranchingType.Labeled): New. + (UsageVector.MergeOrigins): Remove unused 'branching' argument. + (FlowBranchingLabeled): New. Does nothing for now, but will + eventually handle 'goto' flows. + * codegen.cs (StartFlowBranching): Add new LabeledStatement variant. + * statement.cs (LabeledStatement.Resolve): Create a FlowBranching + that's terminated ... + (Block.Resolve): ... here. + + * flowanalysis.cs (UsageVector.MergeFinally): Remove. + (UsageVector.MergeFinallyOrigins): Likewise. + (FlowBranching.InTryOrCatch): Likewise. + (FlowBranching.AddFinallyVector): Likewise. + (FlowBranchingException): Update to changes. + + Fix #78290 + * statement.cs (Return.Resolve): Move error checking to ... + * flowbranching.cs (FlowBranching.AddReturnOrigin): ... this. + (FlowBranchingException): Handle return origins like break and + continue origins. + (FlowBranching.UsageVector.CheckOutParameters): Remove. + +2006-05-04 Marek Safar + + A fix for #76122 + * class.cs (TypeContainer.FindMembers): Includes event method in the methods + filter. + +2006-05-04 Marek Safar + + A fix for #77543 + * class.cs (MethodData.Define): Do public accessor check only when method + implements an interface. + +2006-05-04 Raja R Harinath + + Remove special handling of 'break' + * flowanalysis.cs (Reachability): Remove all mention of 'breaks'. + (Reachability.Meet): Simplify. Remove 'do_breaks' argument. + (UsageVector.Break): Remove. + (FlowBranching.Merge): Use 'Reachable.IsUnreachable' to determine + reachability. + (FlowBranchingBreakable.Merge): Don't ResetBreaks. + + * statement.cs (Break.Resolve): Call UsageVector.Goto (), not + UsageVector.Breaks (). Don't set NeedsReturnLabel. + +2006-05-03 Marek Safar + + A fix for #75726 + * pending.cs (PendingImplementation.BaseImplements): A found member cannot + be the interface member. + +2006-05-03 Marek Safar + + A fix for #60069 + * constant.cs (LongConstant.EmitLong): Fixed to catch also negative values + for emitting small (int) values. + +2006-05-03 Raja R Harinath + + Fix #59427 + * flowanalysis.cs (FlowBranchingException.Merge): Ensure + control-flow passes through the 'finally' after merging-in all the + control-flows from 'try' and the 'catch' clauses. + + * flowanalysis.cs (FlowBranching.IsLoop): Remove. + (FlowBranching.IsTryOrCatch): Remove 'is_return' parameter. It's + always true at the only non-recursive entry point. + (FlowBranching.CreateBranching) [BranchingType.Loop]: Return a + FlowBranchingBreakable. + (FlowBranchingLoop): Remove. + * statement.cs (Return.DoResolve): Update to changes. + + Fix #76471, #76665 + * flowanalysis.cs (FlowBranching.BranchingType.Embedded): New. + (FlowBranching.CreateBranching): Handle it: create a + FlowBranchingContinuable. + (FlowBranching.BreakCrossesExceptionBoundary): Remove. + (FlowBranching.AddContinueOrigin): Similar to AddBreakOrigin, + except that it handles the 'continue' command. + (FlowBranching.UsageVector.MergeOrigins): Rename from + MergeBreakOrigins. + (FlowBranchingContinuable): Similar to FlowBranchingBreakable, + except that it overrides AddContinueOrigin. + (FlowBranchingException): Override AddContinueOrigin, similar to + AddBreakOrigin. + * statement.cs (While.Resolve, Foreach.ArrayForeach.Resolve): + Create a new branching around the embedded statement. + (Do.Resolve, For.Resolve): Likewise. Do reachability analysis for + control flow after the embedded statement. + (Continue.Resolve): Move all error checking to AddContinueOrigin. + + * flowanalysis.cs (FlowBranching.IsSwitch): Remove. + (FlowBranching.CreateBranching) [BranchingType.Switch]: Create a + FlowBranchingBreakable. + (FlowBranchingSwitch): Remove. + + Fix test-503.cs + * statement.cs (Break.Resolve): Simplify. Move responsibility for + error reporting to ... + * flowanalysis.cs (FlowBranching.AddBreakOrigin) ... this. + Rename from 'AddBreakVector'. Add new location argument. Return + a bool indicating whether the 'break' crosses an unwind-protect. + (FlowBranchingException.AddBreakOrigin): Add. + (FlowBranchingException.Merge): Propagate 'break's to surrounding + flowbranching after updating with the effects of the 'finally' + clause. + (FlowBranchingBreakable): New common base class for + FlowBranchingLoop and FlowBranchingSwitch. + + * statement.cs (Foreach.ArrayForeach.Resolve): Set barrier after + embedded statement. + (Foreach.CollectionForeach.Resolve): Remove extraneous flowbranching. + +2006-05-02 Raja R Harinath + + * statement.cs (Do.Resolve): If the loop is infinite, set the + barrier. + (While.Resolve, For.Resolve): Set a barrier after the embedded + statement. There's no direct control flow that goes from the end + of the embedded statement to the end of the loop. + * flowanalysis.cs (FlowBranching.Infinite): Remove. + (FlowBranchingLoop.Merge): Don't look at 'Infinite'. The changes + above ensure that the reachability is correctly computed. + + * flowanalysis.cs (Reachability.ResetBarrier): Remove. + (UsageVector.MergeBreakOrigins): If the current path is + unreachable, treat it as if all parameters/locals are initialized. + (FlowBranchingLoop.Merge): Don't clear any barriers. Handle + infinite loops before merging-in break origins. + + * flowanalysis.cs (Reachability.Meet): Simplify code handling 'returns'. + (Reachability.Reachable): Split part into ... + (Reachability.Unreachable): ... this. Simplify. + (Reachability.IsUnreachable): Use 'Unreachable' instead. + + * flowanalysis.cs (Reachability.SetReturnsSometimes): Remove. + (Reachability.SetThrowsSometimes): Likewise. + (FlowBranchingBlock.MergeTopBlock): Don't compare against + TriState.Always, use corresponding property. + * statement.cs (Lock.Resolve, Try.Resolve, Using.Resolve): Likewise. + (Block.Resolve): Likewise. Remove some redundant checks. + +2006-05-02 Raja R Harinath + + * flowanalysis.cs (UsageVector.Throw): Set barrier too. + (Reachability.Meet): Don't bother checking AlwaysThrows -- + barrier is always set. + (FlowBranchingBlock.Merge): Likewise. + +2006-05-01 Raja R Harinath + + * codegen.cs (EmitContext.ResolveTopBlock): Remove redundant + checks for unreachable. + +2006-05-01 Marek Safar + + A fix for #77980 + * flowanalysis.cs (UsageVector.IsAssigned): Add flag to ignore short path. + + * statement.cs (Block.UsageWarning): Uses newly introduced flag to detect + whether field is really assigned. + +2006-04-30 Raja R Harinath + + * flowanalysis.cs (Reachability): Make 4-argument constructor + private. + (Reachability.Meet): Rename from 'And'. Remove static variant. + (Reachability.Always): Rename from the highly misleading + 'Reachability.Never'. + (FlowBranching.Merge): Update to changes. Mark an impossible + situation with a 'throw'. + (*): Update to changes. + +2006-04-29 Raja R Harinath + + * flowanalysis.cs (TriState): Rename from FlowBranching.FlowReturns. + Remove 'Undefined'. + (FlowBranching.TriState_Meet): Rename from AndFlowReturns. Simplify. + (FlowBranching.TriState_Max): Rename from OrFlowReturns. Simplify. + (*): Update to changes. + * statement.cs: Update to changes. + +2006-04-28 Marek Safar + + A fix for #78049 + *class.cs (Method.FindOutBaseMethod): Base method cannot be property method. + +2006-04-28 Raja R Harinath + + * flowanalysis.cs (FlowBranching.MergeTopBlock): Don't create a + dummy UsageVector. + + * flowanalysis.cs (UsageVector.MergeChild): Change FlowBranching + argument to two arguments: an usage-vector and a bool. Move call + to FlowBranching.Merge () ... + (FlowBranching.MergeChild, FlowBranching.MergeTopBlock): ... here. + + * flowanalysis.cs (UsageVector.MergeChild): Move special-case + handling of loop and switch reachability to ... + (FlowBranchingLoop.Merge, FlowBranchingSwitch.Merge): ... these. + +2006-04-27 Raja R Harinath + + * flowanalysis.cs (FlowBranching.InLoop): Move special-case + handling to FlowBranchingLoop.InLoop. + (FlowBranching.InSwitch): Likewise, to FlowBranchingSwitch. + +2006-04-26 Marek Safar + + A fix for #78115 + * anonymous.cs (AnonymousMethod.DoResolve): Moved the check whether + anonymous method is allowed from AnonymousContainer here. + + * attribute.cs, codegen.cs (EmitContext): Add IsAnonymousMethodAllowed. + +2006-04-24 Raja R Harinath + + Fix #78156 + * flowanalysis.cs (MyBitVector.Or): Add null check on argument. + +2006-04-23 Marek Safar + + A fix for #49011. + * constant.cs (FloatConstant.Reduce): Add range checking for checked context. + (DoubleConstant.Reduce): Ditto. + +2006-04-23 Raja R Harinath + + * expression.cs (LocalVariableReference.DoResolveBase): Simplify. + Remove 'lvalue_right_side' argument. Move parts to ... + (LocalVariableReference.ResolveLocalInfo, LocalVariable.DoResolve) + (LocalVariable.DoResolveLValue): ... these. + +2006-04-21 Raja R Harinath + + Fix cs1655.cs + * codegen.cs (EmitContext.InRefOutArgumentResolving): Remove. + * expression.cs (EmptyExpression.LValueMemberOutAccess): New. + (LocalVariableReference.DoResolveBase): Use it to implement new + CS1655 check. + (IndexerAccess.DoResolveLValue): Handle LValueMemberOutAccess. + (Argument.Resolve): Simplify. Move CS1510 check ... + * ecore.cs (Expression.ResolveLValue): ... here. + (UnboxCast.DoResolveLValue): Handle LValueMemberOutAccess. + (PropertyExpr.DoResolveLValue): Likewise. + (FieldExpr.Report_AssignToReadonly): Likewise. + (FieldExpr.DoResolve): Add 'out_access' argument. Use + LValueMemberAccess or LValueMemberOutAccess on instance depending + on it. + (FieldExpr.DoResolveLValue): Pass 'out_access' argument to + DoResolve as appropriate. + +2006-04-20 Raja R Harinath + + Fix #75800 + * expression.cs (Invocation.VerifyArgumentsCompat): Don't try + implicit conversions on 'out' and 'ref' arguments. + + * expression.cs (Invocation.VerifyArgumentsCompat): Reorganize to + improve clarity. Remove dead code. + + Fix #66031 + * statement.cs (Block.UsageWarning): Allow VariableInfo to be null. + (Catch.Resolve): Resolve VarBlock if it exists. + +2006-04-19 Miguel de Icaza + + * statement.cs (Foreach.EmitFinally): Do not emit the enumerator + twice, this was some residual code, the enumerator was emitted + properly in the two branche of if later. + +2006-04-19 Raja R Harinath + + * expression.cs (Cast.ResolveLValue): Remove. The result of a + cast is never an lvalue. + (Cast.DoResolve, Cast.ResolveRest): Combine. + (Argument.Emit): Simplify slightly. Move 'Expr is + IMemoryLocation' check ... + (Argument.Resolve): ... here. + (Argument.Error_LValueRequired): Remove. Inline into only user. + + Simplifications. Fix cs0191-2.cs + * ecore.cs (FieldExpr.DoResolve): Move handling of CS0192, CS0198, + CS1649 and CS1651 to ... + (FieldExpr.Report_AssignToReadonly): ... this. Simplify by moving + the actual selection of the error code and message to a lookup + table. Add a dummy return value to simplify callsites. + (FieldExpr.ResolveLValue): Don't allow a constructor to write to + readonly fields of other instances of the same type. Move CS0197 + warning from ... + * expression.cs (Argument.Resolve): ... here. Simplify code. + Ensure that ec.InRefOutArgumentResolving is only set during LValue + resolution of an out or ref argument. The code simplification + above uses this invariant. + +2006-04-18 Raja R Harinath + + Possibly fix #77752. Fix cs1690-[4-7].cs. + * ecore.cs (Expression.CheckMarshalByRefAccess): Renamed from + CheckMarshallByRefAccess. Drop parameter. + (FieldExpr.CheckMarshalByRefAccess): Update. Change CS1690 to a + warning. + (FieldExpr.DoResolve): Call CheckMarshalByRefAccess on + InstanceExpression. + * report.cs (AllWarnings): Add CS1690. + * expression.cs (Argument.Resolve): Use EmptyExpression.OutAccess + for ref access too. + (LocalVariableReference.DoResolveBase): Update. + +2006-04-09 Marek Safar + + * class.cs (MethodOrOperator): Moved common parts from method class. + detect obsolete attributes. + (Method.Define): Simplified as it reuses code from base. + (Constructor.ValidAttributeTargets): Fixed issue found during + refactoring. + (Destructor.ValidAttributeTargets): Fixed issue found during + refactoring. + (Operator): Finished refactoring set off by #78020. Operator class is now + ordinary method class. + + * anonymous.cs: Updated. + + * decl.cs (DeclSpace): Add IsGeneric + +2006-04-09 Marek Safar + + * class.cs (Constructor.Emit): Don't emit the attributes twice. + +2006-04-09 Marek Safar + + * class.cs (Operator.Emit): Extracted code from MethodData to correctly + detect obsolete attributes. + (Method.CreateEmitContext): Moved to MethodOrOperator. + +2006-04-09 Marek Safar + + A fix for #78048. + * class.cs (TypeContainer.MemberCoreArrayList.DefineContainerMembers): Throw + customized exception to make crash detection easier. + (MethodOrOperator): Started to work on new base class for methods and + operators. + (Method): Derives from MethodOrOperator. + (Constructor.Emit): Emits its own attributes. + (AbstractPropertyEventMethod.Emit): Ditto. + (Operator): Derives from MethodOrOperator, will refactor fully in extra + patch. + (Operator.Emit): It's temporary more tricky than should be. + + * doc.cs (GetMethodDocCommentName): Updated after operator changes. + + * report.cs (InternalErrorException): Add ctor with inner exception. + +2006-04-08 Marek Safar + + A fix for #76744. + * ecore.cs (SimpleName.ResolveAsTypeStep): Report better error when type is + only not visible. + +2006-04-07 Marek Safar + + A fix for #77916. + * expression.cs (ArrayCreation.GetAttributableValue): Creates correctly typed + array. + +2006-04-06 Marek Safar + + * class.cs (Class.ApplyAttributeBuilder): Report an error when ComImport + attribute is present and Guid not. + (Interface.ApplyAttributeBuilder): Ditto. + + * attribute.cs: Add error message. + +2006-04-06 Marek Safar + + A fix for #78020. + + * attribute.cs (Attribute.AttachTo): The attribute can have multiple + sources (it's composite) so hold them in extra array as they are used in + Emit phase only. It worked in the previous versions by mistake. + (Attribute.Emit): Emit attribute for more owners when exist. + + * codegen.cs, class.cs: Updated to don't re-attach attribute twice as now + it has now different behaviour. + +2006-04-04 Marek Safar + + * constant.cs (Constant.IsDefaultInitializer): New method. + + * class.cs: Updated. + + * expression.cs (ArrayCreation.CheckIndices): Add an optimization to don't + re-initialize default values. It saves KBs almost for every assembly. + Thanks Zoltan for the idea. + (ArrayCreation.ResolveInitializers): Renamed from ValidateInitializers. + (ArrayCreation.DoResolve): Resolve only once. + (ArrayCreation.Emit): Emit static initializer only when it is faster. + (ArrayCreation.GetAttributableValue): Cope with optimized values. + +2006-04-03 Zoltan Varga + + * report.cs (Warning, Error): Add 0-, 1-, and 2- argument specializations. + From #77961. + +2006-04-01 Marek Safar + + * assign.cs (Assign.DoResolve): Assignment to same variable can occur + in an embedded statement too. + +2006-04-01 Raja R Harinath + + Fix #77958 + * statement.cs (Switch.EmitObjectInteger) [ulong]: Remove bad cast. + +2006-04-01 Marek Safar + + A fix for #77966. + + * class.cs (TypeContainer.AddPartial): Don't report an error when modifier + was not specified. + + * modifiers.cs: Add DEFAULT_ACCESS_MODIFER. + +2006-03-31 Marek Safar + + * assign.cs (LocalTemporary): Don't require ILGenerator in the resolve + phase. + + * anonymous.cs, assign.cs, ecore.cs, expression.cs: Updated after + LocalTemporary change. + + * class.cs (ClassOrStruct.DefineDefaultConstructor): Moved from + TypeContainer. + (ClassOrStruct.DefineFieldInitializers): Implemented static field + initializers optimization. + (ClassOrStruct.TypeAttr): Moved from modifiers. + (Constructor.CheckBase): Don't crash when static ctor has parameters. + (FieldBase.ResolveInitializer): Resolves initializer. + (FieldBase.HasDefaultInitializer): New property. + + * cs-parser.jay: Removed message. + + * expression.cs (CompilerGeneratedThis): New specialization. + + * modifiers.cs (TypeAttr): Moved to ClassOrStruct.TypeAttr + +2006-03-28 Marek Safar + + * cs-parser.jay, cs-tokenizer.cs: On demand Stack allocation. + +2006-03-27 Marek Safar + + * ecore.cs (Expression.ResolveAsConstant): Clean up, enum constants should + be now EnumConstants only. + +2006-03-27 Marek Safar + + * attribute.cs, driver.cs: Reset more caches. + +2006-03-26 Marek Safar + + * cs-tokenizer.cs (adjust_real): Uses float.Parse for float literals. + +2006-03-26 Marek Safar + + * constant.cs (Constant.Reduce): Replaced EmitContext with single bool + for easier reuse. Updated all overrides. + (IntegralConstant): New base class for all integral constants. + (IntegralConstant.Error_ValueCannotBeConverted): When assigned value if out + of the constant range, report custom error. + (UIntConstant.Reduce): Fixed uint conversion. + + * ecore.cs, literal.cs: Reduce updates. + +2006-03-26 Marek Safar + + A fix for #75813. + + * class.cs (Constructor.Define): Removed extra if for default ctors. + A patch from Atsushi Enomoto. + +2006-03-26 Marek Safar + + * attribute.cs (Attribute.ResolveConstructor): Conversion was moved to + GetAttributableValue. + + * constant.cs (Constant.GetAttributableValue): Does implicit conversion + when required. + + * convert.cs (ImplicitConversionRequired): Error message moved to + DoubleLiteral. + + * ecore.cs (Expression.GetAttributableValue): Add type parameter for + automatic implicit conversion of an output value. + (EnumConstant.GetAttributableValue): Don't reduce the enum constants. + + * expression.cs (ArrayCreation.GetAttributableValue): Add element type + conversion. + (TypeOf.GetAttributableValue): Add extra handling for object type. + + * literal.cs (DoubleLiteral.Error_ValueCannotBeConverted): Doubles can have + special error message. + +2006-03-25 Marek Safar + + * class.cs (Constructor.Emit): Don't crash when struct ctor is + InternalCall. + (Constructor.ApplyAttributeBuilder): Transform MethodImplAttribute to be + compatible with MS runtime. + +2006-03-23 Marek Safar + + * attribute.cs (Attribute.ResolveConstructor): Check for an invalid + attribute arguments here. + + * class.cs (Indexer.Define): The check was moved to attribute class. + +2006-03-22 Marek Safar + + * assign.cs, class.cs, codegen.cs, convert.cs, decl.cs, ecore.cs, + expression.cs, typemanager.cs: Minor changes from gmcs to make merging + easier. + +2006-03-22 Raja R Harinath + + Support ParameterDefaultValueAttribute in gmcs. Also applied to + mcs to keep code differences small. + * attribute.cs (Attribute.GetParameterDefaultValue): New. + * typemanager.cs (parameter_default_value_attribute_type): New. + * parameter.cs (Parameter.ApplyAttributeBuilder): Use them. Add + CS1908 check. + +2006-03-21 Marek Safar + + * expression.cs (StringConcat.Append): Reverted back to no warning state. + +2006-03-21 Marek Safar + + * const.cs (Error_ConstantCanBeInitializedWithNullOnly): Share a message. + + * statement.cs (Block.ResolveMeta): Look for wrong object constants in + the blocks too. + +2006-03-21 Atsushi Enomoto + + * doc-bootstrap.cs : fix build. + +2006-03-20 Marek Safar + + * expression.cs (StringConcat.Append): Issue a warning when empty string + is going to append. + +2006-03-20 Marek Safar + + * assign.cs (CompoundAssign.ResolveSource): Removed. + + * attribute.cs (ResolvePossibleAttributeType): Updated after MemberAccess + clean up. + + * class.cs (TypeContainer.FindMethods): Removed. + (TypeContainer.CheckMemberUsage): Made static. + + * codegen.cs (GetAssemblyName): Uses Length for empty string test. + + * constant.cs (CheckRange): Removed unused type argument. + (CheckUnsigned): Removed unused type argument. + + * cs-parser.jay: Updated after MemberAccess clean up. + Uses Length for empty string test. + + * cs-tokenizer.cs: Uses Length for empty string test. + (IsCastToken): Made static. + (is_hex): Made static. + (real_type_suffix): Made static. + + * decl.cs (SetupCache): Made static. + (OnGenerateDocComment): Removed unused ds argument. + + * delegate.cs (VerifyDelegate): Removed unused argument. + + * doc.cs: Uses Length for empty string test. + + * driver.cs: Uses Length for empty string test. + + * enum.cs (IsValidEnumType): Made static + + * expression.cs (EnumLiftUp): Removed unused argument. + (ResolveMethodGroup): Ditto. + (BetterConversion): Ditto. + (GetVarargsTypes): Ditto. + (UpdateIndices): Ditto. + (ValidateInitializers): Ditto. + (MemberAccess.ctor): Ditto. + (GetIndexersForType): Ditto. + + * flowanalysis.cs: (MergeFinally): Removed unused argument. + + * iterators.cs: Updated after MemberAccess clean up. + + * location.cs: Uses Length for empty string test. + + * namespace.cs: Uses Length for empty string test. + + * report.cs (CheckWarningCode): Made static. + + * statement.cs (LabeledStatement): Removed unused argument. + + * typemanager.cs (FilterNone): Removed. + +2006-03-18 Marek Safar + + * codegen.cs (EmitContext.TestObsoleteMethodUsage): Removed as it become + obsolete. + + * class.cs: Updated. + +2006-03-18 Marek Safar + + * cs-parser.jay.cs: __arglist is not allowed for delegates. + +2006-03-18 Marek Safar + + A fix for #77822. + + * expression.cs (VerifyArgumentsCompat): Reverted to double error + reporting, it's more tricky than I thought. + +2006-03-18 Marek Safar + + A fix for #77816. + + * anonymous.cs.cs (AnonymousMethod): Add host to allow access to + host container. + (AnonymousMethod.ImplicitStandardConversionExists): New method. + (AnonymousMethod.Compatible): Moved parameter resolving to DoResolve. + Add more error reporting; Fixed issue with params. + + * convert.cs (ImplicitStandardConversionExists): Returned conversion check. + + * cs-parser.jay: AnonymousMethod requires host container. + + * delegate.cs (NewDelegate.DoResolve): Updated after Compatible changes. + +2006-03-18 Raja R Harinath + + * class.cs: Change 'TypeContainer ds' constructor argument to + 'DeclSpace parent'. Some classes were missed below due to + different naming convention. + + * class.cs (MemberCore.Parent): Delete. This makes the + ParentContainer changes below enforceable by the compiler. + + Treat pointers to enclosing declaration space as 'DeclSpace', not + 'TypeContainer'. + * class.cs, const.cs, delegate.cs, enum.cs, iterator.cs: Change + 'TypeContainer parent' constructor argument to 'DeclSpace parent'. + + * statement.cs (LocalInfo..ctor): Use DeclSpace argument instead + of TypeContainer. + (Block.AddThisVariable): Likewise. + * class.cs (MethodData.Define, MethodData.Emit): Likewise. + (AbstractPropertyEventMethod.Emit): Likewise. + (AbstractPropertyEventMethod.EmitMethod): Likewise. + (GetMethod.Define, SetMethod.Define): Likewise. + (PropertyMethod.Define, DelegateMethod.Define): Likewise. + (DelegateMethod.EmitMethod): Likewise. + + Fix regression test-partial-13.cs. + Rationalize use of PartialContainer. Ensure that the partial + class semantics can be tied to type-correctness, i.e., any + violation will cause a compile error. + * class.cs, const.cs: Access all fields that belong to class + TypeContainer via ParentContainer. Arguments of EmitContexts and + Resolve()-like functions still use 'Parent'. + + * class.cs (SourceMethod): Use DeclSpace, not TypeContainer. + (*.CreateEmitContext): Change TypeContainer argument to DeclSpace. + (PropertyMethod.CheckModifiers): Remove unused argument. + * codegen.cs (EmitContext..ctor): Change TypeContainer argument to + DeclSpace. + +2006-03-17 Raja R Harinath + + Make semantics of PartialContainer simpler. + * decl.cs (DeclSpace.IsPartial): Remove. + * class.cs (TypeContainer.IsPartial): Likewise. + (TypeContainer..ctor): Set PartialContainer to point to self. + (TypeContainer.GetClsCompliantAttributeValue): Don't use IsPartial. + (TypeContainer.FindNestedType): Likewise. + (MemberCore.ParentContainer): Simplify. Remove deprecation. + +2006-03-17 Marek Safar + + * typemanager.cs.cs (GetInterfaces): Don't recreate 0-sized arrays. + +2006-03-15 Marek Safar + + * class.cs (FieldMember.Emit): ParentContainer is real parent for partial + classes. + +2006-03-15 Marek Safar + + * class.cs (Operator.Define): An error for base conversion was not + reported correctly. + +2006-03-14 Atsushi Enomoto + + * iterator.cs : yield break is allowed in try statement which has + catch clauses. Fixed bug #77767. + +2006-03-13 Marek Safar + + A fix for #77593, #77574. + + * class.cs (MethodCore.CheckBase): Another if for operator. + +2006-03-09 Marek Safar + + * anonymous.cs (AnonymousMethod.Compatible): Don't crash when parameters + were not resolved + + * delegate.cs (Delegate.GetInvokeMethod): Use emitcontext free MemberLookup. + (DelegateCreation.ImplicitStandardConversionExists): New method for just + conversion test. + + *ecore.cs (Expression.MemberLookup): Don't ask for emitcontext when it's + not needed. + + * assign.cs, constant.cs, convert.cs, delegate.cs, expression.cs: + Updated after another emitcontext usage was clean up. It should help us to + synchronize with gmcs easier. + +2006-03-04 Marek Safar + + A fix for #77353. + + * class.cs (SetMethod.DefineParameters): Uses new parameters type ctor. + (Event.Define): ditto + (SetIndexerMethod.DefineParameters): Uses Parameters.MergeGenerated. + + * delegate.cs (Delegate.Define): Uses Parameters.MergeGenerated. + Removed redundant code and set NewSlot for Invoke method too. + + * parameter.cs (Parameters.ctor): Add custom, type ctor. + (Parameters.MergeGenerated): New method. Use this method when you merge + compiler generated argument with user arguments. + +2006-03-03 Marek Safar + + * attribute.cs (ResolveAsTypeTerminal): Removed. + + * ecore.cs (Expression.ResolveAsTypeTerminal): Make virtual to allow + specialization for predefined types; 30% speed up. + Finally placed obsolete check to right place. + (Expression.ResolveType): Removed. + + * enum.cs, expression.cs, parameter.cs, statement.cs, typemanager.cs: + Updated after ResolveType was removed. + + * expression.cs (Cast.ctor): Check void cast. + (Binary.ResolveAsTypeTerminal): Is never type. + (Conditional.ResolveAsTypeTerminal): Is never type. + + * rootcontext.cs (ResolveCore): Set base type to simplify some code later. + +2006-03-01 Raja R Harinath + + Fix #77679. + * expression.cs (ParameterReference.DoResolveBase): Change return + type to bool. + (ParameterReference.DoResolve, ParameterReference.DoResolveLValue): + Update. + + Fix #77628. + * ecore.cs (PropertyExpr.InstanceResolve): Fix CS1540 check. + + Fix #77642. + * typemanager.cs (GetFullNameSignature): Don't nullref on + protected accessors. + +2006-02-27 Marek Safar + + * attribute.cs (Attribute.PosArguments, Attribute.NamedArguments): Use + these two separated members to simplify the code. + (Attribute.Resolve): Refactored to use new fields and methods. + (Attribute.ResolveConstructor): Extracted from ResolveArguments and + implemented obsolete attribute checking. + (Attribute.ResolveNamedArguments): Extracted from ResolveArguments and + implemented obsolete checking again. It look line never ending quest ;-) + (GlobalAttribute.ResolveConstructor): Need to override as the rest. + + * cfold.cs (BinaryFold): TryReduce throws an exception to indicate error. + + * constanct.cs (TryReduce): Throws OverflowException to indicate error. + + *class.cs (Property.Define): Add RegisterProperty call. + + * cs-parser.jay: Replaced ArrayList with fixed array for attribute + argument groups (only 2). + + * ecore.cs (Expression.GetAttributableValue): New virtual method used for + encoding expression to arguments. + (Expression.ExprClassToResolveFlags): Just turned to property. + + * expression.cs (ArrayCreation.ValidateInitializers): Slightly optimized. + (ArrayCreation.GetAttributableValue): Renamed from EncodeAsAttribute and + optimized as well as implemented support for zero-length attributes. + + * typemanager.cs (TypeManager.RegisterProperty, TypeManager.GetProperty): + Add caching of PropertyInfo's. + +2006-02-25 Marek Safar + + * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Don't report + error multiple times. + +2006-02-25 Marek Safar + + New partial class implementation. + A fix for #77027, #77029, #77403 + + * attribute.cs (Attributable): Made attributes protected. + + * class.cs (TypeContainer): Add PartialContainer and partial_parts as + the replacements of ClassPart and PartialContainer. + (TypeContainer.AddClassOrStruct): Call RecordDecl here. + (TypeContainer.AddInterface): Ditto. + (TypeContainer.AddPartial): The main method for partial classes. It checks + for errors and merges ModFlags and attributes. At the end class is added to + partial_parts list. + (TYpeContainer.DefineDefaultConstructor): Checks whether default ctor is + required here. + (TypeContainer.GetClsCompliantAttributeValue): Cope with partial class too. + (TypeContainer.GetNormalPartialBases): Resolves base classes and interfaces + from the rest of partial classes. + (TypeContainer.GetClassBases): Simplified. + (TypeContainer.DefineTypeBuilder): New method, mostly extracted from + DefineType. + (TypeContainer.DefineDefaultConstructor): Is used by derived classes. + (TypeContainer.HasExplicitLayout): Uses Flags now. + (PartialContainer): Removed. + (ClassOrStruct.AddToContainer): Moved enclosing member name check here. + (StaticClass): Was merged with Class. + (Class.GetClassBases): class and static class bases are verified here. + (Class.TypeAttr): Added static attributes when class is static. + (Struct.RegisterFieldForInitialization): Moved from TypeContainer. + (MemberBase): In some cases we need to call parent container for partial + class. It should be eliminated but it's not easy now. + + * cs-parser.jay: Replaced all PartialContainer with AddPartial. + + * decls.cs (MemberCore.DocComment): Introduced new property as is used by + partial classed to accumulate class comments. + (MemberCore.GetClsCompliantAttributeValue): Moved from TypeContainer. + + * doc.cs (GenerateTypeDocComment): Partial classes clean up. + + * driver.cs (MainDriver): Tree.GetDecl was removed. + + * modifiers.cs (Modifiers): Add partial modifier. + + * tree.cs (Tree.decl): Removed. + (RootTypes): Started to use this class more often for root types + specializations. + +2006-02-22 Marek Safar + + A fix for #77615 + + * attribute.cs (AttributeTester.GetCoClassAttribute): Don't crash when + external interface does not have an attribute. + +2006-02-22 Marek Safar + + Another prerequisites for new partial classs implementation. + + * attribute.cs (Attribute.Equal): Implemented. + (Attribute.Emit): Changed as attributes can be applied more than twice. + (Attributes.Emit): Check for duplicate attributes here. + + * class.cs, decl.cs, delegate.cs, doc.cs, enum.cs: Don't pass DeclSpace + as a parameter, clean-up. + +2006-02-11 Marek Safar + + A fix for #77485 + + * class.cs (TypeContainer.DefineType): Cannot use ResolveType because it + contains obsolete attribute check which can in some cases look for base + type of current class which is not initialized yet. + (TypeContainer.BaseType): Replacement of ptype. + + * decl.cs (MemberCore.CheckObsoleteType): Reuse existing code. + +2006-02-11 Marek Safar + + First of prerequisites for new partial classs implemention. + + * attribute.cs (Attributable): Extended by ResolveContext; + Attributes finally have correct context for resolving in all cases. + (AttachTo): Attribute owner is assigned here. + + * codegen.cs (IResolveContext): Introduce new interface to hold + all information needed in resolving phase. + (EmitContext): Implements IResolveContext; more clean-up needed here. + + * decl.cs (MemberCore): Implemented IResolveContext. + + * anonymous.cs, attribute.cs, class.cs, codegen.cs, const.cs, + decl.cs, ecore.cs, enum.cs, expression.cs, iterators.cs, namespace.cs, + parameter.cs, statement.cs, tree.cs, typemanager.cs: + Refactored to use new IResolveContext instead of EmitContext; cleanup + +2006-02-06 Miguel de Icaza + + * codegen.cs (EmitScopeInitFromBlock): check here the + capture_context, there is no need to make two calls to the + EmitContext. + + * anonymous.cs: Add some debugging messages that might help me + track other instances of this problem in the future (the + regression of test 467). + + * cs-parser.jay: track the variable block, as we need to initalize + any captured variables declared in this block for the "catch" + portion of the "Try" statement. + + * statement.cs (Try.Emit): If the "Catch" has a VarBlock, emit any + scope initialization for captured variables. + + Also, move the emit for the variables after the block location has + been marked. + +2006-02-06 Marek Safar + + * ecore.cs (PropertyExpr.FindAccessors): Just made flags const. + +2006-02-02 Miguel de Icaza + + * anonymous.cs (CaptureContext.EmitInitScope): I was wrong in the + commit yesterday, the initialization for the roots is necessary. + What is not necessary is the scope activation. + +2006-02-02 Raja R Harinath + + * ecore.cs (PropertyExpr.DoResolveLValue): Add CS0206 check. + * expression.cs (IndexerAccess.DoResolveLValue): Add CS1612 and + CS0206 checks. + (Argument.Resolve): Remove CS0206 checks. + +2006-02-01 Miguel de Icaza + + * anonymous.cs (CaptureContext.EmitInitScope): Do not emit the + scopes for all the roots, the scopes will now be emitted when the + Blocks are entered. [This change was wrong, fixed on 2006-02-02] + + (CaptureContext.EmitScopeInitFromBlock): Simply emit the ScopeInfo + code. This reduces a lot of existing cruft. + + * statement.cs (Block.Emit): Call EmitScopeInitFromBlock here, so + that the ScopeInfo is generated as we enter the scope, not at the + time of use, which is what we used to do before. + + * codegen.cs (EmitScopeInitFromBlock): New routine, this is called + every time a Block is about to be emitted if we have a + CaptureContext. + +2006-02-01 Raja R Harinath + + * typemanager.cs (NoTypes, NoTypeExprs): Remove. + (Reset): Update. + * *.cs: Use Type.EmptyTypes instead of TypeManager.NoTypes. + + * typemanager.cs (cons_param_array_attribute): Make private. + (Reset): Set it to null. + (InitCoreHelpers): Don't initialize it. + (ConsParamArrayAttribute): New. Initialize it as needed. + * parameter.cs (ParamsParameter.ApplyAttribute): Update to change. + +2006-01-31 Miguel de Icaza + + * expression.cs: There might be errors reported during the + selection of applicable methods. If there are errors, do not + continue execution as it will lead the compiler to crash. + +2006-01-30 Miguel de Icaza + + * expression.cs: Member access is not allowed on anonymous + methods. Fixes #77402. + +2006-01-30 Raja R Harinath + + Fix #77401 + * cs-parser.jay (VariableDeclaration): Don't set + current_array_type to null. + (field_declaration, event_declaration, declaration_statement): + Set it to null here. + +2006-01-28 Raja R Harinath + + * typemanager.cs (GenericParameterPosition): New. + * doc.cs: Use it. + +2006-01-28 Atsushi Enomoto + + * doc.cs : To process "include" elements, first we should create + another list than XmlNodeList, because it could result in node + removal, which could result in that the XmlNodeList gives up + yielding next node. + + (Also made code identical to gmcs again.) + +2006-01-25 Miguel de Icaza + + * ecore.cs: Introduce an error report that we were not catching + before, if not silent, we must report the error. Gonzalo ran into + it. + +2006-01-23 Miguel de Icaza + + A fix for bug: #76957 + + * iterators.cs (MoveNextMethod.CreateMethodHost): call + ComputeMethodHost before creating the method, this is a new + requirement. + + * anonymous.cs (AnonymousContainer): Now we track all the scopes + that this method references (RegisterScope). The actual scope + where the method is hosted is computed with the ComputeMethodHost + before we create the method. + + Moved the Deepest routine here. + + (AnonymousContainer.ComputeMethodHost): New routine used to + compute the proper ScopeInfo that will host the anonymous method. + + (ScopeInfo): Deal with multiple roots. The problem was that we + did not have a unique root where all ScopeInfos could be hanged + from. Remove `topmost' ScopeInfo, and instead keep an arraylist + of roots. + + Remove AdjustMethodScope which is now computed at the end. Remove + LinkScope which did a partial link, instead link all ScopeInfos + before code generation from the new "LinkScopes" routine. + + Simplify all the Add* routines as they no longer need to maintain + the tree, they just need to record that they are using variables + from a ScopeInfo. + + (IsAncestor, GetAncestorScopes, GetParentScope, LinkScope): New + routines to produce the forest of ScopeInfo trees. + + * class.cs (TypeContainer.AppendMethod): This is just like + AddMethod, but ensures that an interface implementation method + (IEnumerable.XXX) is not inserted at the beginning of the queue of + methods, but at the end. + + We use this functionality to ensure that the generated MoveNext + method in the iterator class is resolved/emitted before the + enumerator methods created. + + This is required because the MoveNext method computes the right + ScopeInfo for the method. And the other methods will eventually + need to resolve and fetch information computed from the anonymous + method. + +2006-01-21 Raja R Harinath + Carlos Alberto Cortez + + Fix rest of #76995. + * namespace.cs (NamespaceEntry.UsingExternalAliases): Don't add to + the 'aliases' hash. + (NamespaceEntry.LookupAlias): Lookup 'extern_aliases' hash too. + (NamespaceEntry.VerifyUsing): Resolve external aliases too. + +2006-01-18 Raja R Harinath + + Fix #76656, cs0231-2.cs. + * cs-parser.jay (formal_parameter_list): Make error case catch + more issues. + (parenthesized_expression_0): Add CS1026 check. + (invocation_expression): Remove unused { $$ = lexer.Location }. + +2006-01-17 Raja R Harinath + + Fix #76824. + * cs-parser.jay (statement_expression): Don't list out the + individual statement-expressions. Convert syntax error into + CS0201 check. + +2006-01-16 Raja R Harinath + + Fix #76874. + * ecore.cs (MemberAccess.CheckIntermediateModification): Remove. + (UnboxCast.DoResolveLValue): New. Move CS0445 check from + CheckIntermediateModification. + (FieldExpr.DoResolve): Add new two-argument version that + allows us to resolve the InstanceExpression as an lvalue. + The one-argument variant is now just a wrapper. + (FieldExpr.DoResolveLValue): Use two-argument DoResolve. + Resolve the lhs as an lvalue if the it has a value type. + (FieldExpr.AssignToReadonly): Move CS1648 and CS1650 checks + from Assign.DoResolve. + (PropertyExpr.InstanceResolve): Allow InstanceExpression to be + resolved as an lvalue. + (PropertyExpr.DoResolve): Update. + (PropertyExpr.DoResolveLValue): Resolve the lhs as an lvalue if it + has a value type. Move CS1612 check here from + CheckIntermediateModification. + * assign.cs (Assign.DoResolve): Remove CS1648 and CS1650 checks. + * expression.cs (EmptyExpression.OutAccess): New. Used as the + 'right_side' of a ResolveLValue on an 'out' argument. + (EmptyExpression.LValueMemberAccess): New. Used as the + 'right_side' of a propagated ResolveLValue on a value type. + (LocalVariableReference.DoResolveBase): Recognize + EmptyExpression.OutAccess and EmptyExpression.LValueMemberAccess. + Add CS1654 check. + (Argument.Resolve): Use EmptyExpression.OutAccess rather than + EmptyExpression.Null. + +2006-01-16 Atsushi Enomoto + + * typemanager.cs : added IsGenericParameter(). In mcs it always + return false. + * doc.cs : for generic parameters, use GenericParameterPosition, + not FullName. + +2006-01-12 Ben Maurer + + * expression.cs: Fix Console.WriteLine ((this = x).foo); + +2006-01-12 Miguel de Icaza + + This fixes the problem where we used ldfld instead of ldflda to + load the "THIS" pointer on captured parameters, when THIS is a + value type. See bug #77205. + + * iterators.cs (CapturedThisReference.Emit): Pass false to + EmitThis (we do not need the address). + + * codegen.cs (EmitThis): it needs to know whether we need the + address of `this' or not. This is used by value types. + + * expression.cs (This.AddressOf): Pass true to the EmitThis call, + every other call passes false. + +2006-01-12 Raja R Harinath + + Fix #77221. + * typemanager.cs (TryGetBaseDefinition): Rename from the mis-named + GetOverride. + * expression.cs (Invocation.OverloadResolve): Update. + (Invocation.DoResolve): Avoid double resolution of invocation. + +2006-01-11 Raja R Harinath + + Fix #77180. + * expression.cs (Unary.Emit): When in /checked+ mode, don't emit + unary negation of floating point types as 0-expr; negation cannot + overflow in floating point types. + + Fix #77204. + * expression.cs (MemberAccess.DoResolve): Disallow the use of '.' + on operands of 'void' type. + + Fix #77200. + * cfold.cs (BinaryFold): Implement folding of BinaryOr, BinaryAnd + and ExclusiveOr for boolean constants too. + +2006-01-09 Raja R Harinath + + Fix #75636. + * expression.cs (Invocation.OverloadResolve): Replace reflected + override methods with their base virtual methods, rather than + skipping over them. + * typemanager.cs (TypeManager.GetOverride): New. + +2006-01-05 Jb Evain + + * class.cs (Property.Define, Indexer.Define): do not tag the + properties as SpecialName | RTSpecialName. + +2006-01-04 Miguel de Icaza + + * class.cs (MethodCore.IsDuplicateImplementation): This method was + doing a low-level comparission of parameter types. It was lacking + a check for __argslist. + +2005-12-30 Miguel de Icaza + + * expression.cs (ParameterReference.DoResolveBase): Allow + reference parameters if they are local to this block. + + This allows the ref and out parameters of a delegate to be used in + an anonymous method, for example: + + delegate void set (out int x); + + set s = delegate (out int x){ + x = 0; + }; + + This is used by functionality introduced late in the C# language. + + * anonymous.cs (AnonymousMethod.Compatible): Allow anonymous + method that take ref and out parameters. + + Fixes #77119 which was a late change in the spec. + +2005-12-23 Miguel de Icaza + + * anonymous.cs (ScopeInfo.LinkScope): Do not link the scope to its + parent if its the same scope. Fixes #77060. + +2005-12-21 Miguel de Icaza + + * driver.cs: Report the case of no source files and no -out: + argument provided. + +2005-12-20 Raja R Harinath + + Fix #77035. + * expression.cs (ComposedCast.GetSignatureForError): Define. + +2005-12-18 Carlos Alberto Cortez + + Fix #76995 + + * namespace.cs (NamespaceEntry): Add extern_aliases as a + ListDictionary, to contain the ExternAliasEntry entries (in + addition to the NamespaceEntry.aliases hashtable). This field is + shared between the original entry and its doppelganger (bodyless + copy of it). + (NamespaceEntry.UsingExternalAlias): Add the extern alias entry to + extern_aliases field. + (NamespaceEntry.Lookup): Move the IsImplicit check after the + lookup in extern_aliases. + +2005-12-16 Raja R Harinath + + Fix #77006. + * class.cs (TypeContainer.Mark_HasEquals): New. + (TypeContainer.Mark_HasGetHashCode): New. + (ClassPart): Override them. + (MethodCore.CheckBase): Use them instead of referring to Parent.Methods. + + Fix #77008. + * enum.cs (EnumMember.EnumMember): Pass the parent_enum as the + 'parent' argument to the base constructor. + + Remove all mention of TypeContainer from decl.cs. + * decl.cs (MemberCore.Parent): Change into a DeclSpace. + (MemberCore.MemberCore): Change type of 'parent' argument to DeclSpace. + (DeclSpace.DeclSpace): Likewise. + (DeclSpace.DefineMembers): Remove unused argument. + * cs-parser.jay (pop_current_class): Update to changes. Simplify + debugging check -- we don't care if the debug code throws an + InvalidCastException instead of an InternalErrorException. + * class.cs (TypeContainer.DefineMembers): Update to changes. + (TypeContainer.DoDefineMembers): Likewise. + (TypeContainer.GetMethods): Likewise. + (PropertyMember.Define): Likewise. + (MemberBase.Parent): New property that forwards to + MemberCore.Parent, but ensures that we get a TypeContainer. + * rootcontext.cs (RootContext.PopulateCoreType): Update to changes. + (RootContext.PopulateTypes): Likewise. Remove special case code + for !RootContext.StdLib: DefineMembers is idempotent. + +2005-12-14 Miguel de Icaza + + * convert.cs (ExplicitConversionCore): Check the return value from + ExplicitConversionCore which can return null on failure. Fixes #76914 + +2005-12-13 Marek Safar + + * class.cs (Method.ApplyAttributeBuilder): Test out modifier properly. + +2005-12-11 Atsushi Enomoto + + * doc.cs : The search for referenced namespace was insufficient to + get global one as it used to do. Fixed bug #76965. + +2005-12-10 Atsushi Enomoto + + * doc.cs : check name in cref in the last phase that whether it is + namespace or not. + +2005-12-09 Atsushi Enomoto + + * cs-tokenizer.cs : reverted the latest change: it somehow broke + Mono.C5. + +2005-12-09 Atsushi Enomoto + + * doc.cs : so it turned out that we cannot skip override check for + interface members. Fixed bug #76954. + +2005-12-09 Atsushi Enomoto + + * cs-tokenizer.cs : fixed bug #75984: + - #warning and #error should not be handled when the source line + is disabled. + - #line is not checked strictly when the source line is disabled. + - #define and #undef is on the other hand checked strictly at any + state. + +2005-12-08 Atsushi Enomoto + + * cs-tokenizer.cs : missing Location (actually, filename) in one of + CS1027 report. + +2005-12-05 Marek Safar + + * attribute.cs (GlobalAttribute.ctor): Pass NamespaceEntry only. + + * class.cs (EmitFieldInitializers): Simplified and fixed to work with + event initializers. + (FieldBase.EmitInitializer): Moved from TypeContainer and simplified. + (FieldBase.Initializer): Initializer is now optional. + (EventField.Define): Only event field can have initializer. + + * codegen.cs (EmitContext): DeclSpace is not readonly (small hack). + + * const.cs (Const): Reuse initializer. + + * cs-parser.jay: Updated after FieldBase changes. + Added current_array_type to simplify array initializers. + + * ecore.cs (NullCast.IsDefaultValue): Implemented. + + * expression.cs, iterators.cs: Updated. + + * namespace.cs (NamespaceEntry): Made UsingFound private. + +2005-12-05 Marek Safar + + * parameterCollection.cs: Obsolete, removed. + * parser.cs: Obsolete, removed. + +2005-12-05 Marek Safar + + Fix #76849. + * class.cs (Constructor.Emit): Set obsolete checking for whole context. + + * enum.cs (Enum.Define): Set obsolete context here. + +2005-12-05 Atsushi Enomoto + + * doc.cs : + - FindDocumentedMember() now expects 1) paramList as null + when "we don't have to check the number of parameters" and + 2) Type.EmptyTypes when "there is no arguments". + - Introduced FoundMember struct to hold the exact type which was + used to find the documented member (the above change broke + test-xml-044; it might be better just to use DeclaringType than + what MS does, like this change does, but it depends on usage.) + +2005-12-05 Atsushi Enomoto + + * doc.cs : documented member might be from DeclaringType for nested + types. Fixed bug #76782. + +2005-12-03 Ben Maurer + + * anonymous.cs: Have the param code handle leaving copies on the + stack etc. Allows anonymous params to take part in the assignment + code (++, +=, etc). Fixes bug #76550 + + * expression.cs: Handle the prepare_for_load/leave_copy by passing + it down to the anon code. + + * iterators.cs: Use dummy var here + + * codegen.cs: Handle new vars + +2005-12-01 Marek Safar + + Fix #76849. + * class.cs (MethodData.Define): Set proper Obsolete context. + + * ecore.cs (FieldExpr.ResolveMemberAccess): Don't check [Obsolete] in + obsolete context. + (FieldExpr.DoResolve): Ditto. + +2005-12-01 Marek Safar + + Fix #76849. + * class.cs (MethodCore.DoDefineParameters): Test [Obsolete] only when + parent is not obsolete. + +2005-12-01 Atsushi Enomoto + + * doc.cs : (FindDocumentedMember) find parameterless members first + and get CS0419 in the early stage. Fixed first case of bug #76727. + +2005-11-30 Marek Safar + + Fix #76859. + * ecore.cs (Expression.ResolveAsConstant): Report constant error only when + no error was reported. + + *expression.cs (Binary.DoResolve): left can be null. + +2005-11-22 Marek Safar + + Fix #76783. + * class.cs (MethodData.Emit): Parameters should be labeled first. + +2005-11-21 Marek Safar + + Fix #76761. + * parameter.cs (Parameter.ApplyAttributeBuilder): Fixed `ref' detection. + +2005-11-18 Marek Safar + + * attribute.cs (AreParametersCompliant): Moved to Parameter. + + * class.cs (MethodCore): Parameter clean up. + (IMethodData): Added ParameterInfo. + (MethodData): Parameter clean up. + (Indexer.Define): Parameter clean up. + + * anonymous.cs, + * codegen.cs, + * cs-parser.jay, + * decl.cs, + * doc.cs, + * ecore.cs, + * flowanalysis.cs, + * iterators.cs, + * pending.cs, + * statement.cs, + * typemanager.cs: Parameter clean up. + + * delegate.cs (Define): Get rid of duplicated code. + + * expression.cs (ParameterReference): Removed useless parameters + and simplified. + (Invocation): Ditto. + + * parameter.cs (ParamsParameter): New class, params specialization. + (ArglistParameter): Attemp to separate arglist. + (Parameter): Refactored to be reusable and faster. + (Parameter.Modifier): Made understandable. + (Parameters): Changed to be used as a class for `this' assembly + parameters. Refactored to use new specialized classes. + + * support.cs (ParameterData): Added Types property. + (InternalParameters): Deleted. + +2005-08-20 Martin Baulig + + Merging this patch from GMCS to fix #75867. + + * anonymous.cs (CaptureContext.CaptureThis): Create the topmost + scope if we don't already have it. + +2005-11-17 Martin Baulig + + * anonymous.cs + (CaptureContext.EmitMethodHostInstance): Use `Ldarg_0' if we + inherit the scope from our parent. Fixes #76653. + +2005-11-16 Atsushi Enomoto + + * doc.cs : the previous patch does not actually fix the bug. + PropertyInfo override check is now implemented and really fixed it. + * expression.cs : Invocation.IsAncestralType() is used from doc.cs. + +2005-11-16 Atsushi Enomoto + + * doc.cs : apply "override filter" also to properties. + Fixed bug #76730. + +2005-11-16 Atsushi Enomoto + + * doc.cs : renamed FindMembers() to FindMethodBase(). For interfaces, + no need to check overrides. For classes, omit those results from + interfaces since they must exist in the class. Fixed bug #76726. + +2005-11-15 Atsushi Enomoto + + * typemanager.cs : (GetFullNameSignature) differentiate indexers + with different parameters. Fixed the second problem in #76685. + +2005-11-15 Atsushi Enomoto + + * doc.cs : (FindDocumentedMember) pass invocation_type as well (to + get expected 'protected' access in CheckValidFamilyAccess()). + Fixed bug #76692. + +2005-11-15 Atsushi Enomoto + + * doc.cs : (GenerateTypeDocComment) Fields could be FixedField. + Fixed bug #76705. CS1569 was incorrectly commented out. + +2005-11-14 Atsushi Enomoto + + * doc.cs : use Invocation.IsOverride() to do real override check. + * expression.cs : made Invocation.IsOverride() internal. + +2005-11-14 Atsushi Enomoto + + * doc.cs : use TypeManager.FindMembers() instead of (possible) + TypeBuilder.FindMembers() and filter overriden base members out. + Fixed bug #76990. + +2005-11-13 Atsushi Enomoto + + * doc.cs : ref/out parameters are represented as '@' (instead of + '&' in type FullName). Fixed bug #76630 (additionally crefs). + +2005-11-13 Atsushi Enomoto + + * doc.cs : when there was no '.' in cref to methods in doc comment, + then parameters were missing in the output. Fixed bug #76691. + +2005-11-13 Atsushi Enomoto + + * driver.cs : don't output docs when there is an error. + Fixed bug #76693. + +2005-11-13 Atsushi Enomoto + + * doc.cs : + Now it should detect indexers. Fixed primary concern in bug #76685. + Fixed CS0419 message to not show the identical member signature in + the message. + +2005-11-13 Atsushi Enomoto + + * doc.cs : (FindDocumentedMember) use TypeManager.MemberLookup() + instead of Type.FindMembers() since it does not handle events. + Fixed bug #71604. + +2005-11-12 Gert Driesen + + * codegen.cs: Fixed typo (speficied -> specified). + +2005-11-11 Marek Safar + + Fix #76369. + * doc.cs (FindDocumentedTypeNonArray): Don't resolve again. + +2005-11-11 Marek Safar + + * attribute.cs: Changed error message. + + * cs-tokenizer.cs: One more check. + +2005-11-10 Marek Safar + + * statement.cs (Block.Resolve): Ignore empty statement. + +2005-11-10 Marek Safar + + * report.cs: Made error/warning methods more strict to avoid + their misuse. + + * anonymous.cs, attribute.cs, class.cs, codegen.cs, constant.cs, + convert.cs, cs-parser.jay, cs-tokenizer.cs, decl.cs, delegate.cs, + doc.cs, driver.cs, ecore.cs, expression.cs, location.cs, + namespace.cs, parameter.cs, statement.cs, typemanager.cs: Updated. + +2005-11-08 Marek Safar + + * attribute.cs (Attribute.GetCoClassAttributeValue): New method. + (AttributeTester.GetCoClassAttribute): Get CoClassAttribute. + + * class.cs (TypeContainer.IsComImport): New property. + (Constructor.Define): Create proper ctor for ComImport types. + + * expression.cs (New.CheckComImport): Fixed. + +2005-11-07 Miguel de Icaza + + * anonymous.cs (CaptureContext.AddParameterToContext): The fact + that a parameter has been captured does not mean that we do not + have to do the rest of the processing. This fixes the second part + of #76592. If there was another anonymous method capturing + values in the past, the Scope would never be set for the second + method that captured the same parameter. + + (CaptureContext.EmitAssignParameter): When `leave_copy' is passed, + properly manipulate the stack. Second part of fix for #76592. + + * expression.cs (New): Add support for invoking "new" on + interfaces that have been flagged with the ComImport attribute and + the CoClass. Fixes #76637 + + * statement.cs (Try.DoEmit): When a variable is captured, do not + try to emit the vi.LocalBuilder variable as it has been captured. + Create a temporary variable and store the results on the + FieldBuilder. Fixes #76642 + +2005-11-07 Marek Safar + + * class.cs (CheckPairedOperators): Made compilable with csc 2.0. + + * ecore.cs (InstanceResolve): Fixed CS1540 detection. + + * expression.cs (Binary.DoResolve): Added && optimalization. + + * typemanager.cs (AddUserType): Removed useless argument. + +2005-11-04 Marek Safar + + * statement.cs (Block.variables): Uses ListDictionary. + +2005-11-03 Marek Safar + + Fix #75969. + * class.cs (PartialContainer.EmitType): Customized to emit + security attributes. + (ClassPart.ApplyAttributeBuilder): Transform security attribute + for partial classes. + +2005-11-03 Marek Safar + + Fix #76599. + * expression.cs (ElementAccess.DoResolveLValue): Fixed buffer + access has to be fixed. + + * typemanager.cs (IsUnmanagedType): Wrong common field type. + +2005-11-01 Marek Safar + + Fix #76590. + * ecore.cs (NullCast.Reduce): Implemented. + + * expression.cs (ArrayCreation.CheckIndices): Correcly check + constant type. + + * statement.cs (SwitchLabel.ResolveAndReduce): Catch null + properly. + (Foreach.Resolve): Catch null properly. + +2005-10-29 Marek Safar + + * cs-tokenizer.cs: Warning text fix. + + * driver.cs: AllWarningNumbers exposed on public interface. + + * report.cs (): Reviewed warning numbers. + (IsValidWarning): Use binary search. + +2005-10-29 Marek Safar + + * driver.cs: Implemeted resource visibility. + (Resources): New class for code sharing between /res: and + /linkres: + +2005-10-28 Marek Safar + + Fix #76568. + * cfold.cs (ConstantFold.BinaryFold): Implemented null cast + folding. + + * convert (Convert.ImplicitReferenceConversion): NullCast holds + contants only. + + * ecore.cs (NullCast): Child is contant only. + + * literal.cs (NullLiteral.Reduce): null can be converted to any + reference type. + +2005-10-28 Kornél Pál + + * driver.cs: Use Encoding.Default as default code page instead + of ISO-28591. + +2005-10-27 Raja R Harinath + + Fix #76085. + * expression.cs (Invocation.Error_InvalidArguments): Handle + __arglist parameters. + (Invocation.VerifyArgumentsCompat): Likewise. + * support.cs (ReflectionParameters.GetSignatureForError): Print + __arglist parameters. + (InternalParamters.GetSignatureForError): Likewise. + * parameter.cs (Parameters.GetSignatureForError): Likewise. + +2005-10-26 Marek Safar + + * attribute.cs (GetPropertyValue): Made public. + + * codegen.cs (AssemblyClass): ResolveClsCompliance renamed to + Resolve. + Add new property WrapNonExceptionThrows to handle 2.0 assembly + attribute. + (AssemblyClass.Emit): Emit RuntimeCompatibilityAttribute when it + is not defined. + + * driver.cs: Reflect method name change. + + * statement.cs (Try.Resolve): Warn when try has both general + exception handlers. + + * typemanager.cs: runtime_compatibility_attr_type new predefined + type. + +2005-10-26 Raja R Harinath + + Fix #76419. + * pending.cs (InterfaceMethod): Allow tm.args [i] to be null -- + treat it as an empty parameter list. + +2005-10-26 Raja R Harinath + + Fix #76271. + * ecore.cs (SimpleName.DoSimpleNameResolve): Make fall-back + ResolveAsTypeStep silent. + * statement.cs (Block.AddConstant): Mark block as used. + (Block.ResolveMeta): Avoid piling on error messages + if a constant initializer resolution fails. + +2005-10-25 Raja R Harinath + + * namespace.cs (RootNamespace.VerifyUsingForAll, Namespace.VerifyUsing): + Remove. + (NamespaceEntry.VerifyAllUsing): New. + (NamespaceEntry.AliasEntry.Resolve): New. Handles common error + behaviour. Delegates actual resolution of alias to ... + (NamespaceEntry.DoResolve): ... this. Renamed from Resolve. + (NamespaceEntry.LocalAliasEntry, NamespaceEntry.ExternAliasEntry): + Update. + * driver.cs (Driver.MainDriver): Update. + + * namespace.cs (NamespaceEntry.DefineNamespace): Remove. + (NamespaceEntry.SymbolFileID): Make into a on-demand computed + property. + (Namespace.DefineNamespaces, RootNamespace.DefineNamespacesForAll): + Remove. + * symbolwriter.cs (SymbolWriter.Initialize): Don't call + RootNamespace.DefineNamespacesForAll. + +2005-10-24 Raja R Harinath + + * typemanager.cs (assemblies, external_aliases, modules) + (AddAssembly, AddExternAlias, AddModule GetAssemblies, Modules) + (ComputeNamespaces, GetRootNamespace): Remove extra staging + overhead. Move resposibility ... + * namespace.cs (GlobalRootNamespace): ... here. Update to changes. + * driver.cs, attribute.cs, codegen.cs: Update to changes. + +2005-10-23 Raja R Harinath + + * namespace.cs (RootNamespace.all_namespaces): Renamed from + cached_namespaces. Improve usage. + (RootNamespace.Reset, RootNamespace.RegisterNamespace) + (RootNamespace.VerifyUsingForAll, RootNamespace.DefineNamespacesForAll): + Move from GlobalRootNamespace and simplify. + (RootNamespace.Global): Make instance variable. + (RootNamespace.RootNamespace): Add "alias name" parameter. + (GlobalRootNamespace): Simplify drastically. + (Namespace.Lookup): Don't use GetNamespace. + * typemanager.cs (GetRootNamespace): Rename from + ComputeNamespaceForAlias. + (NamespaceClash): Use Global.IsNamespace instead of GetNamespace. + +2005-10-23 Marek Safar + + * anonymous.cs (AnonymousContainer): Don't crash when container + doesn't exist. + +2005-10-23 Marek Safar + + * expression.cs (Binary.DoResolve): Warn when comparing same + values. + +2005-10-23 Marek Safar + + Fix #76486. + * expression.cs (Binary.DoResolve): It looks like there are no + convetsion rules in enum context. + +2005-10-19 Carlos Alberto Cortez + + Add support for extern alias qualifiers. + * typemanager.cs: Move some LookupTypeReflection code + to namespace.cs, to have cleaner code. Added some methods + to help us keep track of the extern aliased references. + * driver.cs: Add suport for extern alias assemblies on command + line and check for their warnings/errors. Also keep track of the + extern aliased assemblies. + * namespace.cs: Move the global functionality of Namespace + to GlobalRootNamespace/RootNamespace. Now the global namespace + is GlobalRootNamespace.Globa. Also the code moved from + typemanager.cs lives in GlobalRootNames.cs/RootNamespace.cs. + Finally added LocalAliasEntry (AliasEntry before) and + ExternAliasEntry, to handle alias statements. + * cs-parser.jay: Add support in the grammar for extern alias + statement. + * doc.cs, delegate.cs, expression.cs ecore.cs, symbolwriter.cs: + Update callings to Namespace (now in GlobalRootNamespace). + +2005-10-18 Raja R Harinath + + Fix #76371. + * class.cs (TypeContainer.DefineType): Move updating of + topological sort earlier in the code. + * decl.cs (DeclSpace.ResolveBaseTypeExpr): Don't use TypeBuilder. + +2005-10-18 Marek Safar + + Fix #76273. + * cfold.cs (BinaryFold): Reduce constant in enum conversion. + + * constant.cs (Constant.TryReduce): Moved from Cast class. + (Reduce): Made little bit more OO and fixed missing conversions. + + * ecore.cs (Reduce): Implemented. + (Binary.EnumLiftUp): New method to upgrade values to enum values. + + * literal.cs (Reduce): Implemented. + + * class.cs: Reverted Miguel's wrong commit. + +2005-10-14 Miguel de Icaza + + * ecore.cs (GetMemberType): Report the correct mapping for the MemberCore + +2005-10-14 Atsushi Enomoto + + * cs-parser.jay, expression.cs : CS0214 was missing error location + for constants. Fixed bug #76404. + +2005-10-11 Marek Safar + + Fix #76370. + * convert.cs (ExplicitConversionCore): Fixed object->enum + conversion. + +2005-10-10 Raja R Harinath + + * ecore.cs (PropertyExpr.Emit): Use Invocation.EmitCall to emit + InstanceExpression. + (PropertyExpr.EmitCall): Likewise. + * expression.cs (Invocation.EmitArguments): Handle case where + arguments == null. + (Invocation.EmitCall): Avoid allocating temporary variable if + there are no arguments. + +2005-10-07 Raja R Harinath + + Fix #76323. + * convert.cs (ImplicitConversionStandard): Move conversion of + void* to arbitrary pointer types ... + (ExplicitConversionStandard): .. here. + * ecore.cs (Expression.Error_ValueCannotBeConverted): Fix CS0266 + error to always print typenames. + +2005-10-07 Raja R Harinath + + * convert.cs (GetConversionOperator): Rename from + GetConversionOperators. Move operator selection code from ... + (UserDefinedConversion): ... here. + +2005-10-06 Marek Safar + + * convert.cs (ExplicitConversionCore): Removed duplicate enum + conversion. + +2005-10-05 Marek Safar + + * assign.cs (Assign.DoResolve): Error method changed. + + * cfold.cs (DoConstantNumericPromotions): Error method changed. + + * const.cs (ResolveValue): Reset in_transit immediately. + + * constant.cs: Error method changed. + + * convert.cs: Removed useless location parameter. + (ExplicitNumericConversion): Don't do double enum check. + (ExplicitConversionCore): Renamed from ExplicitConversion. + (ExplicitUnsafe): Extracted from ExplicitConversion. + (ExplicitConversion): Uses for error reporting. + + * ecore.cs (Error_ValueCannotBeConverted): More logic for more + error messages. + (ResolveBoolean): Uses common error method. + (CastToDecimal): Get rid of ec. + (CastFromDecimal): Optimized. + (ConvCast): Get rid of ec. + + * enum.cs (ResolveValue): Reset in_transit immediately. + (Emit): Return after first error. + + * expression.cs: Convert changes. + + * literal.cs: Error method changed. + + * statement.cs: Error method changed. + +2005-10-03 Raja R Harinath + + * support.cs (SeekableStreamReader.Position): Don't error out when + the requested position is just beyond the end of the current + buffered data. + +2005-09-28 Raja R Harinath + + * support.cs (SeekableStreamReader): Simplify drastically. Don't + try to keep in sync with the byte count of the underlying Stream. + However, this limits us to a window size of 2048 characters: i.e., + the maximum lookahead of our lexer/parser can be 2048 characters. + +2005-09-28 Marek Safar + + Fix #76255. + * driver.cs: Fix compilation files with full root path. + +2005-09-25 Miguel de Icaza + + * report.cs (SymbolRelatedToPreviousError): Format the output so + it does not use an open parenthesis that is never closed. + + * driver.cs: Follow coding guidelines + +2005-09-27 Marek Safar + + Fix #72930. + * const.cs (Const.ResolveValue): Check for assigning non-null + value to reference type. + +2005-09-27 Marek Safar + + * anonymous.cs: Implemented ExprClassName. + + * assign.cs (Assign.DoResolve): Don't chrash when type is not + delegate. + + * attribute.cs (ResolveArguments): Enabled MethodImplOptions + check. + + * class.cs (StaticClass.DefineContainerMembers): Report protected + members as error. + + * codegen.cs: if(ed) PRODUCTION. + + * convert.cs (Error_CannotImplicitConversion): Better error + distinction. + + * cs-parser.jay: More error checks. + + * cs-tokenizer.cs (consume_identifier): Fixed Miguel's revert. + + * driver.cs (CSCParseOption): Enabled wrong option check. + + * ecore.cs (Expression.ExprClassName): Turned to property. + (MemberExpr.CheckIntermediateModification): For checking boxed + value types modification. + + * statement.cs (Fixed.Resolve): Expression type must be + convertible to fixed type. + (CollectionForeach.GetEnumeratorFilter,TryType): + Small refactoring for easier error checking. + +2005-09-26 Marek Safar + + * attribute.cs (Attribute.Resolve): Check Obsolete attribute for + attributes. + + * class.cs (GeneratedBaseInitializer): New class for customization + compiler generated initializers. + (MemberBase.DoDefine): Check Obsolete attribute here. + (FieldMember.DoDefine): Ditto. + + * const.cs (ExternalConstant.CreateDecimal): Builder for decimal + constants. + + * decl.cs (MemberCore.EmitContext): Returns valid current ec. + (MemberCore.GetObsoleteAttribute): Removed argument. + (MemberCore.CheckObsoleteness): Obsolete attributes are hierarchic. + (MemberCore.CheckObsoleteType): New helper. + + * delegate.cs, + * enum.cs, + * statement.cs: Updates after MemberCore changes. + + * ecore.cs (TypeExpr.ResolveType): Check type obsoleteness here. + (FieldExpr.ResolveMemberAccess): Fixed decimal constants checks. + + * expression.cs (ComposedCast.DoResolveAsTypeStep): Don't check + obsolete attribute for compiler construct. + (As.DoResolve): Cache result. + + * iterators.cs (Define_Constructor): Use GeneratedBaseInitializer. + +2005-09-26 Raja R Harinath + + Fix #76133. + * expression.cs (This.VerifyFixed): In a value type T, the type of + 'this' is T&, iow, 'this' is either an out or ref parameter. In a + value type R, 'this' is treated as a value parameter. + +2005-09-22 Miguel de Icaza + + * statement.cs (Lock): Use the TemporaryVariable class instead of + manually using local variables as those do not work when variables + are captured. + + * ecore.cs: Moved the TemporaryVariable class from being a nested + class inside Foreach to be a public class that can be employed in + other places. + +2005-09-19 Marek Safar + + * cs-parser.jay: interface_accessors replaced by + accessor_declarations. + + * ecore.cs, literal.cs, statement.cs: NullLiteral holds null + location. + + * statement.cs (GotoCase.Resolve): Convert null constant to + null case. + (SwitchLabel.ResolveAndReduce): Ditto. + (SwitchLabel.NullStringCase): Custom null stamp. + (Switch.SimpleSwitchEmit): Fix from NullLiteral to NullStringCase. + + typemanager.cs (CSharpSignature): Don't skip first argument + for full names. + +2005-09-18 Miguel de Icaza + + * driver.cs: Set InEmacs based on the environment variable EMACS. + + * location.cs (InEmacs): in this mode, do not report column + location as it confuses Emacs. + +2005-09-16 Marek Safar + + * cfold.cs, constant.cs, convert.cs, ecore.cs, + expression.cs, iterators.cs, literal.cs: Store constants and + literals location. + + * class.cs (MemberBase.ShortName): Pass location. + + * cs-parser.jay: Some location fixes. + + * ecore.cs (Expression.Location): Made virtual. + +2005-09-05 Miguel de Icaza + + * expression.cs (Cast.TryReduce): Only reduce to an EnumConstant + if the underlying types are the same, otherwise we need to produce + code that will do the proper cast. + + This was exposed by Marek's constant rewrite which produced + invalid code for the call site: + + enum X : long { a } + void Method (X v) {} + + Method ((X) 5) + + This fixes test-49.cs + +2005-09-05 Atsushi Enomoto + + * attribute.cs : (Attribute.IsValidArgumentType): array of string/ + Type/Object should be allowed as well. Fixed bug #75968. + +2005-09-05 Atsushi Enomoto + + * expression.cs : (Binary.DoResolve): when one is enum constant and + another is constant 0, then return enum one *as enum type*. + Fixed bug 74846. + +2005-09-02 Raja R Harinath + + * attribute.cs (GetMarshal): Work even if "DefineCustom" is + internal. + + Fix #75941. + * ecore.cs (SimpleNameResolve.DoSimpleNameResolve): Disable + flow-branching for LocalVariableReferences in case we were invoked + from a MemberAccess. + * expression.cs (LocalVariableReference.VerifyAssigned): New. + Carved out of ... + (LocalVariableReference.DoResolveBase): ... this. + (MemberAccess.Resolve): Do the check that was disabled during + SimpleNameResolve. + +2005-09-01 Atsushi Enomoto + + * class.cs : + (PartialContainer.Create): check abstract/sealed/static strictly + but abstract/sealed can exist only at one side. Fixed bug #75883. + +2005-09-01 Kornél Pál + + Fix #75945. + * attribute.cs (Attribute.GetMarshal): If ArraySubType is not + specified, don't default to UnmanagedType.I4. + +2005-09-01 Atsushi Enomoto + + * expression.cs : conditional operator should check possibly + incorrect assign expression. Fixed bug #75946. + +2005-08-31 Atsushi Enomoto + + * cs-tokenizer.cs, cs-parser.jay, driver.cs, support.cs : + Reverting the change. gmcs is much complex than mcs on this matter. + +2005-08-31 Atsushi Enomoto + + * cs-tokenizer.cs : To read another token ahead of the actual + consumption, use new SavedToken and cache token instead of moving + back the stream with SeekableStreamReader (it seemed problematic). + * cs-parser.jay, + driver.cs : Thus use StreamReader directly. + * support.cs : Thus removed SeekableStreamReader. + +2005-08-30 Raja R Harinath + + Fix #75934. + * anonymous.cs (ScopeInfo.MakeFieldName): New helper. + (ScopeInfo.EmitScopeType): Use it to construct field names from + names of captured locals. + + Fix #75929. + * ecore.cs (BoxedCast.BoxedCast) [1-argument variant]: Remove. + * convert.cs (ImplicitReferenceConversion, TryImplicitIntConversion): + Pass 'target_type' to BoxedCast. Don't default to 'object'. + (ExplicitConversion): Remove enum cases already handled by + implicit conversion. Move implicit conversion check to the beginning. + * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Update. + * expression.cs (ArrayCreation.EmitDynamicInitializers): + Don't treat System.Enum as a struct. + +2005-08-30 Jb Evain + + * attribute.cs: handles as expression in parameters. + +2005-08-30 Raja R Harinath + + Fix #75802. + * class.cs (TypeContainer.VerifyClsName): Don't use a + PartialContainer when verifying CLS compliance. + (AbstractPropertyEventMethod): Set Parent here, ... + (PropertyMethod): ... not here. + +2005-08-30 Atsushi Enomoto + + * attribute.cs : escaped attribute name should not be allowed to be + resolved (e.g. @class as classAttribute). Fixed bug #75930. + +2005-08-29 Raja R Harinath + + Fix #75927. + * convert.cs (ImplicitStandardConversionExists): Allow zero also + when converting a long constant to unsigned long. + * expression.cs (Invocation.OverloadResolve): Add sanity check to + detect where IsApplicable and VerifyArgumentsCompat disagree. + +2005-08-29 Raja R Harinath + and Carlos Alberto Cortez + + Fix #75848. + * class.cs (TypeContainer.CanElideInitializer): New helper. + (TypeContainer.EmitFieldInitializers): Use it to determine if we + can safely emitting the initializer of a field. + +2005-08-25 Atsushi Enomoto + + * statement.cs : (Continue.Resolve()) Unlike break, continue is not + allowed inside a switch (without loop). Fixed bug #75433. + +2005-08-26 Kornél Pál + + * AssemblyInfo.cs: Using Consts.MonoVersion instead of MonoVersion.cs. + * mcs.exe.sources: Using Consts.MonoVersion instead of MonoVersion.cs. + +2005-08-25 Atsushi Enomoto + + * driver.cs : kinda reverting the default encoding changes (not exact + revert since I noticed that "codepage:reset" might not work fine). + +2005-08-25 Atsushi Enomoto + + * class.cs : (AbstractPropertyEventMethod) SetupName() now takes + Location. Now getter and setter store location correctly. + (errors/cs0111-12.cs now reports the expected location.) + +2005-08-25 Atsushi Enomoto + + * driver.cs : Use default encoding on the environment. + Removed (now that) extra parameter for SeekableStreamReader. + * support.cs : (SeekableStreamReader) third .ctor() argument for + StreamReader is not required (always true). preamble size could + be acquired in simpler and safe way. + +2005-08-24 Atsushi Enomoto + + * cs-parser.jay: report CS0642 at warning level 3 + and report CS0642 for an if else statement also + fixes bug #74745. Patch by John Luke (and a bit + modified by me). + Removed extra CS0642 warning check for "while", + "for" and "fixed". + * statement.cs: In Block.Resolve(), CS0642 check + is reimplemented to check a sequence of an empty + statement and a block. + + Both fix bug #66777. + +2005-08-24 Marek Safar + + * attribute.cs (GetMethodObsoleteAttribute): Disabled obsolete properties + detection until I fix it. + + * cs-tokenizer.cs: Changed error message. + + * cs-parser.jay: Fixed 2 error locations. + + * ecore.cs (Error_TypeDoesNotContainDefinition): Share error message. + (PropertyExpr.Error_PropertyNotFound): First attempt to detect non C# + properties. + + * enum.cs (GetSignatureForError): Fixed. + + * expression.cs (Invocation.IsSpecialMethodInvocation): Improved special + method detection. + + * class.cs, + * typemanager.cs (RegisterProperty): Removed. + + * statement.cs (CheckInvariantMeaningInBlock): Changed error message. + +2005-08-24 Raja R Harinath + + Fix #75874. + * expression.cs (ArrayAccess.EmitLoadOpcode): Emit ldelem.i for pointers. + (ArrayAccess.GetStoreOpcode): Return stelem.i for pointers. + +2005-08-23 Atsushi Enomoto + + * expression.cs : tiny fix is required for not warning positive ulong. + See test-441.cs. + +2005-08-23 Atsushi Enomoto + + * expression.cs : add CS0652 check for constant and integral + expression. Fixed bug #53974. + +2005-08-23 Atsushi Enomoto + + * expression.cs : in DoNumericPromotions(), check if there is implicit + conversion overload for string (to check CS0034). Fixed bug #52492. + +2005-08-23 Atsushi Enomoto + + * cs-tokenizer.cs : Check newline in char constant. Fixed bug #75245. + +2005-08-23 Atsushi Enomoto + + * ecore.cs : report location when it is *not* Null. + +2005-08-23 Atsushi Enomoto + + * codegen.cs, + ecore.cs, + flowanalysis.cs, + expression.cs: + Added OmitStructFlowAnalysis to EmitContext to handle CS0165 check + correctly. Fixed bug #75721. + +2005-08-23 Raja R Harinath + + * support.cs (SeekableStreamReader.Position): Avoid an expensive + loop that performs 'min (pos, char_count)'. + + Fix #75862. + * expression.cs (Unary.ResolveOperator): Don't discard implicit + converted value in Operator.OnesComplement. + +2005-08-22 Ben Maurer + + * anonymous.cs: If the anon method is pulled into a helper class, + it needs to be `internal' not `private'. Fixes runtime behavior on + msft. bug #75704 + +2005-08-20 Martin Baulig + + * anonymous.cs (CaptureContext.CaptureThis): Create the topmost + scope if we don't already have it. + + * expression.cs (Invocation.EmitCall): Use `ec.EmitThis ()' rather + than `ig.Emit (OpCodes.Ldarg_0)' to make it work inside iterators; + fixes #75867. + +2005-08-17 Marek Safar + + Fix #75803 + * decl.cs (DeclSpace.VerifyClsCompliance): Skip when collision object + is a partial class. + +2005-08-16 Marek Safar + + The big constants rewrite + Fix #75746, #75685 and more + As a side effect saved 1MB for MWF ;-) + + * attribute.cs (GetAttributeArgumentExpression): Use ToType, GetTypedValue. + (GetMarshal, GetMethodImplOptions, GetLayoutKindValue): Values are not + enum based for corlib compilation. + + * cfold.cs (BinaryFold): Convert operand for enum additions. Fixed enum + subtractions. + + * class.cs (FixedField.Define): Use ResolveAsConstant. + + * const.cs (IConstant): Interface constants and enums. + (Const.ResolveValue): New method for constant resolvning. + (ExternalConstant): Constants from imported assemblies. + + * constant.cs (Constant.GetTypedValue): Used to get constant with forced + conversion; like enums. + (Constant.ToType): Converts this constant to different type. + (Constant.Increment): Adds 1. + + * convert.cs (ImplicitConversionRequired): Simplified. + + * cs-parser.jay: Create EnumMember directly. + + * decl.cs (MemberCore.CheckObsoleteness): Checks for ObsoleteAttribute presence. + + * doc.cs (GenerateEnumDocComment): Removed. + + * ecore.cs (Expression.ResolveAsConstant): New constant specific method. + (ConvertIntLiteral): Removed. + (FieldExpr.ResolveMemberAccess): Refactored to remove constant specific if(s). + + * enum.cs (EnumMember): Implement IConstant. + (Enum.IsValidEnumConstant): Removed. + (Enum.GetNextDefaultValue): Removed. + (Enum.FindMembers): Updated. + (Enum.GenerateDocComment): Iterate enum members. + + * expression.cs (Cast.TryReduce): Handle enums correctly. + (New.Constantify): Made public. + (MemberAccess.DoResolve): Removed contant specific if(s). + + * literal.cs (NullLiteral): Implement new abstract methods. + + * statement.cs (GotoCase.Resolve): Use new constant methods. + (SwitchLabel.ResolveAndReduce): Use new constant methods. + + * typemanager.cs (LookupEnum): Removed. + (IsEnumType): Fixed to work with corlib. + (RegisterConstant): Removed. + (LookupConstant): Removed. + (GetConstant): Changed to work with IConstant. + +2005-08-04 Atsushi Enomoto + + * location.cs : Fixed overflown (>255) column number. + +2005-08-03 Raja R Harinath + + First cut of the qualified-alias-member feature. + * cs-tokenizer.cs (Tokenizer.is_punct): Recognize the double-colon + token. + * cs-parser.jay (DOUBLE_COLON): New token. + (namespace_or_type_name): Add rule for recognizing + qualified-alias-members. + (primary_expression): Likewise. + (element_access): Allow QualifiedAliasMember as a possible + type-bearing expression. + (local_variable_type, local_variable_pointer_type): Likewise. + * namespace.cs (NamespaceEntry.LookupAlias): New. Looks up + aliases in the current and enclosing namespace declarations. + (NamespaceEntry.UsingAlias): Add CS0440 warning. + * decl.cs (MemberName.is_double_colon): New. + (MemberName.MemberName): Add new constructor for alias-member. + (MemberName.GetTypeExpression): Generate QualifiedAliasMember too. + * expression.cs (QualifiedAliasMember): New expression type. + +2005-08-02 Atsushi Enomoto + + * location.cs : it borked when no argument was specified. + +2005-08-02 Atsushi Enomoto + + * location.cs : tiny ToString() format fix. + +2005-08-02 Atsushi Enomoto + + * statement.cs : oops, it was missing. + +2005-08-02 Atsushi Enomoto + + A set of fixes for precise line/column location. + + * location.cs : + "token" field now holds a file/line "delta", a line number offset + from the segment, and a column number. See also: + http://lists.ximian.com/pipermail/mono-devel-list/2004- + December/009508.html + Removed static IsNull. Use instance IsNull property instead. + * cs-tokenizer.cs : + For some tokens it stores Location. For Identifier it stores + LocatedToken which is a pair of string name and location. + Column numbers are adjusted only at getChar(). + * report.cs : + Use Location.ToString() for reporting (it now contains column). + * cs-parser.jay : + Largely modified to use LocatedToken instead of + string (IDENTIFIER), and to acquire Location from some tokens. + * namespace.cs, decl.cs, ecore.cs, class.cs, delegate.cs, + iterators.cs, const.cs, anonymous.cs, tree.cs, enum.cs, + codegen.cs : + Now MemberName holds Location. DeclSpace.ctor() receives Location + as a parameter. Removed extra parameters to all derived classes. + Replaced Location.IsNull() with instance property. + * assign.cs, expression.cs : + Added .ctor() overload that omits Location. + * attribute.cs : + Added "nameEscaped" flag that indicates the identifier was escaped + in the source file. This fixes bug #57047. + +2005-08-02 Marek Safar + + * attribute.cs (AttributeTester.GetImportedIgnoreCaseClsType): + New method, looking for lo-case imported cls type. + + * decl.cs (DeclSpace.VerifyClsCompliance): Check CS3005 for types + here. + + * driver.cs: Removed VerifyTopLevelNameClsCompliance usage. + + * enum (Enum.VerifyClsCompliance): Hardcode non-compliant types. + + * typemanager.cs (TypeManager.AllClsTopLevelTypes): Renamed from + all_imported_types. + (TypeManager.LoadAllImportedTypes): Lo-case imported types. + + Optimized to save 3.5 MB for SWF compilation. + +2005-08-01 Marek Safar + + * class.cs (AddToTypeContainer): Use inheritance insted of if(s). + (PartialContainer.Create): Moved logic AddToContainer. + (PartialContainer.MarkForDuplicationCheck): Shares name. + + * decl.cs (DeclSpace.AddToContainer): Check name collisions at one + place. + + * namespace.cs (Namespace.AddDeclSpace): Lazy declspaces + initialization. + (Namespace.GetSignatureForError): New method. + + * tree.cs (Tree.RecordDecl): Moved to AddToContainer. + (RootTypes.AddToTypeContainer): se inheritance insted of if(s). + +2005-08-01 Raja R Harinath + + Fix #75669. + * ecore.cs (Expression.MemberLookupFailed): Use queried_type for + member lookup rather than qualifier_type, since qualifier_type can + be null. + +2005-08-01 Marek Safar + + * enum.cs (Enum.VerifyClsName): Fixed to allow not CLSCompliant + enum member. + +2005-07-31 Miguel de Icaza + + * statement.cs: Copy the local exception into the exception + captured local. Fixes 75674 + +2005-07-31 Raja R Harinath + + Fix #75658. + * expression.cs (Invocation.OverloadResolve): Don't report error + CS1501 if error CS1502 has been reported. + (New.DoResolve): Delegate CS1501 reporting to + Invocation.OverloadResolve. + + Fix #75656. + * statement.cs (Block.CheckInvariantMeaningInBlock): Verify + invariant-meaning-in-block property in an enclosing block if + necessary. + +2005-07-29 Marek Safar + + * statement.cs (SwitchLabel.ResolveAndReduce): Refactored. + (SwitchLabel.Erorr_AlreadyOccurs): Share error message. + (Switch.CheckSwitch): Just save 50kb for SWF. + +2005-07-27 Martin Baulig + + * anonymous.cs (CaptureContext.AddField): Added + `AnonymousContainer am' argument; compute its toplevel scope if + it's not already computed. Fixes #75649. + +2005-07-26 Raja R Harinath + + Fix #75628. + * class.cs (Constructor.Emit): Reset block to null if the block + resolve fails. + +2005-07-25 Marek Safar + + * class.cs (TypeContainer.VerifyMembers): Be compatible in warning 169. + +2005-07-25 Marek Safar + + * class.cs (MethodData.Define): Check whether accessor implementing + interface is public. + + * driver.cs (Driver.parse): Try to be smart and check for `MZ' header. + +2005-07-22 Marek Safar + + Fix #57245 + * namespace.cs (LookupType): Moved same type check to... + + * typemanager.cs (LookupTypeReflection): Don't allow to import more types + with the same name. + +2005-07-21 Raja R Harinath + + * namespace.cs (NamespaceLookupType): Avoid a string allocation when we + already found a typebuilder. + * class.cs (MethodCore.IsDuplicateImplementation): Compare + MemberNames, not strings. + + * const.cs (Error_ExpressionMustBeConst): + Rename from Error_EpressionMustBeConst. + * const.cs, class.cs, statement.cd: Update. + +2005-07-21 Marek Safar + + Fix #65573 + + * const.cs (Const.LookupConstantValue): Report missing contant expression + everytime. + (Error_EpressionMustBeConstant): Only one error method. + + * class.cs, statement.c: Updated. + +2005-07-20 Raja R Harinath + + * statement.cs (Block.Flags): Add back HasVarargs. + (Block.flags): Make protected. + (ToplevelBlock.HasVarargs): Convert to a property that updates flags. + + * typemanager.cs (types, typecontainers, user_types): Remove. + (UserTypes, TypeContainers): Likewise. + (HandleDuplicate, AddDelegateType, AddEnumType): Likewise. + (CleanUp, Reset): Update. + (AddUserType): Combine variants. Now, only updates builder_to_declspace. + (GetNestedType): Use Type.GetNestedType. + (CoreLookupType): Take two arguments, the namespace and the + basename of the type. Update to use the Namespace.Lookup + mechanism. + (InitEnumUnderlyingTypes, InitCoreTypes): Update. + (RealMemberLookup): Use IsNestedChildOf instead of playing with + string concatenation and substring matches. + * class.cs, enum.cs, delegate.cs: Update to changes. + +2005-07-20 Marek Safar + + * constant.cs (Constant.Error_ConstantValueCannotBeConverted): Moved from + Expression and made virtual. + + * convert.cs (ImplicitReferenceConversionExists): Skip for value types. + (ImplicitStandardConversionExists): Fixed `byte' typo ? + + * ecore.cs (Expression.Error_ConstantValueCannotBeConverted): Moved. + + * literal.cs (NullLiteral.Error_ConstantValueCannotBeConverted): Customize + error message. + + * convert.cs, ecore.cs, enum.cs: Reflect Error_ConstantValueCannotBeConverted + change. + +2005-07-18 Marek Safar + + Fix #57707 + * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Check whether + AssemblyCultureAttribute is not used on executable. + + * rootcontext.cs, + * typemanager.cs: Add System.Reflection.AssemblyCultureAttribute. + +2005-07-16 Raja R Harinath + + Fix #60638. + * expression.cs (Binary.Warning_UnintendeReferenceComparison): + New. Reports CS0252/CS0253. + Mostly taken from preliminary patch by Duncak Mak. + (Binary.DoResolveOperator): Store results of operator lookup. + Use them to detect if we need to warn about unintended reference + comparisons. + +2005-07-15 Raja R Harinath + + Fix #72969. + * namespace.cs (Namespace.Lookup): Add back location parameter. + (Namespace.LookupType): Add CS0436 report. Add location parameter. + * delegate.cs, ecore.cs, expression.cs: Update to changes. + + * codegen.cs (EmitContext.DeclSpace): Make readonly. + * namespace.cs (Namespace.Lookup): Carve out type lookup into ... + (Namespace.LookupType): ... this. + (NamespaceEntry.GetUsingTable): Allocate only one zero-sized array + of namespaces. + * typemanager.cs (LookupTypeReflection): Remove buggy code that + purported to handle pointers. + (char_ptr_type, void_ptr_type): Use GetPointerType rather than + CoreLookupType. + +2005-07-15 Marek Safar + + * expression.cs (MemberAccess.ResolveNamespaceOrType): Don't report nested + type as namespace. + +2005-07-15 Raja R Harinath + + * namespace.cs (Namespace.Lookup): Drop location parameter. + (NamespaceEntry.LookupAlias): Remove. Merge into ... + (NamespaceEntry.Lookup): ... this. + (NamespaceEntry.Error_AmbiguousTypeReference): + Move here from DeclSpace. + (NamespaceEntry.LookupNamespaceOrType): Move support for dotted + names ... + * ecore.cs (TypeLookupExpression.DoResolveAsTypeStep): ... here. + * decl.cs (DeclSpace.ErrorAmbiguousTypeReference): + Move to NamespaceEntry. + * delegate.cs, expression.cs: Update to changes. + +2005-07-14 Marek Safar + + * attribute.cs (Attribute.ResolveAttributeType): Renamed from + CheckAttributeType and refactored. + (Attribute.ResolvePossibleAttributeType): Changed to reuse + ResolveAsTypeTerminal error handling. + (ResolveAsTypeTerminal): Introduced because of global attributes extra + handling. + (GetSignatureForError): Print errors in same way. + + * class.cs, + * codegen.cs: Reflect attribute GetSignatureForError change. + + * ecore.cs, + * expression.cs: Add silent parameter to ResolveAsTypeStep. + + * namespace.cs (UsingEntry): Refactored to make fields private. + + * assign.cs, + statement.cs: Error_UnexpectedKind has extra parameter. + +2005-07-14 Raja R Harinath + + * ecore.cs (IAlias): Remove. + * decl.cs (DeclSpace): Don't derive from IAlias. Remove members + that implement the interface. + * namespace.cs (Namespace): Likewise. + (Namespace.declspaces): Renamed from 'defined_names'. + (Namespace.AddDeclSpace): Renamed from 'DefineName'. Take a + DeclSpace instead of an IAlias. + * tree.cs (Tree.AddDecl): Update. + +2005-07-12 Raja R Harinath + + * statement.cs (Block.Flags); Remove HasVarargs. + (Block.HasVarargs): Move to ToplevelBlock. + (Block.ThisVariable, Block.AddThisVariable): Likewise. + (Block.Variables): Make protected. Initialize variable hashtable + if necessary. + (Block.AddVariable): Update. + (Block.Resolve): Update to changes. + (ToplevelBlock.HasVarargs): New boolean. + (ToplevelBlock.ThisVariable): Move here from Block. + (ToplevelBlock.AddThisVariable): Likewise. + (ToplevelBlock.IsThisAssigned): New. Forwards call to this_variable. + * expression.cs (This.ResolveBase): Update to changes. + (ArglistAccess.DoResolve): Likewise. + +2005-07-11 Marek Safar + + Fix #75321 + * ecore.cs, class.cs: Use SetAssigned instead of direct access. + + * class.cs (TypeContainer.VerifyMembers): Distinguish between + not used and not used & assigned. + (FieldBase.ASSIGNED): Moved to MemberCore.Flags. + +2005-07-11 Marek Safar + + Fix #75053 + * expression.cs (Is.DoResolve): null is never provided type. + +2005-07-08 Marek Safar + + Fix #52496 + * cs-parser.jay: Less strict event error rule to catch more errors. + +2005-07-08 Martin Baulig + + Fix test-iter-10.cs - distinguish whether we `yield' in a property + gettter (allowed) or setter (not allowed). + + * class.cs (Accessor): Implement IIteratorContainer. + (Accessor.Yields): New public field. + (PropertyBase.PropertyMethod.Define): Handle iterators on a + per-accessor basis. + + * cs-parser.jay + (get_accessor_declaration, set_accessor_declaration): Set the + `yields' flag on the accessor, not the property. + (property_declaration): Do the iterators check on a per-accessor + basis and not for the whole property. + +2005-07-08 Martin Baulig + + * anonymous.cs (CaptureContext.EmitParameterInstance): Correctly + handle parameters in nested scopes; fixes #74808; see gtest-188.cs. + +2005-07-07 Marek Safar + + Fix #74975 + * attribute.cs (orig_sec_assembly): Holds original version of assembly. + (ExtractSecurityPermissionSet): Cope with self referencing security + attributes properly. + + * driver.cs (SetOutputFile): Made public property OutputFile. + +2005-07-07 Raja R Harinath + + Fix #75486. + * class.cs (TypeContainer.first_nonstatic_field): Rename from + has_nonstatic_fields. Make into a FieldBase pointer. + (TypeContainer.AddField): Add CS0282 check. + (TypeContainer.EmitType): Update. + +2005-07-06 Miguel de Icaza + + * cs-tokenizer.cs (consume_identifier): Do not create strings to + compare if they start with __. + +2005-07-06 Raja R Harinath + + * statement.cs (Switch.SwitchGoverningType): Only look at + UserCasts that don't need implicit standard conversions to one of + the allowed switch types (Fixes test-322.cs). + (LocalInfo.Resolve): Re-enable sanity-test. + +2005-07-06 Marek Safar + + * cs-tokenizer.cs (consume_identifier): Detect double undescores + + * ecore.cs (FieldExpr.AddressOf): Changed volatile error to warning. + + * expression.cs (Invocation.DoResolve): Report error CS0245 here. + +2005-07-06 Raja R Harinath + + Fix #75472. + * ecore.cs (SimpleName.GetSignatureForError): Add. + * expression.cs (MemberAccess.DoResolve): Don't clobber 'expr' field. + (MemberAccess.GetSignatureForError): Add. + +2005-07-05 Marek Safar + + The big error and warning messages review. + + * anonymous.cs, + * assign.cs, + * attribute.cs, + * class.cs, + * codegen.cs, + * convert.cs, + * cs-parser.jay, + * cs-tokenizer.cs, + * decl.cs, + * delegate.cs, + * doc.cs, + * driver.cs, + * ecore.cs, + * enum.cs, + * expression.cs, + * flowanalysis.cs, + * iterators.cs, + * literal.cs, + * location.cs, + * modifiers.cs, + * namespace.cs, + * parameter.cs, + * pending.cs, + * report.cs, + * rootcontext.cs, + * statement.cs, + * support.cs, + * tree.cs, + * typemanager.cs: Updated. + + * class.cs: (MethodCore.SetYields): Moved here to share. + (PropertyMethod.Define): Moved iterator setup here. + + * iterators.cs: Add orig_method to have full access to parent + container. + +2005-07-05 Raja R Harinath + + Make 'fixed variable' handling standards compliant. Fix #70807, #72729. + * ecore.cs (IVariable.VerifyFixed): Remove 'is_expression' parameter. + (FieldExpr.VerifyFixed): Ensure that the field is part of a fixed + variable of struct type. + * expression.cs (Unary.ResolveOperator): Update to change. + (Indirection.VerifyFixed): Likewise. + (LocalVariableReference.VerifyFixed): A local variable is always fixed. + (ParameterReference.VerifyFixed): Value parameters are fixed. + (This.VerifyFixed): Treat 'this' as a value parameter. + * statement.cs (LocalInfo.IsFixed): Remove. + +2005-07-01 Martin Baulig + + * iterators.cs (Iterator.CapturedThisReference.Emit): Use + `ec.EmitThis ()' to get the correct scope. + +2005-07-01 Martin Baulig + + * ecore.cs (FieldExpr.DoResolve): Don't capture the field if it's + instance is a ParameterReference; fixes #75299. + +2005-07-01 Martin Baulig + + Reverted Marek's latest patch (r46725): + - it contains structural changes which are neither mentioned in + the ChangeLog nor explained anywhere; for example the additional + argument of EmitContext's and Iterator's .ctor's and the + TypeContainer.DefineMembers() change. + - structural changes like this should go in in seperate patches + and not be hidden in a huge patch which just seems to affect + warnings and errors. + a big and hard to understand patch. + - it breaks iterators and causes regressions, for instance in + test-iter-03.cs. + +2005-06-30 Raja R Harinath + + Fix #75412. + * expression.cs (Indexers.map): Remove. + (Indexers.Append): Filter out inaccessible setters and getters. + (IndexerAccess.DoResolve, IndexerAccess.DoResolveLValue): Update. + + Fix #75283. + * ecore.cs (MemberExpr.EmitInstance): New. Add CS0120 check. + Refactored from ... + (FieldExpr.EmitInstance, PropertyExpr.EmitInstance): ... these. + (FieldExpr.Emit, PropertyExpr.Emit): Update. + (FieldExpr.EmitAssign, PropertyExpr.EmitAssign): Update. + * expression.cs (Invocation.EmitCall): Add CS0120 check. + +2005-06-30 Marek Safar + + Fix #75322 + * class.cs (FieldBase.GetInitializerExpression): One more field + for backup. + +2005-06-28 Miguel de Icaza + + * pending.cs: Do not define a proxy if the base method is virtual, + it will be picked up by the runtime (bug 75270). + +2005-06-08 Martin Baulig + + The big Iterators rewrite :-) + + * iterators.cs: Rewrite this to use the anonymous methods framework. + + * rootcontext.cs (RootContext.DefineTypes): Define Delegates + before the TypeContainers; see 2test-21.cs. + + * class.cs + (TypeContainer.DefineType): Don't create a new EmitContext if we + already have one (this only happens if we're an Iterator). + (TypeContainer.Define): Also call Define() on all our iterators. + (Method.CreateEmitContext): Added support for iterators. + + * anonymous.cs + (AnonymousContainer): New abstract base class for `AnonymousMethod'. + (AnonymousContainer.CreateMethodHost): Moved here from + AnonymousMethod and made abstract. + (AnonymousContainer.CreateScopeType): New abstract method. + (AnonymousContainer.IsIterator): New public property. + (ScopeInfo.EmitScopeType): Call CreateScopeType() on our Host to + get the ScopeTypeBuilder rather than manually defining it here. + (ScopeInfo.EmitScopeInstance): New public method; correctly handle + iterators here. + + * driver.cs (Driver.MainDriver): Call TypeManager.InitCodeHelpers() + before RootContext.DefineTypes(). + + * codegen.cs (EmitContext.RemapToProxy): Removed. + (EmitContext.CurrentAnonymousMethod): Changed type from + AnonymousMethod -> AnonymousContainer. + (EmitContext.ResolveTopBlock): Protect from being called twice. + (EmitContext.MapVariable, RemapParameter(LValue)): Removed. + (EmitContext.EmitThis): Removed the iterators hacks; use the + anonymous methods framework for that. + + * statement.cs + (ToplevelBlock.Container): Make this a property, not a field. + (ToplevelBlock.ReParent): New public method; move the + ToplevelBlock into a new container. + (Foreach.TemporaryVariable): Simplify. + +2005-06-05 Martin Baulig + + * statement.cs (LocalInfo.CompilerGenerated): New flag. + (Block.AddTemporaryVariable): New public method; creates a new + `LocalInfo' for a temporary variable. + (Block.EmitMeta): Create the LocalBuilders for all the temporary + variables here. + (Foreach.TemporaryVariable): Use Block.AddTemporaryVariable() for + non-iterator variables. + +2005-06-05 Martin Baulig + + * statement.cs (Foreach.TemporaryVariable): Create the + LocalBuilder in the Emit phase and not in Resolve since in some + situations, we don't have an ILGenerator during Resolve; see + 2test-19.cs for an example. + +2005-06-04 Martin Baulig + + **** Merged r45395 from GCS **** + + The big Foreach rewrite - Part II. + + * typemanager.cs (TypeManager.object_getcurrent_void): Replaced + with `PropertyInfo ienumerator_getcurrent'. + + * codegen.cs (VariableStorage): Removed. + + * statement.cs + (Foreach): Derive from Statement, not ExceptionStatement. + (Foreach.CollectionForeach): New nested class. Moved all the code + dealing with collection foreach here. + (Foreach.ForeachHelperMethods): Removed. + (Foreach.TemporaryVariable): Implement IMemoryLocation. + +2005-05-23 Martin Baulig + + * statement.cs (Try.DoResolve): Don't create a `finally' if we + don't need to. Fix #75014. + +2005-05-20 Martin Baulig + + Merged r44808 from GMCS. + + * class.cs (TypeContainer.CircularDepException): Removed. + (TypeContainer.DefineType): Removed the `InTransit' stuff. + (TypeContainer.CheckRecursiveDefinition): Check for circular class + (CS0146) and interface (CS0529) dependencies here. + +2005-06-21 Raja R Harinath + + * expression.cs (Invocation.EmitCall): Fix initialization + 'this_call' to reflect current behaviour. Fix indentation. + + * convert.cs (FindMostEncompassedType): Add two trivial special + cases (number_of_types == 0 || number_of_types == 1). + (FindMostEncompasingType): Likewise. + +2005-06-17 Raja R Harinath + + Some cleanups preparing for the fix of #75283. + * ecore.cs (PropertyExpr.InstanceResolve): Tighten conditions for + error testing. + (EventExpr.InstanceResolve): Likewise. + (EventExpr.DoResolve): Remove redundant checks. + +2005-06-10 Duncan Mak + + * cs-tokenizer.cs (process_directives): New flag for controlling + the processing of preprocessor directives. + (x_token): After seeing a '#', return Token.NONE instead of going + to handle_preprocessing_directive() when not processing + directives. This avoids unnecessary processing during the token peek in + is_punct(). + + This fixes #74939. + + * cs-tokenizer.cs (handle_preprocessing_directive, xtoken): Use + the existing error reporting methods instead of Report.Error. + + * convert.cs (priv_fmt_expr): Remove. It's not needed anymore + after Raja's rewrite. + +2005-06-08 Miguel de Icaza + + * class.cs: Small fix. + +2005-06-08 Raja R Harinath + + Fix #75160. + * class.cs (GetPartialBases): Fix return value check of + part.GetClassBases. + +2005-06-07 Raja R Harinath + + Ensure that partial classes are registered in their enclosing + namespace. Initial part of fix of #75160. + * tree.cs (Tree.RecordDecl): Add new namespace argument. + Register declspace with namespace here, not in + DeclSpace.RecordDecl. + * cs-parser.jay: Pass namespace to RecordDecl. + * class.cs (PartialContainer.Create): Likewise. + (ClassPart.DefineType): New sanity-check. Throws an exception if + called. + * decl.cs (Declspace.RecordDecl): Remove. + * namespace.cs (NamespaceEntry.DefineName): Remove. + +2005-06-06 Marek Safar + + * rootcontext.cs: Reset TargetExt as well. + +2005-06-03 Raja R Harinath + + * ecore.cs (Expression.Resolve): Emit CS0654 error when + -langversion:ISO-1. + +2005-06-02 Raja R Harinath + + Fix #75080, cs0119.cs. + * ecore.cs (Expression.ExprClassToResolveFlags): New. Broken out + of ... + (Expression.Resolve): ... this. Use it. Remove bogus code + allowing ExprClass.Type and ExprClass.Namespace for + ResolveFlags.VariableOrValue. + (Expression.Resolve) [1-argument variant]: Change default resolve + flags based on language version. + (Expression.Error_UnexpectedKind): Use a simple string array + rather than an ArrayList. + * expression.cs (TypeOf.DoResolve): Set eclass to ExprClass.Value, + not ExprClass.Type. + (TypeOfVoid.DoResolve): Likewise. + (MemberAccess.DoResolve) [3-argument variant]: Make private. Drop + flags argument -- it always has the same value. + +2005-05-31 Raja R Harinath + + Fix #75081. + * ecore.cs (Expression.ResolveLValue): Add a Location parameter. + Use it in the error message. + * assign.cs, expression.cs, statement.cs: Update. + +2005-05-30 Raja R Harinath + + Fix #75088. + * ecore.cs (Expression.MemberLookupFailed): Add CS0122 check in + the "almostMatchedMember" case too. + * typemanager.cs (Closure.CheckValidFamilyAccess): Add anything + that failed the accessibility checks to 'almost_match'. + +2005-05-27 Vladimir Vukicevic + + * attribute.cs: Use internal MethodBuilder methods to set + ExactSpelling and SetLastError on PInvoke methods, instead + of passing them via charset. Fixes #75060. + +2005-05-27 Raja R Harinath + + * parameter.cs (Parameter): Remove TODO comment. + (Parameter.DefineParameter): Remove Location parameter. + (Parameters.LabelParameters): Likewise. + * class.cs (Constructor.Emit): Update to change. + (MethodData.Emit): Likewise. + * anonymous.cs (AnonymousMethod.EmitMethod): Likewise. + * delegate.cs (Delegate.Define, Delegate.Emit): Likewise. + +2005-05-27 Atsushi Enomoto + + * parameter.cs, + Removed Parameters.Location and added Parameter.Location instead. + Removed Location parameter from Emit() and GetSignature(). + * anonymous.cs, + class.cs, + cs-parser.jay, + delegate.cs, + iterators.cs, + statement.cs : + Modified all related calls. + +2005-05-26 Raja R Harinath + + Improve user-defined conversion handling. + * convert.cs (GetConversionOperators): Rewrite. Return only the + applicable operators. + (AddConversionOperators): New. Helper for GetConversionOperators. + (FindMostEncompassedType, FindMostEncompassingType): Verify that + there is only one most encompassed/encompassing type. + (FindMostSpecificSource, FindMostSpecificTarget): Remove + "applicable operator" handling. + (UserConversion): Move cache here from GetConversionOperators. + Directly cache the chosen operator, rather than the whole + MethodGroup. + (ExplicitNumericConversion): Fix buggy implementation of Decimal + case. Allow conversion of decimal to sbyte and byte too. + * expression.cs (EmptyExpression.Grab, EmptyExpression.Release): + New static methods. Used to avoid allocating EmptyExpressions in + convert.cs. + +2005-05-24 Duncan Mak + + * ecore.cs (CastFromDecimal): New class for casting a decimal to + another class, used in Convert.ExplicitNumericConversion. + (CastToDecimal): New class, similar to above, but casts to + System.Decimal, used in Convert.ImplicitNumericConversion and also + in explicit convesion from double/float to decimal. + + * convert.cs (ImplicitNumericConversion): Handle implicit + conversions to System.Decimal. + (ExplicitNumericConversion): handle explicit conversions to + System.Decimal. + + This fixes #68711. + +2005-05-20 Miguel de Icaza + + * typemanager.cs (EnumToUnderlying): Do not throw if we do not + know the type at this stage, just break through. Fixes #75008 + +2005-05-19 Martin Baulig + + * delegate.cs + (ImplicitDelegateCreation.Check): Added `bool check_only' argument + to disable error reporting. + + * convert.cs (Convert.ImplicitStandardConversionExists): Use it + here since we don't want to report an error; see the new test-336.cs. + +2005-05-19 Raja R Harinath + + * statement.cs (ToplevelBlock.GetParameterReference) + (ToplevelBlock.IsParameterReference,ToplevelBlock.IsLocalParameter): + Move here from class Block. + * ecore.cs (SimpleName.SimpleNameResolve): Update to changes. + * expression.cs (ParameterReference.DoResolveBase): Likewise. + +2005-05-18 Martin Baulig + + Fix #74978. + + * flowanalysis.cs + (FlowBranching.Reachability): Add non-static public And() and Or() + methods. + (FlowBranchingSwitch): New class; do the `break_origins' thing + like in FlowBranchingLoop. + (FlowBranching.UsageVector.MergeBreakOrigins): Also merge the + reachability, not just locals and parameters. + (FlowBranching.MergeChild): Remove some of the hacks for loop and + switch; MergeBreakOrigins() now takes care of that. + +2005-05-18 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + a loop and may leave it, reset the barrier; fixes #74974. + +2005-05-17 Marek Safar + + * attribute.cs (Attribute.ResolveArguments): GuidAttribute check + is back. + + * cs-parser.jay: Catch more lexical errors. + + * report.cs: Add one more Error method. + + * rootcontext.cs, + * typemanager.cs: Register System.Runtime.InteropServices.GuidAttribute + +2005-05-17 Martin Baulig + + * expression.cs (Argument.Resolve): Turn on flow analysis; fix + #70970. + +2005-05-16 Raja R Harinath + + Fix test-382.cs. Emit values of decimal constants. + * class.cs (TypeContainer.RegisterFieldForInitialization): New. + Carved out of ... + (TypeContainer.AddField): ... this. + (TypeContainer.EmitFieldInitializers): Allow the list of fields + with initializers to include 'Const's. + (ClassPart.RegisterFieldForInitialization): Forward to + PartialContainer. + * const.cs (Const.Const): Pass initializer to base class. + (Const.Define): In case of decimal constants, register them for + initialization in a static constructor. + +2005-05-14 Martin Baulig + + * statement.cs (Block.Resolve): Correctly handle unreachable code; + do not call ResolveUnreachable() on unreachable statements in + here, see the comment in the source code. + +2005-05-13 Raja R Harinath + + Fix #74934. + * expression.cs (BinaryResolveOperator): If one of the operands of + an equality comparison is 'null' and the other is a pointer type, + convert the null to a NullPointer. + * convert.cs (ImplicitReferenceConversion): If the expression is a + NullLiteral and the target type is a pointer type, return a + NullPointer instead. + (ImplicitConversionStandard): Likewise. + +2005-05-13 Marek Safar + + * cs-parser.jay: Set readonly context based on special constructs. + + * expression.cs (LocalVariableReference.DoResolveBase): Improved + readonly variable error handling. + + * rootcontext.cs (EmitCode): Don't verify members when error + occurred. + + * statement.cs (LocalInfo): Add reaodnly context information. + (SetReadOnlyContext, GetReadOnlyContext): New methods. + +2005-05-13 Raja R Harinath + + * statement.cs (Block.Resolve): Revert change below. Modify fix + for #74041 to initialize 'resolved' to false only for explicit + blocks. Fixes #74873. + +2005-05-12 Raja R Harinath + + Fix #74920. + * typemanager.cs (unmanaged_enclosing_types): New. + (IsUnmanagedType): Avoid infloops by using + 'unmanaged_enclosing_types' to talk with recursive invocations. + +2005-05-13 Martin Baulig + + * statement.cs (Block.Resolve): Make the `bool unresolved' flag an + instance variable, not a local. Fix #74873. + (Block.ResolveUnreachable): Set it to true here. + +2005-05-11 Duncan Mak + + * cs-tokenizer.cs (get_cmd_arg): Check that 'c' is not -1 before + continuing to process for 'arg'. + (handle_preprocessing_directive): Check the argument of the #endif + directive and report error CS1025 if there are any trailing + characters. + + According to the C# spec, having even whitespace after the #endif + directive is illegal; however, because we call arg.TrimEnd () + beforehand, we have the same behavior as csc, allowing whitespace + after the directive. + + Fixes #74892. + +2005-05-11 Marek Safar + + Fix #74863. + + * class.cs (ConstructorInitializer.GetOverloadedConstructor): Removed. + (Constructor.GetObsoleteAttribute): Implemented correctly. + +2005-05-10 Martin Baulig + + * support.cs (ReflectionParameters.ParameterModifier): Use + `Parameter.Modifier.REF' if we both have `ParameterAttributes.Out' + and `ParameterAttributes.In'. Fixes #74884. + +2005-05-10 Marek Safar + + * class.cs (Method.Define): Catch attempt for Finalizer declaration. + + * expression.cs (Argument.GetParameterModifier): Turned to property. + (Invocation.Error_InvalidArguments): Add more descriptive errors. + + * parameter.cs (Parameter.GetModifierSignature): Translates modifier to + its C# equivalent. + +2005-05-09 Raja R Harinath + + Fix #74852. + * decl.cs (MemberCache.AddMethods): Register override methods, + rather than non-override methods. + * typemanager.cs (RegisterOverride): New. + (IsOverride): Update. + +2005-05-09 Marek Safar + + Fix #73105. + + * ecore.cs (SimpleName.SimpleNameResolve): Add in_transit to catch + recursive declaration. + + * statement.cs (Block.ResolveMeta): Report any error in resolving. + +2005-05-06 Marek Safar + + * cfold (DoConstantNumericPromotions): Don't try to convert 0 enum. + + * expression.cs (Binary.DoResolve): (x && 0) is always 0. + +2005-05-05 Raja R Harinath + + Fix #74797. + * decl.cs (DeclSpace.FamilyAccessible): + Use TypeManager.IsNestedFamilyAccessible. + + Fix reopened #64812. + * typemanager.cs (Closure.Filter): Introduce checks for 'protected + internal'. + +2005-05-04 Raja R Harinath + Abin Thomas + Anoob V E + Harilal P R + + Fix #64812. + * typemanager.cs (Closure.CheckValidFamilyAccess): Don't blindly + allow access to all static members. + +2005-05-04 Martin Baulig + + * ecore.cs (FieldExpr.DoResolveLValue): Always call fb.SetAssigned(). + +2005-05-04 Martin Baulig + + Fix #74655. + + * statement.cs (Switch.SimpleSwitchEmit): Always emit the default + section at the end; make things work if `default' is not the last + section. + +2005-05-04 Martin Baulig + + Fix #70400. + + * statement.cs (Switch): Replaced the `got_default' field with a + `default_section' one. + (Switch.CheckSwitch): Set `default_section' here. + (Switch.Resolve): If we're a constant switch and the constant is + not found, use the default section. + +2005-05-03 Martin Baulig + + * expression.cs (ArrayAccess.EmitGetLength): New public method. + + * statement.cs (Foreach.ArrayForeach): New nested class. + (Foreach.TemporaryVariable): New nested class. + (Foreach.EmitArrayForeach): Removed; this is now in the new + ArrayForeach class. + +2005-05-03 Raja R Harinath + + * pending.cs (BaseImplements): Move the #74773 fix here. This is + more conservative. + (VerifyPendingMethods): Revert change below. + + * typemanager.cs (IsOverride, RegisterNonOverride): New. + * decl.cs (MemberCache.AddMethod): Register "non-override" methods + that used to trigger warning -28. Remove warning -28. + * expression.cs (Invocation.OverloadResolve): Use + TypeManager.IsOverride to distinguish override methods. + + Fix #74773. + * pending.cs (VerifyPendingMethods): If a base type implements the + requested interface, don't bother checking individual methods of + the base type. As a side-effect, this prevents the creation of + unnecessary proxies. + +2005-05-02 Martin Baulig + + Fix #70182. + + * flowanalysis.cs (FlowBranching.UsageVector.MergeJumpOrigins): + Also `And' the locals if the old vector is null. + (FlowBranching.UsageVector.BitVector.And): Allow `vector' being + null; in this case we basically reset all the variables. + +2005-05-02 Martin Baulig + + Fix #74529. + + * flowanalysis.cs (FlowBranching.UsageVector.MergeBreakOrigins): + Added `FlowBranching branching' argument; always `and' the + variables instead of `or'ing them unless we're an infinite loop. + + * statement.cs (While.Resolve): Create a new sibling unless we're + infinite. + +2005-05-02 Martin Baulig + + Fix #70140. + + * class.cs (ConstructorInitializer.Resolve): Added `Block block' + arguments; use it instead of creating a new TopLevelBlock. + (Constructor.Emit): Call `block.ResolveMeta ()' before resolving + our ConstructorInitializer. + + * statement.cs + (TopLevelBlock.TopLevelBranching): New public property. + (TopLevelBlock.ResolveMeta): New public method; call ResolveMeta() + and create our `TopLevelBranching'. + + * codegen.cs (EmitContext.ResolveTopBlock): If we're not an + anonymous method host, use `block.TopLevelBranching' rather than + creating a new branching. + +2005-04-20 Miguel de Icaza + + * anonymous.cs (ScopeInfo.AddChild): when adding a new child to + a ScopeInfo, if any of the current children is a child of the new + entry, move those children there. + +2005-04-30 Martin Baulig + + * statement.cs (Switch.SimpleSwitchEmit): Reset `default_at_end' + at the beginning of a SwitchSection. Fix #73335. + +2005-04-27 Marek Safar + + Fix #74378 + * class.cs (EmitFieldInitializers): Use FieldExpr in initializer. + + * ecore.cs (FieldExpr): Add a new ctor with in_initializer. + (FieldExpr.DoResolve): Obsolete members are ignored for field + initializers. + +2005-04-26 Marek Safar + + * attribute.cs (AreOverloadedMethodParamsClsCompliant): Add array + of arrays detection. + + * class.cs (Interface.VerifyClsCompliance): Add base interfaces + verification. + (Field.VerifyClsCompliance): Volatile fields are not compliant. + + * decl.cs (MemberCache.VerifyClsParameterConflict): Add array of + arrays report. + +2005-04-25 Ben Maurer + + * cs-parser.jay: Use the prefered version of -unsafe in error + message. + +2005-04-22 Marek Safar + + * driver.cs (CompilerCallableEntryPoint.Invoke): Reset under any + circumstances. + +2005-04-20 John Luke + + * driver.cs: fix typo in error message, --outout to --output + +2005-04-20 Marek Safar + + * codegen.cs (InRefOutArgumentResolving): New field. + + * ecore.cs (FieldExpr.DoResolve): Check for assigning to readonly + fields outside contructor. + + * expression.cs (Argument.Resolve): Set InRefOutArgumentResolving. + +2005-04-19 Miguel de Icaza + + * anonymous.cs (CaptureContext.EmitParameterInstance): The + parameter code was not completed ever, so it was not as up-to-date + as local variables. Must finish it. + + The bug fix was to compare the Toplevel of the block, not the + current block. Thanks for Ben for pointing this out. + +2005-04-19 Raja R Harinath + + * decl.cs (AddMethods): Use the declaring type of the problem + method to determine if we want to squash a warning. + +2005-04-19 Marek Safar + + * attribute.cs: Removed debug output. + + * decl.cs (MemberCache.AddMethods): Fixed Finalize ignoring. + + * driver.cs (Driver.parse): Synchronize parser ErrorOutput with + Report.Stderr. + +2005-04-18 Raja R Harinath + + Fix #74481. + * expression.cs (Binary.EqualsNullIsReferenceEquals): New. + (Binary.DoResolveOperator): Use it to avoid blindly optimizing out + all null comparisons against reference types. + +2005-04-18 Marek Safar + + Fix# 74565 + * class.cs (TypeContainer.CircularDepException) New nested + exception class. + (GetPartialBases, GetNormalBases, GetClassBases): Removed error. + (TypeContainer.DefineType): Removed error, reset InTransit before + exit. + (Class.DefineType): Throw exception when is in Transit. + Catch exception and report error. + (Struct.DefineType): Throw exception when is in Transit. + Catch exception and report error. + (Interface.DefineType): Throw exception when is in Transit. + Catch exception and report error. + + * codegen.cs: Add InCatch,InFinally to EmitContext to easily + handle nested exception handlers. + + * flowanalysis.cs (InTryWithCatch): New method, search for try with + a catch. + + * iterators.cs (Yield.CheckContext): Add CS1626 report. Updated + InFinally and InCatch storage. + + * statement.cs (Throw.Resolve): Use InCatch, InFinally from ec. + (Catch.Resolve): Set and Restore ec.InCatch. + (Try.Resolve): Set and Restore ec.InFinally. + (Try.HasCatch): True when try has catch. + +2005-04-17 Atsushi Enomoto + + * doc.cs : In some cases FilterName returns MonoEvent and MonoField + for the same event member, so exclude such cases from warning 419. + Fixed bug #74633. + +2005-04-16 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Apply patch from John + Luke to fix bug 59864: operators &, | and ^ on enumerations + require that the same enum type on both sides. + + * driver.cs: Add warnings to old flag usage, this is to assist + people who produce Makefiles and hope that the Makefiles will be + used on Windows. + + * class.cs (TypeContainer.EmitType): Moved the definition of the + special $PRIVATE$ field from the resolve phase to the Emit phase. + During resolve we do not know if we are a struct with + HasExplicitLayout, we know this only after the attributes for the + type are emitted. + + Set the FieldOffset to zero on the dummy field that we create for + the class. Fixes 74590. + +2005-04-16 Raja R Harinath + + Fix #73834. + * ecore.cs (PropertyExpr.resolved): New. + (DoResolve): Use it to handle a case of double resolution here. + Handle a case of identical-name-and-type-name. + * expression.cs (ArrayCreation.CheckIndices): Avoid double + resolution by storing the results of expression resolution back + into the "probes" array. + +2005-04-15 Raja R Harinath + + Fix cs0208-7.cs and cs0208-8.cs. + * typemanager.cs (IsUnmanagedType): Arrays are not allowed + (cf. ECMA standard, behaviour of CSC 1.1 and CSC 2.0). Improve + error reporting to point out the reason a struct is not unmanaged. + +2005-04-13 Atsushi Enomoto + + * doc.cs : In FindDocumentedType(), avoid TypeExpr.ResolveType() and + just use TypeExpr.Type. This fixes bug #74595 when merged to gmcs. + +2005-04-13 Raja R Harinath + + Fix #74528. + * ecore.cs (PropertyExpr.InstanceResolve): Handle a case of + IdenticalNameAndTypeName here. + (EventExpr.InstanceResolve): Likewise. + +2005-04-13 Marek Safar + + C# 2.0 DefaultCharSetAttribute implementation + + * attribute.cs (Attribute.ResolveAsTypeStep): New protected method + which allows us to set GlobalNamespace for every resolve. + (Attribute.ResolveArguments): Cut from Resolve. + (Attribute.GetCharSetValue): Returns CharSet named argument. + (Attribute.DefinePInvokeMethod): Gets default charset from + module settings. + (GlobalAttribute.ResolveAsTypeStep): Override. + (GlobalAttribute.ResolveArguments): Override. + + * class.cs (TypeAttr): Is protected. + + * codegen.cs (ModuleClass.DefaultCharSet): New member. + (ModuleClass.DefaultCharSetType): New memeber. + (ModuleClass.ResolveAttributes): Resolves DefaultCharSetAttribute. + + * decl.cs (Decl.TypeAttr): New protected virtual. Returns default + charset from module. + + * delegate.cs (TypeAttr): Override. + (Delegate.DefineType): Use this TypeAttr. + + * driver.cs (Driver.MainDriver): Call Module.ResolveAttributes + at very early stage (before types are defined) to resolve model + module attributes. It will probably not work with corlib but it + should be ok. + + * enum.cs (Enum.TypeAttr): New protected virtual. Returns default + charset from module. + + * typemanager.cs (default_charset_type): New type. + +2005-04-13 Raja R Harinath + + * decl.cs (MemberCache.AddMethods): Don't warn if + System.Object.Finalize has buggy MethodAttributes. + + * typemanager.cs (IsUnmanagedType): Restore !IsValueType check + removed below. + +2005-04-13 Atsushi Enomoto + + * doc.cs : detect ambiguous reference to overloaded members. + Fixed bug #71603. MS 1.1 csc does not detect it. + +2005-04-13 Atsushi Enomoto + + * doc.cs : delegates must not be referenced with parameters. + Fixed bug #71605. + +2005-04-12 Miguel de Icaza + + * typemanager.cs (IsUnmanagedType): Arrays are allowed. + +2005-04-10 Miguel de Icaza + + * driver.cs (MainDriver): Stop processing if the CLS stage found + errors. + + (CompilerCallableEntryPoint.InvokeCompiler): Always + reset after execution; Take a TextWriter argument for the + output. + + * report.cs: Use the error stream instead of hardcoding stderr. + +2005-04-09 Miguel de Icaza + + * class.cs: Reduce code paths to test, too small of an + optimization to make it worth the extra testing. Always perform + it. + +2005-04-08 Raja R Harinath + + Fix #74510. + * class.cs (OperatorArrayList.CheckPairedOperators): Skip + operators that had errors reported on them. + +2005-04-08 Marek Safar + + * attribute.cs (Attribute.IsValidArgumentType): Test valid named + argument types. + (Attribute.Resolve): Add named argument type checking. + + * class.cs (FixedField.Define): Use IsPrimitiveType + + * expression.cs (Binary.ResolveOperator): Reflect IsCLRType renaming. + + * iterators.cs (Iterator.DefineIterator): Add check for arglist and + unsafe parameter types. + + * statement.cs (Using.ResolveExpression): Add better error description. + + * typemanager.cs (IsCLRType): Renamed to IsPrimitiveType. + +2005-04-08 Raja R Harinath + + Fix #74484. + * attribute.cs (Attribute.GetAttributeUsage): Resolve + AttributeUsageAttribute in the emitcontext of the attribute class, + not in the emitcontext of the attributable entity it was attached to. + * cs-parser.jay: Use 'current_class', not 'current_container', + when creating a GlobalAttribute. + +2005-04-08 Alp Toker + + * pending.cs: The fix to #58413 failed to compile methods implementing + interfaces with/without params modifiers and vice versa, even though + params modifiers aren't part of the signature. Make the modifier check + less strict as in csc. + +2005-04-07 Abin Thomas + Anoob V E + Harilal P R + + Fix #58413. + * pending.cs (TypeAndMethods.mods): New. Store the parameter + modifiers of pending methods. + (PendingImplementation.PendingImplementation): Initialize it. + Add Parameter.Modifier [][] mods and initialize it with ParameterData. + (PendingImplementation.InterFaceMethod): Repalce Type[] argument + with ParameterData. Add check for modifiers. + * class.cs (MethodData.Define): Update to changes. + +2005-04-07 Raja R Harinath + + * ecore.cs (Expression.IsAccessorAccessible): Clarify code somewhat. + +2005-04-07 Marek Safar + + * class.cs (PropertyMethod.Define): Check private accessor in abstract + property. + + * decl.cs (DeclSpace.ApplyAttributeBuilder): Don't allow RequiredAttribute + + * rootcontext.cs, + * typemanager.cs: Registered RequiredAttributeAttribute. + +2005-04-06 Marek Safar + + * class.cs (VerifyMembers): Doesn't need EmitContext argument. + Warning CS0169 is back at level 3. + (IMethodData.SetMemberIsUsed): New method. + + * decl.cs (IsUsed): New value; moved from FieldBase.Status + (SetMemberIsUsed, IsUsed): New methods, encapsulate IsUsed. + + * delegate.cs (ResolveMethodGroupExpr): Call SetMemberIsUsed. + + * ecore.cs (FieldExpr.ResolveMemberAccess): Call SetMemberIsUsed for + contants. + (PropertyExpr.ResolveAccessors): Call SetMemberIsUsed when delegate + is used. + + * expression.cs (OverloadResolve): Call SetMemberIsUsed. when method + is used. + + * rootcontext.cs (RootContext.EmitCode): Call VerifyMembers in extra run + to avoid the problems with nested types. + +2005-04-05 Abin Thomas + Anoob V.E + Harilal P.R + Raja R Harinath + + Fix #73820. + * delegate.cs (Define): Emit ParamArrayAttribute for 'params' + attribute. + * typemanager (GetConstructor): Make public. + +2005-04-05 John Luke + Raja R Harinath + + Fix #62232. + * typemanager.cs (IsUnmanagedType): Check non-public fields of a + struct too. Return false quicker in a few cases. + (VerifyUnManaged): Use it. + +2005-04-05 Raja R Harinath + + Fix #74041. + * statement.cs (Block.Resolve): Initialize 'unreachable' to false, + not 'unreachable_seen'. + +2005-04-04 Marek Safar + + * attribute.cs (Attribute.GetValue): Removed unused. + + * codegen.cs (CodeGen.TrimExt): Removed unused. + + * cs-parser.jay (output): Removed unused. + + * cs-tokenizer.cs (hex_digits): Removed unused. + + * enum.cs (MapToInternalType, GetEnumeratorName): Removed unused. + + * expression.cs (Indirection.LoadExprValue): Removed unused. + (ArrayCreation.ExpressionToArrayArgument): Removed unused. + + * iterators.cs (Iterator.param_types): Removed unused. + + * statement.cs (Goto.block): Removed unused. + (ToplevelBlock.did): Removed unused. + (Switch.ResolveConstantSwitch): Removed unused. + +2005-04-01 Ben Maurer + + * rootcontext.cs: Allow mcs to bootstrap with the compilation + resetting thingy. + +2005-04-01 Raja R Harinath + + Fix #74232 and cs0208-3.cs. + * expression.cs (ComposedCast.DoResolveAsTypeStep): Add CS0208 check. + * typemanager.cs (IsUnmanagedType): Don't allow 'object' as an + unmanaged type. Don't use FieldBuilders when 't' is a + TypeBuilder. Use ModFlags and MemberType fields. + * class.cs (MemberBase.member_type): Rename from MemberType. + (MemberBase.MemberType): New property. Determines member_type on + demand. + (MemberBase.DoDefine): Don't initialize MemberType here. + (FieldMember.Define): Likewise. + +2005-04-01 Marek Safar + + Fix #74241 + * class.cs (Event.Emit): Call Add/Remove emit even for interfaces. + Attributes are emitted there. + +2005-04-01 Raja R Harinath + + * cs-tokenizer.cs (consume_identifier): Treat 'partial' as a + keyword in 'partial enum' too. + * cs-parser.jay (enum_declaration): Add CS0267 check ('partial enum' + is not allowed). + Report from Kamil Skalski . + + Fix #74309. + * rootcontext.cs (ResolveTree): The 'root.Interfaces' list can + have partial containers too. + + * ecore.cs (SimpleName.SimpleNameResolve): Move 'invariant meaning + in block' checks to Block.CheckInvariantMeaningInBlock. + * statement.cs (Block.GetKnownVariableInfo): Make private. + (Block.IsVariableUsedInChildBlock): Remove. + (Block.IsVariableUsedInBlock): Likewise. + (Block.CheckInvariantMeaningInBlock): New. Show location of + conflicting declaration. + (Block.AddVariable): Make error messages less long-winded and more + specific. Show location of conflicting declaration. + * parameter.cs (Parameters.Location): New readonly property. + +2005-03-31 Raja R Harinath + + Clean up semantics of invoking ResolveMemberAccess. + * ecore.cs (SimpleName.DoSimpleNameResolve): If a MemberExpression + can have an instance, ensure that we pass in a non-TypeExpression + to ResolveMemberAccess. Tighten up IdenticalNameAndTypeName checks. + (MemberExpr.DoSimpleNameResolve): Remove type_is_inferred + argument. Update to changes and simplify. + (FieldExpr.Emitinstance): Remove CS0120 check. + (PropertyExpr.EmitInstance): Likewise. + * expression.cs (Argument.Resolve): Likewise. + (Invocation.DoResolve): Update to changes in semantics of + InstanceExpression. + +2005-03-31 Marek Safar + + Fix #74241 + * class.cs (AbstractPropertyEventMethod.EmitMethod): Enable emit method + customization. + + * decl.cs (MemberCache.AddMethods): Fix infinite loop. + +2005-03-31 Raja R Harinath + + Fix difference in behaviour with commandline invocation. + * driver.cs (Driver.Reset): New. + (CompilerCallableEntryPoint): Call it. + + * statement.cs (If.Resolve): Avoid spurious "uninitialized + variable" warnings if the boolean expression failed to resolve. + +2005-03-30 Sebastien Pouliot + + * attribute.cs: Fix the union of several permissions when some of them + are unrestricted (so the result isn't an unrestricted permission set). + Fix #74036. + +2005-03-30 Raja R Harinath + + * ecore.cs (MemberExpr): New class. Convert from interface + IMemberExpr. + (MemberExpr.ResolveMemberAccess): Refactor and move here from + MemberAccess.ResolveMemberAccess. Tighten up pre-conditions and + error checks. + (MethodGroupExpr, FieldExpr, PropertyExpr, EventExpr): Update. + (MethodGroupExpr.IsExplicitImpl): Remove. + (Expression.GetFieldFromEvent): Remove. + (SimpleName.MemberStaticCheck): Remove. + (SimpleName.DoSimpleNameResolve): Update to changes. + * expression.cs (MemberAccess.ResolveMemberAccess): Refactor. + (MemberAccess.IdenticalNameAndTypeName): Remove. + (MemberAccess.error176): Move to MemberExpr. + (MemberAccess.DoResolve): Update to changes. + (BaseAccess.DoResolve): Likewise. + +2005-03-30 Marek Safar + + C# 2.0 Conditional attribute class implementation + + * attribute.cs (AttributeTester.IsAttributeExcluded): New method. + Analyzes class whether it has attribute which has ConditionalAttribute + and its condition is not defined. + + * class.cs (Class.ApplyAttributeBuilder): Add IsAttributeExcluded check. + (Class.IsExcluded): New method. Search for at least one defined + condition in ConditionalAttribute of attribute class. + +2005-03-30 Raja R Harinath + + * ecore.cs (PropertyExpr): Derive from Expression, not + ExpressionStatement. + (PropertyExpr.EmitStatement): Remove. + +2005-03-29 Raja R Harinath + + Fix #74060. + * expression.cs (MemberAccess.ResolveMemberAccess): Allow the + internal field "value__" of an enum be private. The examples for + "value__" that I found on MSDN all used FieldAttributes.Private. + + * decl.cs (MemberCache.AddMethods): Use C# terminology in warning. + Don't mention IL method attribute names. + + Fix #47991. Remove a TODO. + * statement.cs (Block.Toplevel): Make into a field. + (Block.Parameters): Move into ToplevelBlock. + (Block.known_variables): Rename from child_variable_names. + (Block.Block): Remove variants that take Parameters. Initialize + 'Toplevel' with the immediately surrounding toplevel block. + (Block.AddKnownVariable): Rename from AddChildVariableName. Add a + LocalInfo parameter. + (Block.GetKnownVariableInfo): New. + (Block.IsVariableNameUsedInChildBlock): Update. + (Block.IsVariableNameUsedInBlock): New. Checks if a name is used in + the block, even though it may not be in scope. + (Block.AddVariable): Remove Parameters parameter. Use + Toplevel.Parameters instead. + (Block.AddConstant): Remove Parameters parameter. + (Block.GetParameterReference): Update to use Toplevel.Parameters. + (Block.IsParamaterReference): Likewise. + (Block.IsLocalParameter): Likewise. Simplify a lot. + (ToplevelBlock.Parameters): New. Moved from Block. + (ToplevelBlock.ToplevelBlock): Update to changes. Always + initialize Parameters to a non-null value. + * cs-parser.jay: Update to changes. + * ecore.cs (SimpleName.SimpleNameResolve): Emit cs0136 error for + simple names that mean different things in the same block. Use + Block.IsVariableNameUsedInBlock. + +2005-03-28 Raja R Harinath + + * typemanager.cs (TypeHandle.BaseType): Make into an IMemberContainer. + (TypeHandle.TypeHandle): Use LookupMemberCache rather than + GetTypeHandle. It is possible for a reflected type to derive from + a TypeBuilder (e.g., int[] derives from the TypeBuilder + System.Array during mscorlib compilation). + * decl.cs (MemberCache.MemberCache): If the base cache doesn't + contain a method_hash, don't create one either. Don't create a + deep copy of the base cache's method_hash. + (MemberCache.SetupCache): Rename back from DeepCopy. + (MemberCache.AddMethods): Rewrite, now that method_hash isn't + already initialized. If we see an override function, add its + underlying base virtual function to the member_hash too. + + * enum.cs (Enum.LookupEnumValue): Remove debugging code. + +2005-03-26 Raja R Harinath + + Fix #73038. + * assign.cs (Assign.DoResolve): When the RHS of an assignment + fails to resolve, ensure that the LHS is still resolved as an + lvalue. + +2005-03-25 Raja R Harinath + + * enum.cs (Enum.DefineType): Set ec.InEnumContext and + ec.ContainerType. + (Enum.current_ec): Remove. + (Enum.LookupEnumValue): Remove EmitContext argument. + Just uses the one created during DefineType. + (Enum.FindMembers): Update. + * expression.cs (MemberAccess.DoResolve): Update. + +2005-03-22 Marek Safar + + * assign.cs (Assign.DoResolve): Check for CS1717 when + source and target are same (uses Equals). + + * expression.cs (LocalVariableReference, ParameterReference, + This): Implemented Equals, GetHashCode. + + * statement.cs (Block.GetParameterReference): Removed useless + local variable. + +2005-03-22 Raja R Harinath + + Fix cs0128.cs + * statement.cs (Block.AddVariable): Ensure that we skip implicit + blocks before deciding whether the error is cs0136 or cs0128. + + * cs-parser.jay: Pass MemberName to RootContext.Tree.RecordDecl. + (using_alias_directive, using_namespace_directive): Pass + MemberName, not an expression to Namespace.UsingAlias and + Namespace.Using. + (MakeName): Use the MemberName of the namespace. + * namespace.cs (Namespace.MemberName): New. + (UsingEntry.UsingEntry): Take a MemberName, not an expression. + (AliasEntry.AliasEntry, Namespace.Using, Namespace.UsingAlias): + Likewise. + * decl.cs (MemberName.Name): Make readonly. + (MemberName.FromDotted): New "constructor". + (MemberName.Equals, MemberName.GetHashCode): Implement overrides. + (MemberCore.Name): Compute from MemberName on demand. + (MemberCore.SetMemberName): Provide a way to change the + MemberName. + (MemberCore.AddToContainer): Don't take a fullname parameter. + * class.cs (TypeContainer.AddToMemberContainer): Don't add the + fully qualified name of the container to the member name. + (TypeContainer.AddToTypeContainer): Use a fully qualified name + only if the type is a member of the root container. + (TypeContainer.AddMethod, TypeContainer.AddProperty): Use + MemberName.Left rather than searching for an embedded ".". + (PartialContainer.CreatePart): Update to changes in RootContext. + (MemberBase.ShortName): Turn into a property. Use + MemberCore.SetMemberName. + (MemberBase.ExplicitInterfaceName): Remove. + (MemberBase.UpdateMemberName): Remove. + (AbstractPropertyEventMethod.UpdateName): Use SetMemberName. + (PropertyBase.SetMemberName): New override. + * tree.cs (Tree.RecordDecl): Take a MemberName and use it as hash key. + (Tree.GetDecl): New. + (Tree.AllDecls): Rename from Decls. + * attribute.cs, enum.cs, report.cs: Update to changes. + * driver.cs (MainDriver): Use MemberName.FromDotted on + RootContext.MainClass. + +2005-03-21 Marek Safar + + * class.cs (FixedField.Define): Check for CS1664 and more sanity + checks. + + * expression.cs (ElementAccess.DoResolveLValue): Check for CS1708. + +2005-03-18 Marek Safar + + * modifiers.cs (Modifiers.PROPERTY_CUSTOM): New constant for + property accessor modifiers. + + * class.cs (FieldMember.ApplyAttributeBuilder): Don't allow apply + fixed buffer attribute (CS1716). + (PropertyMethod.HasCustomAccessModifier): When property accessor + has custom modifier. + + * ecore (PropertyExpr.DoResolve): Add CS0271 for custom accessor + modifiers. + (PropertyExpr.DoResolveLValue): Add CS0272. + +2005-03-17 Miguel de Icaza + + * convert.cs: When converting to a pointer, use the proper Conv.U + or Conv.I depending on the source data type. + + * cs-tokenizer.cs: Make the size for large decimal constants, + fixes #72957. + +2005-03-17 Martin Baulig + + * anonymous.cs (AnonymousMethod.method_modifiers): Change default + from `Modifiers.INTERNAL' to `Modifiers.PRIVATE'. Fixes #73260. + +2005-03-17 Martin Baulig + + * anonymous.cs (AnonymousMethod.EmitMethod): Changed return type + to bool so we can return an error condition. + (AnonymousDelegate.Emit): Check whether AnonymousMethod.EmitMethod() + returned an error. + +2005-03-16 Zoltan Varga + + * attribute.cs: Encode ThrowOnUnmappableChar and BestFitMapping + attributes. + +2005-03-16 Raja R Harinath + + Remove TypeManager.LookupType and TypeManager.LookupTypeDirect. + Refactor to avoid traversing the list of assemblies, and to avoid + string concatenation. + * typemanager.cs (guid_attr_type): Remove. + (negative_hits, pointers, references): Remove hashes. + (type_hash): New. + (GetConstructedType): New. Uses type_hash to handle constructed + types (arrays, references, pointers). + (GetReferenceType, GetPointerType): Use it. + (GetNestedType): New. Uses type_hash to handle nested types of + reflected types. + (LookupType, LookupTypeDirect): Remove. + (CoreLookupType): Inline parts of old LookupTypeDirect code. Use + 'types' hash and LookupTypeReflection directly. + (params_string, params_object): Use GetConstructedType. + * namespace.cs (Namespace.cached_types): New. Cache of reflected + top-level types. + (Namespace.Lookup): Use cached_types. + (NamespaceEntry.LookupNamespaceOrType): Inline the functionality + provided by old TypeManager.LookupType. + * rootcontext.cs (MakeFQN): Remove. + * decl.cs (DeclSpace.MakeFQN): Likewise. + (DeclSpace.LookupType): Use TypeManager.GetNestedType. + * expression.cs (ComposedCast.DoResolveAsTypeStep): Use + TypeManager.GetConstructedType. + * tree.cs (decl_ns_hash, LookupByNamespace): Remove. + +2005-03-15 Marek Safar + + * class.cs (MethodCore.CheckBase): Report CS1715 for properties and + indexers. + + * cs-parser.jay: Reports CS1527 for any namespace element. + + * delegate.cs (DelegateCreation.Error_NoMatchingMethodForDelegate): + Added CS0407. + + * expression.cs (ParameterReference.IsAssigned): Changed error to + CS0269. + (Error_WrongNumArguments): Moved CS0245 detection here. + + * statement.cs (Return.Resolve): Add CS1622 report. + +2005-03-11 Marek Safar + + * class.cs (StaticClass.DefineContainerMembers): Added CS0720. + +2005-03-11 Zoltan Varga + + * attribute.cs expression.cs: Get rid of some allocations. + +2004-03-11 Atsushi Enomoto + + * doc.cs : just eliminate the latest change. + +2004-03-10 Atsushi Enomoto + + * doc.cs : commented out the latest change. It breaks xml-030.cs + +2004-03-10 Atsushi Enomoto + + * doc.cs : When TypeBuilder did not create Type yet, GetEvents() will + fail. So invoke CreateType() in FindDocumentedType(). + +2004-03-10 Atsushi Enomoto + + * cs-tokenizer.cs : added IsKeyword(). + * doc.cs : Detect keyword incorrectly used as identifier. + Allow identifiers prefixed by @. + +2005-03-10 Marek Safar + + * attributes.cs (Attributes.Emit): Continue after CheckTargets. + It caused exception in namespace resolving (again!). + + * class.cs (Class.ctor): Removed exit. + (PropertyMethod.ctor): ditto. + + * codegen.cs (Codegen.Reset): Reset static data. + (Codegen.ResolveTopBlock): Forward error status from ResolveMeta. + + * cs-tokenizer.cs (Cleanup): Removed. + + * driver.cs (GetSystemDir): Rewrote to one line command. + It caused problem with unloaded dynamic modules. + (UnixParseOption): Removed Exit. + (CompilerCallableEntryPoint.InvokeCompiler): Make static. + (CompilerCallableEntryPoint.Reset): Reset suitable static data. + Now can be mcs used as library. + + * ecore.cs (Expression.ResolveBoolean): Use Location.Null for + empty location. + + * location.cs (Reset): Reset static data. + + * namespace.cs (Reset): Reset static data. + + * report.cs (Report.Reset): Reset static data. + + * rootcontext.cs (RootContext.Reset): Reset static data. + + * tree.cs (RootTypes.ctor): Use Location.Null + + * typemanager.cs (TypeManager.Reset): Reset static data. + (CoreLookupType): Removed Exit. + (TypeHandle.Reset): Reset static data. + +2005-03-10 Raja R Harinath + + Fix #73516. + * typemanager.cs (ComputeNamespaces): Import namespaces from + referenced modules too. + +2005-03-09 Raja R Harinath + + * class.cs (TypeContainer.AddToMemberContainer): Use "." rather + than '.'. + +2005-03-09 Raja R Harinath + + * decl.cs (DeclSpace.LookupType): Don't loop but recurse into + enclosing DeclSpace. This ensures that a name-lookup populates + more caches and there are fewer 'TypeExpression's. Carve out + nested type lookup into ... + (LookupNestedTypeInHierarchy): ... this. + +2005-03-09 Raja R Harinath + + Clean up a few partial-class semantics. + Fixes test-357.cs and cs1618-2.cs. + * cs-parser.jay (struct_declaration): Use 'current_class' as + parent of newly-created struct. Remove call to Register (). + Use 'pop_current_class' to complete handing the current struct. + (interface_declaration): Likewise. + (class_declaration): Likewise. + (enum_declaration): Use 'current_class' as parent of newly created + enum. + (delegate_declaration): Likewise. + (pop_current_class): New function. This is used to handle closing + up the 'current_class' and 'current_container', and pointing them + to the enclosing class/container. + (CSharpParser): Initialize 'current_class' too. + * decl.cs (MemberCore): Add check for invariant: a partial + container is not a parsed entity, and thus does not enclose any + parsed members. + (DeclSpace.TypeResolveEmitContext): Expose 'type_resolve_ec'. + (DeclSpace.BaseTypeExpr): Use it. + (DeclSpace.LookupType): Add check for invariant. + * class.cs (TypeContainer): Add check for invariant: a nested + class should have the same NamespaceEntry as its enclosing class. + (TypeContainer.EmitFieldInitializers): Make virtual. + (TypeContainer.DefineDefaultConstructor): Adhere to invariant in + MemberCore. + (TypeContainer.Register): Remove. + (TypeContainer.DefineType): Set the 'ec' of a PartialContainer to + null. Use TypeResolveEmitContext for resolving base types and + interfaces. Move initialization of Parts.TypeBuilder here from + ... + (TypeContainer.DefineNestedTypes): ... here. + (PartialContainer): Take a Namespace not a NamespaceEntry. + (PartialContainer.Create): Don't use Register. Call the + appropriate Add... function directly. + (ClassPart): Take both the PartialContainer and the enclosing + class as constructor arguments. + (ClassPart.EmitFieldInitializers): Override. + (ClassPart.PartFindNestedTypes): Remove. + (FieldBase.GetInitializerExpression): Resolve the initializer + expression in the emit context of the enclosing class. + * tree.cs (RootTypes): Remove Register (). + +2005-03-08 Marek Safar + + * cs-parser.jay: Removed CS0134. + + * driver.cs: Removed CS1901. + + * expression.cs (SizeOf.DoResolve): Don't report CS0233 + for predefined types. + +2005-03-07 Duncan Mak + + * codegen.cs (Save): Catch UnauthorizedAccessException as + well. Fixes bug #73454. + +2005-03-07 Marek Safar + + * cs-tokenizer.cs (xtoken): Add CS1035. + + * class.cs (MethodData.Define): Add CS0683. + (FieldMember.ctor): Add CS0681. + +2005-03-07 Raja R Harinath + + * ecore.cs (SimpleName.DoResolve): Rename from + SimpleName.DoResolveAllowStatic. + (SimpleName.DoSimpleNameResolve): Remove 'allow_static' argument. + Pass 'intermediate' flag to MemberStaticCheck. + (SimpleName.MemberStaticCheck): Skip "static check" only in case + of "intermediate" lookups via MemberAccess. + (SimpleName.IdenticalNameAndTypeName): New. Carved out of ... + * expression.cs (MemberAccess.IdenticalNameAndTypeName): ... this. + +2005-03-07 Raja R Harinath + + Fix #73394. + * ecore.cs (FieldExpr.EmitInstance): Catch cases of CS0120 that + slipped in because of variable names that are identical to a + builtin type's BCL equivalent ('string String;', 'int Int32;'). + (PropertyExpr.EmitInstance): Likewise. + +2005-03-04 Marek Safar + + * cs-tokenizer.cs (PreProcessPragma): Add warning 1633, 1635. + + * report.cs (warning_ignore_table): Made public. + +2005-03-04 Raja R Harinath + + Fix #73282. + * class.cs (MethodData.Emit): Pass 'container' to + container.GetObsoleteAttribute instead of 'container.Parent'. + +2005-03-03 Marek Safar + + * cs-parser.jay: Add 1534 error test. + + * iterators.cs (Yield.CheckContext): Add error 1629. + (Iterator.ctor): Save unsafe modifier. + (MoveNextMethod.DoEmit): Restore unsafe context. + + * namespace.cs (UsingAlias): Better error message. + +2005-03-03 Dan Winship + + * convert.cs (Error_CannotImplicitConversion): fix two bugs in + the warning message [#73219] + +2005-03-03 Raja R Harinath + + Fix compile with MCS 1.0.0.0. + * cs-tokenizer.cs (PreProcessPragma): Simplify w_disable and + w_restore to not depend on string constant folding. + +2005-03-03 Raja R Harinath + + * decl.cs (DeclSpace.LookupType): Remove 'silent' argument. Move + CS0246 check to users who passed 'silent = false'. + * ecore.cs (TypeLookupExpression.DoResolveAsTypeStep): Add CS0246 + check. + (SimpleName.SimpleNameResolve): Update. + * expression.cs (ComposedCast.DoResolveAsTypeStep): Add CS0246 check. + (MemberAccess.IdenticalNameAndTypeName): Update. + * doc.cs (FindDocumentedTypeNonArray): Update. + +2005-03-03 Raja R Harinath + + * codegen.cs (EmitContext): Remove ResolvingTypeTree. + * parameters.cs (ComputeAndDefineParameters): Remove. + * decl.cs (ResolveBaseTypeExpr): Don't set ResolvingTypeTree. + * delegate.cs (Define): Don't invoke ComputeAndDefineParameters. + Use GetParameterInfo. + +2005-03-02 Marek Safar + + * report.cs (StaticClass.DefineContainerMembers): Add warning 628. + +2005-03-02 Raja R Harinath + + Unify DeclSpace.LookupType and DeclSpace.FindType. + * decl.cs (DeclSpace.FindNestedType): New virtual function. This + is in charge of defining nested types on demand. + (DeclSpace.LookupType): Use it when the current_type is a + TypeBuilder. Use LookupTypeDirect for reflected types. + (DeclSpace.FindType): Remove. + (DeclSpace.LookupInterfaceOrClass): Likewise. + (DeclSpace.DefineTypeAndParents): Likewise. + * ecore.cs (SimpleName.ResolveAsTypeStep): Just call + DeclSpace.LookupType. + * doc.cs (FindDocumentedTypeNonArray): Use DeclSpace.LookupType. + * typemanager.cs (LookupType): Simplify. + (AddUserType): Remove type from negative_hits. + * namespace.cs (Namespace.Lookup): Use TypeManager.LookupTypeDirect. + * class.cs (TypeContainer.FindMembers): Move handling of nested + types ... + (TypeContainer.FindMembers_NestedTypes): ... here. + (TypeContainer.FindNestedType): Implement override. + (ClassPart.FindNestedType): Delegate to PartialContainer. + (ClassPart.PartFindNestedType): Looks up the nested types of the + part alone. + +2005-03-02 Martin Baulig + + * class.cs (TypeContainer.DoDefineMembers): We also need a default + static constructor in static classes. + +2005-03-01 Zoltan Varga + + * attribute.cs: Pass -1 to DefineLPArrayInternal if sizeConst or + sizeParamIndex is not specified. + +2005-03-01 Marek Safar + + Fix #73117 + * report.cs (WarningMessage.IsEnabled): Missing null check. + +2005-02-28 Marek Safar + + * attribute.cs (DefinePInvokeMethod): Fix, all data are stored + in the fields and not in the properties. + +2005-02-28 Zoltan Varga + + * attribute.cs (GetMarshal): Marshal SizeConst and SizeParamIndex + fields as well. + +2005-02-28 Marek Safar + + * attribute.cs: Small refactoring (improved robustness). + (ImplOptions, UnmanagedType, UsageAttribute): Removed members. + (ValidateGuid): Removed. + (Resolve): Removed referenced to above mentioned. + (GetAttributeUsage): Made private and changed to work without + class assistance. + (GetIndexerAttributeValue): Don't crash. + (GetConditionalAttributeValue): Ditto. + (GetClsCompliantAttributeValue): Ditto. + (ExtractSecurityPermissionSet): All attributes exceptions are + error 648. + (GetPropertyValue): New helper. + (GetMethodImplOptions): New method. + (DefinePInvokeMethod): Reuse common code. Implemented handling of + some missing properties. + + * class.cs (ClassOrStruct.ApplyAttributeBuilder): Updated. + (Method.ApplyAttributeBuilder): Updated. + + * decl.cs (DeclSpace.ApplyAttributeBuilder): Don't catch shared + exception. + +2005-02-28 Raja R Harinath + + Fix #73052. + * report.cs (Report.SymbolRelatedToPreviousError): Handle + non-simple types (array, pointer, reference). + +2005-02-28 Marek Safar + + * cs-parser.jay: Add errors 1617, 650, 1007, 531, 547, 548 + + * class.cs (MethodCore.IsDuplicateImplementation): Special error + for operators. + (Method.CheckBase): Catch wrong destructor here. + (MethodData.Define): Add errors 550, 668. + + * cs-tokenizer.cs (PreProcessPragma): Add warning 1634. + + * ecore.cs (PropertyExpr.DoResolveLValue): Fixed wrong error code. + + * pending.cs (VerifyPendingMethods): Add error 551. + + * typemanager.cs (CSharpName): Next error report helper. + +2005-02-25 Marek Safar + + * attribute.cs (Atttribute.Resolve): Add cache for parameter-less + attributes. Removed useless attribute double check. + It saves almost 2MBs for corlib. + +2005-02-25 Raja R Harinath + + Fix #72924. + * statement.cs (ExpressionStatement.Resolve): Make robust to being + called twice in case of error. + +2005-02-23 Chris Toshok + + Fix compiler portions of #72827. + * statement.cs (Block.Emit): call Begin/EndScope on the + EmitContext instead of the ILGenerator. + + * codegen.cs (EmitContext.BeginScope): new method, call + ILGenerator.BeginScope as well as the SymbolWriter's OpenScope (if + we have one.) + (EmitContext.BeginScope): same, but EndScope and CloseScope + + * symbolwriter.cs (SymbolWriter.OpenScope): get the current il + offset and call the superclass's OpenScope(int) with it. + (SymbolWriter.CloseScope): get the current il + offset and call superclass's CloseScope(int) with it. + +2005-02-23 Marek Safar + + * anonymous.cs (AnonymousMethod.Compatible): Fixed to report + CS1677 for out and ref as well. + + * class.cs (Method.Define): Add error CS1599 detection. + + * cs-parser.jay: Add CS1609, CS1670, CS1627 detection. + + * cs-tokenizer.cs (xtoken): Add error CS1646 detection. + + * delegate.cs (Delegate.Define): Add error CS1599 detection. + + * support.cs.cs (ModifierDesc): New helper method. + +2005-02-23 Raja R Harinath + Abin Thomas + Anoob V E + Harilal P R + + Fix #57851, #72718. + * class.cs (ConstructorBuilder.Resolve): Make sure that the second + MemberLookup (used for error reporting) actually returns a result. + Fix error report number (122, not 112). + +2005-02-22 Abin Thomas + Anoob V E + Harilal P R + + Fix #71134. + * pending.cs (PendingImplementation.GetAbstractMethods): + Find NonPublic members too. + +2005-02-22 Marek Safar + + * expression.cs.cs (ConditionalLogicalOperator.DoResolve): + Fixed error 217. + + * class.cs (MethodCore.CheckMethodAgainstBase): + Add error 239 report. + +2005-02-21 Raja R Harinath + + Fix #68955. + * expression.cs (Invocation.IsApplicable): Make public. + (Invocation.IsParamsMethodApplicable): Likewise. + * delegate.cs (Delegate.VerifyApplicability): Don't use + Invocation.VerifyArgumentCompat for parameter applicability + testing. Use Invocation.IsApplicable and + Invocation.IsParamsMethodApplicable. + +2005-02-21 Marek Safar + + * ecore.cs (PropertyExpr.DoResolve): Add error 214 report. + + * class.cs (Operator.Define): Add error 217 report. + +2005-02-21 Raja R Harinath + + * namespace.cs (UsingEntry.Resolve): Undo change below. + +2005-02-21 Raja R Harinath + + Fix #72756. + * ecore.cs (Expression.MemberLookupFailed): Add argument to + disable the error message when the extended MemberLookup also + fails. + (Expression.MemberLookupFinal): Update. + (SimpleName.DoSimpleNameResolve): Update. + * expression.cs (MemberAccess.ResolveNamespaceOrType): + Don't use MemberLookupFinal. + (New.DoResolve): Update. + (BaseAccess.CommonResolve): Update. + +2005-02-21 Raja R Harinath + + Fix #72732. + * attribute.cs (Attribute.ResolveType): If a 'resolve_error' had + occured previously, don't resolve again. + +2005-02-21 Marek Safar + + Fix #69949 + * attribute.cs (Attribute.GetAttributeUsage): Add EmitContext + argument. Call ResolveAttributeUsage for unresolved. + when types doesn't match ctor arguments. + + * class.cs (DoDefineMembers.TypeContainer): Removed safety check + for nested attribute classes. + (Class.attribute_usage): Removed. + (Class.ResolveAttributeUsage): Resolves AttributeUsageAttribute + for attribute class. + + * ecore.cs (IsAttribute): Removed. + + * namespace.cs (UsingEntry.Resolve): Don't destroy NamespaceEntry. + + * rootcontext.cs (RegisterAttribute): Removed, attributes are + now normal types. + (attribute_types): Removed. + (EmitCode): Global attributes are emited as the latest. + +2005-02-18 Marek Safar + + * class.cs (EmitFieldInitializers): Don't emit field initializer + for default values when optimilization is on. + + * constant.cs (Constant.IsDefaultValue): New property. + + * driver.cs: Add /optimize handling. + + * constant.cs, + * ecore.cs, + * literal.cs: Implement new IsDefaultValue property. + + * rootcontext.cs (Optimize): New field, holds /optimize option. + +2005-02-18 Raja R Harinath + + Fix crasher in re-opened #72347. + * namespace.cs (Namespace.Lookup): Return null if + DeclSpace.DefineType returns null. + + Fix #72678. + * expression.cs (Argument.Resolve): Handle a case of CS0120 here. + +2005-02-18 Raja R Harinath + + Fix remainder of #63202. Change semantics of DoResolveLValue: it + now returns null if it cannot resolve to an lvalue. + * ecore.cs (Expression.DoResolveLValue): Return 'null' by default. + (Expression.ResolveLValue): Emit CS0131 error if DoResolveLValue + returned null. Remove check for SimpleName. + (EventExpr.DoResolveLValue): New. + * iterators.cs (Iterator.FieldExpression.DoResolveLValue): New. + * expression.cs (Argument.Error_LValueRequired): New. Move CS1510 + error from ... + (Argument.Resolve): ... here. Use it. Use DoResolveLValue to + avoid CS0131 error. + (Unary.ResolveOperator): Move CS0211 check ... + (Unary.DoResolve): ... here. Use DoResolveLValue to avoid + CS0131 error. + (Unary.DoResolveLValue): Simplify. + (AddressOf.DoResolveLValue): New. + (ArrayAccess.DoResolveLValue): New. + +2005-02-16 Marek Safar + + * attribute.cs (Attribute.Resolve): Add arguments casting for + when types doesn't match ctor arguments. + +2005-02-16 Raja R Harinath + + Fix parts of #63202. + * expression.cs (UnaryMutator.ResolveOperator): Remove redundant + lookup of operator in base type. Ensure that all checks happen + when the operator resolves to an "op_..." method. + +2005-02-15 Raja R Harinath + + Fix #71992. + * namespace.cs (NamespaceEntry.LookupNamespaceOrType): Add + 'ignore_cs0104' parameter. Pass it to ... + (NamespaceEntry.Lookup): ... this. + * decl.cs (DeclSpace.LookupType): Add 'ignore_cs0104' parameter. + * ecore.cs (SimpleName.ResolveAsTypeStep): Update. + (TypeLookupExpression.DoResolveAsTypeStep): Update. + * expression.cs (MemberAccess.IdenticalNameAndTypeName): + Update. Request that cs0104 errors be ignored. + (ComposedCast.ResolveAsTypeStep): Update. + +2005-02-14 Raja R Harinath + + Fix #59209. + * expression.cs (Invocation.BetterFunction): Remove support for + comparing virtual functions and their overrides. + (Invocation.IsOverride): New. + (Invocation.OverloadResolve): Don't consider 'override' functions + during candidate selection. Store them in a lookaside list. + If the selected method is a 'virtual' function, use the list to + find any overrides that are closer to the LHS type. + +2005-02-14 Marek Safar + + * expression.cs (New.DoResolve): Add complex core type reduction. + (New.Constantify): Converts complex core type syntax like 'new int ()' + to simple constant. + +2005-02-14 Raja R Harinath + + * decl.cs (EntryType.EntryType): New constructor to create an + updated copy of a cache entry. + (MemberCache.AddMethods): Use it. + (MemberCache.ClearDeclaredOnly): Remove. + (MemberCache.MemberCache): Update. + +2005-02-11 Miguel de Icaza + + * codegen.cs (EmitContext): Introduce the `MethodIsStatic' + variable. This one is represents the actual low-level declaration + of the method, as opposed to the semantic level `IsStatic'. + + An anonymous method which is hosted into a static method might be + actually an instance method. IsStatic would reflect the + container, while MethodIsStatic represents the actual code + generated. + + * expression.cs (ParameterReference): Use the new MethodIsStatic + instead of IsStatic. + + * anonymous.cs (AnonymousMethod.Compatible): Pass the + Modifiers.STATIC to the Anonymous' Method EmitContext if static is + set on the current EmitContext. + + * expression.cs (Cast): Overload DoResolveLValue so we can pass + resolve our casted expression as an LValue. This triggers the + proper LValue processing that is later required by Assign. + + This fixes 72347. + + * cs-tokenizer.cs (pp_and): recurse on pp_and, fixes #61903. + +2005-02-11 Marek Safar + + C# 2.0 Fixed buffer implementation + + * anonymous.cs: Update after RegisterHelperClass renaming. + + * attribute.cs (AttributeTester.fixed_buffer_cache): + Cache of external fixed buffers. + (AttributeTester.GetFixedBuffer): Returns IFixedBuffer + implementation if field is fixed buffer else null. + + * class.cs + (TypeContainer.AddField): Accept FieldMember instead of Field. + (FieldBase.IsFieldClsCompliant): Extracted code from + VerifyClsCompliance descendant customization. + (FixedField): New class handles fixed buffer fields. + (FixedFieldExternal): Keeps information about imported fixed + buffer. + (IFixedField): Make access to internal or external fixed buffer + same. + + * cs-parser.jay: Add fixed buffer parsing. + + * ecore.cs (FieldExpr.Emit): Add special emit case for fixed + buffer. + + * expression.cs (Indirection): Extended implementation to accept + fixed buffer field. + (PointerArithmetic.Emit): Get element from fixed buffer as well. + (ElementAccess.MakePointerAccess): Get type as parameter. + (DoResolve): Add fixed buffer field expression conversion. + (DoResolveLValue): Ditto. + (FixedBufferPtr): New class. Moved most of original ArrayPtr. + (ArrayPtr): Derives from FixedBufferPtr. + (ArrayPtr.Emit): Add extra emit for array elements. + + * flowanalysis.cs.cs (StructInfo): Use FieldMember. + + * rootcontext.cs (CloseTypes): Emit CompilerGenerated attribute + for compiler generated types. + (RegisterCompilerGeneratedType): Renamed from RegisterHelperClass. + + * statement.cs (Fixed): Refactored to be easier add fixed buffer + and consume less memory. + (Fixed.Resolve): Add fixed buffer case. + + * typemanager.cs (compiler_generated_attr_ctor, + fixed_buffer_attr_ctor): Add new 2.0 compiler attributes. + (HasElementType): Add our own implementation to work on every + runtime. + +2005-02-11 Miguel de Icaza + + * anonymous.cs (CaptureContext): Track whether `this' has been + referenced. + + * expression.cs (This.ResolveBase): Call CaptureThis. Before we + only captured `this' if it was implicitly done (instance + methods/variables were used). + + * codegen.cs (EmitContext.CaptureThis): New method to flag that + `this' must be captured. + +2005-01-30 Miguel de Icaza + + * anonymous.cs (CreateMethodHost): If there Scope.ScopeTypeBuilder + is null it means that there has been no need to capture anything, + so we just create a sibling. + + Renamed `EmitHelperClasses' to `EmitAnonymousHelperClasses' + + Just a partial fix. The other half is fairly elusive. + +2005-02-10 Raja R Harinath + + Fix #52586, cs0121-4.cs. + * decl.cs (MemberCache.DeepCopy): Rename from SetupCache. Take + and return a hashtable. + (MemberCache.ClearDeclaredOnly): New. + (MemberCache.MemberCache): Update to change. Make a deep copy of + the method_hash of a base type too. + (MemberCache.AddMethods): Adapt to having a deep copy of the base + type methods. Overwrite entries with the same MethodHandle so + that the ReflectedType is correct. The process leaves in base + virtual functions and their overrides as distinct entries. + (CacheEntry): Now a class instead of a struct. It shouldn't alter + matters since it was boxed in a ArrayList before. + (CacheEntry.Member, CacheEntry.EntryType): Remove 'readonly' + modifier. + * expression.cs (Invocation.BetterFunction): Simplify. Handle the + case of a virtual function and its override (choose the overload + as better). + (Invocation.OverloadResolve): Avoid 'override' members during + 'applicable_type' calculation. + +2005-02-09 Raja R Harinath + + Combine two near-redundant caches. + * typemanager.cs (method_params): Rename from method_internal_params. + (TypeManager.GetParameterData): New. Replace + Invocation.GetParameterData. + (TypeManager.LookupParametersByBuilder): Remove. + * expression.cs (Invocation.method_parameter_cache): Remove. + (Invocation.GetParameterData): Remove. + Update to changes. + * anonymous.cs, attribute.cs, convert.cs, delegate.cs: + Update to changes. + +2005-02-08 Raja R Harinath + + Fix #72015. + * delegate.cs (Delegate.DefineType): When bootstrapping corlib, if + TypeManager.multicast_delegate_type is null, resolve it by looking + up "System.MulticastDelegate". + * rootcontext.cs (RootContext.ResolveCore): Simplify. + +2005-02-07 Abin Thomas (NOSIP) + Anoob V.E (NOSIP) + Harilal P.R (NOSIP) + + Fix cs0164.cs. + * statement.cs (LabeledStatement.Resolve): Don't set 'referenced'. + (LabeledStatement.AddReference): New. Set 'referenced'. + (Goto.Resolve): Use it. + +2005-02-05 John Luke + + * driver.cs: remove duplicate -doc line in Usage () + +2005-02-04 Raja R Harinath + + * location.cs (Location.AddFile): Fix CS2002 error report. + +2005-02-02 Martin Baulig + + * delegate.cs (Delegate.DefineType): Report an internal error if + TypeManager.multicast_delegate_type is null. See bug #72015 for + details. + +2005-02-02 Raja R Harinath + + Fix a crasher in a variant of #31984. + * const.cs (Constant.CheckBase): New override that defers the + new-or-override check in case the base type hasn't been populated + yet. + (Constant.Define): Ensure the new-or-override check is performed. + +2005-02-01 Duncan Mak + + * const.cs (LookupConstantValue): Check that `ce' is not null + before calling GetValue (). + +2005-02-01 Raja R Harinath + + Fix test-334.cs (#69519). + * cs-parser.jay (using_alias_directive): Pass in an expression to + NamespaceEntry.UsingAlias. + (using_namespace_directive): Pass in an expression to + NamespaceEntry.Using. + (namespace_name): Don't flatten to a string. + * namespace.cs (NamespaceEntry.AliasEntry): Store an expression. + (NamespaceEntry.AliasEntry.Resolve): Lookup using + ResolveAsTypeStep. + (NamespaceEntry.UsingEntry): Likewise. + (NamespaceEntry.Using,NamespaceEntry.UsingAlias): Update to + changes. + (NamespaceEntry.LookupForUsing): Remove. + (NamespaceEntry.LookupNamespaceOrType): Add support for dotted + names. + (NamespaceEntry.Lookup): Remove support for dotted names. + +2005-02-01 Raja R Harinath + + * namespace.cs (NamespaceEntry.NamespaceEntry): Simplify, and + split into two. + (NamespaceEntry.ImplicitParent): Compute on demand. + (NamespaceEntry.Doppelganger): New implicit namespace-entry that + parallels the current. + (NamespaceEntry.LookupForUsing): Use it. + (NamespaceEntry.Lookup): If the current namespace-entry is + implicit, don't search aliases and using tables. + +2005-02-01 Raja R Harinath + + Fix #31984. + * class.cs (TypeContainer.DoDefineMembers): Don't initialize + BaseCache here. + (TypeContainer.BaseCache): Compute on demand. + (TypeContainer.FindMembers): Define constants and types if they're + not already created. + (FieldMember.Define): Move resetting of ec.InUnsafe before error + check. + * const.cs (Constant.Define): Make idempotent. + +2005-01-29 Miguel de Icaza + + * pending.cs: Produce better code (no nops produced by using Ldarg + + value). + + * pending.cs (PendingImplementation.DefineProxy): It was not `arg + i - 1' it should be arg + 1. + + Fixes bug #71819. + +2005-01-28 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType): Make private + non-virtual. + (Attribute.ResolveType): Make virtual. + (GlobalAttribute.ResolveType,GlobalAttribute.Resolve): Simplify + handling of RootContext.Tree.Types. + +2005-01-27 Raja R Harinath + + Update attribute-handling to use the SimpleName/MemberAccess + mechanisms. + * cs-parser.jay (attribute): Pass in an expression to the + constructors of Attribute and GlobalAttribute. + * attribute.cs (Attribute): Take an expression for the name. + (Attribute.ResolvePossibleAttributeTypes): New. Resolves the + passed in attribute name expression. + (Attribute.CheckAttributeType): Use it. + * ecore.cs (FullNamedExpression.ResolveAsTypeStep): New. + * expression.cs (MemberAccess.ResolveAsTypeStep): Move body to ... + (MemberAccess.ResolveNamespaceOrType): ... here. Add 'silent' + argument to prevent error messages if the lookup fails. + +2005-01-27 Marek Safar + + * expression.cs (Indirection): Implemented IVariable interface + to support indirection in AddressOf operator. + (PointerArithmetic.Emit): Add optimalization for case where + result can be precomputed. + +2005-01-26 Martin Baulig + + * class.cs (TypeContainer.AttributeTargets): Return the correct + AttributeTargets depending on our `Kind' instead of throwing an + exception; fixes #71632. + +2005-01-26 Marek Safar + + Fix #71257 + * expression.cs (MemberAccess.ResolveMemberAccess): Add CS0176 test for + constant members. + +2005-01-25 Raja R Harinath + + Fix #71602. + * expression.cs (MemberAccess.DoResolve): Don't complain with + cs0572 when the LHS of a member access has identical name and type + name. + +2005-01-25 Marek Safar + + Fix #71651, #71675 + * attribute.cs (ExtractSecurityPermissionSet): Catch exceptions from + CreatePermission. + Create custom PermissionSet only for PermissionSetAttribute. + +2005-01-24 Marek Safar + + Fix #71649 + * class.cs (StaticClass.DefineContainerMembers): Enable enums and + delegates in static class. + +2005-01-24 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + merging an implicit block, just use its reachability. + + * statement.cs (Block.Resolve): Make the unreachable code check + work wrt. implicit blocks; see test-337 from #63842. + +2005-01-21 Alp Toker + + * cs-parser.jay: destructor_declaration's container is PartialContainer + not Class when partial types are used, so use Kind prop instead of + 'is'. + +2005-01-22 Miguel de Icaza + + * cs-parser.jay: Improve error reporting when an interface + declares new types. + +2005-01-20 Dick Porter + + * support.cs: SeekableStreamReader fix from Sandor Dobos + (dobos_s@ibcnet.hu) to cope with Position setting when multibyte + chars are read. Fixes bug 70369. + +2005-01-20 Raja R Harinath + + * cs-parser.jay (catch_clause): Simplify current_block handling + somewhat. + +2005-01-17 Miguel de Icaza + + * convert.cs (ImplicitStandardConversionExists): Synchronize the + code with ImplicitStandardConversion to handle the implicit + conversion of method groups into valid delegate invocations. + + The problem is that in parameter handling we were using this code + path. Fixes bug #64698 + +2005-01-19 Raja R Harinath + + * cs-parser.jay: Fix several infelicities. + - Avoid assigning to the parser value stack. Code like + '$3 = null' is unclean. Synthesize a value for the code block + instead. + - Avoid using oob_stack for storing location information. Use ... + (_mark_): ... this. New (empty) rule. Saves the current location + in $$. + (foreach_statement): Avoid using oob_stack for current_block + handling. Use technique used in for_statement and + using_statement. Synthesize a value for the code block to store + additional intermediate information. + +2005-01-13 Miguel de Icaza + + * ecore.cs (IsAccessorAccessible): Accessibility to private fields + of a different type is only allowed to private fields of a + containing type, not on fields of a base class. + + See test-174.cs and error cs0122-9.cs + +2005-01-13 Raja R Harinath + + Fix test-335.cs (bug #58126). + * cs-parser.jay (argument): Split out non-expression parts of the + rule into 'non_simple_argument'. + (invocation_expression): Support parenthesized invocations with + multiple arguments, and with single non-simple arguments. + +2005-01-13 Raja R Harinath + + * cs-tokenizer.cs (xtoken): Reset 'comments_seen' in a couple more + places. + +2005-01-12 Raja R Harinath + + Fix cs0038-1.cs, cs1640-6.cs. + * ecore.cs (Expression.Resolve): Remove special-case for + SimpleName in error-handling. + (Expression.almostMatchedMembers): Relax access permission to + protected. + (Expression.MemberLookupFailed): Handle duplicates in + almostMatchedMembers list. + (SimpleName.DoSimpleNameResolve): Catch CS0038 errors earlier. + * expression.cs (New.DoResolve): Report CS1540 for more cases. + * typemanager.cs (GetFullNameSignature): Use the MethodBase + overload if the passed in MemberInfo is a MethodBase. + +2005-01-12 Marek Safar + + Fix #70749 + * attribute.cs (ExtractSecurityPermissionSet): Don't report error + for non-CAS & merge permission sets properly. + +2005-01-11 Raja R Harinath + + Improve standard-compliance of simple name and member access + resolution. Fixes bugs #52697, #57200, #67520, #69519. + * ecore.cs (FullNamedExpression): New abstract base class + for Namespaces and TypeExpressions. + (ResolveFlags.SimpleName): Remove. + (SimpleName): Remove support for dotted names. + (SimpleName.ResolveAsTypeStep): Simplify. Now just a wrapper to + DeclSpace.FindType and DeclSpace.LookupType. + (SimpleName.DoSimpleNameResolve): Remove support for dotted names. + (Expression.ExprClassName): Make member function. + * expression.cs (MemberAccess.ResolveAsTypeStep): Support LHS being + a namespace. Remove creation of dotted "SimpleName"s. + (MemberAccess.DoResolve): Likewise. + * decl.cs (DeclSpace.Cache): Make private. + (DeclSpace.LookupInterfaceOrClass): Return a FullNamedExpression. + (DeclSpace.FindType): Update. + (DeclSpace.LookupType): Move here from RootContext. Return a + FullNamedExpression. + * namespace.cs (Namespace): Derive from FullNamedExpression + so that it can be part of expression resolution. + (Namespace.Lookup): Return an FullNamedExpression. + (NamespaceEntry.LookupAlias): Lookup aliases only in current + namespace. + * rootcontext.cs (NamespaceLookup): Remove. + (LookupType): Move to DeclSpace. + * attribute.cs (CheckAttributeType): Update. + * doc.cs (FindDocumentedType): Remove allowAlias argument. + (FindDocumentedTypeNonArray): Likewise. + +2005-01-11 Raja R Harinath + + Fix cs0509.cs, cs1632.cs. + * class.cs (TypeContainer.GetNormalBases): Don't assume !IsClass + is the same as IsInterface. + (TypeContainer.GetClassBases): Likewise. + * statement.cs (LabeledStatement.ig): New field. + (LabeledStatement.LabelTarget): Save ILGenerator which created the + label. + (LabeledStatement.DoEmit): Check that the label was created with + the same ILGenerator. + +2005-01-10 Marek Safar + + Fix #71058 + * attribute.cs (GetMethodObsoleteAttribute): Need to transform + accessors to its properties. + + * ecore.cs (PropertyExpr): Add AccessorTable to help track back + from accessors to property. + +2005-01-10 Marek Safar + + Fix #70722 + * class.cs (MethodCore.CheckBase): Test base method obsoleteness + only for overrides. + +2005-01-08 Miguel de Icaza + + * attribute.cs: Check for null and empty strings. + + I have lost another battle to Paolo. + +2005-01-07 Marek Safar + + Fix #70942 + * class.cs (PropertyMethod): Set Parent field in ctors. + (SetMethod.InternalParameters): Add unsafe switch hack. + Override MarkForDuplicationCheck where it is appropriate. + + * decl.cs (MemberCore.MarkForDuplicationCheck): New method. + It says whether container allows members with the same name. + Base default is no. + (DeclSpace.AddToContainer): Use MarkForDuplicationCheck. + Removed is_method parameter. + +2005-01-06 Duncan Mak + + * cs-tokenizer.cs (xtoken): Redo the work for signaling CS1040 + because the previous change led to incorrect reporting of CS1032 + ("Cannot define/undefine preprocessor symbols after first token in + file"). Instead of using `tokens_seen' as the only flag that + triggers CS1040, introduce `comments_seen'. This new flag is used + to signify having seen comments on the current line, so it is + unset after a newline. + +2005-01-06 Atsushi Enomoto + + * doc.cs : When searching for a type, find nested type too. + This fixes bug #71040. + +2005-01-06 Atsushi Enomoto + + * doc.cs : + - Warn missing member comment on those classes which also does not + have doc comments. Fixed bug #71041. + - Don't warn missing doc comment on default constructor. + Fixed bug #71042. + +2005-01-06 Duncan Mak + + * cs-tokenizer.cs (xtoken): After handling traditional C-style + comments, set `tokens_seen' to true. This allows us to detect + misplaced preprocessor directives (i.e. not at the beginning of + the a line, nor after whitespaces). In that case, report error + CS1040. This fixes bug #56460. + + * cs-parser.jay (interface_member_declaration): Add checks for + IsExplicitImpl, and report CS0541 error if an interface member is + defined as an explicit interface declaration. + +2005-01-06 Marek Safar + + Fix #70817 + * class.cs (PropertyMethod): Set Parent field in ctors. + (SetMethod.InternalParameters): Add unsafe switch hack. + + * decl.cs (MemberCore.Parent): Cannot be readonly. + +2005-01-06 Raja R Harinath + + * decl.cs (DeclSpace.ResolveType): Remove. + (DeclSpace.ResolveBaseTypeExpr): Rename from ResolveTypeExpr. + Merge in code from ... + (DeclSpace.GetTypeResolvingEmitContext): ... here. Remove. + * class.cs, enum.cs: Update to changes. + +2005-01-06 Miguel de Icaza + + * anonymous.cs: Ensure that we init the scope of our parent if it + has not been initialized yet. + +2004-12-30 Duncan Mak + + * typemanager.cs (TypeManager.CheckStructCycles): Don't crash here + if field.FieldBuilder is null. Fixes #70758. + + * convert.cs: Fixed some typos and updated some of the comments. + (ImplicitStandardConversionExists): + (TryImplicitIntConversion): If `target_type' is an interface and + the type of `ic' implements this interface, return true or a new + BoxedCast instead of null. This fixes #70468. + +2004-12-29 Duncan Mak + + * expression.cs (Argument.Emit): Check that Expr is + IMemoryLocation before casting to it, and report CS1510 otherwise. + + This fixes #70402. + +2004-12-21 Ben Maurer + + * statement.cs (Block.ThisVariable): remove the recursion here, to + make the --profile more sane. + +2004-12-17 Carlos Cortez + + * driver.cs: Patch to handle a xsp bug that prevents to reference an .exe + assembly, by JB Evain. + +2004-12-17 Raja R Harinath + + * class.cs, decl.cs, ecore.cs, iterators.cs, pending.cs, + rootcontext.cs, typemanager.cs: Make nomenclature consistent. + "parent" refers to enclosing type/class. "base" refers to superclass. + +2004-12-17 Raja R Harinath + + * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute): + Ensure that we only have GlobalAttributes. + * attribute.cs (Attribute.Emit): Make non-virtual. + (GlobalAttribute.Emit): Remove. + (Attribute.Resolve): Make virtual. + (GlobalAttribute.Resolve): New. Set Rootcontext.Tree.Types.NamespaceEntry. + (Attribute.GetConditionalAttributeValue): Take an EmitContext as + the argument. Don't create one. + (Attribute.GetObsoleteAttribute): Likewise. + (Attribute.GetClsCompliantAttributeValue): Likewise. + * class.cs, decl.cs: Update to changes. + +2004-12-17 Marek Safar + + * delegate.cs (NewDelegate.DoResolve): Add error 149 report. + + * ecore.cs (Expression.MemberLookupFailed): Fixed error 143. + + * statement.cs (Foreach.Resolve): Add error 186 report. + +2004-12-16 Marek Safar + + * expression.cs (Conditional.DoResolve): Add warning 429. + + * statement.cs (If.Resolve): Add warning 665. + +2004-12-16 Raja R Harinath + + New invariant: RootContext.Tree.Types.NamespaceEntry == null + except when in the parser, and in GlobalAttribute. + * driver.cs (MainDriver): Reset RootContext.Tree.Types.NamespaceEntry. + * attribute.cs (GlobalAttribute.CheckAttributeType): Reset + RootContext.Tree.Types.NamespaceEntry once work is done. + (GlobalAttribute.Emit): New. Wrapper for Attribute.Emit, but sets + and resets RootContext.Tree.Types.NamespaceEntry. + +2004-12-15 Marek Safar + + * cs-parser.jay: Don't create a block for every variable. + +2004-12-14 Miguel de Icaza + + * location.cs: Provide extra information. + + * statement.cs: The instance is not `ldarg_0.THIS' when accessing + variables from the captured environment, it is the ldarg_0. + +2004-12-14 Marek Safar + + * cs-parser.jay: Changed warning level for 642 to 4 until Miguel + find a conclusion. + + * class.cs: Changed warning level for 169 to avoid developer + displeasure from warning flooding. It will be changed back when they + fix most of current BCL warnings. + + * RootContext.cs: Pushed default WarningLevel to 3. + + * statement.cs: Removed unused variable. + +2004-12-14 Marek Safar + + * class.cs (TypeContainer.GetClassBases): Add error 1521 report. + (TypeContainer.MethodModifiersValid): Refactored to use MemberCore. + Add error 502 report. + (StaticClass.DefineType): Add error 441 report. + (Class.AllowedModifiersProp): New virtual property as temporary + extension to AllowedModifiers. + (Class.DefineType): Add error 418 report. Moved ModFlags check here + to share implementation with StaticClass and don't call virtual + methods from ctor. + + * driver.cs (MainDriver): Add error 1558 test. + + * parameter.cs (Parameter.ApplyAttributeBuilder): Add error 662 + report. Moved error 36 test here. + + * statement.cs (Throw.Resolve): Add error 724 report. + + * typemanager.cs: Add out_attribute_type core type. + +2004-12-13 Marek Safar + + * class.cs (TypeContainer.VerifyClsCompliance): Add error + 3018 report. + (PropertyBase.VerifyClsCompliance): Add errror 3025 report. + + * codegen.cs (ModuleClass.ApplyAttributeBuilder): Add error + 3017 report. + + * decl.cs (MemberCore.VerifyClsCompliance): Add warning 3021. + + * parameter.cs (ReturnParameter.ApplyAttributeBuilder): + Add error 3023 report. + (Parameter.ApplyAttributeBuilder): Add error 3022 report. + + * tree.cs (RootTypes.IsClsCompliaceRequired): Add fake + implementation. + +2004-12-12 John Luke + + * driver.cs (AddArgs): take -- into account when + adding arguments, fixes bug 65710 + +2004-12-12 Martin Baulig + + * expression.cs (Unary.TryReduceNegative): Added support for + SByteConstant and ByteConstant. + (Unary.Reduce): Check error values from TryReduceNegative(). + +2004-12-10 Marek Safar + + * attributes.cs (Attribute.Resolve): Avoid multiple error report + and report exception as error 182. + +2004-12-10 Raja R Harinath + + * driver.cs (Main): Fix message when there are warnings. + +2004-12-09 Miguel de Icaza + + * delegate.cs: Fixed my fix from yesterday, sorry about that. + +2004-12-09 Marek Safar + + * anonymous.cs, class.cs, convert.cs, doc.cs, support.cs: + Reduced number of warnings. + + * class.cs (TypeContainer.VerifyClsCompliance): One if is enough. + +2004-12-08 Miguel de Icaza + + * driver.cs: Removed message. + + * delegate.cs: Fix bug introduced in 1.1.x: 70219. + +2004-12-08 + + * cs-tokenizer.cs: Add workaround for NET 2.0 beta 1 csc bug. + +2004-12-08 Martin Baulig + + * class.cs (TypeContainer.VerifyClsCompliance): Report a CS3003 + instead of a CS3002 for properties and indexer. + +2004-12-08 Martin Baulig + + * decl.cs (MemberName.ToString): Make this work again. + +2004-12-08 Marek Safar + + * attribute.cs (Resolve): Add error 591 detection. + + * class.cs (FieldMember.Define): Add error 1547 detection. + (Indexer.Define): Add error 620 detection. + (Operator.Define): Add error 590 detection. + + * ecore.cs: Missing argument for error 79. + + * expression.cs (ComposedCast.DoResolveAsTypeStep): Add error 611 + detection. + +2004-12-07 Marek Safar + + Fix #70106 + * assign.cs.cs (Assign.DoResolve): Reports error 1648 for value types + only. + +2004-12-07 Atsushi Enomoto + + * cs-parser.jay : handle doc comments on implicit/explicit operators. + Some operator comments were suppressed. + * doc.cs : Implicit/explicit operator name in doc comments are like + "op_Explicit(type)~returnType", so added suffix handling. + +2004-12-07 Martin Baulig + + * decl.cs + (MemberCore.GetObsoleteAttribute): Don't create a new EmitContext. + (MemberCore.GetClsCompliantAttributeValue): Likewise. + (DeclSpace.ec): New protected field; store the EmitContext here. + (DeclSpace.EmitContext): New public property; moved here from + `TypeContainer'. + (DeclSpace.GetClsCompliantAttributeValue): Don't create a new + EmitContext. + + * enum.cs (Enum.Define): Store the EmitContext in the `ec' field. + (Enum.Emit): Don't create a new EmitContext. + + * delegate.cs (Delegate.DefineType): Always create the + EmitContext. + + * iterators.cs (Iterators.DefineIterator): Create a new + EmitContext and store it in `ec'. + +2004-08-24 Martin Baulig + + * typemanager.cs + (TypeManager.IsSubclassOf): Renamed to IsFamilyAccessible; use + this for accessibility checks. + (TypeManager.IsSubclassOrNestedChildOf): Renamed to + IsNestedFamilyAccessible. + (TypeManager.IsSubclassOf): New method, do what the name actually + says. + +2004-12-06 Raja R Harinath + + Fix crash on cs0657-17.cs. + * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute): + Use RootContext.Tree.Types, not 'new RootTypes ()'. + * attribute.cs (GlobalAttribute.CheckAttributeType): Narrow down + the case where the NamespaceEntry gets overwritten. + +2004-12-06 Marek Safar + + Fixed #69195, #56821 + * ecore.cs (ResolveBoolean): Tiny refactoring. + + * expression.cs (Binary.DoResolve): Add warning 429 and skipping + of right expression resolving when left is false constant and + operator is LogicalAnd OR true constant and operator is LogicalOr. + + * statement.cs (ResolveUnreachable): Always reports warning. + +2004-12-05 Miguel de Icaza + + * class.cs: Distinguish between 1721 and 1722 (just a little help + for the programmer). + +2004-12-03 Miguel de Icaza + + * delegate.cs: Only allow this on new versions of the language. + +2004-12-02 Duncan Mak + + * ecore.cs (PropertyExpr.IsAccessorAccessible): Moved to + Expression class. + (Expression.IsAccessorAccessible): Moved from the PropertyExpr to + here as a static method. Take an additional bool out parameter + `must_do_cs1540_check' for signaling to InstanceResolve. + (PropertyExpr.InstanceResolve): Removed the `must_do_cs1540_check' + member field from PropertyExpr class and made it an argument of + the method instead. + (EventExpr.InstanceResolve): Copied from PropertyExpr, removed the + check for MarshalByRefObject, and report CS0122 instead of CS1540. + (EventExpr.DoResolve): Call IsAccessorAccessible on `add_accessor' + and `remove_accessor' as well as InstanceResolve: report CS0122 + where applicable. + + Fixes #70129. + +2004-12-03 Raja R Harinath + + Fix test-327.cs, test-328.cs, and put in early infrastructure + for eventually fixing #52697. + * namespace.cs (NamespaceEntry.LookupForUsing): New method. + (NamespaceEntry.LookupNamespaceOrType): New method, refactored + from other methods. + (NamespaceEntry.Lookup): Remove 'ignore_using' flag. + (AliasEntry.Resolve, UsingEntry.Resolve): Use 'LookupForUsing'. + (VerifyUsing, error246): Update. + * rootcontext.cs (RootContext.NamespaceLookup): Just use + 'NamespaceEntry.LookupNamespaceOrType'. + +2004-12-03 Martin Baulig + + * delegate.cs (NewDelegate.DoResolve): If we have an anonymous + method as our child, call AnonymousMethod.Compatible() on it. + +2004-12-03 Raja R Harinath + + Disable XML documentation support in 'basic' profile. + * decl.cs, class.cs [BOOTSTRAP_WITH_OLDLIB]: Don't import System.Xml. + Redirect XmlElement to System.Object. + * driver.cs, enum.cs, rootcontext.cs: Don't reference System.Xml. + * doc.cs [BOOTSTRAP_WITH_OLDLIB]: Disable compile. + * mcs.exe.sources: Add doc-bootstrap.cs. + * doc-bootstrap.cs: New file. Contains empty stub implementation + of doc.cs. + +2004-12-03 Atsushi Enomoto + + * cs-tokenizer.cs : Only '////' is rejected. Other non-whitespace + comments are allowed. + +2004-12-03 Carlos Alberto Cortez + + * delegate.cs: Add checks for subtypes in paramaters and return values + in VerifyMethod () to add support for Covariance/Contravariance + in delegates. + +2004-12-02 Miguel de Icaza + + * report.cs: Remove extra closing parenthesis. + + * convert.cs (Error_CannotImplicitConversion): If the name of the + types are the same, provide some extra information. + + * class.cs (FieldBase): Use an unused bit field from the field to + encode the `has_offset' property from the FieldMember. This saves + a couple of Ks on bootstrap compilation. + + * delegate.cs (NewDelegate.DoResolve): If we have an anonymous + method as our child, return the AnonymousMethod resolved + expression. + + * expression.cs (New.DoResolve): Allow return values from + NewDelegate to also include AnonymousMethods. + + Fixes #70150. + +2004-12-02 Marek Safar + + Fix bug #70102 + * attribute.cs (Resolve): Improved implementation of params + attribute arguments. + + * support.cs (ParameterData): Add HasParams to be faster. + +2004-12-02 Atsushi Enomoto + + all things are for /doc support: + + * doc.cs: new file that supports XML documentation generation. + * mcs.exe.sources: added doc.cs. + * driver.cs: + Handle /doc command line option. + Report error 2006 instead of 5 for missing file name for /doc. + Generate XML documentation when required, after type resolution. + * cs-tokenizer.cs: + Added support for picking up documentation (/// and /** ... */), + including a new XmlCommentState enumeration. + * cs-parser.jay: + Added lines to fill Documentation element for field, constant, + property, indexer, method, constructor, destructor, operator, event + and class, struct, interface, delegate, enum. + Added lines to warn incorrect comment. + * rootcontext.cs : + Added Documentation field (passed only when /doc was specified). + * decl.cs: + Added DocComment, DocCommentHeader, GenerateDocComment() and + OnGenerateDocComment() and some supporting private members for + /doc feature to MemberCore. + * class.cs: + Added GenerateDocComment() on TypeContainer, MethodCore and Operator. + * delegate.cs: + Added overriden DocCommentHeader. + * enum.cs: + Added overriden DocCommentHeader and GenerateDocComment(). + +2004-12-01 Miguel de Icaza + + * cfold.cs (ConstantFold.DoConstantNumericPromotions): After + unwrapping the enumeration values, chain to + DoConstantNumericPromotions again, so we can promote things to the + fundamental types (takes care of enums that are bytes, sbytes). + + Fixes bug #62054. + +2004-12-01 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType): Remove complain flag. + Fix long-standing bug in type-lookup. Use FindType instead of + LookupType when ec.ResolvingTypeTree. + (Attribute.ResolveType, Attribute.Resolve) + (Attribute.DefinePInvokeMethod,GlobalAttribute.CheckAttributeType): + Update to changes. + (Attributes.Search): Remove internal version. Update. + (Attributes.SearchMulti): Update. + (Attributes.GetClsCompliantAttribute): Remove. + (Attributes.GetIndexerNameAttribute): Remove. + * decl.cs (MemberCore.GetClsCompliantAttributeValue): Update to changes. + (DeclSpace.GetClsCompliantAttributeValue): Likewise. + * class.cs (Indexer.Define): Likewise. + +2004-12-01 Marek Safar + + Fix bug #68790 + * ecore.cs: CheckMarshallByRefAccess new virtual method for testing + MarshallByReference members access. + + * expression.cs: Use CheckMarshallByRefAccess; + Better error CS0197 message. + + * report.cs: Print whole related error message. + +2004-11-30 Raja R Harinath + + * Makefile (mcs.exe) [PROFILE=default]: Keep a copy of mcs.exe in + the current directory to help debugging. + +2004-11-29 Marek Safar + + * class (GetClassBases): Better error 60 report. + (EventProperty): Disabled warning 67 detection. + +2004-11-29 Marek Safar + + Fix bug #60324 + * cfold.cs (Assign.DoResolve): Add subtraction for DecimalConstant. + + * constant.cs (DecimalConstant.Emit): Don't use int ctor for + precise values. + +2004-11-29 Marek Safar + + Fix bug #49488 + * assign.cs (Assign.DoResolve): Add error 1648, 1650 report. + + * decl.cs (MemberCore.MemberName): Error 1648 in compiler. + +2004-11-26 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Refine error reporting and + report a cs0117 if the identifier does not exist, to distinguish + from 0617 which is a miss-use of the actual identifier. + + * ecore.cs (EventExpr.Emit): Refine error report and distinguish + between cs0070 and cs0079. + + * class.cs (MemberBase.DoDefine): When reporting a wrong + accessibility level, we use MethodCore to compare instead of + Method (this was a regression in some refactoring effort). + + So now we correctly report cs0056 again. + + * convert.cs (ImplicitReferenceConversion): Corrected typo, I was + testing the target_type (which was known to be object_type) and + not the source type (which is anonymous_method). + + Fixed reporting of error cs1660. + + * expression.cs (UserCast.Source): Expose the underlying cast. + + * statement.cs (Switch.SwitchGoverningType): Sort the list of + allowed types to find a match to int32 first (most common). + + In addition, it ignores any ImplicitUserConversions that did an + internal implicit conversion (as the switch statement allows only + one integral conversion to exist). + + * class.cs (PartialContainer.Create): rename `name' to + `member_name' for clarity. Then replace the string calls with a + call to MemberName.GetPartialName, as now using + MemberName.ToString is an error (this is due to the side effects + it had, that were fixed in the past). + + This will restore the error reporting on a number of partial class + errors that were missusing this (and getting an exception as a + results, which is now just a plain textual warning, because + yyparse debug output would crash otherwise). + +2004-11-26 Raja R Harinath + + * Makefile (PROGRAM_INSTALL_DIR): Remove. + +2004-11-25 Ben Maurer + + * rootcontext.cs (LookupType): Make sure to cache lookups that + don't give us a negative result. This saves about 5% of corlib + compilation time. + +2004-11-25 Miguel de Icaza + + * report.cs (AbstractMessage.Print): messages are sent to stderr + + * class.cs (TypeContainer.GetClassBases): It is an error to have a + non-interface in the list of interfaces (at this point, either + parent was properly set, or a base class is being listed in the + interfaces section). + + This flags error 1722, and resolves the crash from bug 69259. + +2004-11-25 Ben Maurer + + * statement.cs (Using.EmitExpressionFinally): make this work right + for valuetypes. Fixes 69926. + +2004-11-25 Miguel de Icaza + + * const.cs (Const.ChangeType): Cope with the "0 literal can be + converted to an enum" here, before we try to change the underlying + type. This code exists, but it is a different code path than the + one used while encoding constants. + + * convert.cs (ImplicitReferenceConversionExists): A surprisingly + old bug: when converting from the null literal to a pointer, + return an EmptyCast, not the NullLiteral. + + This fixes #69921, the recent null_type changes probably made this + bug more prominent. + + (ImplicitReferenceConversionExists): In addition, resynchronized + the code here, so it matches the same code in + ImplicitReferenceConversionExists for the `from any class-type S + to any interface-type T'. + + +2004-11-25 Marek Safar + + * cfold.cs (BinaryFold): Add addition for DecimalConstant. + +2004-11-24 Miguel de Icaza + + * cs-parser.jay: Use verbosity accordingly. + +2004-11-24 Marek Safar + + * expression.cs (Unary.ResolveOperator): Do not report warning; + AddressOf reads from variable. + + (LocalVariableReferences.DoResolveBase): Improved my previous fix. + +2004-11-24 Marek Safar + + Fix bug #69462 + + * attribute.cs (Attributable): Removed CheckTargets. + (Attributes.Emit): Explicit attribute targets are tested here. + + * class.cs (EventField.ValidAttributeTargets): Explicit target "field" is + not enabled for interfaces. + + * codegen.cs (CommonAssemblyModulClass.AddAttributes): Removed CheckTargets. + (GetAssemblyName): Ouch next bug there. + +2004-11-23 Carlos Alberto Cortez + + * expression.cs: Error 275 added. + +2004-11-23 Marek Safar + + Fix bug #69177 (Implemented decimal constant support) + + * cfold.cs (DoConstantNumericPromotions: Add DecimalConstant. + (BinaryFold): Add DecimalConstant. + + * const.cs (Define): Decimal constant + (is not constant. + (ChangeType): Add decimal type handling. + (LookupConstantValue): Don't set value for decimal type but + emit DecimalConstantAttribute. Needed for constant optimization. + + * constant.cs (ToDecimal): New method. + (ConvertToDecimal): New method. + (IntConstant): Implemented ConvertToDecimal. + (DecimalConstant.Emit): Emit optimized version for decimals in + int range. + + * expression.cs (ResolveOperator): Changed order of constant + reduction to work correctly with native types which have + overloaded operators. + (ResolveMemberAccess): Extract constant value from attribute + for decimal type. + + * rootcontext.cs (ResolveCore): Add DecimalConstantAttribute. + + * typemanager.cs (TypeManager): Add decimal_constant_attribute_type, + void_decimal_ctor_int_arg, decimal_constant_attribute_ctor. + (ChangeType): Decimal is special. + (TypeToCoreType): Add decimal type. + +2004-11-22 Marek Safar + + * convert.cs (ImplicitConversionRequired): Add error cs0642 for + decimal types. + +2004-11-22 Marek Safar + + * class.cs (EventField.ApplyAttributeBuilder): Fix error + test cs1667-5.cs. + +2004-11-19 Marek Safar + + * class.cs (MemberBase.DoDefine): Fix error cs0508 report. + + * pending.cs (PendingImplementation): Grab only interfaces. + +2004-11-19 Marek Safar + + * statement.cs (ForeachHelperMethods): Add location member and + error 202 detection. + +2004-11-19 Raja R Harinath + + * Makefile (EXTRA_DISTFILES): Remove mcs.exe.config. It's + automatically handled by executable.make. + (PROGRAM): Make profile-specific. + +2004-11-18 Marek Safar + + * expression.cs (DoResolveBase): Fixed wrong warning for out + variables. + +2004-11-18 Martin Baulig + + Merged latest changes into gmcs. Please keep this comment in + here, it makes it easier for me to see what changed in MCS since + the last time I merged. + +2004-11-17 Raja R Harinath + + * typemanager.cs (TypeHandle.GetTypeHandle): Make private. + (TypeHandle.GetMemberCache): New. + (TypeHandle.TypeHandle): Update. + (TypeManager.LookupMemberCache): Rewritten from LookupMemberContainer. + (TypeManager.LookupParentInterfacesCache): + Rename from LookupInterfaceCache. Optimize slightly. + (TypeManager.MemberLookup_FindMembers): Update. + * decl.cs (MemberCache.MemberCache): Set Container to null in the + multi-type variant. + (AddCacheContents): Rename from AddHashtable. + * class.cs (TypeContainer.parent_container): Remove. + (TypeContainer.VerifyClsCompliance): Don't use parent_container. + (TypeContainer.DoDefineMembers): Don't initialize it. + Update to name changes. + +2004-11-17 Miguel de Icaza + + * class.cs (MethodCore.CheckAccessModifiers): New helper routine + that factors the code to check access modifiers on override. + + (PropertyBase): Use the code here. + + Patch from Lluis S'anchez, fixes bug #69361. + +2004-11-15 Miguel de Icaza + + * anonymous.cs (AnonymousMethod.Error_AddressOfCapturedVar): New + routine that is used to report the use of a captured variable + whose address has been taken. + + There are two checks: one when variables are being captured and + the other check is when the address of a variable is taken. + + (because an anonymous methods might be resolved before *or* after + the address has been taken) and + + * expression.cs (Conditional.DoResolve): Remove the special + casing that Martin added to trueExpr and falseExpr being both + NullLiteral. We get the right behavior now just by introducing + the null_type into the compiler. + + * convert.cs (ExplicitConversion): Change the code to use + null_type instead of testing `expr is NullLiteral'. + (ImplicitConversionStandard): use null_type too. + (ImplicitReferenceConversionExists): use null_type too. + (ImplicitReferenceConversion): use null_type too. + + * literal.cs: The type of `NullLiteral' is now null_type instead + of object_type. + (Resolve): Set the type here. + + * typemanager.cs: Introduce null_type. + +2004-11-17 Martin Baulig + + * decl.cs (MemberCache.AddHashtable): Add entries in the opposite + direction, like FindMembers() does. Fixes #69546, testcase is in + test-315.cs. + +2004-11-16 Martin Baulig + + This is based on a patch from Marek Safar, see bug #69082. + Fixes bugs #63705 and #67130. + + * typemanager.cs (TypeManager.LookupInterfaceCache): New public + method; create a MemberCache for an interface type and cache the + result. + + * decl.cs (IMemberContainer.ParentContainer): Removed. + (IMemberContainer.ParentCache): New property. + (MemberCache.SetupCacheForInterface): Removed. + (MemberCache..ctor): Added .ctor which takes a `Type[]'; use this + to create a cache for an interface's "parent". + + * class.cs (TypeContainer.DoDefineMembers): Setup cache for + interfaces too. + +2004-11-16 Martin Baulig + + Merged back from gmcs; these changes already went into gmcs a + couple of weeks ago. + + * typemanager.cs + (TypeManager.AddUserType): Removed the `ifaces' argument. + (TypeManager.RegisterBuilder): Take a `Type []' instead of a + `TypeExpr []'. + (TypeManager.AddUserInterface): Removed. + (TypeManager.ExpandInterfaces): Return a `Type []' instead of a + `TypeExpr []'. + (TypeManager.GetInterfaces): Likewise. + (TypeManager.GetExplicitInterfaces): Likewise. + + * ecore.cs (TypeExpr.GetInterfaces): Removed. + + * class.cs (TypeContainer.base_class_type): Replaced with `ptype'. + (TypeContainer.base_inteface_types): Replaced with `ifaces'. + +2004-11-14 Ben Maurer + + * statement.cs: Avoid adding bools to a hashtable. + +2004-11-07 Miguel de Icaza + + * expression.cs (Invocation.OverloadResolve): Flag error if we are + calling an unsafe method from a safe location. + +2004-11-06 Marek Safar + + Fix #69167 + * codegen.cs (ApplyAttributeBuilder): Do not return; it is only warning. + +2004-11-06 Miguel de Icaza + + * namespace.cs (VerifyUsing): use GetPartialName instead of + ToString. + +2004-11-05 Miguel de Icaza + + * statement.cs (Return.Resolve): Fix regression in typo: if + `in_exc', we have to request a NeedReturnLabel, this was a typo + introduced in the anonymous method check-in. Fixes #69131. + + * Indexers were using the ShortName when defining themselves, + causing a regression in the compiler bootstrap when applying the + patch from 2004-11-02 (first part), now they use their full name + and the bug is gone. + +2004-11-04 Zoltan Varga + + * driver.cs: Strip the path from the names of embedded resources. Fixes + #68519. + +2004-11-04 Raja R Harinath + + Fix error message regression: cs0104-2.cs. + * namespace.cs (NamespaceEntry.Lookup): Remove 'silent' flag. + (AliasEntry.Resolve): Update. + * rootcontext.cs (RootContext.NamespaceLookup): Update. Remove + 'silent' flag. + (RootContext.LookupType): Update. + +2004-11-03 Carlos Alberto Cortez + + * cs-parser.jay: Add support for handling accessor modifiers + * class: Add support port accessor modifiers and error checking, + define PropertyMethod.Define as virtual (not abstract anymore) + * ecore.cs: Add checking for proeprties access with access modifiers + * iterators.cs: Modify Accessor constructor call based in the modified + constructor +2004-11-02 Ben Maurer + + * expression.cs (StringConcat): Handle being called twice, + as when we have a concat in a field init with more than two + ctors in the class + +2004-11-02 Miguel de Icaza + + * class.cs (Event.Define, Indexer.Define, Property.Define): Do not + special case explicit implementations, we should always produce + the .property or .event declaration. + + * decl.cs (MemberName): Renamed GetFullName to GetPartialName + since it will not return correct data if people use this + unresolved in the presence of using statements (see test-313). + + * class.cs (MethodData.Define): If we are an explicit interface + implementation, set the method name to the full name of the + interface plus the name of the method. + + Notice that using the method.MethodName.GetFullName() does not + work, as it will only contain the name as declared on the source + file (it can be a shorthand in the presence of using statements) + and not the fully qualifed type name, for example: + + using System; + + class D : ICloneable { + object ICloneable.Clone () { + } + } + + Would produce a method called `ICloneable.Clone' instead of + `System.ICloneable.Clone'. + + * namespace.cs (Alias.Resolve): Use GetPartialName. + +2004-11-01 Marek Safar + + * cs-parser.jay: Add error 1055 report. + +2004-11-01 Miguel de Icaza + + * assign.cs (Assign.DoResolve): Only do the transform of + assignment into a New if the types are compatible, if not, fall + through and let the implicit code deal with the errors and with + the necessary conversions. + +2004-11-01 Marek Safar + + * cs-parser.jay: Add error 1031 report. + + * cs-tokenizer.cs: Add location for error 1038. + +2004-10-31 Marek Safar + + * cs-parser.jay: Add error 1016 report. + +2004-10-31 Marek Safar + + * cs-parser.jay: Add errors 1575,1611 report. + +2004-10-31 Marek Safar + + * cs-parser.jay: Add error 1001 report. + +2004-10-31 Marek Safar + + Fix #68850 + * attribute.cs (GetMarshal): Add method argument for + caller identification. + + * class.cs, codegen.cs, enum.cs, parameter.cs: Added + agument for GetMarshal and RuntimeMissingSupport. + +2004-10-31 Marek Safar + + * attribute.cs (ExtractSecurityPermissionSet): Removed + TypeManager.code_access_permission_type. + + * typemanager.cs: Removed TypeManager.code_access_permission_type. + +2004-10-27 Miguel de Icaza + + * expression.cs (LocalVariableReference.DoResolveLValue): Check + for obsolete use of a variable here. Fixes regression on errors + cs0619-25 and cs0619-26. + +2004-10-27 Marek Safar + + Fix #62358, implemented security attribute encoding. + + * attribute.cs (Attribute.CheckSecurityActionValididy): New method. + Tests permitted SecurityAction for assembly or other types. + (Assembly.ExtractSecurityPermissionSet): New method. Transforms + data from SecurityPermissionAttribute to PermisionSet class. + + * class.cs (ApplyAttributeBuilder): Added special handling + for System.Security.Permissions.SecurityAttribute based types. + + * codegen.cs (AssemblyClass.ApplyAttributeBuilder): Added + special handling for System.Security.Permissions.SecurityAttribute + based types. + + * enum.cs (ApplyAttributeBuilder): Added special handling + for System.Security.Permissions.SecurityAttribute based types. + + * parameter.cs (ApplyAttributeBuilder): Added special handling + for System.Security.Permissions.SecurityAttribute based types. + + * rootcontext.cs: Next 2 core types. + + * typemanager.cs (TypeManager.security_permission_attr_type): + Built in type for the SecurityPermission Attribute. + (code_access_permission_type): Build in type. + +2004-10-17 Miguel de Icaza + + * expression.cs (LocalVariableReference.DoResolveBase, Emit): + Remove the tests for `ec.RemapToProxy' from here, and encapsulate + all of this information into + EmitContext.EmitCapturedVariableInstance. + + * codegen.cs (EmitCapturedVariableInstance): move here the + funcionality of emitting an ldarg.0 in the presence of a + remapping. This centralizes the instance emit code. + + (EmitContext.EmitThis): If the ScopeInfo contains a THIS field, + then emit a load of this: it means that we have reached the + topmost ScopeInfo: the one that contains the pointer to the + instance of the class hosting the anonymous method. + + * anonymous.cs (AddField, HaveCapturedFields): Propagate field + captures to the topmost CaptureContext. + +2004-10-12 Miguel de Icaza + + * expression.cs (LocalVariableReference): Move the knowledge about + the iterators into codegen's EmitCapturedVariableInstance. + +2004-10-11 Miguel de Icaza + + * codegen.cs (EmitContext.ResolveTopBlock): Emit a 1643 when not + all code paths return a value from an anonymous method (it is the + same as the 161 error, but for anonymous methods). + +2004-10-08 Miguel de Icaza + + The introduction of anonymous methods in the compiler changed + various ways of doing things in the compiler. The most + significant one is the hard split between the resolution phase + and the emission phases of the compiler. + + For instance, routines that referenced local variables no + longer can safely create temporary variables during the + resolution phase: they must do so from the emission phase, + since the variable might have been "captured", hence access to + it can not be done with the local-variable operations from the runtime. + + * statement.cs + + (Block.Flags): New flag `IsTopLevel' to indicate that this block + is a toplevel block. + + (ToplevelBlock): A new kind of Block, these are the blocks that + are created by the parser for all toplevel method bodies. These + include methods, accessors and anonymous methods. + + These contain some extra information not found in regular blocks: + A pointer to an optional CaptureContext (for tracking captured + local variables and parameters). A pointer to the parent + ToplevelBlock. + + (Return.Resolve): Catch missmatches when returning a value from an + anonymous method (error 1662). + Invoke NeedReturnLabel from the Resolve phase instead of the emit + phase. + + (Break.Resolve): ditto. + + (SwitchLabel): instead of defining the labels during the + resolution phase, we now turned the public ILLabel and ILLabelCode + labels into methods called GetILLabelCode() and GetILLabel() that + only define the label during the Emit phase. + + (GotoCase): Track the SwitchLabel instead of the computed label + (its contained therein). Emit the code by using + SwitchLabel.GetILLabelCode (). + + (LocalInfo.Flags.Captured): A new flag has been introduce to track + whether the Local has been captured or not. + + (LocalInfo.IsCaptured): New property, used to tell whether the + local has been captured. + + * anonymous.cs: Vastly updated to contain the anonymous method + support. + + The main classes here are: CaptureContext which tracks any + captured information for a toplevel block and ScopeInfo used to + track the activation frames for various local variables. + + Each toplevel block has an optional capture context associated + with it. When a method contains an anonymous method both the + toplevel method and the anonymous method will create a capture + context. When variables or parameters are captured, they are + recorded on the CaptureContext that owns them, for example: + + void Demo () { + int a; + MyDelegate d = delegate { + a = 1; + } + } + + Here `a' will be recorded as captured on the toplevel + CapturedContext, the inner captured context will not have anything + (it will only have data if local variables or parameters from it + are captured in a nested anonymous method. + + The ScopeInfo is used to track the activation frames for local + variables, for example: + + for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j++){ + MyDelegate d = delegate { + call (i, j); + } + } + + At runtime this captures a single captured variable `i', but it + captures 10 different versions of the variable `j'. The variable + `i' will be recorded on the toplevel ScopeInfo, while `j' will be + recorded on a child. + + The toplevel ScopeInfo will also track information like the `this' + pointer if instance variables were referenced (this is necessary + as the anonymous method lives inside a nested class in the host + type of the method). + + (AnonymousMethod): Expanded to track the Toplevel, implement + `AnonymousMethod.Compatible' to tell whether an anonymous method + can be converted to a target delegate type. + + The routine now also produces the anonymous method content + + (AnonymousDelegate): A helper class that derives from + DelegateCreation, this is used to generate the code necessary to + produce the delegate for the anonymous method that was created. + + * assign.cs: API adjustments for new changes in + Convert.ImplicitStandardConversionExists. + + * class.cs: Adjustments to cope with the fact that now toplevel + blocks are of type `ToplevelBlock'. + + * cs-parser.jay: Now we produce ToplevelBlocks for toplevel blocks + insteda of standard blocks. + + Flag errors if params arguments are passed to anonymous methods. + + * codegen.cs (EmitContext): Replace `InAnonymousMethod' with + `CurrentAnonymousMethod' which points to the current Anonymous + Method. The variable points to the AnonymousMethod class that + holds the code being compiled. It is set in the new EmitContext + created for the anonymous method. + + (EmitContext.Phase): Introduce a variable and an enumeration to + assist in enforcing some rules about when and where we are allowed + to invoke certain methods (EmitContext.NeedsReturnLabel is the + only one that enfonces this right now). + + (EmitContext.HaveCaptureInfo): new helper method that returns + whether we have a CapturedContext initialized. + + (EmitContext.CaptureVariable): New method used to register that a + LocalInfo must be flagged for capturing. + + (EmitContext.CapturedParameter): New method used to register that a + parameters must be flagged for capturing. + + (EmitContext.CapturedField): New method used to register that a + field must be flagged for capturing. + + (EmitContext.HaveCapturedVariables, + EmitContext.HaveCapturedFields): Return whether there are captured + variables or fields. + + (EmitContext.EmitMethodHostInstance): This is used to emit the + instance for the anonymous method. The instance might be null + (static methods), this (for anonymous methods that capture nothing + and happen to live side-by-side with the current method body) or a + more complicated expression if the method has a CaptureContext. + + (EmitContext.EmitTopBlock): Routine that drives the emission of + code: it will first resolve the top block, then emit any metadata + and then emit the code. The split is done so that we can extract + any anonymous methods and flag any captured variables/parameters. + + (EmitContext.ResolveTopBlock): Triggers the resolution phase, + during this phase, the ILGenerator should not be used as labels + and local variables declared here might not be accessible to any + code that is part of an anonymous method. + + Exceptions to this include the temporary variables that are + created by some statements internally for holding temporary + variables. + + (EmitContext.EmitMeta): New routine, in charge of emitting all the + metadata for a cb + + (EmitContext.TemporaryReturn): This method is typically called + from the Emit phase, and its the only place where we allow the + ReturnLabel to be defined other than the EmitMeta. The reason is + that otherwise we would have to duplicate a lot of logic in the + Resolve phases of various methods that today is on the Emit + phase. + + (EmitContext.NeedReturnLabel): This no longer creates the label, + as the ILGenerator is not valid during the resolve phase. + + (EmitContext.EmitThis): Extended the knowledge in this class to + work in anonymous methods in addition to iterators. + + (EmitContext.EmitCapturedVariableInstance): This emits whatever + code is necessary on the stack to access the instance to a local + variable (the variable will be accessed as a field). + + (EmitContext.EmitParameter, EmitContext.EmitAssignParameter, + EmitContext.EmitAddressOfParameter): Routines to support + parameters (not completed at this point). + + Removals: Removed RemapLocal and RemapLocalLValue. We probably + will also remove the parameters. + + * convert.cs (Convert): Define a `ConstantEC' which points to a + null. This is just to prefity some code that uses + ImplicitStandardConversion code and do not have an EmitContext + handy. + + The idea is to flag explicitly that at that point in time, it is + known that the conversion will not trigger the delegate checking + code in implicit conversions (which requires a valid + EmitContext). + + Everywhere: pass new EmitContext parameter since + ImplicitStandardConversionExists now requires it to check for + anonymous method conversions. + + (Convert.ImplicitStandardConversionExists): If the type of an + expression is the anonymous_method_type, and the type is a + delegate, we invoke the AnonymousMethod.Compatible method to check + whether an implicit conversion is possible. + + (Convert.ImplicitConversionStandard): Only do implicit method + group conversions if the language level is not ISO_1. + + * delegate.cs (Delegate.GetInvokeMethod): Common method to get the + MethodInfo for the Invoke method. used by Delegate and + AnonymousDelegate. + + * expression.cs (Binary.DoNumericPromotions): only allow anonymous + method conversions if the target type is a delegate. + + Removed extra debugging nops. + + (LocalVariableReference): Turn the `local_info' into a public + field. + + Add `prepared' field, the same hack used for FieldExprs to cope + with composed assignments, as Local variables do not necessarily + operate purely on the stack as they used to: they can be captured + fields. + + Add `temp' for a temporary result, like fields. + + Refactor DoResolve and DoResolveLValue into DoResolveBase. + + It now copes with Local variables that are captured and emits the + proper instance variable to load it from a field in the captured + case. + + (ParameterReference.DoResolveBase): During the resolve phase, + capture parameters if we are in an anonymous method. + + (ParameterReference.Emit, ParameterReference.AddressOf): If in an + anonymous method, use the EmitContext helper routines to emit the + parameter reference. + + * iterators.cs: Set RemapToProxy to true/false during the + EmitDispose class. + + * parameters.cs (GetParameterByName): New helper method. + + * typemanager.cs (anonymous_method_type) a new type that + represents an anonyous method. This is always an internal type, + used as a fencepost to test against the anonymous-methodness of an + expression. + +2004-10-20 Marek Safar + + * class.cs (MethodCore.CheckBase): Add errors 505, 533, 544, + 561 report. + (PropertyBase.FindOutParentMethod): Add errors 545, 546 report. + +2004-10-18 Martin Baulig + + * statement.cs (Fixed.Resolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (Catch.Resolve): Likewise. + (Foreach.Resolve): Likewise. + +2004-10-18 Martin Baulig + + * expression.cs (Cast.DoResolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (Probe.DoResolve): Likewise. + (ArrayCreation.LookupType): Likewise. + (TypeOf.DoResolve): Likewise. + (SizeOf.DoResolve): Likewise. + +2004-10-18 Martin Baulig + + * expression.cs (Invocation.BetterFunction): Put back + TypeManager.TypeToCoreType(). + +2004-10-18 Raja R Harinath + + * class.cs (FieldMember.DoDefine): Reset ec.InUnsafe after doing + the ResolveType. + +2004-10-18 Martin Baulig + + * parameter.cs (Parameter.Resolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + +2004-10-18 Martin Baulig + + * class.cs (FieldMember.Define): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (MemberBase.DoDefine): Likewise. + + * expression.cs (New.DoResolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + (ComposedCast.DoResolveAsTypeStep): Likewise. + + * statement.cs (LocalInfo.Resolve): Don't access the TypeExpr's + `Type' directly, but call ResolveType() on it. + +2004-10-17 John Luke + + * class.cs (Operator.GetSignatureForError): use CSharpName + + * parameter.cs (Parameter.GetSignatureForError): Returns + correct name even if was not defined. + +2004-10-13 Raja R Harinath + + Fix #65816. + * class.cs (TypeContainer.EmitContext): New property. + (DefineNestedTypes): Create an emitcontext for each part. + (MethodCore.DoDefineParameters): Use container's emitcontext. + Pass type array to InternalParameters. + (MemberBase.DoDefine): Use container's emitcontext. + (FieldMember.Define): Likewise. + (Event.Define): Likewise. + (SetMethod.GetParameterInfo): Change argument to EmitContext. + Pass type array to InternalParameters. + (SetIndexerMethod.GetParameterInfo): Likewise. + (SetMethod.Define): Pass emitcontext to GetParameterInfo. + * delegate.cs (Define): Pass emitcontext to + ComputeAndDefineParameterTypes and GetParameterInfo. Pass type + array to InternalParameters. + * expression.cs (ParameterReference.DoResolveBase): Pass + emitcontext to GetParameterInfo. + (ComposedCast.DoResolveAsTypeStep): Remove check on + ec.ResolvingTypeTree. + * parameter.cs (Parameter.Resolve): Change argument to + EmitContext. Use ResolveAsTypeTerminal. + (Parameter.GetSignature): Change argument to EmitContext. + (Parameters.ComputeSignature): Likewise. + (Parameters.ComputeParameterTypes): Likewise. + (Parameters.GetParameterInfo): Likewise. + (Parameters.ComputeAndDefineParameterTypes): Likewise. + Re-use ComputeParameterTypes. Set ec.ResolvingTypeTree. + * support.cs (InternalParameters..ctor): Remove variant that takes + a DeclSpace. + * typemanager.cs (system_intptr_expr): New. + (InitExpressionTypes): Initialize it. + +2004-10-12 Chris Toshok + + * cs-parser.jay: fix location for try_statement and catch_clause. + +2004-10-11 Martin Baulig + + * report.cs: Don't make --fatal abort on warnings, we have + -warnaserror for that. + +2004-10-07 Raja R Harinath + + More DeclSpace.ResolveType avoidance. + * decl.cs (MemberCore.InUnsafe): New property. + * class.cs (MemberBase.DoDefine): Use ResolveAsTypeTerminal + with newly created EmitContext. + (FieldMember.Define): Likewise. + * delegate.cs (Delegate.Define): Likewise. + * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup with alias + only if normal name-lookup fails. + (TypeExpr.DoResolve): Enable error-checking. + * expression.cs (ArrayCreation.DoResolve): Use ResolveAsTypeTerminal. + (SizeOf.DoResolve): Likewise. + (ComposedCast.DoResolveAsTypeStep): Likewise. + (StackAlloc.DoResolve): Likewise. + * statement.cs (Block.Flags): Add new flag 'Unsafe'. + (Block.Unsafe): New property. + (Block.EmitMeta): Set ec.InUnsafe as appropriate. + (Unsafe): Set 'unsafe' flag of contained block. + (LocalInfo.Resolve): Use ResolveAsTypeTerminal. + (Fixed.Resolve): Likewise. + (Catch.Resolve): Likewise. + (Using.ResolveLocalVariableDecls): Likewise. + (Foreach.Resolve): Likewise. + +2004-10-05 John Luke + + * cs-parser.jay: add location to error CS0175 + +2004-10-04 Miguel de Icaza + + * ecore.cs (Expression.Constantity): Add support for turning null + into a constant. + + * const.cs (Const.Define): Allow constants to be reference types + as long as the value is Null. + +2004-10-04 Juraj Skripsky + + * namespace.cs (NamespaceEntry.Using): No matter which warning + level is set, check if this namespace name has already been added. + +2004-10-03 Ben Maurer + + * expression.cs: reftype [!=]= null should always use br[true,false]. + # 67410 + +2004-10-03 Marek Safar + + Fix #67108 + * attribute.cs: Enum conversion moved to + GetAttributeArgumentExpression to be applied to the all + expressions. + +2004-10-01 Raja R Harinath + + Fix #65833, test-300.cs, cs0122-5.cs, cs0122-6.cs. + * class.c (TypeContainer.DefineType): Flag error if + base types aren't accessible due to access permissions. + * decl.cs (DeclSpace.ResolveType): Move logic to + Expression.ResolveAsTypeTerminal. + (DeclSpace.ResolveTypeExpr): Thin layer over + Expression.ResolveAsTypeTerminal. + (DeclSpace.CheckAccessLevel, DeclSpace.FamilyAccess): + Refactor code into NestedAccess. Use it. + (DeclSpace.NestedAccess): New. + * ecore.cs (Expression.ResolveAsTypeTerminal): Add new + argument to silence errors. Check access permissions. + (TypeExpr.DoResolve, TypeExpr.ResolveType): Update. + * expression.cs (ProbeExpr.DoResolve): Use ResolveAsTypeTerminal. + (Cast.DoResolve): Likewise. + (New.DoResolve): Likewise. + (InvocationOrCast.DoResolve,ResolveStatement): Likewise. + (TypeOf.DoResolve): Likewise. + + * expression.cs (Invocation.BetterConversion): Return the Type of + the better conversion. Implement section 14.4.2.3 more faithfully. + (Invocation.BetterFunction): Make boolean. Make correspondence to + section 14.4.2.2 explicit. + (Invocation.OverloadResolve): Update. + (Invocation): Remove is_base field. + (Invocation.DoResolve): Don't use is_base. Use mg.IsBase. + (Invocation.Emit): Likewise. + +2004-09-27 Raja R Harinath + + * README: Update to changes. + +2004-09-24 Marek Safar + + * cs-parser.jay: Reverted 642 warning fix. + +2004-09-23 Marek Safar + + Fix bug #66615 + * decl.cs (FindMemberWithSameName): Indexer can have more than + 1 argument. + +2004-09-23 Marek Safar + + * expression.cs (LocalVariableReference.DoResolveLValue): + Do not report warning 219 for out values. + (EmptyExpression.Null): New member to avoid extra allocations. + +2004-09-23 Marek Safar + + * cs-parser.jay: Fix wrong warning 642 report. + + * cs-tokenizer.cs (CheckNextToken): New helper; + Inspect next character if is same as expected. + +2004-09-23 Martin Baulig + + * convert.cs (Convert.ImplicitReferenceConversion): Some code cleanup. + (Convert.ImplicitReferenceConversionExists): Likewise. + +2004-09-23 Marek Safar + + * class.cs (Operator.Define): Add error 448 and 559 report. + +2004-09-22 Marek Safar + + * class.cs (MemberBase.IsTypePermitted): New protected + method for checking error CS0610. + +2004-09-22 Marek Safar + + * class.cs (TypeContainer.HasExplicitLayout): New property + Returns whether container has StructLayout attribute set Explicit. + (FieldMember): New abstract class for consts and fields. + (FieldMember.ApplyAttributeBuilder): Add error 636 and 637 report. + (Field): Reuse FieldMember. + + * const.cs (Const): Reuse FieldMember. + + * rootcontext.cs: EmitConstants call moved to class. + +2004-09-22 Martin Baulig + + Thanks to Peter Sestoft for this bug report. + + * expression.cs (Conditional): If both the `trueExpr' and the + `falseExpr' is a NullLiteral, return a NullLiteral. + +2004-09-22 Martin Baulig + + * statement.cs (Foreach.EmitCollectionForeach): If we're in an + iterator, use `enumerator.EmitThis()' instead of `ec.EmitThis()' + for the "get_Current" call. + +2004-09-22 Martin Baulig + + Marek and me just fixed one of our oldest bugs: #28562 :-) + + * ecore.cs (EnumConstant.GetValueAsEnumType): New public method. + + * attribute.cs (Attribute.GetAttributeArgumentExpression): If + we're an EnumConstant, just return that. + (Attribute.Resolve): GetAttributeArgumentExpression() may give us + an EnumConstant. In this case, we need to use GetValueAsEnumType() + to get the value which'll actually be written into the attribute. + However, we have to use GetValue() to access the attribute's value + in the compiler. + +2004-09-22 Marek Safar + + * constant.cs (Constant.IsNegative): New abstract property + IsNegative. + + * expression.cs (ArrayAccess.DoResolve): Add warning 251. + (StackAlloc.DoResolve): Reused IsNegative. + +2004-09-21 Martin Baulig + + * codegen.cs (VariableStorage): Don't store the ILGenerator here; + if we're used in an iterator, we may be called from different + methods. + + * statement.cs (Foreach.EmitFinally): Only emit an `Endfinally' if + we actually have an exception block. + +2004-09-20 John Luke + + * class.cs, cs-parser.jay: Improve the error report for 1520: + report the actual line where the error happens, not where the + class was declared. + + * assign.cs, delegate.cs, ecore.cs, expression.cs, statement.cs: + Pass location information that was available elsewhere. + +2004-09-19 Sebastien Pouliot + + * codegen.cs: Fix bug #56621. It is now possible to use MCS on the MS + runtime to delay sign assemblies. + +2004-09-19 Miguel de Icaza + + * cs-parser.jay: Do not report the stack trace, this is barely + used nowadays. + +2004-08-22 John Luke + + * driver.cs : check that a resource id is not already used + before adding it, report CS1508 if it is, bug #63637 + +2004-09-19 Miguel de Icaza + + * ecore.cs: Removed dead code. + +2004-09-18 Marek Safar + + * class.cs: Do not report warning CS0067 on the interfaces. + +2004-09-16 Marek Safar + + * cs-parser.jay: Add error 504 report. + +2004-09-16 Marek Safar + + * rootcontext.cs: WarningLevel is 4 by default now. + + * statement.cs (Fixed.Resolve): Do not null + VariableInfo. + +2004-09-16 Marek Safar + + Fixed bug #55780 + * ecore.cs (PropertyExpr.FindAccessors): Do not perform + deep search when property is not virtual. + (PropertyExpr.ResolveAccessors): Make one call for both + accessors. + +2004-09-15 Marek Safar + + Fixed bug #65766 + * statement.cs: Error 152 report constains also location. + +2004-09-15 Marek Safar + + Fixed bug #65766 + * const.cs: Explicitly set constant as static. + +2004-09-15 Marek Safar + + Fixed bug #64226 + * cs-parser.jay: Add error 1017 report. + +2004-09-15 Marek Safar + + Fixed bug #59980, #64224 + * expression.cs (Invocation.DoResolve): Fixed error CS0571 test. + + * typemanager.cs (IsSpecialMethod): Simplified + +2004-09-14 Marek Safar + + * decl.cs (MemberCore.Emit): Resuscitated VerifyObsoleteAttribute + condition with better params. + +2004-09-14 Marek Safar + + Fixed bug #65238 + * attribute.cs (Resolve): Property has to have both + accessors. + +2004-09-14 Martin Baulig + + * decl.cs (MemberCore.Emit): Always call VerifyObsoleteAttribute(). + +2004-09-14 Marek Safar + + Fixed bug #61902 + * codegen.cs (TestObsoleteMethodUsage): Trace when method is + called and is obsolete then this member suppress message + when call is inside next [Obsolete] method or type. + + * expression.cs: Use TestObsoleteMethodUsage member. + +2004-09-14 Martin Baulig + + * cs-parser.jay: Sync a bit with the GMCS version. + +2004-09-14 Martin Baulig + + * cs-parser.jay (CSharpParser): Don't derive from GenericsParser. + (CSharpParser.yacc_verbose_flag): New public field. + + * genericparser.cs: Removed. + +2004-09-14 Raja R Harinath + + * cs-parser.jay (event_declaration): Re-enable cs0071 error. + +2004-09-13 Marek Safar + + * class.cs (MethodCore.CheckBase): Fix bug #65757. + +2004-09-10 Martin Baulig + + Backported my MemberName changes from GMCS into MCS. + + - we are now using a special `MemberName' class instead of using + strings; in GMCS, the `MemberName' also contains the type + arguments. + + - changed the grammar rules a bit: + * the old `member_name' is now a `namespace_or_type_name': + The rule is that we use `namespace_or_type_name' everywhere + where we expect either a "member name" (GetEnumerator) or a + "member name" with an explicit interface name + (IEnumerable.GetEnumerator). + In GMCS, the explicit interface name may include type arguments + (IEnumerable.GetEnumerator). + * we use `member_name' instead of just `IDENTIFIER' for + "member names": + The rule is that we use `member_name' wherever a member may + have type parameters in GMCS. + + * decl.cs (MemberName): New public class. + (MemberCore.MemberName): New public readonly field. + (MemberCore.ctor): Take a `MemberName' argument, not a string. + (DeclSpace): Likewise. + + * delegate.cs (Delegate.ctor): Take a MemberName, not a string. + * enum.cs (Enum.ctor): Likewise. + + * namespace.cs (AliasEntry.Alias): Changed type from Expression to + MemberName. + (AliasEntry.ctor): Take a MemberName, not an Expression. + (AliasEntry.UsingAlias): Likewise. + + * class.cs (TypeContainer.ctor): Take a MemberName, not a string. + (IMethodData.MemberName): Changed type from string to MemberName. + (MemberBase.ExplicitInterfaceName): Likewise. + (AbstractPropertyEventMethod.SetupName): Make this private. + (AbstractPropertyEventMethod.ctor): Added `string prefix' + argument; compute the member name here. + (AbstractPropertyEventMethod.UpdateName): Recompute the name based + on the `member.MemberName' and the `prefix'. + + * cs-parser.jay (attribute_name): Use `namespace_or_type_name', + not `type_name'. + (struct_declaration): Use `member_name' instead of `IDENTIFIER'; + thus, we get a `MemberName' instead of a `string'. These + declarations may have type parameters in GMCS. + (interface_method_declaration, delegate_declaration): Likewise. + (class_declaration, interface_declaration): Likewise. + (method_header): Use `namespace_or_type_name' instead of + `member_name'. We may be an explicit interface implementation. + (property_declaration, event_declaration): Likewise. + (member_name): This is now just an `IDENTIFIER', not a + `namespace_or_type_name'. + (type_name, interface_type): Removed. + (namespace_or_type_name): Return a MemberName, not an Expression. + (primary_expression): Use `member_name' instead of `IDENTIFIER'; + call GetTypeExpression() on the MemberName to get an expression. + (IndexerDeclaration.interface_type): Changed type from string to + MemberName. + (MakeName): Operate on MemberName's instead of string's. + +2004-09-13 Raja R Harinath + + Fix bug #55770. + * namespace.cs (AliasEntry.Resolve): Implement section 16.3.1. + (NamespaceEntry.Lookup): Add new argument to flag if we want the + lookup to avoid symbols introduced by 'using'. + * rootcontext.cs (NamespaceLookup): Update. + +2004-09-12 Marek Safar + + * class.cs (TypeContainer.DoDefineMembers): Do not call + DefineDefaultConstructor for static classes. + +2004-09-12 Marek Safar + + * attribute.cs (Attribute.Resolve): Add error 653 report. + + * class.cs (Class.ApplyAttributeBuilder): Add error 641 + report. + (Method.ApplyAttributeBuilder): Add error 685 report. + (Operator.Define): Add error 564 report. + + * cs-tokenizer.cs (handle_hex): Add error 1013 report. + + * expression.cs (Invocation.DoResolve): Add error + 245 and 250 report. + + * parameter.cs (Parameter.ApplyAttributeBuilder): Add + error 674 report. + +2004-09-11 Marek Safar + + * class.cs (ConstructorInitializer.Resolve): + Wrong error number (515->516). + +2004-09-11 Marek Safar + + * class.cs (Indexer.Define): Add error 631 report. + +2004-09-11 Marek Safar + + * ecore.cs (Error_NegativeArrayIndex): Fix 248 error. + +2004-09-11 Marek Safar + + * expression.cs (Probe.DoResolve): Add error CS0241 report. + +2004-09-10 Marek Safar + + * cs-parser.jay: Added error CS0241 report. + +2004-09-10 Raja R Harinath + + * cs-parser.jay (fixed_statement): Introduce a scope for the + declaration in the 'fixed' statement. + +2004-09-09 Marek Safar + + * cs-parser.jay: Added CS0230 error report. + +2004-09-09 Marek Safar + + * cs-parser.jay: Added errors CS0231 and CS0257 report. + +2004-09-09 Marek Safar + + * expression.cs (Argument.Resolve): Added error CS0192 and + CS0199 report. + +2004-09-09 Marek Safar + + C# 2.0 #pragma warning feature + + * cs-tokenizer.cs (PreProcessPragma): New method; + Handles #pragma directive. + + * report.cs (WarningRegions): New class; Support + class for #pragma warning directive. It tests whether + warning is enabled for a given line. + +2004-09-08 Miguel de Icaza + + * const.cs: Add more descriptive error report, tahnks to + Sebastien. + +2004-09-08 Marek Safar + + * ecore.cs (FieldExpr.DoResolveLValue): Fixed CS0198 report. + +2004-09-07 Miguel de Icaza + + * expression.cs: Apply patch from Ben: Remove dead code from + ArrayCreation, and remove the TurnintoConstant call in const.cs, + as that code just threw an exception anwyays. + + * const.cs: Remove the call to the turnintoconstant, for details + see bug: #63144 + + * literal.cs: The type of the null-literal is the null type; So + we use a placeholder type (literal.cs:System.Null, defined here) + for it. + + * expression.cs (Conditional.DoResolve): Remove some old code that + is no longer needed, conversions have been fixed. + + (ArrayCreationExpression.DoResolve): Return false if we fail to + resolve the inner expression. + +2004-09-07 Raja R Harinath + + Fix test-290.cs. + * cs-parser.jay (delegate_declaration): Record a delegate + declaration as a type declaration. + Reported by Jo Vermeulen . + +2004-09-06 Miguel de Icaza + + * parameter.cs: Do not crash if the type can not be resolved. + + * expression.cs: Report errors with unsafe pointers, fixes #64896 + +2004-09-06 Ben Maurer + + * expression.cs: Pointer arith always needs to do a conv.i + if the operand is a long. fix 65320 + +2004-09-04 Marek Safar + + Fixed cs0619-37.cs, cs0619-38.cs + + * enum.cs (GetObsoleteAttribute): Removed. + + * expression.cs (MemberAccess.DoResolve): Test for [Obsolete] + on Enum member is double staged. The first is tested member + and then enum. + +2004-09-04 Marek Safar + + Fixed #56986, #63631, #65231 + + * class.cs: (TypeContainer.AddToMemberContainer): New method, + adds member to name container. + (TypeContainer.AddToTypeContainer): New method, adds type to + name container. + (AddConstant, AddEnum, AddClassOrStruct, AddDelegate, AddMethod, + AddConstructor, AddInterface, AddField, AddProperty, AddEvent, + AddOperator): Simplified by reusing AddToMemberContainer. + (TypeContainer.UserDefinedStaticConstructor): Changed to property + instead of field. + (Method.CheckForDuplications): Fixed implementation to test all + possibilities. + (MemberBase): Detection whether member is explicit interface + implementation is now in constructor. + (MemberBase.UpdateMemberName): Handles IndexerName. + (Accessor): Changed to keep also location information. + (AbstractPropertyEventMethod): Is derived from MemberCore. + (AbstractPropertyEventMethod.IsDummy): Says whether accessor + will be emited or not. + (PropertyBase.AreAccessorsDuplicateImplementation): + Tests whether accessors are not in collision with some method. + (Operator): Is derived from MethodCore to simplify common + operations. + + * decl.cs (Flags.TestMethodDuplication): Test for duplication + must be performed. + (DeclSpace.AddToContainer): Adds the member to defined_names + table. It tests for duplications and enclosing name conflicts. + + * enum.cs (EnumMember): Clean up to reuse the base structures + +2004-09-03 Martin Baulig + + * class.cs (TypeContainer.DefineDefaultConstructor): Put this back + into TypeContainer, to make partial classes work again. + +2004-09-03 Martin Baulig + + * rootcontext.cs (RootContext.V2): Removed. + +2004-03-23 Martin Baulig + + * expression.cs (Invocation.OverloadResolve): Added `bool + may_fail' argument and use it instead of the Location.IsNull() hack. + +2004-09-03 Martin Baulig + + Merged latest changes into gmcs. Please keep this comment in + here, it makes it easier for me to see what changed in MCS since + the last time I merged. + +2004-09-03 Raja R Harinath + + Fix #61128. + * expression.cs (BetterConversion): Don't allow either conversion + to be null. Remove redundant implicit conversion test when 'q == + null' -- when this function is invoked, we already know that the + implicit conversion exists. + (BetterFunction): Assume that 'best' is non-null. Remove + redundant reimplementation of IsApplicable when 'best' is null. + (IsParamsMethodApplicable, IsApplicable): Add new parameter for + number of arguments. + (IsAncestralType): Extract from OverloadResolve. + (OverloadResolve): Make robust to the MethodGroupExpr being + unsorted. Implement all the logic of Section 14.5.5.1, and + support overloading of methods from multiple applicable types. + Clean up logic somewhat. Don't pass null methods to BetterFunction. + + * report.cs (SymbolRelatedToPreviousError): Cleanup output. + (RealError, Warning): Append type of report to related symbol. + +2004-09-03 Marek Safar + + * enum.cs: Fixed CLS-Compliance checks for enum members. + Error tests cs3008-8.cs, cs3014-8.cs + +2004-09-02 Marek Safar + + Fixed bug #62342, #63102 + * class.cs: ImplementIndexer uses member.IsExplicitImpl + like ImplementMethod. + +2004-09-02 Marek Safar + + * attribute.cs (Attribute.GetAttributeArgumentExpression): + Fixed bug #65170. + +2004-09-02 Martin Baulig + + * statement.cs (Using.EmitLocalVariableDeclFinally): Use + TypeManager.GetArgumentTypes() rather than calling GetParameters() + on the MethodBase. + +2004-09-01 Marek Safar + + C# 2.0 Static classes implemented + + * class.cs (TypeContainer): instance_constructors, + initialized_fields, initialized_static_fields, + default_constructor, base_inteface_types are protected to be + accessible from StaticClass. + (TypeContainer.DefineDefaultConstructor): New virtual method + for custom default constructor generating + (StaticClass): New class to handle "Static classes" feature. + + * cs-parser.jay: Handle static keyword on class like instance + of StaticClass. + + * driver.cs: Added "/langversion" command line switch with two + options (iso-1, default). + +2004-08-31 Marek Safar + + * ecore.cs (FieldExpr.Resolve): Fixed bug #64689. + +2004-08-31 Miguel de Icaza + + * delegate.cs: Style. + +2004-08-31 Ben Maurer + + * delegate.cs: Add seperate instance expr field for miguel. + +2004-08-29 Ben Maurer + + * PointerArithmetic (Resolve): make sure we are not doing + pointer arith on void*. Also, make sure we are resolved + by not setting eclass until resolve. + + All callers: Make sure that PointerArithmetic gets resolved. + +2004-08-29 Ben Maurer + + * ArrayCreation (LookupType): If the type does not resolve + to an array, give an error. + +2004-08-27 Marek Safar + + * statement.cs (Try.Resolve): Fixed bug #64222 + +2004-08-27 Martin Baulig + + * class.cs + (TC.OperatorArrayList.OperatorEntry.CheckPairedOperators): Don't + crash here. + +2004-08-26 Marek Safar + + * ecore.cs (Constantify): Get underlying type via + System.Enum.GetUnderlyingType to avoid StackOverflow on the + Windows in special cases. + +2004-08-26 Marek Safar + + * typemanager.cs (GetAddMethod): Used GetAddMethod (true) + for obtaining also private methods. + (GetRemoveMethod): Used GetRemoveMethod (true) + for obtaining also private methods. + +2004-08-24 Martin Baulig + + * class.cs (Method.Define): Set MethodAttributes.SpecialName and + MethodAttributes.HideBySig for operators. + +2004-08-23 Martin Baulig + + Back to the old error reporting system :-) + + * report.cs (Message): Removed. + (Report.MessageData, ErrorData, WarningData): Removed. + (Report.Error, Warning): Back to the old system. + +2004-08-23 Martin Baulig + + * decl.cs (IMemberContainer.Parent): Renamed to ParentContainer. + + * class.cs (TypeContainer.ParentContainer): New public virtual + method; replaces the explicit interface implementation. + (ClassPart.ParentContainer): Override. + +2004-08-23 Martin Baulig + + * statement.cs (Switch): Added support for constant switches; see + #59428 or test-285.cs. + +2004-08-22 Marek Safar + + Fixed bug #62740. + * statement.cs (GetEnumeratorFilter): Removed useless + logic because C# specs is strict. GetEnumerator must be + public. + +2004-08-22 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + a switch and may break, reset the barrier. Fixes #59867. + +2004-08-22 Marek Safar + + CLS-Compliance speed up (~5% for corlib) + + * attribute.cs (AttributeTester.VerifyTopLevelNameClsCompliance): + New method. Tests container for CLS-Compliant names + + * class.cs (TypeContainer.VerifyClsName): New method. + Checks whether container name is CLS Compliant. + (Constructor): Implements IMethodData. + + * decl.cs (MemberCache.GetPublicMembers ): New method. Builds + low-case table for CLS Compliance test. + (MemberCache.VerifyClsParameterConflict): New method. + Checks method parameters for CS3006 error. + + * enum.cs (EnumMember): Is derived from MemberCore. + (Enum.VerifyClsName): Optimized for better performance. + +2004-08-06 Marek Safar + + * report.cs: Renamed Error_T to Error and changed all + references. + +2004-08-06 Marek Safar + + * class.cs (TypeContainer.IndexerArrayList): New inner class + container for indexers. + (TypeContainer.DefaultIndexerName): New constant for default + indexer name. Replaced all "Item" with this constant. + (TypeContainer.DefineIndexers): Moved to IndexerArrayList class. + + * typemanager.cs (TypeManager.default_member_ctor): Cache here + DefaultMemberAttribute constructor. + +2004-08-05 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeJumpOrigins): + Fix bug #59429. + +2004-08-05 Marek Safar + + * mcs.exe.sources: $(EXTRA_SOURCES) are now here to avoid + multi platforms problem. + + * compiler.csproj: Included shared files. + +2004-08-04 Marek Safar + + Fix bug 60333, 55971 in the more general way + * attribute.cs (Attribute.GetAttributeArgumentExpression): + Added arg_type argument for constant conversion. + (Attribute.Resolve): Reuse GetAttributeArgumentExpression. + +2004-08-04 Marek Safar + + Fix bug #59760 + * class.cs (TypeContainer ): New inner classes MethodArrayList, + OperatorArrayList, MethodCoreArrayList for typecontainer + containers. Changed class member types to these new types. + (MethodArrayList.DefineMembers): Added test for CS0659. + +2004-08-04 Miguel de Icaza + + * cfold.cs: Synchronize the folding with the code in expression.cs + Binary.DoNumericPromotions for uint operands. + + * attribute.cs: Revert patch from Raja, it introduced a regression + while building Blam-1.2.1 (hard to isolate a test case). + +2004-08-04 Marek Safar + + Fix for #55382 + * class.cs: + (TypeContainer.Define): Renamed to DefineContainerMembers because of + name collision. + (MethodCore.parent_method): New member. The method we're overriding + if this is an override method. + (MethodCore.CheckBase): Moved from Method class and made common. + (MethodCore.CheckMethodAgainstBase): Moved from MemberBase and made + private. + (MethodCore.CheckForDuplications): New abstract method. For custom + member duplication search in a container + (MethodCore.FindOutParentMethod): New abstract method. Gets parent + method and its return type. + (Event.conflict_symbol): New member. Symbol with same name in the + parent class. + + * decl.cs: + (MemberCache.FindMemberWithSameName): New method. The method + is looking for conflict with inherited symbols. + +2004-08-04 Martin Baulig + + * codegen.cs (VariableStorage.EmitLoadAddress): New public method. + + * statement.cs (Foreach.EmitFinally): Make this work for valuetypes. + +2004-08-03 Marek Safar + + * report.cs (Message): New enum for better error, warning reference in + the code. + (MessageData): New inner abstract class. It generally handles printing of + error and warning messages. + Removed unused Error, Warning, Message methods. + +2004-08-03 Marek Safar + + Fix for cs0592-8.cs test + * attribute.cs + (Attributable.ValidAttributeTargets): Made public. + (Attribute.ExplicitTarget): New member for explicit target value. + (Attribute.CheckTargets): Now we translate explicit attribute + target to Target here. + +2004-08-03 Ben Maurer + + * ecore.cs (MethodGroupExpr): new IsBase property. + + * expression.cs (BaseAccess): Set IsBase on MethodGroupExpr. + + * delegate.cs (DelegateCreation): store a MethodGroupExpr + rather than an instance expr. + + (DelegateCreation.Emit): Use the method group rather than + the instance expression. Also, if you have base.Foo as the + method for a delegate, make sure to emit ldftn, not ldftnvirt. + + (ResolveMethodGroupExpr): Use the MethodGroupExpr. + + (NewDelegate.DoResolve): Only check for the existance of Invoke + if the method is going to be needed. Use MethodGroupExpr. + + (NewDelegate.Emit): Remove, DelegateCreation implements this. + + * expression.cs: For pointer arith., make sure to use + the size of the type, not the size of the pointer to + the type. + +2004-08-03 Marek Safar + + Fix for #60722 + * class.cs (Class): Added error CS0502 test. + +2004-08-03 John Luke + Raja R Harinath + + Fix for #60997. + * attribute.cs (Attribute.complained_before): New flag. + (Attribute.ResolveType, Attribute.Resolve), + (Attribute.DefinePInvokeMethod): Set it. + (Attributes.Search): Pass 'complain' to Attribute.ResolveType. + +2004-08-03 Martin Baulig + + * expression.cs (Binary.ResolveOperator): Don't abort if we can't + use a user-defined operator; we still need to do numeric + promotions in case one argument is a builtin type and the other + one has an implicit conversion to that type. Fixes #62322. + +2004-08-02 Martin Baulig + + * statement.cs (LocalInfo.Flags): Added `IsThis'. + (LocalInfo.IsThis): New public property. + (Block.EmitMeta): Don't create a LocalBuilder for `this'. + +2004-08-01 Martin Baulig + + * class.cs (TypeContainer.GetClassBases): Don't set the default + here since we may get called from GetPartialBases(). + (TypeContainer.DefineType): If GetClassBases() didn't return a + parent, use the default one. + +2004-07-30 Duncan Mak + + * Makefile (mcs2.exe, mcs3.exe): add $(EXTRA_SOURCES). + +2004-07-30 Martin Baulig + + * Makefile (EXTRA_SOURCES): List the symbol writer's sources here. + + * class.cs (SourceMethod): New public class, derive from the + symbol writer's ISourceMethod. + (Method): Use the new symbol writer API. + + * codegen.cs (CodeGen.InitializeSymbolWriter): Take the filename + as argument and use the new symbol writer. + + * location.cs + (SourceFile): Implement the symbol writer's ISourceFile. + (Location.SymbolDocument): Removed. + (Location.SourceFile): New public property. + + * symbolwriter.cs: Use the new symbol writer API. + +2004-07-30 Raja R Harinath + + * Makefile (install-local): Remove. Functionality moved to + executable.make. + +2004-07-28 Lluis Sanchez Gual + + * Makefile: Install mcs.exe.config file together with mcs.exe. + * mcs.exe.config: Added supportedRuntime entry to make sure it runs in the + correct runtime version. + +2004-07-25 Martin Baulig + + * class.cs + (TypeContainer.RegisterOrder): Removed, this was unused. + (TypeContainer, interface_order): Removed. + (TypeContainer.AddClass, AddStruct, AddInterface): Take a + TypeContainer as argument since we can also be called with a + `PartialContainer' for a partial class/struct/interface. + (TypeContainer.IsInterface): Use `Kind == Kind.Interface' instead + of checking whether we're an `Interface' - we could be a + `PartialContainer'. + (PartialContainer.Register): Override; call + AddClass()/AddStruct()/AddInterface() on our parent. + + * cs-parser.jay (interface_member_declaration): Add things to the + `current_container', not the `current_class'. + + * rootcontext.cs (RegisterOrder): The overloaded version which + takes an `Interface' was unused, removed. + + * typemanager.cs (TypeManager.LookupInterface): Return a + `TypeContainer', not an `Interface'. + (TypeManager.IsInterfaceType): The `builder_to_declspace' may + contain a `PartialContainer' for an interface, so check it's + `Kind' to figure out what it is. + +2004-07-25 Martin Baulig + + * class.cs (Class.DefaultTypeAttributes): New public constant. + (Struct.DefaultTypeAttributes): Likewise. + (Interface.DefaultTypeAttributes): Likewise. + (PartialContainer.TypeAttr): Override this and add the + DefaultTypeAttributes. + +2004-07-25 Martin Baulig + + * decl.cs (DeclSpace.Emit): Removed the `TypeContainer' argument, + we can just use the `Parent' field instead. + +2004-07-25 Martin Baulig + + * class.cs (TypeContainer.Emit): Renamed to EmitType(). + +2004-07-25 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Call DefineMembers() on + our parts before defining any methods. + (TypeContainer.VerifyImplements): Make this virtual. + (ClassPart.VerifyImplements): Override and call VerifyImplements() + on our PartialContainer. + +2004-07-25 Martin Baulig + + * iterators.cs (Iterator.Define): Renamed to DefineIterator(). + + * decl.cs (DeclSpace.Define): Removed the `TypeContainer' + argument, we can just use the `Parent' field instead. + + * class.cs + (MemberBase.CheckBase): Removed the `TypeContainer' argument. + (MemberBase.DoDefine): Likewise. + +2004-07-24 Martin Baulig + + * decl.cs (MemberCore.Parent): New public field. + (DeclSpace.Parent): Moved to MemberCore. + + * class.cs (MethodCore.ds): Removed; use `Parent' instead. + (MemberBase.ctor): Added TypeContainer argument, pass it to our + parent's .ctor. + (FieldBase, Field, Operator): Likewise. + (EventProperty.ctor): Take a TypeContainer instead of a DeclSpace. + (EventField, Event): Likewise. + +2004-07-23 Martin Baulig + + * class.cs (PartialContainer): New public class. + (ClassPart): New public class. + (TypeContainer): Added support for partial classes. + (TypeContainer.GetClassBases): Splitted some of the functionality + out into GetNormalBases() and GetPartialBases(). + + * cs-tokenizer.cs (Token.PARTIAL): New token. + (Tokenizer.consume_identifier): Added some hacks to recognize + `partial', but only if it's immediately followed by `class', + `struct' or `interface'. + + * cs-parser.jay: Added support for partial clases. + +2004-07-23 Martin Baulig + + * class.cs (MethodCore.ds): Made this a `TypeContainer' instead of + a `DeclSpace' and also made it readonly. + (MethodCore.ctor): Take a TypeContainer instead of a DeclSpace. + (Method.ctor, Constructor.ctor, Destruktor.ctor): Likewise. + (PropertyBase.ctor, Property.ctor, Indexer.ctor): Likewise. + + * cs-parser.jay: Pass the `current_class', not the + `current_container' (at the moment, this is still the same thing) + to a new Method, Property, Event, Indexer or Constructor. + +2004-07-23 Martin Baulig + + * cs-parser.jay (CSharpParser): Added a new `current_class' field + and removed the `current_interface' one. + (struct_declaration, class_declaration, interface_declaration): + Set `current_class' to the newly created class/struct/interface; + set their `Bases' and call Register() before parsing their body. + +2004-07-23 Martin Baulig + + * class.cs (Kind): New public enum. + (TypeContainer): Made this class abstract. + (TypeContainer.Kind): New public readonly field. + (TypeContainer.CheckDef): New public method; moved here from + cs-parser.jay. + (TypeContainer.Register): New public abstract method. + (TypeContainer.GetPendingImplementations): New public abstract + method. + (TypeContainer.GetClassBases): Removed the `is_class' and + `is_iface' parameters. + (TypeContainer.DefineNestedTypes): Formerly known as + DoDefineType(). + (ClassOrStruct): Made this class abstract. + + * tree.cs (RootTypes): New public type. + +2004-07-20 Martin Baulig + + * tree.cs (Tree.RecordNamespace): Removed. + (Tree.Namespaces): Removed. + + * rootcontext.cs (RootContext.IsNamespace): Removed. + + * cs-parser.jay (namespace_declaration): Just create a new + NamespaceEntry here. + +2004-07-20 Martin Baulig + + * statement.cs (ExceptionStatement): New abstract class. This is + now used as a base class for everyone who's using `finally'. + (Using.ResolveLocalVariableDecls): Actually ResolveLValue() all + our local variables before using them. + + * flowanalysis.cs (FlowBranching.StealFinallyClauses): New public + virtual method. This is used by Yield.Resolve() to "steal" an + outer block's `finally' clauses. + (FlowBranchingException): The .ctor now takes an ExceptionStatement + argument. + + * codegen.cs (EmitContext.StartFlowBranching): Added overloaded + version which takes an ExceptionStatement. This version must be + used to create exception branchings. + + * iterator.cs + (Yield.Resolve): "Steal" all `finally' clauses from containing blocks. + (Iterator.EmitMoveNext): Added exception support; protect the + block with a `fault' clause, properly handle 'finally' clauses. + (Iterator.EmitDispose): Run all the `finally' clauses here. + +2004-07-20 Martin Baulig + + * iterator.cs: This is the first of a set of changes in the + iterator code. Match the spec more closely: if we're an + IEnumerable, then GetEnumerator() must be called. The first time + GetEnumerator() is called, it returns the current instance; all + subsequent invocations (if any) must create a copy. + +2004-07-19 Miguel de Icaza + + * expression.cs: Resolve the constant expression before returning + it. + +2004-07-19 Martin Baulig + + * iterators.cs (Iterator.MapVariable): Don't define fields twice. + (Iterator.MoveNextMethod.DoEmit): Use `TypeManager.int32_type' as + the return type of the new EmitContext. + +2004-07-18 Martin Baulig + + * class.cs (Property.Define): Fix iterators. + + * iterators.cs (Iterator.Define): Moved the + `container.AddInterator (this)' call here from the .ctor; only do + it if we resolved successfully. + +2004-07-17 Miguel de Icaza + + * cs-tokenizer.cs (handle_preprocessing_directive): Do not return + `true' for preprocessing directives that we parse. The return + value indicates whether we should return to regular tokenizing or + not, not whether it was parsed successfully. + + In the past if we were in: #if false ... #line #endif, we would + resume parsing after `#line'. See bug 61604. + + * typemanager.cs: Removed an old hack from Gonzalo to get corlib + building: IsEnumType should return true only for enums, not for + enums or System.Enum itself. This fixes #61593. + + Likely what happened is that corlib was wrong: mcs depended on + this bug in some places. The bug got fixed, we had to add the + hack, which caused bug 61593. + + * expression.cs (ArrayAccess.GetStoreOpCode): Remove an old hack + that was a workaround for the older conditions. + +2004-07-16 Ben Maurer + + * assign.cs: IAssignMethod has a new interface, as documented + inline. All assignment code now uses this new api. + + * ecore.cs, expression.cs: All classes which implement + IAssignMethod now use the new interface. + + * expression.cs (Invocation): add a hack to EmitCall so that + IndexerAccess can be the target of a compound assignment without + evaluating its arguments twice. + + * statement.cs: Handle changes in Invocation api. + +2004-07-16 Martin Baulig + + * iterators.cs: Rewrote this. We're now using one single Proxy + class for both the IEnumerable and the IEnumerator interface and + `Iterator' derives from Class so we can use the high-level API. + + * class.cs (TypeContainer.AddIterator): New method. + (TypeContainer.DoDefineType): New protected virtual method, which + is called from DefineType(). + (TypeContainer.DoDefineMembers): Call DefineType() and + DefineMembers() on all our iterators. + (TypeContainer.Emit): Call Emit() on all our iterators. + (TypeContainer.CloseType): Call CloseType() on all our iterators. + + * codegen.cs (EmitContext.CurrentIterator): New public field. + +2004-07-15 Martin Baulig + + * typemanager.cs + (TypeManager.not_supported_exception_type): New type. + +2004-07-14 Martin Baulig + + * iterators.cs: Use real error numbers. + +2004-07-14 Martin Baulig + + * iterator.cs (IteratorHandle.IsIEnumerable): The spec explicitly + requires this to be a System.Collection.IEnumerable and not a + class implementing that interface. + (IteratorHandle.IsIEnumerator): Likewise, for IEnumerator. + +2004-07-13 Marek Safar + + * class.cs: Fixed previous fix, it broke some error tests. + +2004-07-12 Martin Baulig + + * enum.cs (Enum.Define): Call Emit() to emit the attributes. + Fixes #61293. + +2004-07-09 Miguel de Icaza + + * assign.cs (LocalTemporary): Add new argument: is_address,If + `is_address' is true, then the value that we store is the address + to the real value, and not the value itself. + + * ecore.cs (PropertyExpr): use the new local temporary + stuff to allow us to handle X.Y += z (where X is a struct) + +2004-07-08 Martin Baulig + + * statement.cs (Lock.Resolve): Set ec.NeedReturnLabel() if we do + not always return, just like we're doing in Using.Resolve(). + +2004-07-07 Miguel de Icaza + + * cs-parser.jay (fixed_statement): flag this as Pinned. + +2004-07-06 Miguel de Icaza + + * typemanager.cs (TypeManager): Removed MakePinned method, this + mechanism is replaced with the .NET 2.x compatible mechanism of + calling `ILGenerator.DeclareLocal (Type t, bool pinned)'. + + * statement.cs (LocalInfo): Remove MakePinned, add Pinned property + Rename `Fixed' to `Pinned' as a flag, to distinguish from the + `IsFixed' property which has a different meaning. + +2004-07-02 Raja R Harinath + + * ecore.cs (DoSimpleNameResolve): Expand CS0038 check to all names + visible from inside a nested class, not just the names of the + immediately enclosing class. + Fix for bug #60730. + +2004-06-24 Raja R Harinath + + * expression.cs (BetterConversion): Remove buggy special-case + handling of "implicit constant expression conversions". At this + point, we already know that the conversion is possible -- we're + only checking to see which is better. + +2004-06-24 Marek Safar + + * cs-parser.jay: Added error CS0210 test. + +2004-06-24 Marek Safar + + * cs-parser.jay: Added error CS0134 test. + +2004-06-24 Marek Safar + + Fix bug #52507 + * cs-parser.jay: Added error CS0145 test. + +2004-06-24 Marek Safar + + * class.cs (Operator.Define): Added test for errors CS0553, CS0554. + +2004-06-23 Ben Maurer + + * expression.cs (StackAlloc.Resolve): The argument may not + be a constant; deal with this case. + +2004-06-23 Marek Safar + + * attribute.cs (IndexerName_GetIndexerName): Renamed to + GetIndexerAttributeValue. + (ScanForIndexerName): Renamed to GetIndexerNameAttribute. + + * class.cs (Indexer.Define): Added error tests for CS0415, + CS0609. + +2004-06-23 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Keep field code in sync with + property code. + +2004-06-23 Martin Baulig + + * flowanalysis.cs (UsageVector.MergeChild): If we're a loop and we + neither return nor throw, reset the barrier as well. Fixes #60457. + +2004-06-22 Atsushi Enomoto + + * class.cs : EventAttributes is now set to None by default. + This fixes bug #60459. + +2004-06-18 Marek Safar + + Fix bug #60219 + * class.cs (ConstructorInitializer.GetOverloadedConstructor): + Don't throw exception but return null (it's sufficient now). + +2004-06-18 Marek Safar + + * typemanager.cs (GetArgumentTypes): Faster implementation. + +2004-06-18 Martin Baulig + + * attribute.cs (Attribute.Resolve): Check whether we're an + EmptyCast which a Constant child. Fixes #60333. + +2004-06-17 Ben Maurer + + * statement.cs (EmitCollectionForeach): Account for the fact that + not all valuetypes are in areas which we can take the address of. + For these variables, we store to a temporary variable. Also, make + sure that we dont emit a `callvirt' on a valuetype method. + +2004-06-15 Marek Safar + + * expression.cs (StackAlloc.DoReSolve): Added test for + negative parameter (CS0247). + +2004-06-15 Marek Safar + + Fix bug #59792 + * class.cs: (Event.DelegateMethod.Emit): Added synchronization flag. + +2004-06-15 Marek Safar + + Fix bug #59781 + * expression.cs: (Binary.DoNumericPromotions): Added conversion for + ulong. + +2004-06-14 Marek Safar + + Fix bug #58254 & cs1555.cs, cs1556.cs + * driver.cs (MainDriver): Added tests for errors CS1555, CS1556. + +2004-06-14 Marek Safar + + * cs-parser.jay: Added error CS1669 test for indexers. + +2004-06-11 Martin Baulig + + * expression.cs (Invocation.IsParamsMethodApplicable): We need to + call this twice: for params and varargs methods. + +2004-06-11 Marek Safar + + * class.cs: + (FieldBase.DoDefine, PropertyBase.DoDefine): Added error test CS0610. + +2004-06-11 Marek Safar + + * attribute.cs (Attribute.GetValidTargets): Made public. + + * class.cs: + (AbstractPropertyEventMethod): New class for better code sharing. + (AbstractPropertyEventMethod.ApplyAttributeBuilder): Add error + CS1667 report. + (PropertyMethod, DelegateMethod): Derived from AbstractPropertyEventMethod + +2004-06-11 Raja R Harinath + + Fix bug #59477. + * ecore.cs (ResolveFlags): Add new 'Intermediate' flag to tell + that the call to Resolve is part of a MemberAccess. + (Expression.Resolve): Use it for SimpleName resolution. + (SimpleName.SimpleNameResolve, SimpleName.DoResolveAllowStatic): + Add 'intermediate' boolean argument. + (SimpleName.DoSimpleNameResolve): Likewise. Use it to disable an + error message when the SimpleName can be resolved ambiguously + between an expression and a type. + * expression.cs (MemberAccess.IdenticalNameAndTypeName): Make + public. + (MemberAccess.Resolve): Pass 'Intermediate' flag to the Resolve() + call on the left-side. + +2004-06-11 Marek Safar + + * class.cs: + (MethodCore.VerifyClsCompliance): Added test for error CS3000. + +2004-06-11 Marek Safar + + * attribute.cs (Attribute.Emit): Fixed error CS0579 reporting. + +2004-06-11 Martin Baulig + + * expression.cs (Invocation.EmitCall): Use OpCodes.Callvirt for + varargs methods if applicable. + +2004-06-11 Martin Baulig + + * expression.cs (Invocation.EmitCall): Don't use + `method.CallingConvention == CallingConventions.VarArgs' since the + method could also have `CallingConventions.HasThis'. + +2004-06-11 Marek Safar + + * class.cs (Event.GetSignatureForError): Implemented. + Fixed crash in error test cs3010.cs + +2004-06-10 Miguel de Icaza + + * cs-tokenizer.cs: Change the way we track __arglist to be + consistent with the other keywords. + +2004-06-09 Miguel de Icaza + + * codegen.cs: FAQ avoider: turn 1577 into a warning for now until + tomorrow. + +2004-06-09 Sebastien Pouliot + + * codegen.cs: Check that all referenced assemblies have a strongname + before strongnaming the compiled assembly. If not report error CS1577. + Fix bug #56563. Patch by Jackson Harper. + * typemanager.cs: Added a method to return all referenced assemblies. + Fix bug #56563. Patch by Jackson Harper. + +2004-06-08 Marek Safar + + * class.cs: + (Method.ApplyAttributeBuilder): Moved and added conditional + attribute error tests (CS0577, CS0578, CS0243, CS0582, CS0629). + + * delegate.cs: + (DelegateCreation.ResolveMethodGroupExpr): Added error CS1618 test. + +2004-06-08 Marek Safar + + Fixed #59640 + * class.cs: (EventField.attribute_targets): Changed default target. + +2004-06-08 Martin Baulig + + * expression.cs (Invocation.EmitCall): Enable varargs methods. + +2004-06-08 Martin Baulig + + * rootcontext.cs (ResolveCore): Added "System.RuntimeArgumentHandle". + +2004-06-07 Martin Baulig + + Added support for varargs methods. + + * cs-tokenizer.cs (Token.ARGLIST): New token for the `__arglist' + keyword. + + * cs-parser.jay: Added support for `__arglist'. + + * decl.cs (MemberCache.AddMethods): Don't ignore varargs methods. + + * expression.cs (Argument.AType): Added `ArgList'. + (Invocation): Added support for varargs methods. + (ArglistAccess): New public class. + (Arglist): New public class. + + * parameter.cs (Parameter.Modifier): Added `ARGLIST'. + + * statement.cs (Block.Flags): Added `HasVarargs'. We set this on + a method's top-level block if the method has varargs. + + * support.cs (ReflectionParameters, InternalParameters): Added + support for varargs methods. + +2004-06-07 Miguel de Icaza + + * class.cs: Provide location in indexer error report. + + * driver.cs: Use standard names. + + * namespace.cs: Catch the use of using after a namespace has been + declared also on using aliases. + +2004-06-03 Raja R Harinath + + Bug #50820. + * typemanager.cs (closure_private_ok, closure_invocation_type) + (closure_qualifier_type, closure_invocation_assembly) + (FilterWithClosure): Move to ... + (Closure): New internal nested class. + (Closure.CheckValidFamilyAccess): Split out from Closure.Filter. + (MemberLookup, RealMemberLookup): Add new almost_match parameter. + * ecore.cs (almostMatchedMembers): New variable to help report CS1540. + (MemberLookup, MemberLookupFailed): Use it. + * expression.cs (New.DoResolve): Treat the lookup for the + constructor as being qualified by the 'new'ed type. + (Indexers.GetIndexersForTypeOrInterface): Update. + +2004-06-03 Marek Safar + + * attribute.cs + (GetConditionalAttributeValue): New method. Returns + condition of ConditionalAttribute. + (SearchMulti): New method. Returns all attributes of type 't'. + Use it when attribute is AllowMultiple = true. + (IsConditionalMethodExcluded): New method. + + * class.cs + (Method.IsExcluded): Implemented. Returns true if method has conditional + attribute and the conditions is not defined (method is excluded). + (IMethodData): Extended interface for ConditionalAttribute support. + (PropertyMethod.IsExcluded): Implemented. + + * decl.cs + (MemberCore.Flags): Excluded_Undetected, Excluded new caching flags. + + * expression.cs + (Invocation.IsMethodExcluded): Checks the ConditionalAttribute + on the method. + +2004-06-02 Ben Maurer + + * expression.cs (ArrayCreationExpression): Make this just an + `expression'. It can't be a statement, so the code here was + dead. + +2004-06-02 Marek Safar + + Fixed #59072 + * typemanager.cs (GetFullNameSignature): New method for + MethodBase types. + +2004-06-02 Marek Safar + + Fixed #56452 + * class.cs (MemberBase.GetSignatureForError): New virtual method. + Use this method when MethodBuilder is null. + (MethodData.DefineMethodBuilder): Encapsulated code to the new method. + Added test for error CS0626 (MONO reports error for this situation). + (IMethodData.GetSignatureForError): Extended interface. + +2004-06-01 Marek Safar + + * attribute.cs + (AttributeTester.GetObsoleteAttribute): Returns instance of + ObsoleteAttribute when type is obsolete. + + * class.cs + (TypeContainer.VerifyObsoleteAttribute): Override. + (Method.GetSignatureForError): New method for usage when MethodBuilder is null. + (MethodCode.VerifyObsoleteAttribute): Override. + (MemberBase.VerifyObsoleteAttribute): Override. + + * decl.cs + (MemberCore.CheckUsageOfObsoleteAttribute): Tests presence of ObsoleteAttribute + and report proper error. + + *delegate.cs + Delegate.VerifyObsoleteAttribute): Override. + + * ecore.cs + (Expression.CheckObsoleteAttribute): Tests presence of ObsoleteAttribute + and report proper error. + (FieldExpr.DoResolve): Added tests for ObsoleteAttribute. + + * enum.cs + (Enum.GetObsoleteAttribute): Returns ObsoleteAttribute for both enum type + and enum member. + + * expression.cs + (Probe.DoResolve, Cast.DoResolve, LocalVariableReference.DoResolve, + New.DoResolve, SizeOf.DoResolve, TypeOf.DoResolce, MemberAccess.DoResolve): + Added test for ObsoleteAttribute. + + * statement.cs + (Catch): Derived from Statement. + +2004-06-01 Marek Safar + + Fixed bug #59071 & cs0160.cs + + * statement.cs (Try.Resolve): Check here whether order of catch + clauses matches their dependencies. + +2004-05-31 Miguel de Icaza + + * Reverted patch to namespace.cs (Use lookuptypedirect). This + caused a regression: #59343. Referencing nested classes from an + assembly stopped working. + +2004-05-31 Martin Baulig + + MCS is now frozen for beta 2. + +2004-05-30 Ben Maurer + + * convert.cs: add a trivial cache for overload operator resolution. + +2004-05-30 Ben Maurer + + * decl.cs: If possible, use lookuptypedirect here. We can only do + this if there is no `.' after the namespace. Avoids using + LookupType, which does lots of slow processing. + (FindNestedType) New method, does what it says :-). + * namespace.cs: use LookupTypeDirect. + * rootcontext.cs: use membercache, if possible. + * typemanager.cs (LookupTypeDirect): Cache negative hits too. + +2004-05-30 Ben Maurer + + * expression.cs: + According to the spec, + + In a member access of the form E.I, if E is a single identifier, + and if the meaning of E as a simple-name (§7.5.2) is a constant, + field, property, localvariable, or parameter with the same type as + the meaning of E as a type-name (§3.8), then both possible + meanings of E are permitted. + + We did not check that E as a simple-name had the same type as E as + a type name. + + This trivial check gives us 5-7% on bootstrap time. + +2004-05-30 Ben Maurer + + * expression.cs (Invocation.OverloadResolve): Avoid the + use of hashtables and boxing here by allocating on demand. + +2004-05-30 Martin Baulig + + * rootcontext.cs (RootContext.LookupType): Don't cache things if + we're doing a silent lookup. Don't try to lookup nested types in + TypeManager.object_type (thanks to Ben Maurer). + +2004-05-30 Martin Baulig + + Committing a patch from Ben Maurer. + + * rootcontext.cs (RootContext.LookupType): Cache negative results. + +2004-05-29 Martin Baulig + + * class.cs (IMethodData.ShouldIgnore): New method. + + * typemanager.cs (TypeManager.MethodFlags): Don't take a + `Location' argument, we don't need it anywhere. Use + `IMethodData.ShouldIgnore ()' instead of + `MethodData.GetMethodFlags ()'. + (TypeManager.AddMethod): Removed. + (TypeManager.AddMethod2): Renamed to AddMethod. + +2004-05-29 Martin Baulig + + Committing a patch from Benjamin Jemlich . + + * convert.cs (Convert.ImplicitReferenceConversion): If we're + converting from a class type S to an interface type and we already + have an object on the stack, don't box it again. Fixes #52578. + +2004-05-29 Martin Baulig + + * class.cs (ConstructorInitializer.GetOverloadedConstructor): + Added support for `params' parameters. Fixes #59267. + +2004-05-29 Martin Baulig + + * literal.cs (NullPointer): Provide a private .ctor which sets + `type' to TypeManager.object_type. Fixes #59048. + +2004-05-29 Martin Baulig + + * expression.cs (MemberAccess.ResolveMemberAccess): If we're an + EventExpr, set `ee.InstanceExpression = left'. Fixes #59188. + + * ecore.cs (EventExpr.instance_expr): Make the field private. + +2004-05-26 Marek Safar + + Fixed bug #50080 & cs0214-2.cs + * expression.cs (Cast.DoResolve): Check unsafe context here. + + * statement.cs (Resolve.DoResolve): Likewise. + +2004-05-26 Martin Baulig + + * namespace.cs (NamespaceEntry.Lookup): Added `bool silent'. + + * rootcontext.cs (RootContext.NamespaceLookup): Added `bool silent'. + (RootContext.LookupType): Pass down the `silent' flag. + +2004-05-25 Martin Baulig + + * expression.cs + (MethodGroupExpr.IdenticalTypeName): New public property. + (Invocation.DoResolve): Don't report a CS0176 if the "instance" + expression actually refers to a type. + +2004-05-25 Martin Baulig + + * expression.cs (Invocation.DoResolve): Applied Ben Maurer's patch + for #56176 and made it actually work. + +2004-05-25 Martin Baulig + + * ecore.cs (Expression.CacheTemporaries): Make this virtual. + (FieldExpr, PropertyExpr): Override and implement + CacheTemporaries. Fixes #52279. + +2004-05-25 Miguel de Icaza + + * location.cs: In the new compiler listing a file twice is a + warning, not an error. + +2004-05-24 Martin Baulig + + * enum.cs (Enum.DefineType): For the `BaseType' to be a + TypeLookupExpression; otherwise, report a CS1008. Fixes #58571. + +2004-05-24 Martin Baulig + + * decl.cs (DeclSpace.FindType): Try doing an alias lookup before + walking the `using' list. Fixes #53921. + +2004-05-24 Martin Baulig + + * const.cs (Const.LookupConstantValue): Added support for + EmptyCast's; fixes #55251. + +2004-05-24 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Renamed to + DoSimpleNameResolve() and provide a SimpleNameResolve() wrapper + which does the CS0135 check. The reason is that we first need to + check whether the variable actually exists. + +2004-05-24 Martin Baulig + + * class.cs (MemberBase.DoDefine): Use DeclSpace.FindType() rather + than RootContext.LookupType() to find the explicit interface + type. Fixes #58584. + +2004-05-24 Raja R Harinath + + * Makefile: Simplify. Use executable.make. + * mcs.exe.sources: New file. List of sources of mcs.exe. + +2004-05-24 Anders Carlsson + + * decl.cs: + * enum.cs: + Use the invariant culture when doing String.Compare for CLS case + sensitivity. + +2004-05-23 Martin Baulig + + * decl.cs (DeclSpace.FindType): Only check the `using' list if we + don't have any dots. Fixes #52622, added cs0246-8.cs. + + * namespace.cs (NamespaceEntry.Lookup): Likewise. + +2004-05-23 Marek Safar + + * class.cs (MemberBase.Define): Reuse MemberType member for + resolved type. Other methods can use it too. + +2004-05-23 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Only report a CS0135 if + the variable also exists in the current block (otherwise, we need + to report a CS0103). Fixes #58670. + +2004-05-23 Martin Baulig + + * flowanalysis.cs (Reachability.Reachable): Compute this + on-the-fly rather than storing it as a field. + +2004-05-23 Martin Baulig + + * flowanalysis.cs (Reachability.And): Manually compute the + resulting `barrier' from the reachability. + +2004-05-23 Marek Safar + + Fix bug #57835 + * attribute.cs (AttributeTester.GetMethodObsoleteAttribute): Returns + instance of ObsoleteAttribute when symbol is obsolete. + + * class.cs + (IMethodData): Extended interface for ObsoleteAttribute support. + +2004-05-22 Marek Safar + + * attribute.cs: Fix bug #55970 + +2004-05-22 Marek Safar + + Fix bug #52705 + * attribute.cs + (GetObsoleteAttribute): New method. Creates the instance of + ObsoleteAttribute. + (AttributeTester.GetMemberObsoleteAttribute): Returns instance of + ObsoleteAttribute when member is obsolete. + (AttributeTester.Report_ObsoleteMessage): Common method for + Obsolete error/warning reporting. + + * class.cs + (TypeContainer.base_classs_type): New member for storing parent type. + + * decl.cs + (MemberCore.GetObsoleteAttribute): Returns instance of ObsoleteAttribute + for this MemberCore. + +2004-05-21 Marek Safar + + * attribute.cs, const.cs: Fix bug #58590 + +2004-05-21 Martin Baulig + + * flowanalysis.cs (FlowBranching.MergeTopBlock): Don't check for + out parameters if the end of the method is unreachable. Fixes + #58098. + +2004-05-21 Marek Safar + + * codegen.cs, cs-parser.jay: Removed SetAttributes method. + Hari was right, why extra method. + +2004-05-21 Marek Safar + + * attribute.cs, cs-parser.jay: Fix errors/cs0579-7.cs. + +2004-05-20 Martin Baulig + + Merged this back from gmcs to keep the differences to a minumum. + + * attribute.cs (Attribute.CheckAttributeType): Take an EmitContext + instead of a Declspace. + (Attribute.ResolveType): Likewise. + (Attributes.Search): Likewise. + (Attributes.Contains): Likewise. + (Attributes.GetClsCompliantAttribute): Likewise. + + * class.cs (TypeContainer.VerifyMembers): Added EmitContext + argument. + (MethodData.ApplyAttributes): Take an EmitContext instead of a + DeclSpace. + +2004-05-19 Marek Safar + + Fix bug #58688 (MCS does not report error when the same attribute + is assigned twice) + + * attribute.cs (Attribute.Emit): Distinction between null and default. + +2004-05-19 Raja R Harinath + + * cs-parser.jay (attribute): Create a GlobalAttribute for the case + of a top-level attribute without an attribute target. + * attribute.cs (Attribute.Error_AttributeConstructorMismatch): + Make non-static. + (Attribute.Conditional_GetConditionName), + (Attribute.Obsolete_GetObsoleteMessage): Update. + (Attribute.IndexerName_GetIndexerName): New. Attribute-specific + part of ScanForIndexerName. + (Attribute.CanIgnoreInvalidAttribute): New function. + (Attribute.ScanForIndexerName): Move to ... + (Attributes.ScanForIndexerName): ... here. + (Attributes.Attrs): Rename from now-misnamed AttributeSections. + (Attributes.Search): New internal variant that can choose not to + complain if types aren't resolved. The original signature now + complains. + (Attributes.GetClsCompliantAttribute): Use internal variant, with + complaints suppressed. + (GlobalAttribute.CheckAttributeType): Overwrite ds.NamespaceEntry + only if it not useful. + (CanIgnoreInvalidAttribute): Ignore assembly attribute errors at + top-level for attributes that are shared between the assembly + and a top-level class. + * parameter.cs (ImplicitParameter): Rename from ParameterAtribute. + * class.cs: Update to reflect changes. + (DefineIndexers): Fuse loops. + * codegen.cs (GetAssemblyName): Update to reflect changes. Accept + a couple more variants of attribute names. + +2004-05-18 Marek Safar + + Fix bug #52585 (Implemented explicit attribute declaration) + + * attribute.cs: + (Attributable.ValidAttributeTargets): New abstract method. It gets + list of valid attribute targets for explicit target declaration. + (Attribute.Target): It holds target itself. + (AttributeSection): Removed. + (Attribute.CheckTargets): New method. It checks whether attribute + target is valid for the current element. + + * class.cs: + (EventProperty): New class. For events that are declared like + property (with add and remove accessors). + (EventField): New class. For events that are declared like field. + class.cs + + * cs-parser.jay: Implemented explicit attribute target declaration. + + * class.cs, decl.cs, delegate.cs, enum.cs, parameter.cs: + Override ValidAttributeTargets. + + * parameter.cs: + (ReturnParameter): Class for applying custom attributes on + the return type. + (ParameterAtribute): New class. Class for applying custom + attributes on the parameter type. + +2004-05-17 Miguel de Icaza + + * class.cs (MemberBase.DoDefine): Pass UNSAFE on interface + definitions. + + (Method): Allow UNSAFE here. + + * modifiers.cs: Support unsafe reporting. + +2004-05-17 Marek Safar + + * decl.cs: Fix bug #58478. + +2004-05-17 Gonzalo Paniagua Javier + + * statement.cs: When checking for unreachable code on an EmptyStatement, + set the location. Fixes bug #58488. + +2004-05-13 Miguel de Icaza + + * driver.cs: Add -pkg handling. + + From Gonzalo: UseShelLExecute=false + +2004-05-12 Marek Safar + + * attribute.cs: + (Attribute.GetAttributeTargets): New method. Gets AttributeTargets + for attribute. + (Attribute.IsClsCompliaceRequired): Moved to base for better + accesibility. + (Attribute.UsageAttribute): New property for AttributeUsageAttribute + when attribute is AttributeUsageAttribute. + (Attribute.GetValidTargets): Simplified. + (Attribute.GetAttributeUsage): New method returns AttributeUsage + attribute for this type. + (Attribute.ApplyAttributes): Method renamed to Emit and make + non-static. + (GlobalAttributeSection): New class for special handling of global + attributes (assembly, module). + (AttributeSection.Emit): New method. + + * class.cs: Implemented Attributable abstract methods. + (MethodCore.LabelParameters): Moved to Parameter class. + (Accessor): Is back simple class. + (PropertyMethod): Implemented Attributable abstract class. + (DelegateMethod): Implemented Attributable abstract class. + (Event): New constructor for disctintion between normal Event + and Event with accessors. + + * cs-parser.jay: Used new Event ctor and GlobalAttributeSection. + + * codegen.cs, const.cs, decl.cs, delegate.cs: + (CommonAssemblyModulClass): Implemented Attributable abstract class + and simplified. + + * enum.cs: Implement IAttributeSupport interface. + (EnumMember): New class for emum members. Implemented Attributable + abstract class + + * parameter.cs: + (ParameterBase): Is abstract. + (ReturnParameter): New class for easier [return:] attribute handling. + + * typemanager.cs: Removed builder_to_attr. + +2004-05-11 Raja R Harinath + + Fix bug #57151. + * attribute.cs (Attribute.GetPositionalValue): New function. + * class.cs (TypeContainer.VerifyMembers): New function. + (TypeContainer.Emit): Use it. + (ClassOrStruct): New base class for Class and Struct. + (ClassOrStruct.ApplyAttributeBuilder): New function. Note if + StructLayout(LayoutKind.Explicit) was ascribed to the struct or + class. + (ClassOrStruct.VerifyMembers): If the struct is explicitly laid out, + then each non-static field should have a FieldOffset attribute. + Otherwise, none of the fields should have a FieldOffset attribute. + * rootcontext.cs (RootContext.ResolveCore): Resolve StructLayout + and FieldOffset attributes. + * typemanager.cs (TypeManager.struct_layout_attribute_type) + (TypeManager.field_offset_attribute_type): New core types. + (TypeManager.InitCoreTypes): Initialize them. + +2004-05-11 Michal Moskal + + * class.cs (Event.RemoveDelegateMethod.DelegateMethodInfo): + Return correct type. + From bug #58270. + +2004-05-09 Miguel de Icaza + + * expression.cs (Binary.DoNumericPromotions): 0 long constant can + be implicitly converted to ulong. + + * expression.cs: The logic for allowing operator &, | and ^ worked + was wrong, it worked before because we did not report an error in + an else branch. Fixes 57895. + + * class.cs: Applied patch from iain@mccoy.id.au Iain McCoy to + allow volatile fields to be reference types. + +2004-05-07 Miguel de Icaza + + * driver.cs: Add support for /debug- + +2004-05-07 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType, Attribute.ResolveType): + Add a 'complain' parameter to silence errors. + (Attribute.Resolve): Update to changes. Put in sanity check to catch + silently overlooked type-resolutions. + (Attribute.ScanForIndexerName, Attribute.DefinePInvokeMethod): Update + to reflect changes. + (Attributes.Search): New function. + (Attributes.Contains, Attributes.GetClsCompliantAttribute): Use Search. + (Attributes.GetAttributeFullName): Remove hack. + * class.cs (MethodCore.LabelParameters, MethodData.ApplyAttributes): + Update to reflect changes. + * codegen.cs (CommonAssemblyModulClass.GetClsCompliantAttribute): + Use Attributes.Search instead of nested loops. + +2004-05-07 Marek Safar + + * decl.cs: + (MemberCore.Flags): Extended for caching presence of CLSCompliantAttribute. + (MemberCore.VerifyClsCompliance): Implemented CS3019 error report. + (DeclSpace.GetClsCompliantAttributeValue): Returns simple bool. + + * report.cs: (Report.Warning): Renamed to Warning_T because of + parameter collision. + +2004-05-05 Raja R Harinath + + * expression.cs (MemberAccess.ResolveMemberAccess): + Exit with non-zero status after Report.Error. + * rootcontext.cs (RootContext.BootstrapCorlib_ResolveDelegate): + Likewise. + * typemanager.cs (TypeManager.CoreLookupType): Likewise. + +2004-05-04 Lluis Sanchez Gual + + * support.cs: Don't hang when the file is empty. + +2004-05-04 Lluis Sanchez Gual + + * support.cs: In SeekableStreamReader, compute the preamble size of the + underlying stream. Position changes should take into account that initial + count of bytes. + +2004-05-03 Todd Berman + + * driver.cs: remove unused GetSysVersion function. + +2004-05-03 Todd Berman + + * driver.cs: Remove the hack from saturday, as well as the hack + from jackson (LoadAssemblyFromGac), also adds the CWD to the + link_paths to get that bit proper. + +2004-05-01 Todd Berman + + * driver.cs: Try a LoadFrom before a Load, this checks the current + path. This is currently a bug in mono that is be fixed, however, this + provides a workaround for now. This will be removed when the bug + is fixed. + +2004-05-01 Sebastien Pouliot + + * CryptoConvert.cs: Updated to latest version. Fix issue with + incomplete key pairs (#57941). + +2004-05-01 Todd Berman + + * driver.cs: Remove '.' from path_chars, now System.* loads properly + from the GAC + +2004-04-30 Jackson Harper + + * codegen.cs: Open keys readonly. + +2004-04-30 Gonzalo Paniagua Javier + + * typemanager.cs: don't report cyclic struct layout when a struct + contains 2 or more fields of the same type. Failed for Pango.AttrShape + which has 2 Pango.Rectangle fields. + +2004-04-29 Ben Maurer + + * expression.cs: Handle IntPtr comparisons with IL code + rather than a method call. + +2004-04-29 Martin Baulig + + * ecore.cs (PropertyExpr.FindAccessor): New private method. Walk + the list of PropertyInfo's in class hierarchy and find the + accessor. Fixes #56013. + +2004-04-29 Martin Baulig + + * typemanager.cs (TypeManager.CheckStructCycles): Fixed. + +2004-04-29 Martin Baulig + + Applying a patch from Benjamin Jemlich . + + * ecore.cs (FieldExpr.AddressOf): Make this work for valuetypes. + +2004-04-29 Martin Baulig + + * class.cs (ConstructorInitializer.Resolve): Check whether the + parent .ctor is accessible. Fixes #52146. + +2004-04-29 Martin Baulig + + Applying a patch from Benjamin Jemlich . + + * statement.cs (Using.EmitLocalVariableDecls): Use + TypeManager.idisposable_type, not typeof (IDisposable). + (Foreach.EmitCollectionForeach): Added support for valuetypes. + +2004-04-29 Martin Baulig + + * class.cs (Event.Define): Don't emit the field and don't set + RTSpecialName and SpecialName for events on interfaces. Fixes + #57703. + +2004-04-29 Raja R Harinath + + Refactor Attribute.ApplyAttributes. + * attribute.cs (Attributable): New base class for objects that can + have Attributes applied on them. + (Attribute): Make AttributeUsage fields public. + (Attribute.GetFieldValue, Attribute.GetMarshal): Make non-static. + (Attribute.IsInternalCall): New property. + (Attribute.UsageAttr): Convert to a public read-only property. + (Attribute.CheckAttributeType): Use a DeclSpace, not an EmitContext. + (Attribute.ResolveType, Attribute.Resolve) + (Attribute.ScanForIndexerName): Update to reflect changes. + (Attribute.CheckAttributeTarget): Re-format. + (Attribute.ApplyAttributes): Refactor, to various + Attributable.ApplyAttributeBuilder methods. + * decl.cs (MemberCore): Make Attributable. + * class.cs (Accessor): Make Attributable. + (MethodData.ApplyAttributes): Use proper attribute types, not + attribute names. + (TypeContainer.LabelParameters): Pass Parameter to ApplyAttributes. + (TypeContainer.ApplyAttributeBuilder) + (Method.ApplyAttributeBuilder, Constructor.ApplyAttributeBuilder) + (Field.ApplyAttributeBuilder, Accessor.ApplyAttributeBuilder) + (PropertyBase.ApplyAttributeBuilder, Event.ApplyAttributeBuilder) + (Operator.ApplyAttributeBuilder): New factored-out methods. + * const.cs (Const.ApplyAttributeBuilder): Likewise. + * delegate.cs (Delegate.ApplyAttributeBuilder): Likewise. + * enum.cs (Enum.ApplyAttributeBuilder): Likewise. + * parameter.cs (ParameterBase): New Attributable base class + that can also represent Return types. + (Parameter): Update to the changes. + +2004-04-29 Jackson Harper + + * driver.cs: Prefer the corlib system version when looking for + assemblies in the GAC. This is still a hack, but its a better hack + now. + +2004-04-29 Marek Safar + + * decl.cs, enum.cs: Improved error 3005 reporting. + + * report.cs (SymbolRelatedToPreviousError): New method for error reporting. + (related_symbols): New private member for list of symbols + related to reported error/warning. + + * tree.cs: Do not use now obsolete Report.LocationOfPreviousError. + +2004-04-29 Martin Baulig + + * ecore.cs (Expression.Constantify): If we're an enum and + TypeManager.TypeToCoreType() doesn't give us another type, use + t.UnderlyingSystemType. Fixes #56178. + +2004-04-29 Martin Baulig + + * decl.cs (MemberCache.SetupCacheForInterface): Look over all our + interfaces and for each interface, only add members directly + declared in that interface. Fixes #53255. + +2004-04-28 Martin Baulig + + * expression.cs (ConditionalLogicalOperator): Use a temporary + variable for `left' to avoid that we evaluate it more than once; + bug #52588. + +2004-04-28 Martin Baulig + + * expression.cs (ComposedCast.DoResolveAsTypeStep): Don't allow + `void[]' (CS1547). + +2004-04-28 Martin Baulig + + * statement.cs (LocalInfo.Resolve): Check whether the type is not + void (CS1547). + + * class.cs (MemberBase.CheckParameters, FieldBase.DoDefine): Check + whether the type is not void (CS1547). + +2004-04-28 Martin Baulig + + * expression.cs (Unary.DoResolveLValue): Override this and report + CS0131 for anything but Operator.Indirection. + +2004-04-28 Martin Baulig + + Committing a patch from Ben Maurer; see bug #50820. + + * typemanager.cs (TypeManager.FilterWithClosure): Added CS1540 + check for classes. + + * ecore.cs (Expression.MemberLookupFailed): Added CS1540 check for + classes. + +2004-04-28 Martin Baulig + + Committing a patch from Ben Maurer; see bug #50820. + + * typemanager.cs (TypeManager.FilterWithClosure): Added CS1540 + check for classes. + + * ecore.cs (Expression.MemberLookupFailed): Added CS1540 check for + classes. + +2004-04-28 Martin Baulig + + * statement.cs (Block.LookupLabel): Also lookup in implicit child blocks. + (Block.AddLabel): Call DoLookupLabel() to only search in the + current block. + +2004-04-28 Martin Baulig + + * cfold.cs (ConstantFold.BinaryFold): Added special support for + comparing StringConstants and NullLiterals in Equality and Inequality. + +2004-04-28 Jackson Harper + + * driver.cs: Attempt to load referenced assemblies from the + GAC. This is the quick and dirty version of this method that + doesnt take into account versions and just takes the first + canidate found. Will be good enough for now as we will not have more + then one version installed into the GAC until I update this method. + +2004-04-28 Martin Baulig + + * typemanager.cs (TypeManager.CheckStructCycles): New public + static method to check for cycles in the struct layout. + + * rootcontext.cs (RootContext.PopulateTypes): Call + TypeManager.CheckStructCycles() for each TypeContainer. + [Note: We only need to visit each type once.] + +2004-04-28 Martin Baulig + + * constant.cs (StringConstant.Emit): Emit Ldnull if we're null. + + * const.cs (Const.LookupConstantValue): Return a `bool' signalling + success and added `out object value'. Use a `bool resolved' field + to check whether we've already been called rather than + `ConstantValue != null' since this breaks for NullLiterals. + +2004-04-28 Raja R Harinath + + * driver.cs (Driver.MainDriver) [IsModuleOnly]: Open code the + setting of this flag, since the 'set' method may be non-public. + +2004-04-28 Raja R Harinath + + * flowanalysis.cs (FlowBranchingException.LookupLabel): Add a null + check on current_vector.Block. + +2004-04-27 Martin Baulig + + * expression.cs (BaseAccess.CommonResolve): Don't allow `base' in + a field initializer. Fixes #56459. + +2004-04-27 Martin Baulig + + * ecore.cs (PropertyExpr.DoResolve/DoResolveLValue): Check whether + we're not attempting to use an indexer. Fixes #52154. + +2004-04-27 Martin Baulig + + * statement.cs (Return): Don't create a return label if we don't + need it; reverts my change from January 20th. Thanks to Ben + Maurer for this. + +2004-04-27 Martin Baulig + + According to the spec, `goto' can only leave a nested scope, but + never enter it. + + * statement.cs (Block.LookupLabel): Only lookup in the current + block, don't recurse into parent or child blocks. + (Block.AddLabel): Check in parent and child blocks, report + CS0140/CS0158 if we find a duplicate. + (Block): Removed this indexer for label lookups. + (Goto.Resolve): Call LookupLabel() on our current FlowBranching; + this already does the error reporting for us. + + * flowanalysis.cs + (FlowBranching.UsageVector.Block): New public variable; may be null. + (FlowBranching.CreateSibling): Added `Block' argument. + (FlowBranching.LookupLabel): New public virtual method. Lookup a + label for the target of a `goto' and check whether we're not + leaving a `finally'. + +2004-04-27 Martin Baulig + + * flowanalysis.cs (FlowBranching.UsageVector.MergeChild): If we're + a finite loop block, also do the ALWAYS->SOMETIMES for throws (not + just for returns). + +2004-04-27 Martin Baulig + + * statement.cs (Block.AddLabel): Also check for implicit blocks + and added a CS0158 check. + +2004-04-27 Martin Baulig + + * flowanalysis.cs (FlowBranchingLoop): New class. + (FlowBranching.UsageVector.MergeJumpOrigins): Take a list of + UsageVector's instead of an ArrayList. + (FlowBranching.Label): Likewise. + (FlowBranching.UsageVector.MergeBreakOrigins): New method. + (FlowBranching.AddBreakVector): New method. + +2004-04-27 Miguel de Icaza + + * attribute.cs: Small regression fix: only convert the type if we + the type is different, fixes System.Drawing build. + +2004-04-27 Martin Baulig + + * attribute.cs (Attribute.Resolve): If we have a constant value + for a named field or property, implicity convert it to the correct + type. + +2004-04-27 Raja R Harinath + + * statement.cs (Block.Block): Implicit blocks share + 'child_variable_names' fields with parent blocks. + (Block.AddChildVariableNames): Remove. + (Block.AddVariable): Mark variable as "used by a child block" in + every surrounding block. + * ecore.cs (SimpleName.SimpleNameResolve): If the name has already + been used in a child block, complain about violation of "Invariant + meaning in blocks" rule. + * cs-parser.jay (declare_local_variables): Don't use + AddChildVariableNames. + (foreach_statement): Don't create an implicit block: 'foreach' + introduces a scope. + +2004-04-23 Miguel de Icaza + + * convert.cs (ImplicitNumericConversion): 0 is also positive when + converting from 0L to ulong. Fixes 57522. + +2004-04-22 Marek Safar + + * decl.cs (FindMemberToOverride): Fix wrong warning for case when + derived class hides via 'new' keyword field from base class (test-242.cs). + TODO: Handle this in the more general way. + + * class.cs (CheckBase): Ditto. + +2004-04-22 Marek Safar + + * decl.cs (caching_flags): New member for storing cached values + as bit flags. + (MemberCore.Flags): New enum where bit flags for caching_flags + are defined. + (MemberCore.cls_compliance): Moved to caching_flags. + (DeclSpace.Created): Moved to caching_flags. + + * class.cs: Use caching_flags instead of DeclSpace.Created + +2004-04-21 Miguel de Icaza + + * ecore.cs (PropertyExpr.GetAccesor): Only perform the 1540 check + if we are only a derived class, not a nested class. + + * typemanager.cs: Same as above, but do this at the MemberLookup + level (used by field and methods, properties are handled in + PropertyExpr). Allow for the qualified access if we are a nested + method. + +2004-04-21 Marek Safar + + * class.cs: Refactoring. + (IMethodData): New inteface; Holds links to parent members + to avoid member duplication (reduced memory allocation). + (Method): Implemented IMethodData interface. + (PropertyBase): New inner classes for get/set methods. + (PropertyBase.PropertyMethod): Implemented IMethodData interface + (Event): New inner classes for add/remove methods. + (Event.DelegateMethod): Implemented IMethodData interface. + + * cs-parser.jay: Pass DeclSpace to Event class for creation of valid + EmitContext (related to class.cs refactoring). + +2004-04-21 Raja R Harinath + + * delegate.cs (Delegate.VerifyApplicability): If the number of + arguments are the same as the number of parameters, first try to + verify applicability ignoring any 'params' modifier on the last + parameter. + Fixes #56442. + +2004-04-16 Raja R Harinath + + * class.cs (TypeContainer.AddIndexer): Use + 'ExplicitInterfaceName' to determine if interface name was + explicitly specified. 'InterfaceType' is not initialized at this time. + (TypeContainer.DefineIndexers): Remove use of temporary list. The + Indexers array is already in the required order. Initialize + 'IndexerName' only if there are normal indexers. + (TypeContainer.DoDefineMembers): Don't initialize IndexerName. + (TypeContainer.Emit): Emit DefaultMember attribute only if + IndexerName is initialized. + Fixes #56300. + +2004-04-15 Benjamin Jemlich + + * enum.cs (Enum.DefineType): Don't allow char as type for enum. + Fixes #57007 + +2004-04-15 Raja R Harinath + + * attribute.cs (Attribute.CheckAttributeType): Check for ambiguous + attributes. + Fix for #56456. + + * attribute.cs (Attribute.Resolve): Check for duplicate named + attributes. + Fix for #56463. + +2004-04-15 Miguel de Icaza + + * iterators.cs (MarkYield): track whether we are in an exception, + and generate code accordingly. Use a temporary value to store the + result for our state. + + I had ignored a bit the interaction of try/catch with iterators + since their behavior was not entirely obvious, but now it is + possible to verify that our behavior is the same as MS .NET 2.0 + + Fixes 54814 + +2004-04-14 Miguel de Icaza + + * iterators.cs: Avoid creating temporaries if there is no work to + do. + + * expression.cs (ArrayAccess.EmitLoadOpcode): If dealing with + Enumerations, use TypeManager.EnumToUnderlying and call + recursively. + + Based on the patch from Benjamin Jemlich (pcgod@gmx.net), fixes + bug #57013 + + (This.Emit): Use EmitContext.EmitThis to emit our + instance variable. + + (This.EmitAssign): Ditto. + + * ecore.cs (FieldExpr.Emit): Remove RemapToProxy special + codepaths, we will move all the functionality into + Mono.CSharp.This + + (FieldExpr.EmitAssign): Ditto. + + This fixes several hidden bugs that I uncovered while doing a code + review of this today. + + * codegen.cs (EmitThis): reworked so the semantics are more clear + and also support value types "this" instances. + + * iterators.cs: Changed so that for iterators in value types, we + do not pass the value type as a parameter. + + Initialization of the enumerator helpers is now done in the caller + instead of passing the parameters to the constructors and having + the constructor set the fields. + + The fields have now `assembly' visibility instead of private. + +2004-04-11 Miguel de Icaza + + * expression.cs (Argument.Resolve): Check if fields passed as ref + or out are contained in a MarshalByRefObject. + + * typemanager.cs, rootcontext.cs: Add System.Marshalbyrefobject as + another compiler type. + +2004-04-06 Ben Maurer + + * class.cs (Indexer.Define): use the new name checking method. + Also, return false on an error. + * cs-tokenizer.cs (IsValidIdentifier): Checks for a valid identifier. + (is_identifier_[start/part]_character): make static. + +2004-04-10 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Do no append strings + twice: since we can be invoked more than once (array evaluation) + on the same concatenation, take care of this here. Based on a fix + from Ben (bug #56454) + +2004-04-08 Sebastien Pouliot + + * codegen.cs: Fix another case where CS1548 must be reported (when + delay-sign isn't specified and no private is available #56564). Fix + loading the ECMA "key" to delay-sign an assembly. Report a CS1548 + error when MCS is used on the MS runtime and we need to delay-sign + (which seems unsupported by AssemblyBuilder - see #56621). + +2004-04-08 Marek Safar + + * typemanager.cs (TypeManager.TypeToCoreType): Handle IntPtr too. + (TypeManager.ComputeNamespaces): Faster implementation for + Microsoft runtime. + + * compiler.csproj: Updated AssemblyName to mcs. + +2004-04-07 Miguel de Icaza + + * rootcontext.cs: Add new types to the boot resolution. + + * ecore.cs (TypeExpr.CanInheritFrom): Inheriting from + MulticastDelegate is not allowed. + + * typemanager.cs: Add new types to lookup: System.TypedReference + and ArgIterator. + + * paramter.cs (Parameter.Resolve): if we are an out/ref parameter, + check for TypedReference or ArgIterator, they are not allowed. + + * ecore.cs (BoxedCast): Set the eclass to ExprClass.Value, this + makes us properly catch 1510 in some conditions (see bug 56016 for + details). + +2004-04-06 Bernie Solomon + + * CryptoConvert.cs: update from corlib version + with endian fixes. + +2004-04-05 Miguel de Icaza + + * class.cs (Indexer.Define): Check indexername declaration + +2004-04-05 Marek Safar + + * attribute.cs (IsClsCompliant): Fixed problem with handling + all three states (compliant, not-compliant, undetected). + +2004-03-30 Marek Safar + + * attribute.cs (Attribute): Location is now public. + (Resolve): Store resolved arguments (pos_values) in attribute class. + Attribute extractors (now GetClsCompliantAttributeValue) can reuse them. + (GetClsCompliantAttributeValue): New method that gets + CLSCompliantAttribute value. + (GetClsCompliantAttribute): Returns CLSCompliantAttribute for DeclSpace + if exists else null. + (AttributeTester): New class for CLS-Compliant verification routines. + + * class.cs (Emit): Add CLS-Compliant verification. + (Method.GetSignatureForError): Implemented. + (Constructor.GetSignatureForError): Implemented + (Constructor.HasCompliantArgs): Returns if constructor has + CLS-Compliant arguments. + (Constructor.Emit): Override. + (Construcor.IsIdentifierClsCompliant): New method; For constructors + is needed to test only parameters. + (FieldBase.GetSignatureForError): Implemented. + (TypeContainer): New member for storing base interfaces. + (TypeContainer.FindMembers): Search in base interfaces too. + + * codegen.cs (GetClsComplianceAttribute): New method that gets + assembly or module CLSCompliantAttribute value. + (ResolveClsCompliance): New method that resolve CLSCompliantAttribute + for assembly. + (ModuleClass.Emit): Add error 3012 test. + + * const.cs (Emit): Override and call base for CLS-Compliant tests. + + * decl.cs (ClsComplianceValue): New enum that holds CLS-Compliant + state for all decl types. + (MemberCore.Emit): Emit is now virtual and call VerifyClsCompliance + if CLS-Compliant tests are required. + (IsClsCompliaceRequired): New method. Analyze whether code + must be CLS-Compliant. + (IsExposedFromAssembly): New method. Returns true when MemberCore + is exposed from assembly. + (GetClsCompliantAttributeValue): New method. Resolve CLSCompliantAttribute + value or gets cached value. + (HasClsCompliantAttribute): New method. Returns true if MemberCore + is explicitly marked with CLSCompliantAttribute. + (IsIdentifierClsCompliant): New abstract method. This method is + used to testing error 3005. + (IsIdentifierAndParamClsCompliant): New method. Common helper method + for identifier and parameters CLS-Compliant testing. + (VerifyClsCompliance): New method. The main virtual method for + CLS-Compliant verifications. + (CheckAccessLevel): In one special case (System.Drawing) was TypeBuilder + null. I don't know why is null (too many public members !). + (GetClsCompliantAttributeValue). New method. Goes through class hierarchy + and get value of first CLSCompliantAttribute that found. + + * delegate.cs (Emit): Override and call base for CLS-Compliant tests. + (VerifyClsCompliance): Override and add extra tests. + + * driver.cs (CSCParseOption): New command line options (clscheck[+|-]). + clscheck- disable CLS-Compliant verification event if assembly is has + CLSCompliantAttribute(true). + + * enum.cs (Emit): Override and call base for CLS-Compliant tests. + ApllyAttribute is now called in emit section as in the other cases. + Possible future Emit integration. + (IsIdentifierClsCompliant): New override. + (VerifyClsCompliance): New override. + (GetEnumeratorName): Returns full enum name. + + * parameter.cs (GetSignatureForError): Implemented. + + * report.cs (WarningData): New struct for Warning message information. + (LocationOfPreviousError): New method. + (Warning): New method. Reports warning based on the warning table. + (Error_T): New method. Reports error based on the error table. + + * rootcontext.cs (EmitCode): Added new Emit(s) because CLS-Compliant + verifications are done here. + + * tree.cs (RecordDecl): Used new LocationOfPreviousError method. + + * typemanager.cs (cls_compliant_attribute_type): New member thath holds + CLSCompliantAttribute. + (all_imported_types): New member holds all imported types from other + assemblies. + (LoadAllImportedTypes): New method fills static table with exported types + from all referenced assemblies. + (Modules): New property returns all assembly modules. + +2004-03-30 Miguel de Icaza + + * cs-parser.jay: Add a rule to catch wrong event syntax instead of + throwing a parser error. + + * ecore.cs (PropertyExpr.GetAccessor): Apply patch from Patrik Reali + which removes the hardcoded get_/set_ prefixes for properties, as + IL allows for the properties to be named something else. + + Bug #56013 + + * expression.cs: Do not override operand before we know if it is + non-null. Fix 56207 + +2004-03-29 Ben Maurer + + * typemanager.cs: support for pinned variables. + +2004-03-29 Ben Maurer + + * decl.cs, typemanager.cs: Avoid using an arraylist + as a buffer if there is only one result set. + +2004-03-29 Ben Maurer + + * expression.cs: Make sure you cant call a static method + with an instance expression, bug #56174. + +2004-03-29 Miguel de Icaza + + * class.cs (IsDuplicateImplementation): Improve error reporting to + flag 663 (method only differs in parameter modifier). + + * cs-tokenizer.cs: Do not require whitespace when a ( or " will do + in preprocessor directives. + + * location.cs (LookupFile): Allow for the empty path. + + * attribute.cs (DefinePInvokeMethod): Fix 56148; I would like a + better approach for some of that patch, but its failing with the + CharSet enumeration. For now try/catch will do. + + * typemanager.cs: Do not crash if a struct does not have fields. + Fixes 56150. + +2004-03-28 Ben Maurer + + * expression.cs: cs0213, cant fix a fixed expression. + fixes 50231. + +2004-03-28 Ben Maurer + + * cs-parser.jay: detect invalid embeded statements gracefully. + bug #51113. + +2004-03-28 Ben Maurer + + * ecore.cs, typemanager.cs: Correct impl of cs1540 check. + As a regex: + s/ + the invocation type may not be a subclass of the tye of the item/ + The type of the item must be a subclass of the invocation item. + /g + + Fixes bug #50820. + +2004-03-25 Sebastien Pouliot + + * attribute.cs: Added methods to get a string and a bool from an + attribute. Required to information from AssemblyKeyFileAttribute, + AttributeKeyNameAttribute (string) and AssemblyDelaySign (bool). + * codegen.cs: Modified AssemblyName creation to include support for + strongnames. Catch additional exceptions to report them as CS1548. + * compiler.csproj: Updated include CryptoConvert.cs. + * compiler.csproj.user: Removed file - user specific configuration. + * CryptoConvert.cs: New. A COPY of the class CryptoConvert from + Mono.Security assembly. The original class is maintained and tested in + /mcs/class/Mono.Security/Mono.Security.Cryptography/CryptoConvert.cs. + * drivers.cs: Added support for /keyfile, /keycontainer and /delaysign + like CSC 8.0 (C# v2) supports. + * Makefile: Added CryptoConvert.cs to mcs sources. + * rootcontext.cs: Added new options for strongnames. + +2004-03-24 Ben Maurer + + * driver.cs: For --expect-error, report error code `2' + if the program compiled with no errors, error code `1' if + it compiled with an error other than the one expected. + +2004-03-24 Sebastien Pouliot + + * compiler.csproj: Updated for Visual Studio .NET 2003. + * compiler.csproj.user: Updated for Visual Studio .NET 2003. + * compiler.sln: Updated for Visual Studio .NET 2003. + +2004-03-24 Ravi Pratap M + + * expression.cs: Fix bug #47234. We basically need to apply the + rule that we prefer the conversion of null to a reference type + when faced with a conversion to 'object' (csc behaviour). + +2004-03-23 Ben Maurer + + * statement.cs: Shorter form for foreach, eliminates + a local variable. r=Martin. + +2004-03-23 Ben Maurer + + * constant.cs, ecore.cs, literal.cs: New prop IsZeroInteger that + checks if we can use brtrue/brfalse to test for 0. + * expression.cs: use the above in the test for using brtrue/brfalse. + cleanup code a bit. + +2004-03-23 Ben Maurer + + * expression.cs: Rewrite string concat stuff. Benefits: + + - "a" + foo + "b" + "c" becomes "a" + foo + "bc" + - "a" + foo + "b" + bar + "c" + baz ... uses concat (string []). + rather than a concat chain. + + * typemanager.cs: Add lookups for more concat overloads. + +2004-03-23 Ben Maurer + + * expression.cs: Emit shorter il code for array init. + + newarr + dup + // set 1 + + // set 2 + + newarr + stloc.x + + ldloc.x + // set 1 + + ldloc.x + // set 2 + +2004-03-22 Ben Maurer + + * statement.cs: Before, two switch blocks would be merged if the + total size of the blocks (end_item - begin_item + 1) was less than + two times the combined sizes of the blocks. + + Now, it will only merge if after the merge at least half of the + slots are filled. + + fixes 55885. + +2004-03-20 Atsushi Enomoto + + * class.cs : csc build fix for GetMethods(). See bug #52503. + +2004-03-20 Ben Maurer + + * expression.cs: Make sure fp comparisons work with NaN. + This fixes bug #54303. Mig approved this patch a long + time ago, but we were not able to test b/c the runtime + had a related bug. + +2004-03-19 Miguel de Icaza + + * ecore.cs (TypExpr.GetHashCode): implement this overload. + +2004-03-19 Martin Baulig + + * class.cs (MemberCore.IsDuplicateImplementation): Report the + error here and not in our caller. + +2004-03-19 Martin Baulig + + * interface.cs: Completely killed this file. + (Interface): We're now a TypeContainer and live in class.cs. + + * class.cs (TypeContainer.GetClassBases): Added `bool is_iface' + argument; we're now also called for interfaces. + (TypeContainer.DefineMembers): Allow this method being called + multiple times. + (TypeContainer.GetMethods): New public method; formerly known as + Interface.GetMethod(). This is used by PendingImplementation. + (TypeContainer.EmitDefaultMemberAttr): Moved here from Interface; + it's now private and non-static. + (Interface): Moved this here; it's now implemented similar to + Class and Struct. + (Method, Property, Event, Indexer): Added `bool is_interface' + argument to their .ctor's. + (MemberBase.IsInterface): New public field. + + * cs-parser.jay: Create normal Method, Property, Event, Indexer + instances instead of InterfaceMethod, InterfaceProperty, etc. + (opt_interface_base): Removed; we now use `opt_class_base' instead. + (InterfaceAccessorInfo): Create `Get' and `Set' Accessor's. + +2004-03-19 Martin Baulig + + * class.cs (MethodCore.IsDuplicateImplementation): New private + method which does the CS0111 checking. + (Method.CheckBase, Constructor.CheckBase, PropertyBase.CheckBase): + Use IsDuplicateImplementation(). + +2004-03-17 Ben Maurer + + * decl.cs (FindMemberToOverride): New method to find the correct + method or property to override in the base class. + * class.cs + - Make Method/Property use the above method to find the + version in the base class. + - Remove the InheritableMemberSignatureCompare as it is now + dead code. + + This patch makes large code bases much faster to compile, as it is + O(n) rather than O(n^2) to do this validation. + + Also, it fixes bug 52458 which is that nested classes are not + taken into account when finding the base class member. + + Reviewed/Approved by Martin. + +2004-03-17 Marek Safar + + * interface.cs: In all interface classes removed redundant + member initialization. + +2004-03-16 Martin Baulig + + * class.cs (TypeContainer.GetClassBases): Fix the CS0528 check. + +2004-03-15 Miguel de Icaza + + * decl.cs (DefineTypeAndParents): New helper method to define a + type's containers before the type itself is defined; This is a + bug exposed by the recent changes to Windows.Forms when an + implemented interface was defined inside a class that had not been + built yet. + + * modifiers.cs (MethodAttr): All methods in C# are HideBySig. + + (Check): Loop correctly to report errors modifiers + (UNSAFE was not in the loop, since it was the same as TOP). + + * interface.cs: Every interface member now takes a ModFlags, + instead of a "is_new" bool, which we set on the base MemberCore. + + Every place where we called "UnsafeOk" in the interface, now we + call the proper member (InterfaceMethod.UnsafeOK) instead to get + the unsafe settings from the member declaration instead of the + container interface. + + * cs-parser.jay (opt_new): Allow unsafe here per the spec. + + * pending.cs (TypeAndMethods): Add `get_indexer_name' and + `set_indexer_name' to the pending bits (one per type). + + We fixed a bug today that was picking the wrong method to + override, since for properties the existing InterfaceMethod code + basically ignored the method name. Now we make sure that the + method name is one of the valid indexer names. + +2004-03-14 Gustavo Giráldez + + * support.cs (SeekableStreamReader): Keep track of stream byte + positions and don't mix them with character offsets to the buffer. + + Patch from Gustavo Giráldez + +2004-03-15 Marek Safar + + * interface.cs (InterfaceSetGetBase): Removed double member + initialization, base class does it as well. + +2004-03-13 Martin Baulig + + * class.cs: Reverted Miguel's latest commit; it makes mcs crash + when compiling corlib. + +2004-03-13 Miguel de Icaza + + * convert.cs (ExplicitConversion): We were reporting an error on + certain conversions (object_type source to a value type, when the + expression was `null') before we had a chance to pass it through + the user defined conversions. + + * driver.cs: Replace / and \ in resource specifications to dots. + Fixes 50752 + + * class.cs: Add check for duplicate operators. Fixes 52477 + +2004-03-11 Miguel de Icaza + + * statement.cs (Switch.SimpleSwitchEmit): Deal with default labels + that are in the middle of the statements, not only at the end. + Fixes #54987 + + * class.cs (TypeContainer.AddField): No longer set the + `HaveStaticConstructor' flag, now we call it + `UserDefineStaticConstructor' to diferentiate the slightly + semantic difference. + + The situation is that we were not adding BeforeFieldInit (from + Modifiers.TypeAttr) to classes that could have it. + BeforeFieldInit should be set to classes that have no static + constructor. + + See: + + http://www.yoda.arachsys.com/csharp/beforefieldinit.html + + And most importantly Zoltan's comment: + + http://bugzilla.ximian.com/show_bug.cgi?id=44229 + + "I think beforefieldinit means 'it's ok to initialize the type sometime + before its static fields are used', i.e. initialization does not need + to be triggered by the first access to the type. Setting this flag + helps the JIT to compile better code, since it can run the static + constructor at JIT time, and does not need to generate code to call it + (possibly lots of times) at runtime. Unfortunately, mcs does not set + this flag for lots of classes like String. + + csc sets this flag if the type does not have an explicit static + constructor. The reasoning seems to be that if there are only static + initalizers for a type, and no static constructor, then the programmer + does not care when this initialization happens, so beforefieldinit + can be used. + + This bug prevents the AOT compiler from being usable, since it + generates so many calls to mono_runtime_class_init that the AOT code + is much slower than the JITted code. The JITted code is faster, + because it does not generate these calls if the vtable is type is + already initialized, which is true in the majority of cases. But the + AOT compiler can't do this." + +2004-03-10 Miguel de Icaza + + * class.cs (MethodData.Emit): Refactor the code so symbolic + information is generated for destructors; For some reasons we + were taking a code path that did not generate symbolic information + before. + +2004-03-11 Ben Maurer + + * class.cs: Create a Constructor.CheckBase method that + takes care of all validation type code. The method + contains some code that was moved from Define. + + It also includes new code that checks for duplicate ctors. + This fixes bug #55148. + +2004-03-09 Joshua Tauberer + + * expression.cs (ArrayCreation): Fix: More than 6 nulls in + a { ... }-style array creation invokes EmitStaticInitializers + which is not good for reference-type arrays. String, decimal + and now null constants (NullCast) are not counted toward + static initializers. + +2004-03-05 Martin Baulig + + * location.cs (SourceFile.HasLineDirective): New public field; + specifies whether the file contains or is referenced by a "#line" + directive. + (Location.DefineSymbolDocuments): Ignore source files which + either contain or are referenced by a "#line" directive. + +2004-02-29 Ben Maurer + + * class.cs (Method.CheckBase): Avoid using FindMembers, we have + direct access to our parent, so check the method inline there. + +2004-02-27 Ben Maurer + + * expression.cs (Invocation.EmitCall): Miguel's last commit + caused a regression. If you had: + + T t = null; + t.Foo (); + + In Foo the implict this would be null. + +2004-02-27 Miguel de Icaza + + * expression.cs (Invocation.EmitCall): If the method is not + virtual, do not emit a CallVirt to it, use Call. + + * typemanager.cs (GetFullNameSignature): Improve the method to + cope with ".ctor" and replace it with the type name. + + * class.cs (ConstructorInitializer.Resolve): Now the method takes + as an argument the ConstructorBuilder where it is being defined, + to catch the recursive constructor invocations. + +2004-02-26 Miguel de Icaza + + * iterators.cs (IteratorHandler.IsIEnumerator, IsIEnumerable): New + routines to check if a type is an enumerable/enumerator allow + classes that implement the IEnumerable or IEnumerator interfaces. + + * class.cs (Property, Operator): Implement IIteratorContainer, and + implement SetYields. + + (Property.Define): Do the block swapping for get_methods in the + context of iterators. We need to check if Properties also + include indexers or not. + + (Operator): Assign the Block before invoking the + OperatorMethod.Define, so we can trigger the Iterator code + replacement. + + * cs-parser.jay (SimpleIteratorContainer): new helper class. Both + Property and Operator classes are not created when we parse the + declarator but until we have the block completed, so we use a + singleton SimpleIteratorContainer.Simple to flag whether the + SetYields has been invoked. + + We propagate this setting then to the Property or the Operator to + allow the `yield' to function. + +2004-02-25 Marek Safar + + * codegen.cs: Implemented attribute support for modules. + New AssemblyClass, ModuleClass and CommonAssemblyModulClass for + Assembly/Module functionality. + + * attribute.cs, class.cs, cs-parser.jay, delegate.cs, driver.cs, enum.cs + interface.cs, rootcontext.cs, statement.cs, typemanager.cs: + Updated dependencies on CodeGen.ModuleBuilder and CodeGen.AssemblyBuilder. + +2004-02-16 Marek Safar + + * interface.cs (FindMembers): The operation is performed on all base + interfaces and not only on the first. It is required for future CLS Compliance patch. + +2004-02-12 Ben Maurer + + * statement.cs, codegen.cs: + This patch deals with patterns such as: + + public class List : IEnumerable { + + public MyEnumerator GetEnumerator () { + return new MyEnumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator () { + ... + } + + public struct MyEnumerator : IEnumerator { + ... + } + } + + Before, there were a few things we did wrong: + 1) we would emit callvirt on a struct, which is illegal + 2) we emited ldarg when we needed to emit ldarga + 3) we would mistakenly call the interface methods on an enumerator + type that derived from IEnumerator and was in another assembly. For example: + + public class MyEnumerator : IEnumerator + + Would have the interface methods called, even if there were public impls of the + method. In a struct, this lead to invalid IL code. + +2004-02-11 Marek Safar + + * const.cs: Const is now derived from FieldBase. Method EmitConstant name + renamed to Emit. + + * delegate.cs (Define): Fixed crash when delegate type is undefined. + +2004-02-11 Miguel de Icaza + + * cs-parser.jay: Fix small regression: we were not testing V2 + compiler features correctly. + + * interface.cs: If the emit context is null, then create one + +2004-02-09 Marek Safar + + * decl.cs (GetSignatureForError): New virtual method to get full name + for error messages. + + * attribute.cs (IAttributeSupport): New interface for attribute setting. + Now it is possible to rewrite ApplyAttributes method to be less if/else. + + * interface.cs : All InterfaceXXX classes are now derived from MemberCore. + Duplicated members and code in these classes has been removed. + Better encapsulation in these classes. + +2004-02-07 Miguel de Icaza + + * assign.cs (Assign.DoResolve): When dealing with compound + assignments, there is a new rule in ECMA C# 2.4 (might have been + there before, but it is documented here) that states that in: + + a op= b; + + If b is of type int, and the `op' is a shift-operator, then the + above is evaluated as: + + a = (int) a op b + + * expression.cs (Binary.ResolveOperator): Instead of testing for + int/uint/long/ulong, try to implicitly convert to any of those + types and use that in pointer arithmetic. + + * delegate.cs (Error_NoMatchingMethodForDelegate): Compute the + method to print information for from the type, not from the + null-method we were given. + +2004-02-01 Duncan Mak + + * cs-tokenizer.cs (get_cmd_arg): Skip over whitespace before + parsing for cmd, fixes bug #53694. + +2004-02-04 Marek Safar + + * class.cs, decl.cs: Fixed problem where IndexerName attribute was ignored + in the member name duplication tests. Property and operator name duplication + was missing too (error tests cs0102-{2,3,4,5}.cs, cs0111-{3,4}.cs). + +2004-02-03 Marek Safar + + * interface.cs (PopulateMethod): Fixed crash when interface method + returns not existing type (error test cs0246-3.cs). + +2004-02-02 Ravi Pratap M + + * cs-parser.jay (interface_accessors): Re-write actions to also + store attributes attached to get and set methods. Fix spelling + while at it. + + (inteface_property_declaration): Modify accordingly. + + (InterfaceAccessorInfo): New helper class to store information to pass + around between rules that use interface_accessors. + + * interface.cs (Emit): Apply attributes on the get and set + accessors of properties and indexers too. + + * attribute.cs (ApplyAttributes): Modify accordingly to use the + right MethodBuilder when applying attributes to the get and set accessors. + +2004-01-31 Miguel de Icaza + + * cs-tokenizer.cs: Applied patch from Marek Safar to fix bug 53386 + +2004-01-26 Miguel de Icaza + + * cs-tokenizer.cs: Handle #line hidden from PDC bits. + +2004-01-25 Miguel de Icaza + + * cs-parser.jay: Remove YIELD token, instead use the new grammar + changes that treat `yield' specially when present before `break' + or `return' tokens. + + * cs-tokenizer.cs: yield is no longer a keyword. + +2004-01-23 Marek Safar + + * cs-parser.jay, class.cs (DefineDefaultConstructor): Fixed ModFlags + setting for default constructors. + For default constructors are almost every time set wrong Modifier. The + generated IL code has been alright. But inside mcs this values was + wrong and this was reason why several of my CLS Compliance tests + failed. + +2004-01-22 Martin Baulig + + * cs-parser.jay (namespace_or_type_name): Return an Expression, + not a QualifiedIdentifier. This is what `type_name_expression' + was previously doing. + (type_name_expression): Removed; the code is now in + `namespace_or_type_name'. + (qualified_identifier): Removed, use `namespace_or_type_name' + instead. + (QualifiedIdentifier): Removed this class. + +2004-01-22 Martin Baulig + + * namespace.cs (NamespaceEntry.UsingAlias): Take an Expression, + not a string as alias name. + +2004-01-21 Miguel de Icaza + + * ecore.cs (FieldInfo.AddressOf): Revert patch from previous + #52730 bug, and instead compute correctly the need to use a + temporary variable when requesting an address based on the + static/instace modified of the field and the constructor. + +2004-01-21 Martin Baulig + + * ecore.cs (SimpleName.ResolveAsTypeStep): Lookup in the current + class and namespace before looking up aliases. Fixes #52517. + +2004-01-21 Martin Baulig + + * flowanalysis.cs (UsageVector.Merge): Allow variables being + assinged in a 'try'; fixes exception4.cs. + +2004-01-21 Marek Safar + * class.cs : Implemented parameter-less constructor for TypeContainer + + * decl.cs: Attributes are now stored here. New property OptAttributes + + * delegate.cs, enum.cs, interface.cs: Removed attribute member. + + * rootcontext.cs, tree.cs: Now use parameter-less constructor of TypeContainer + +2004-01-21 Marek Safar + + * typemanager.cs (CSharpSignature): Now reports also inner class name. + (CSharpSignature): New method for indexer and property signature. + +2004-01-21 Marek Safar + + * pending.cs (IsVirtualFilter): Faster implementation. + +2004-01-21 Marek Safar + + * typemanager.cs: Avoid inclusion of same assembly more than once. + +2004-01-21 Marek Safar + + * cs-parser.jay: Fixed problem where the last assembly attribute + has been applied also to following declaration (class, struct, etc.) + +2004-01-21 Marek Safar + + * class.cs: Added error CS0538, CS0539 reporting. + Fixed crash on Microsoft runtime when field type is void. + + * cs-parser.jay: Added error CS0537 reporting. + + * pending.cs: Added error CS0535 reporting. + Improved error report for errors CS0536, CS0534. + +2004-01-20 Miguel de Icaza + + Merge a few bits from the Anonymous Method MCS tree. + + * statement.cs (ToplevelBlock): New class for toplevel methods, + will hold anonymous methods, lifted variables. + + * cs-parser.jay: Create toplevel blocks for delegates and for + regular blocks of code. + +2004-01-20 Martin Baulig + + * codegen.cs (EmitContext): Removed `InTry', `InCatch', + `InFinally', `InLoop', `TryCatchLevel', `LoopBeginTryCatchLevel' + and `NeedExplicitReturn'; added `IsLastStatement'. + (EmitContext.EmitTopBlock): Emit the explicit "ret" if we either + have a `ReturnLabel' or we're not unreachable. + + * flowanalysis.cs (FlowBranching.MergeChild): Actually merge the + child's reachability; don't just override ours with it. Fixes + #58058 (lluis's example). + (FlowBranching): Added public InTryOrCatch(), InCatch(), + InFinally(), InLoop(), InSwitch() and + BreakCrossesTryCatchBoundary() methods. + + * statement.cs (Return): Do all error checking in Resolve(). + Unless we are the last statement in a top-level block, always + create a return label and jump to it. + (Break, Continue): Do all error checking in Resolve(); also make + sure we aren't leaving a `finally'. + (Block.DoEmit): Set `ec.IsLastStatement' when emitting the last + statement in a top-level block. + (Block.Flags): Added `IsDestructor'. + (Block.IsDestructor): New public property. + +2004-01-20 Martin Baulig + + * statement.cs (Break.DoEmit): Set ec.NeedExplicitReturn; fixes #52427. + +2004-01-20 Martin Baulig + + * statement.cs (Statement.ResolveUnreachable): New public method. + (If, While): Do the dead-code elimination in Resolve(), not in Emit(). + (Block.Resolve): Resolve unreachable statements. + +2004-01-19 Ben Maurer + + * expression.cs: We need to fix the case where we do + not have a temp variable here. + + * assign.cs: Only expression compound assignments need + temporary variables. + +2004-01-19 Ben Maurer + + * flowanalysis.cs: Reduce memory allocation in a few ways: + - A block with no variables should not allocate a bit + vector for itself. + - A method with no out parameters does not need any tracking + for assignment of the parameters, so we need not allocate + any data for it. + - The arrays: + public readonly Type[] VariableTypes; + public readonly string[] VariableNames; + Are redundant. The data is already stored in the variable + map, so we need not allocate another array for it. + - We need to add alot of checks for if (params | locals) == null + due to the first two changes. + +2004-01-18 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): For ValueTypes that do not + implement IMemoryLocation, we store a copy on a local variable and + take the address of it. Patch from Benjamin Jemlich + + * cs-parser.jay: Applied patch from Ben Maurer to the "type" rule + to use a special "type_name_expression" rule which reduces the + number of "QualifiedIdentifier" classes created, and instead + directly creates MemberAccess expressions. + +2004-01-17 Miguel de Icaza + + * convert.cs: Applied patch from Benjamin Jemlich (pcgod@gmx.net) + that fixes #52853. Null literal assignment to ValueType + + * class.cs (MethodData.Emit): Instead of checking the name of the + method to determine if its a destructor, create a new derived + class from Method called Destructor, and test for that. + + * cs-parser.jay: Create a Destructor object instead of a Method. + + Based on a fix from Benjamin Jemlich (pcgod@gmx.net) + + Fixes: 52933 + +2004-01-16 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Perform an implicit + conversion from MethodGroups to their delegate types on the + Addition operation. + + * delegate.cs: Introduce a new class DelegateCreation that is the + base class for `NewDelegate' and `ImplicitDelegateCreation', + factor some code in here. + + * convert.cs (Convert.ImplicitConversionStandard): Add an implicit + conversion from MethodGroups to compatible delegate types. + + * ecore.cs (Expression.Resolve): Do not flag error 654 + (Methodgroupd needs parenthesis) if running on the V2 compiler, as + we allow conversions from MethodGroups to delegate types now. + + * assign.cs (Assign.DoResolve): Do not flag errors on methodgroup + assignments in v2 either. + +2004-01-10 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): Fix generated IL for accessing + static read-only fields in ctors. + + Applied patch from Benjamin Jemlich + + * expression.cs (UnaryMutator): Avoid leaking local variables. + +2004-01-09 Miguel de Icaza + + * cs-tokenizer.cs (IsCastToken): Allow the various native types + here to return true, as they can be used like this: + + (XXX) int.MEMBER () + + Fixed 49836 and all the other dups + +2004-01-09 Zoltan Varga + + * driver.cs: Implement /win32res and /win32icon. + +2004-01-08 Miguel de Icaza + + * cs-parser.jay: Add a rule to improve error handling for the + common mistake of placing modifiers after the type. + +2004-01-07 Miguel de Icaza + + * cs-parser.jay (interface_event_declaration): Catch + initialization of events on interfaces, and report cs0068 + + * cs-parser.jay (interface_event_declaration): Catch + initialization of events. + + * ecore.cs: Better report missing constructors. + + * expression.cs (Binary.ResolveOperator): My previous bug fix had + the error reporting done in the wrong place. Fix. + + * expression.cs (Binary.ResolveOperator): Catch the + operator + (E x, E y) error earlier, and later allow for implicit + conversions in operator +/- (E e, U x) from U to the underlying + type of E. + + * class.cs (TypeContainer.DefineDefaultConstructor): Fix bug + 52596, if the container class is abstract, the default constructor + is protected otherwise its public (before, we were always public). + + * statement.cs (Fixed.Resolve): Catch a couple more errors in the + fixed statement. + + (Using.EmitLocalVariableDecls): Applied patch from Benjamin + Jemlich that fixes bug #52597, MCS was generating invalid code for + idisposable structs. Thanks to Ben for following up with this + bug as well. + +2004-01-06 Miguel de Icaza + + * driver.cs: Allow assemblies without code to be generated, fixes + 52230. + +2004-01-07 Nick Drochak + + * attribute.cs: Remove unneeded catch variables. Eliminates a warning. + +2004-01-05 Miguel de Icaza + + * cs-parser.jay: Add rules to improve error reporting if fields or + methods are declared at the namespace level (error 116) + + * Add rules to catch event add/remove + +2004-01-04 David Sheldon + + * expression.cs: Added matching ")" to error message for + CS0077 + +2004-01-03 Todd Berman + + * ecore.cs, attribute.cs: + Applying fix from #52429. + +2004-01-03 Ben Maurer + + * ecore.cs, expression.cs, statement.cs: + Total rewrite of how we handle branching. We + now handle complex boolean expressions with fewer + jumps. As well if (x == 0) no longer emits a ceq. + + if (x is Foo) is much faster now, because we generate + better code. + + Overall, we get a pretty big improvement on our benchmark + tests. The code we generate is smaller and more readable. + + I did a full two-stage bootstrap. The patch was reviewed + by Martin and Miguel. + +2004-01-03 Ben Maurer + + * cs-parser.jay: Make primary_expression not take a QI. + we dont need this because the member_access rule covers + us here. So we replace the rule with just IDENTIFIER. + + This has two good effects. First, we remove a s/r conflict. + Second, we allocate many fewer QualifiedIdentifier objects. + +2004-01-03 Ben Maurer + + * attribute.cs: Handle MarshalAs attributes as pseudo, and + set the correct information via SRE. This prevents + hanging on the MS runtime. Fixes #29374. + +2004-01-03 Ben Maurer + + * convert.cs: correctly handle conversions to value types + from Enum and ValueType as unboxing conversions. + + Fixes bug #52569. Patch by Benjamin Jemlich. + +2004-01-02 Ravi Pratap + + * expression.cs (BetterConversion): Prefer int -> uint + over int -> ulong (csc's behaviour). This fixed bug #52046. + +2004-01-02 Ben Maurer + + * decl.cs (MemberCache.FindMembers): now returns a + MemberInfo []. + + * typemanager.cs: In general, go with with ^^. + (CopyNewMethods): take an IList. + (RealMemberLookup): Only allocate an arraylist + if we copy from two sets of methods. + + This change basically does two things: + 1) Fewer array lists allocated due to CopyNewMethods. + 2) the explicit cast in MemberList costed ALOT. + +2004-01-02 Zoltan Varga + + * cs-tokenizer.cs (consume_identifier) driver.cs: Cache identifiers in + a hashtable to avoid needless string allocations when an identifier is + used more than once (the common case). + +2004-01-01 Ben Maurer + + * pending.cs: MS's TypeBuilder.GetInterfaces () + is broken, it will not return anything. So, we + have to use the information we have in mcs to + do the task. + + * typemanager.cs: Add a cache for GetInterfaces, + since this will now be used more often (due to ^^) + + (GetExplicitInterfaces) New method that gets the + declared, not effective, interfaces on a type + builder (eg, if you have interface IFoo, interface + IBar, Foo : IFoo, Bar : Foo, IBar, GetExplInt (Bar) == + { IBar }. + + This patch makes MCS able to bootstrap itself on + Windows again. + +2004-01-01 Ben Maurer + + * expression.cs: Remove the Nop's that Miguel put + in by mistake. + +2003-12-31 Ben Maurer + + * report.cs, codegen.cs: Give the real stack trace to + the error when an exception is thrown. + +2003-12-31 Ben Maurer + + * decl.cs: only allocate hashtables for ifaces if + it is an iface! + +2003-12-31 Ben Maurer + + * expression.cs: fix the error from cs0121-2.cs + (a parent interface has two child interfaces that + have a function with the same name and 0 params + and the function is called through the parent). + +2003-12-30 Ben Maurer + + * class.cs, rootcontext.cs, typmanager.cs: do not + leak pointers. + +2003-12-28 Ben Maurer + + * codegen.cs: remove stack for the ec flow branching. + It is already a linked list, so no need. + +2003-12-27 Ben Maurer + + * Makefile: Allow custom profiler here. + +2003-12-26 Ben Maurer + + * typemanager.cs (LookupType): + - Use a static char [], because split takes + a param array for args, so it was allocating + every time. + - Do not store true in a hashtable, it boxes. + +2003-12-26 Ben Maurer + + * flowanalysis.cs: bytify common enums. + +2003-12-25 Ben Maurer + + * modifiers.cs: Add a new set of flags for the + flags allowed on explicit interface impls. + * cs-parser.jay: catch the use of modifiers in + interfaces correctly. + * class.cs: catch private void IFoo.Blah (). + + All related to bug #50572. + +2003-12-25 Ben Maurer + + * decl.cs: Rewrite the consistant accessability checking. + Accessability is not linear, it must be implemented in + a tableish way. Fixes #49704. + +2003-12-25 Ben Maurer + + * expression.cs: Handle negation in a checked context. + We must use subtraction from zero. Fixes #38674. + +2003-12-23 Ben Maurer + + * class.cs: Ignore static void main in DLLs. + * rootcontext.cs: Handle the target type here, + since we are have to access it from class.cs + * driver.cs: account for the above. + +2003-12-23 Ben Maurer + + * report.cs: Give line numbers and files if available. + +2003-12-20 Zoltan Varga + + * driver.cs: Implement /addmodule. + + * typemanager.cs: Change 'modules' field so it now contains Modules not + ModuleBuilders. + +2003-12-20 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Don't do the CS0649 check here. + (FieldBase.IsAssigned): Removed this field. + (FieldBase.SetAssigned): New public method. + (TypeContainer.Emit): Make the CS0169/CS0649 checks actually work. + +2003-12-20 Martin Baulig + + * expression.cs (LocalVariableReference.DoResolve): Don't set + `vi.Used' if we're called from DoResolveLValue(). + + * statement.cs (Block.DoResolve): `ec.DoEndFlowBranching()' now + returns the usage vector it just merged into the current one - + pass this one to UsageWarning(). + (Block.UsageWarning): Take the `FlowBranching.UsageVector' instead + of the `EmitContext', don't call this recursively on our children. + +2003-12-19 Zoltan Varga + + * driver.cs: Implement /target:module. + +2003-12-18 Zoltan Varga + + * support.cs (CharArrayHashtable): New helper class. + + * cs-tokenizer.cs: Store keywords in a hashtable indexed by + char arrays, not strings, so we can avoid creating a string in + consume_identifier if the identifier is a keyword. + +2003-12-16 Martin Baulig + + * statement.cs (LocalInfo.Assigned): Removed this property. + (LocalInfo.Flags): Removed `Assigned'. + (LocalInfo.IsAssigned): New public method; takes the EmitContext + and uses flow analysis. + (Block.UsageWarning): Made this method private. + (Block.Resolve): Call UsageWarning() if appropriate. + + * expression.cs (LocalVariableReference.DoResolve): Always set + LocalInfo.Used here. + +2003-12-13 Martin Baulig + + * statement.cs (Statement.DoEmit, Statement.Emit): Don't return + any value here; we're now using flow analysis to figure out + whether a statement/block returns a value. + +2003-12-13 Martin Baulig + + * flowanalysis.cs (UsageVector.MergeFinallyOrigins): Made this + working again. + (FlowBranching.MergeFinally): Don't call + `branching.CheckOutParameters()' here, this is called in + MergeTopBlock(). + (FlowBranchingException.AddSibling): Call MergeFinallyOrigins() + when adding the `finally' vector. + +2003-12-13 Martin Baulig + + * flowanalysis.cs + (UsageVector.MergeJumpOrigins, FlowBranching.Label): Make this + actually work and also fix #48962. + +2003-12-12 Ben Maurer + + * decl.cs: Do not check System.Object for nested types, + since we know it does not have any. Big bang for buck: + + BEFORE: + Run 1: 8.35 seconds + Run 2: 8.32 seconds + corlib: 17.99 seconds + AFTER: + Run 1: 8.17 seconds + Run 2: 8.17 seconds + corlib: 17.39 seconds + +2003-12-11 Ben Maurer + + * class.cs (FindMembers): Allocate arraylists on demand. Most of the + time we are returning 0 members, so we save alot here. + +2003-12-11 Martin Baulig + + * flowanalysis.cs (UsageVector.MergeResult): Renamed this back to + `MergeChild()', also just take the `FlowBranching' as argument; + call Merge() on it and return the result. + (FlowBranching.Merge): We don't need to do anything if we just + have one sibling. + +2003-12-11 Martin Baulig + + * flowanalysis.cs: Use a list of `UsageVector's instead of storing + them in an `ArrayList' to reduce memory usage. Thanks to Ben + Maurer for this idea. + +2003-12-11 Martin Baulig + + * flowanalysis.cs (MergeResult): This class is now gone; we now + use the `UsageVector' for this. The reason for this is that if a + branching just has one sibling, we don't need to "merge" them at + all - that's the next step to do. + (FlowBranching.Merge): We now return a `UsageVector' instead of a + `MergeResult'. + +2003-12-11 Martin Baulig + + Reworked flow analyis and made it more precise and bug-free. The + most important change is that we're now using a special `Reachability' + class instead of having "magic" meanings of `FlowReturns'. I'll + do some more cleanups and optimizations and also add some more + documentation this week. + + * flowanalysis.cs (Reachability): Added `Throws' and `Barrier'; + largely reworked this class. + (FlowReturns): Removed `Unreachable' and `Exception'; we now use + the new `Reachability' class instead of having "magic" values here. + (FlowBranching): We're now using an instance of `Reachability' + instead of having separate `Returns', `Breaks' etc. fields. + + * codegen.cs (EmitContext.EmitTopBlock): Set `has_ret' solely + based on flow analysis; ignore the return value of block.Emit (). + +2003-12-10 Zoltan Varga + + * driver.cs typemanager.cs: Find the mono extensions to corlib even + if they are private. + +2003-12-09 Martin Baulig + + * flowanalyis.cs (FlowBranching.Return, Goto, Throw): Removed; + call them directly on the UsageVector. + +2003-12-09 Martin Baulig + + * flowanalysis.cs (FlowBranching.MergeChild, MergeTopBlock): + Changed return type from `FlowReturns' to `Reachability'. + +2003-12-09 Martin Baulig + + * flowanalysis.cs (FlowBranching.Reachability): New sealed class. + (FlowBranching.MergeResult): Replaced the `Returns', `Breaks' and + `Reachable' fields with a single `Reachability' one. + +2003-12-08 Ben Maurer + + * class.cs (FindMembers): Remove foreach's. + + Bootstrap times: + + BEFORE + Run 1: 8.74 seconds + Run 2: 8.71 seconds + + AFTER + Run 1: 8.64 seconds + Run 2: 8.58 seconds + + +2003-12-08 Ben Maurer + + * cs-parser.jay: + * gen-treedump.cs: + * statement.cs: + This patch does a few things: + 1. EmptyStatement is now a singleton, so it is never reallocated. + 2. All blah is EmptyStatement constructs have been changed to + blah == EmptyStatement.Value, which is much faster and valid + now that EmptyStatement is a singleton. + 3. When resolving a block, rather than allocating a new array for + the non-empty statements, empty statements are replaced with + EmptyStatement.Value + 4. Some recursive functions have been made non-recursive. + Mainly the performance impact is from (3), however (1) and (2) are needed for + this to work. (4) does not make a big difference in normal situations, however + it makes the profile look saner. + + Bootstrap times: + + BEFORE + 9.25user 0.23system 0:10.28elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k + 9.34user 0.13system 0:10.23elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k + Total memory allocated: 56397 KB + + AFTER + 9.13user 0.09system 0:09.64elapsed 95%CPU (0avgtext+0avgdata 0maxresident)k + 8.96user 0.24system 0:10.13elapsed 90%CPU (0avgtext+0avgdata 0maxresident)k + Total memory allocated: 55666 KB + +2003-12-08 Ben Maurer + + * support.cs: Rewrite DoubleHash to use its own impl. Is faster + than the hashtable in a hashtable version + + * decl.cs: Right now, whenever we try to lookup a type inside a namespace, + we always end up concating a string. This results in a huge perf + loss, because many strings have to be tracked by the GC. In this + patch, we first use a hashtable that works with two keys, so that + the strings do not need to be concat'ed. + + Bootstrap times: + BEFORE + Run 1: 8.74 seconds + Run 2: 8.71 seconds + + AFTER + Run 1: 8.65 seconds + Run 2: 8.56 seconds + +2003-12-08 Ben Maurer + + * Makefile: Add a new target `do-time' that does a quick and simple + profile, leaving easy to parse output. + +2003-12-08 Zoltan Varga + + * codegen.cs (Init): Create the dynamic assembly with + AssemblyBuilderAccess.Save, to enable some optimizations in the runtime. + +2003-12-02 Ben Maurer + + * support.cs: Make the PtrHashtable use only one + instance of its comparer. + +2003-11-30 Zoltan Varga + + * typemanager.cs: Fix lookup of GetNamespaces. + +2003-11-29 Miguel de Icaza + + * expression.cs: Removed redundant line. + + * statement.cs (Block.Resolve, Block.Emit): Avoid foreach on + ArrayLists, use for loops with bounds. + + * flowanalysis.cs (FlowBranching.Merge): Avoid foreach on + arraylist. + + * expression.cs (Invocation.OverloadResolve): Avoid foreach on + arraylists, use for loop with bounds. + + The above three changes give us a 0.071 second performance + improvement out of 3.294 seconds down to 3.223. On my machine + the above changes reduced the memory usage by 1,387 KB during + compiler bootstrap. + + * cs-parser.jay (QualifiedIdentifier): New class used to represent + QualifiedIdentifiers. Before we created a new string through + concatenation, and mostly later on, the result would be + manipulated by DecomposeQI through string manipulation. + + This reduced the compiler memory usage for bootstrapping from + 59380 KB to 59007 KB on my machine, 373 KB, and also reduced the + compile times in 0.05 seconds. + +2003-11-28 Dick Porter + + * support.cs: Do string compares with the Invariant culture. + + * rootcontext.cs: + * gen-treedump.cs: + * expression.cs: + * driver.cs: + * decl.cs: + * codegen.cs: + * class.cs: Use the char forms of IndexOf and LastIndexOf, so that + the comparison is done with the Invariant culture. + +2003-11-27 Miguel de Icaza + + * statement.cs (Foreach.TryType): Use DeclaredOnly to find the + GetEnumerator method. + + (ProbeCollectionType): Iterate starting at the most specific type + upwards looking for a GetEnumerator + + * expression.cs: Shift count can be up to 31 for int/uint and 63 + for long/ulong. + +2003-11-26 Miguel de Icaza + + * statement.cs (Block.LookupLabel): Also look for the label on the + children blocks. Use a hash table to keep track of visited + nodes. + + * cfold.cs (IntConstant to UIntConstant mapping): Only return if + we actually did transform the other operand, otherwise fall back + to the common codepath that casts to long. + + * cs-tokenizer.cs: Use the same code pattern as the int case. + Maybe I should do the parsing myself, and avoid depending on the + Parse routines to get this done. + +2003-11-25 Miguel de Icaza + + * expression.cs: Apply fix from l_m@pacbell.net (Laurent Morichetti), + which fixes bug 51347. This time test it. + + * expression.cs: Make TypeOfVoid derive from TypeOf, so code in + attributes for example can not tell the difference between these. + The difference was only a syntax feature of the language. + + * attribute.cs: Apply attributes to delegates. + + * delegate.cs: Call the apply attributes method. + +2003-11-24 Miguel de Icaza + + * convert.cs (TryImplicitIntConversion): One line bug fix: we were + comparing 0 vs Byte.MinValue, not the value + + (ImplicitConversionRequired): When reporting a conversion error, + use error 31 to print out the constant error instead of the + simpler 29. + + * expression.cs: Apply fix from l_m@pacbell.net (Laurent Morichetti), + which fixes bug 51347. + +2003-11-22 Miguel de Icaza + + * driver.cs: Applied patch from gert.driesen@pandora.be (Gert Driesen) + which fixes the -warnaserror command line option. + +2003-11-21 Miguel de Icaza + + * cfold.cs (DoNumericPromotions): During constant folding of + additions on UIntConstant, special case intconstants with + IntConstants like we do on the expression binary operator. + +2003-11-12 Miguel de Icaza + + * convert.cs (ImplicitReferenceConversion): We were missing a case + (System.Enum are not value types or class types, so we need to + classify them separatedly). + + * driver.cs: We do not support error 2007. + +2003-11-12 Jackson Harper + + * driver.cs: Use corlib.dll or mscorlib.dll when looking up the + system directory. Also use the full file name so users can + libraries names mscorlib-o-tron.dll in a non system dir. + +2003-11-10 Martin Baulig + + * typemanager.cs (TypeManager.ResolveExpressionTypes): Removed. + (TypeManager.InitCoreTypes): Initialize them here, but instead of + calling `ResolveType()' on them, directly assign their `Type'. + +2003-11-08 Martin Baulig + + * class.cs (TypeContainer.GetClassBases): Use TypeExpr's for the + return value and the `out parent' parameter. + (TypeContainer.DefineType): Moved the CS0644 check into + GetClassBases(). Don't pass the interface types to the + `builder.DefineType()'/`builder.DefineNestedType()', but resolve + them later and then call `TypeBuilder.AddInterfaceImplementation()'. + + * ecore.cs (TypeExpr.IsAttribute): New property. + (TypeExpr.GetInterfaces): New method. + + * interface.cs (Interface.GetInterfaceTypeByName): Return a + TypeExpr instead of a Type. + (Interface.GetInterfaceBases): Return TypeExpr's instead of Type's. + (Interface.DefineType): Don't pass the interface types to the + `builder.Definetype()'/`builder.DefineNestedType()', but resolve + them later and then call `TypeBulider.AddInterfaceImplementation()'. + + * typemanager.cs (TypeManager.AddUserType): Take a `TypeExpr[]' + instead of a `Type[]'. + (TypeManager.RegisterBuilder): Likewise. + (TypeManager.AddUserInterface): Likewise. + (TypeManager.ExpandInterfaces): Take a `Type[]' instead of a + `Type[]' and also return a `TypeExpr[]'. + (TypeManager.GetInterfaces): Return a `TypeExpr[]'. + +2003-11-08 Martin Baulig + + * decl.cs (DeclSpace.ResolveTypeExpr): Return a TypeExpr, not an + Expression. + +2003-11-08 Martin Baulig + + * decl.cs (DeclSpace.GetTypeResolveEmitContext): Call + TypeManager.ResolveExpressionTypes(). + + * ecore.cs (Expression.ResolveAsTypeTerminal): Return a TypeExpr + instead of an Expression. + (TypeExpr): This is now an abstract base class for `TypeExpression'. + (TypeExpression): New public class; formerly known as `TypeExpr'. + + * expression.cs (ComposedCast): Derive from TypeExpr. + + * typemanager.cs (TypeManager.system_*_expr): These are now + TypExpr's instead of Expression's. + (TypeManager.ResolveExpressionTypes): New public static function; + called from DeclSpace.GetTypeResolveEmitContext() to resolve all + of them. + +2003-11-06 Miguel de Icaza + + * expression.cs (New.DoResolve): Do not dereference value that + might be a null return. + + * statement.cs (Block.EmitMeta): Use the Const.ChangeType to make + sure that the constant value has the right type. Fixes an + unreported bug, similar to 50425. + + * const.cs (Const.LookupConstantValue): Call + ImplicitStandardConversionExists before doing a conversion to + avoid havng the TypeManager.ChangeType do conversions. + + Reduced the number of casts used + + (Const.ChangeType): New routine to enable reuse of the constant + type changing code from statement. + + * typemanager.cs (ChangeType): Move common initialization to + static global variables. + + Fixes #50425. + + * convert.cs (ImplicitReferenceConversion): Somehow we allowed + every value type to go through, even if it was void. Fix that. + + * cs-tokenizer.cs: Use is_identifier_start_character on the start + character of the define, and the is_identifier_part_character for + the rest of the string. + +2003-11-05 Miguel de Icaza + + * expression.cs (UnaryMutator.EmitCode): When I updated + LocalVariableReference.DoResolve, I overdid it, and dropped an + optimization done on local variable references. + +2003-11-04 Miguel de Icaza + + * ecore.cs: Convert the return from Ldlen into an int. + +2003-10-20 Miguel de Icaza + + * decl.cs (DeclSpace.GetAccessLevel): Handle NotPublic case for + the accessibility, this is a special case for toplevel non-public + classes (internal for instance). + +2003-10-20 Nick Drochak + + * ecore.cs: Fix typo and build. Needed another right paren. + +2003-10-19 Miguel de Icaza + + * ecore.cs: Applied fix from Ben Maurer. We were handling in the + `internal' case regular and protected, but not allowing protected + to be evaluated later. Bug 49840 + +2003-10-15 Miguel de Icaza + + * statement.cs (Switch.TableSwitchEmit): Compare the upper bound + to kb.Nlast, and not the kb.nFirst to isolate the switch + statement. + + Extract the underlying type, so enumerations of long/ulong are + treated like long/ulong. + +2003-10-14 Miguel de Icaza + + * expression.cs (New): Overload the meaning of RequestedType to + track the possible creation of the NewDelegate type, since + DoResolve is invoked more than once for new constructors on field + initialization. + + See bugs: #48800 and #37014 + + * cs-parser.jay (declare_local_constants): Take an arraylist + instead of a single constant. + + (local_constant_declaration): It should take a + constant_declarators, not a constant_declarator. Fixes 49487 + + * convert.cs: Fix error report. + +2003-10-13 Jackson Harper + + * typemanager.cs (TypeToCoreType): Add float and double this fixes + bug #49611 + +2003-10-09 Martin Baulig + + * class.cs (MethodCore): Added additional `DeclSpace ds' argument + to the .ctor. + (MethodCore.DoDefineParameters): Removed the TypeContainer + argument; use the DeclSpace which was passed to the .ctor instead. + (MethodCore.CheckParameter): Take a DeclSpace instead of a + TypeContainer; we only need a DeclSpace here. + +2003-10-09 Martin Baulig + + * class.cs (MethodData): Added additional `DeclSpace ds' argument + to the .ctor. + (MethodData.Define, MethodData.Emit): Pass the `ds' to the + EmitContext's .ctor. + +2003-10-09 Martin Baulig + + * decl.cs (DeclSpace.AsAccessible): Moved here from TypeContainer. + (AccessLevel, CheckAccessLevel, GetAccessLevel): They're used by + AsAccessible(), moved them as well. + + * class.cs (TypeContainer.AsAccessible): Moved to DeclSpace. + +2003-10-08 Atsushi Enomoto + + * cs-parser.jay : Renamed yyName to yyNames related to jay. + +2003-10-07 Miguel de Icaza + + * expression.cs (Binary.Emit.GreatherThanOrEqual): Fix the code + generation for >=, as spotted by Paolo, bug 48679. + Patch from David Waite. + + * cs-tokenizer.cs: Add handling for #pragma. + + * cs-parser.jay: Allow for both yield and yield return in the + syntax. The anti-cobolization of C# fight will go on! + + * class.cs (TypeBuilder.DefineType): Catch error condition here + (Parent.DefineType erroring out and returning null). + + * expression.cs (ArrayCreation.EmitDynamicInitializers): When + coping with enumerations variables, we were mistakenly processing + them as a regular value type instead of built-in types. Fixes the + bug #48063 + + * typemanager.cs (IsBuiltinOrEnum): New method. + +2003-09-30 Miguel de Icaza + + * cs-parser.jay: Upgrade: yield now needs the return clause. + +2003-09-19 Martin Baulig + + * decl.cs (MemberCache.SetupCacheForInterface): Take a + `MemberCache parent' argument. Normally, an interface doesn't + have a parent type except System.Object, but we use this in gmcs + for generic type parameters. + +2003-09-18 Martin Baulig + + * typemanager.cs (TypeHandle.ctor): Set `IsInterface' solely based + on `type.IsInterface'; don't check whether the type has a parent + to determine whether it's an interface. + +2003-09-15 Martin Baulig + + * class.cs (TypeContainer.DefineType): Added an error flag to + avoid reporting duplicate CS0146's ("class definition is + circular."). + + * driver.cs (Driver.MainDriver): Abort if + RootContext.ResolveTree() reported any errors. + +2003-09-07 Martin Baulig + + * report.cs (Error, Warning): Added overloaded versions which take + a `params object[] args' and call String.Format(). + +2003-09-07 Martin Baulig + + * decl.cs (DeclSpace..ctor): Don't call + NamespaceEntry.DefineName() here; do it in RecordDecl() which is + called from Tree.RecordDecl(). Fixes the CS0101 reporting. + (DeclSpace.RecordDecl): New method. + + * tree.cs (Tree.RecordDecl): Call ds.RecordDecl(). + +2003-09-02 Ravi Pratap + + * attribute.cs (CheckAttributeTarget): Ensure that we allow return + value attributes to be applied to ParameterBuilders. + + * class.cs (MethodCore.LabelParameters): Make static and more + generic so that it can be used from other places - like interface + methods, for instance. + + * interface.cs (Interface.Emit): Call LabelParameters before + emitting attributes on the InterfaceMethod. + +2003-08-26 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Look for members before + resolving aliases; fixes #47927. + +2003-08-26 Martin Baulig + + * statement.cs (Using.DoResolve): This is internally emitting a + try/finally clause, so we need to set ec.NeedExplicitReturn if we + do not always return. Fixes #47681. + +2003-08-26 Martin Baulig + + * decl.cs (MemberCore): Moved WarningNotHiding(), + Error_CannotChangeAccessModifiers() and CheckMethodAgainstBase() + into MemberBase. + (AdditionResult): Make this nested in DeclSpace. + (DeclSpace.ctor): The .ctor now takes an additional NamespaceEntry + argument; call NamespaceEntry.Define() unless we're nested in a + class or struct. + + * namespace.cs (Namespace.DefineName): New public function. This + is called from DeclSpace's .ctor to add + (Namespace.Lookup): Include DeclSpaces in the lookup. + + * class.cs (Operator): Derive from MemberBase, not MemberCore. + + * const.cs (Const): Derive from MemberBase, not MemberCore. + +2003-08-25 Martin Baulig + + * convert.cs (Convert.ExplicitReferenceConversion): When + converting from an interface type to a class, unbox if the target + type is a struct type. Fixes #47822. + +2003-08-24 Gonzalo Paniagua Javier + + * typemanager.cs: fixed the values of MethodFlags. Closes #47855 and + #47854. + +2003-08-22 Martin Baulig + + * class.cs (TypeManager.DefineType): When defining a nested type, + call DefineType() on our parent; fixes #47801. + +2003-08-22 Martin Baulig + + * class.cs (MethodData.Define): While checking if a method is an + interface implementation, improve the test a bit more to fix #47654. + +2003-08-22 Martin Baulig + + * expression.cs (Probe.DoResolve): Check whether `expr' resolved + correctly; fixes #47722. + +2003-08-22 Martin Baulig + + * expression.cs (UnaryMutator.ResolveVariable): If the target is a + LocalVariableReference, ensure it's not read-only. Fixes #47536. + + * statement.cs (Fixed.DoResolve): Make all variables read-only. + +2003-08-22 Martin Baulig + + * ecore.cs (FieldExpr.DoResolveLValue): Static read-only fields + can only be assigned in static constructors. Fixes #47161. + +2003-08-22 Martin Baulig + + Rewrote and improved the flow analysis code. + + * flowbranching.cs (FlowBranching): Make this class abstract. + (FlowBranching.CreateBranching): New static function to create a + new flow branching. + (FlowBranchingBlock, FlowBranchingException): New classes. + (FlowBranching.UsageVector.Type): New public readonly field. + (FlowBranching.UsageVector.Breaks): Removed the setter. + (FlowBranching.UsageVector.Returns): Removed the setter. + (FlowBranching.UsageVector): Added Break(), Return(), + NeverReachable() and Throw() methods to modify the reachability. + (FlowBranching.UsageVector.MergeChildren): Removed, this is now + done by FlowBranching.Merge(). + (FlowBranching.UsageVector.MergeChild): New method; merges the + merge result into the current vector. + (FlowBranching.Merge): New abstract method to merge a branching. + +2003-08-12 Martin Baulig + + * expression.cs (Indirection.CacheTemporaries): Create the + LocalTemporary with the pointer type, not its element type. + +2003-08-10 Miguel de Icaza + + * cs-parser.jay: FIRST_KEYWORD, LAST_KEYWORD: used to know if a + token was a keyword or not. + + Add `error' options where an IDENTIFIER was expected; Provide + CheckToken and CheckIdentifierToken convenience error reporting + functions. + + Do not use `DeclSpace.Namespace', use `DeclSpace.NamespaceEntry'. + + * decl.cs: Rename `NamespaceEntry Namespace' public field into + NameSpaceEntry NameSpaceEntry. + + (LookupInterfaceOrClass): Avoid creating a full qualified name + from namespace and name: avoid doing lookups when we know the + namespace is non-existant. Use new Tree.LookupByNamespace which + looks up DeclSpaces based on their namespace, name pair. + + * driver.cs: Provide a new `parser verbose' to display the + exception thrown during parsing. This is turned off by default + now, so the output of a failure from mcs is more graceful. + + * namespace.cs: Track all the namespaces defined in a hashtable + for quick lookup. + + (IsNamespace): New method + +2003-08-09 Miguel de Icaza + + * namespace.cs: Remove redundant call; Avoid using MakeFQN when + we know that we need to concatenate (full typename can never be + null). + + * class.cs: ditto. + + * statement.cs: Use a bitfield; Do not initialize to null things + which are done by the constructor by default. + + * cs-parser.jay: bug fix, parameter was 4, not 3. + + * expression.cs: Just use the property; + + * statement.cs: No need for GetVariableInfo method. + +2003-08-08 Martin Baulig + + * flowanalysis.cs (FlowReturns): This is now nested in the + `FlowBranching' class. + (MyBitVector): Moved this here from statement.cs. + (FlowBranching.SiblingType): New enum type. + (FlowBranching.CreateSibling): Added `SiblingType' argument. + +2003-08-07 Martin Baulig + + * flowanalysis.cs (FlowBranchingType): This is now nested in the + `FlowBranching' class and called `BranchingType'. + +2003-08-07 Martin Baulig + + * flowanalysis.cs: Moved all the control flow analysis code into + its own file. + +2003-08-07 Martin Baulig + + * assign.cs (Assign.DoResolve): `target' must either be an + IAssignMethod or an EventAccess; report a CS0131 otherwise. Fixes + #37319. + +2003-08-07 Miguel de Icaza + + * expression.cs (BinaryMethod): This kind of expression is created by the + Binary class if it determines that the operator has to be handled + by a method. + + (BinaryDelegate): This kind of expression is created if we are + dealing with a + or - operator on delegates. + + (Binary): remove method, argumetns, and DelegateOperator: when + dealing with methods, + + * ecore.cs (EventExpr.EmitAddOrRemove): Update to new layout. + + * statement.cs (Block): use bitfields for the three extra booleans + we had in use. Remove unused topblock parameter. + + * codegen.cs: Remove unecessary argument to Block.EmitTopBlock + + * assign.cs: Drop extra unneeded tests. + +2003-08-06 Miguel de Icaza + + * iterators.cs (Mapvariable): provide a mechanism to use prefixes. + + * statement.cs (Foreach): Use VariableStorage instead of + LocalBuilders. + + * codegen.cs (VariableStorage): New class used by clients that + require a variable stored: locals or fields for variables that + need to live across yield. + + Maybe provide a convenience api for EmitThis+EmitLoad? + + (GetTemporaryLocal, FreeTemporaryLocal): Recycle + these bad boys. + +2003-08-05 Miguel de Icaza + + * codegen.cs (RemapLocal, RemapLocalLValue, RemapParameter, + RemapParameterLValue): New methods that are used to turn a + precomputed FieldInfo into an expression like this: + + instance.FieldInfo + + The idea is to use this instead of making LocalVariableReference + have more than one meaning. + + * cs-parser.jay: Add error production to BASE. + + * ecore.cs: Deal with TypeManager.GetField returning null, which + is now a valid return value. + + (FieldExprNoAddress): New expression for Fields whose address can + not be taken. + + * expression.cs (LocalVariableReference): During the resolve + phases, create new expressions if we are in a remapping context. + Remove code that dealt with remapping here. + + (ParameterReference): same. + + (ProxyInstance): New expression, like the `This' expression, but + it is born fully resolved. We know what we are doing, so remove + the errors that are targeted to user-provided uses of `this'. + + * statement.cs (Foreach): our variable is now stored as an + Expression; During resolution, follow the protocol, dont just + assume it will return this. + +2003-08-06 Martin Baulig + + * support.cs (SeekableStreamReader.cs): New public class. + + * cs-tokenizer.cs, cs-parser.jay, driver.cs: Use the new + SeekableStreamReader instead of the normal StreamReader. + +2003-08-04 Martin Baulig + + * cs-parser.jay (CLOSE_PARENS_CAST, CLOSE_PARENS_NO_CAST, + CLOSE_PARENS_OPEN_PARENS, CLOSE_PARENS_MINUS): New tokens to + deambiguate casts and delegate invocations. + (parenthesized_expression): Use the new tokens to ensure this is + not a cast of method invocation. + + * cs-tokenizer.cs (is_punct): Return one of the new special tokens + when reading a `)' and Deambiguate_CloseParens () was previously + called. + + * expression.cs (ParenthesizedExpression): New class. This is + just used for the CS0075 test. + (Binary.DoResolve): Check for CS0075. + +2003-07-29 Ravi Pratap + + * expression.cs (Invocation.MakeUnionSet): Patch from Lluis + Sanchez : use TypeManager.ArrayContainsMethod instead of a direct + reference comparison. + + (TypeManager.ArrayContainsMethod): When we have a MethodInfo, also + examine the ReturnType for equality - this is necessary in the + cases of implicit and explicit operators whose signature also + includes the return type. + +2003-07-26 Miguel de Icaza + + * namespace.cs: Cache the result of the namespace computation, + instead of computing it every time. + +2003-07-24 Miguel de Icaza + + * decl.cs: Use a global arraylist that we reuse over invocations + to avoid excesive memory consumption. Reduces memory usage on an + mcs compile by one meg (45 average). + + * typemanager.cs (LookupTypeReflection): In .NET pointers are + private, work around that. + +2003-07-23 Miguel de Icaza + + * literal.cs (IntLiteral): Define Zero and One static literals. + + * cs-parser.jay (integer_literal): use static literals to reduce + memory usage for the most used literals (0, 1 and -1). 211kb + reduced in memory usage. + + Replace all calls to `new ArrayList' with `new + ArrayList(4)' which is a good average number for most allocations, + and also requires only 16 bytes of memory for its buffer by + default. + + This reduced MCS memory usage in seven megabytes for the RSS after + bootstrapping. + +2003-07-28 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Fix the algorithm to + handle params methods the correct way by forming only one + applicable set with params and normal methods in them. Earlier we + were looking at params methods only if we found no normal methods + which was not the correct thing to do. + + (Invocation.BetterFunction): Take separate arguments indicating + when candidate and the best method are params methods in their + expanded form. + + This fixes bugs #43367 and #46199. + + * attribute.cs: Documentation updates. + + (CheckAttribute): Rename to CheckAttributeTarget. + (GetValidPlaces): Rename to GetValidTargets. + + * expression.cs (Invocation.IsParamsMethodApplicable): Fix trivial + bug - use Convert.ImplicitConversion, not ImplicitUserConversion! + + Fixes bug #44468. + +2003-07-28 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Use the base type's full + name when looking up the base class of a nested class. Fixes #46977. + +2003-07-26 Martin Baulig + + * expression.cs (Indexers.Indexer): New nested struct; contains + getter, setter and the indexer's type. + (Indexers.Properties): This is now an ArrayList of + Indexers.Indexer's. + (IndexerAccess.DoResolveLValue): Correctly set the type if the + indexer doesn't have any getters. + + * assign.cs (Assign.DoResolve): Also do the implicit conversions + for embedded property and indexer assignments. + +2003-07-26 Martin Baulig + + * cs-tokenizer.cs (Tokenizer.xtoken): Report a CS1040 if a + preprocessor directive is not the first non-whitespace character + on a line. + +2003-07-26 Martin Baulig + + * namespace.cs (NamespaceEntry.Lookup): New method; rewrote the + namespace parsing, follow the spec more closely. + + * rootcontext.cs (RootContext.NamespaceLookup): Use the new + NamespaceEntry.Lookup(). + +2003-07-25 Martin Baulig + + * MethodCore.cs (OverridesSomething): New public field; it's set + from TypeContainer.DefineMembers if this method overrides + something (which doesn't need to be a method). Fix #39462. + +2003-07-25 Ravi Pratap + + * typemanager.cs (GetMembers): Ensure that the list of members is + reversed. This keeps things in sync. + + * attribute.cs (Attribute.CheckAttribute): Break as soon as we + find an AttributeUsage attribute. + + * expression.cs (Invocation.OverloadResolve): Perform the check + which disallows Invoke to be directly called on a Delegate. + + (Error_InvokeOnDelegate): Report error cs1533. + +2003-07-25 Martin Baulig + + * expression.cs (Indexers.GetIndexersForType): Only look in the + interface hierarchy if the requested type is already an + interface. Fixes #46788 while keeping #46502 fixed. + +2003-07-25 Martin Baulig + + * class.cs (TypeContainer.DefineMembers): Check whether all + readonly fields have been assigned and report warning CS0649 if + not. + + * statement.cs (LocalInfo.IsFixed): Always return true if this is + a valuetype. + +2003-07-24 Ravi Pratap + + * decl.cs (MemberCache.AddMethods): Reverse the order of the array + returned from GetMethods to make things consistent with the + assumptions MCS makes about ordering of methods. + + This should comprehensively fix bug #45127 and it does :-) + + * ecore.cs (MethodGroupExpr.DeclaringType): Correct bug - the + ordering is actually reverse. + + * Clean up some debug messages I left lying around. + + * interface.cs (Populate*): Get rid of code which emits attributes + since the stage in which we emit attributes is the 'Emit' stage, + not the define stage. + + (Emit): Move attribute emission for interface members here. + +2003-07-22 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Follow the spec more + closely: we eliminate methods in base types when we have an + applicable method in a top-level type. + + Please see section 14.5.5.1 for an exact description of what goes + on. + + This fixes bug #45127 and a host of other related to corlib compilation. + + * ecore.cs (MethodGroupExpr.DeclaringType): The element in the + array is the method corresponding to the top-level type (this is + because of the changes made to icall.c) so we change this + accordingly. + + (MethodGroupExpr.Name): This too. + + * typemanager.cs (GetElementType): New method which does the right + thing when compiling corlib. + + * everywhere: Make use of the above in the relevant places. + +2003-07-22 Martin Baulig + + * cs-parser.jay (invocation_expression): Moved + `OPEN_PARENS expression CLOSE_PARENS unary_expression' here from + `cast_expression', but create a InvocationOrCast which later + resolves to either an Invocation or a Cast. + + * ecore.cs (ExpressionStatement.ResolveStatement): New virtual + method; call this before EmitStatement() to make sure that this + expression can be used as a statement. + + * expression.cs (InvocationOrCast): New class; resolves to either + an Invocation or a Cast. + + * statement.cs (StatementExpression): Call ResolveStatement() on + the ExpressionStatement before emitting it. + +2003-07-21 Martin Baulig + + * expression.cs (Invocation.VerifyArgumentsCompat): Check whether + `ref' and `out' attributes match; fixes #46220. + (MemberAccess.ResolveMemberAccess): You can't reference a type + through an expression; fixes #33180. + (Indexers.GetIndexersForType): Don't return the indexers from + interfaces the class implements; fixes #46502. + +2003-07-21 Martin Baulig + + * class.cs (TypeContainer.CheckPairedOperators): Added CS0660 and + CS0661 checks; fixes bug #30442. + +2003-07-21 Martin Baulig + + * decl.cs (AdditionResult): Added `Error'. + + * enum.cs (AddEnumMember): Report a CS0076 if name is `value__'. + + * typemanager.cs (TypeManager.ChangeType): Catch exceptions; + makes cs0031.cs actually work. + +2003-07-20 Martin Baulig + + * namespace.cs: Fixed that bug which caused a crash when compiling + the debugger's GUI. + +2003-07-20 Miguel de Icaza + + * typemanager.cs (LookupTypeReflection): Never expose types which + are NotPublic, NestedPrivate, NestedAssembly, or + NestedFamANDAssem. We used to return these, and later do a check + that would report a meaningful error, but the problem is that we + would not get the real match, if there was a name override. + +2003-07-18 Miguel de Icaza + + * namespace.cs (Namespace, Name): Do not compute the namespace + name dynamically, compute it in the constructor. This reduced + memory usage by 1697 KB. + + * driver.cs: Use --pause to pause at the end. + +2003-07-17 Peter Williams + + * Makefile: Change the name of the test target so that it doesn't + conflict with the recursive test target. + +2003-07-17 Miguel de Icaza + + * expression.cs (LocalVariableReference.Emit, EmitAssign, + AddressOf): Do not use EmitThis, that was wrong, use the actual + this pointer. + +2003-07-15 Miguel de Icaza + + * class.cs (MethodData.Define): While checking if a method is an + interface implementation, improve the test: If we are not public + (use new test here: use the computed MethodAttributes directly, + instead of the parsed modifier flags) check if the `implementing' + method comes from an interface or not. + + * pending.cs (VerifyPendingMethods): Slightly better error + message. + + * makefile: add test target that does the mcs bootstrap. + +2003-07-16 Ravi Pratap + + * interface.cs (Define): Do nothing here since there are no + members to populate etc. Move the attribute emission out of here + since this was just totally the wrong place to put it. Attribute + application happens during the 'Emit' phase, not in the 'Define' + phase. + + (Emit): Add this method and move the attribute emission here + + * rootcontext.cs (EmitCode): Call the Emit method on interface + types too. + +2003-07-14 Ravi Pratap M + + * expression.cs (OverloadResolve): Report error only if Location + is not 'Null' which means that there was a probe going on. + +2003-07-14 Martin Baulig + + * expression.cs (ConditionalLogicalOperator): New public class to + implement user defined conditional logical operators. + This is section 14.11.2 in the spec and bug #40505. + +2003-07-14 Martin Baulig + + * ecore.cs (FieldExpr.DoResolveLValue): Fixed bug #46198. + +2003-07-14 Martin Baulig + + * codegen.cs (EmitContext.InFixedInitializer): New public field. + + * ecore.cs (IVariable.VerifyFixed): New interface method. + + * expression.cs (Unary.ResolveOperator): When resolving the `&' + operator, check whether the variable is actually fixed. Fixes bug + #36055. Set a variable definitely assigned when taking its + address as required by the spec. + + * statement.cs (LocalInfo.IsFixed): New field. + (LocalInfo.MakePinned): Set `IsFixed' to true. + +2003-07-14 Ravi Pratap M + + * attribute.cs (Attribute.Resolve): While doing a Member lookup + for .ctors, ensure that we only ask for members declared in the + attribute type (BindingFlags.DeclaredOnly). + + Fixes bug #43632. + + * expression.cs (Error_WrongNumArguments): Report error 1501 + correctly the way CSC does. + +2003-07-13 Martin Baulig + + * expression.cs (MemberAccess.ResolveAsTypeStep): Try to do a type + lookup on the fully qualified name, to make things like "X.X" work + where "X.X" is a fully qualified type name, but we also have a + namespace "X" in the using list. Fixes #41975. + +2003-07-13 Martin Baulig + + * assign.cs (Assign.GetEmbeddedAssign): New protected virtual + function. If we're a CompoundAssign, we need to create an embedded + CompoundAssign, not an embedded Assign. + (Assign.DoResolve): Make this work for embedded CompoundAssign's. + Fixes #45854. + +2003-07-13 Martin Baulig + + * typemanager.cs (TypeManager.IsNestedChildOf): Make this actually + work to fix bug #46088. + +2003-07-13 Ravi Pratap + + * class.cs (Operator.Emit): Do not emit attributes here - it is + taken care of by the Method class that we delegate too. This takes + care of bug #45876. + +2003-07-10 Martin Baulig + + * expression.cs (TypeOfVoid): New class. + (TypeOf): Report a CS0673 if it's System.Void. Fixes #42264. + +2003-07-10 Martin Baulig + + * class.cs (MethodCore.DoDefineParameters): Added CS0225 check; + bug #35957. + +2003-07-10 Martin Baulig + + * rootcontext.cs (RootContext.NamespaceLookup): Take a DeclSpace, + not a NamespaceEntry, so we can use DeclSpace.CheckAccessLevel(). + + * decl.cs (DeclSpace.FindType): Use DeclSpace.CheckAccessLevel(). + + * typemanager.cs (TypeManager.IsAccessibleFrom): Removed. + +2003-07-10 Martin Baulig + + * expression.cs (ArrayCreation): Don't use a byte blob for arrays + of decimal. Fixes #42850. + + NOTE: I also fixed the created byte blob, but this doesn't work on + the MS runtime and csc never produces any byte blobs for decimal + arrays. + +2003-07-10 Martin Baulig + + * statement.cs (StructInfo.GetStructInfo): Catch deep cycles in + structs; fixes #32068. + (Block.AddChildVariableNames): Fixed #44302. + +2003-07-07 Gonzalo Paniagua Javier + + * namespace.cs: fixed compilation with csc. It's bugzilla #44302. + +2003-07-07 Miguel de Icaza + + * attribute.cs: And this test is onger needed. + +2003-07-08 Martin Baulig + + * rootcontext.cs (RootContext.NamespaceLookup): Ignore + inaccessible types. Fixes #36313. + + * decl.cs (DeclSpace.FindType): Ignore inaccessible types. + + * namespace.cs (NamespaceEntry): Create implicit entries for all + namespaces; ie. if we have `namespace N1.N2.N3 { ... }', we create + implicit entries for N1.N2 and N1. + +2003-07-08 Martin Baulig + + Rewrote the handling of namespaces to fix a lot of the issues + wrt. `using' aliases etc. + + * namespace.cs (Namespace): Splitted this class into a + per-assembly `Namespace' and a per-file `NamespaceEntry'. + + * typemanager.cs (TypeManager.IsNamespace): Removed. + (TypeManager.ComputeNamespaces): Only compute namespaces from + loaded assemblies here, not the namespaces from the assembly we're + currently compiling. + +2003-07-08 Martin Baulig + + * rootcontext.cs, class.cs: Fixed the CS1530 reporting. + +2003-07-07 Miguel de Icaza + + * typemanager.cs: Reverted patch from Gonzalo, my previous patch + already fixed it. + + I thought about the memory savings here, but LookupTypeReflection + is used under already very constrained scenarios. Compiling + corlib or mcs only exposes one hit, so it would not really reduce + any memory consumption. + +2003-07-07 Gonzalo Paniagua Javier + + * typemanager.cs: fixes bug #45889 by only adding public types from + other assemblies to the list of known types. + +2003-07-07 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Add call to CheckAccessLevel + on the type we resolved. + +2003-07-05 Martin Baulig + + * pending.cs (PendingImplementation.ParentImplements): Don't + create the proxy if the parent is abstract. + + * class.cs (TypeContainer.DefineIndexers): Process explicit + interface implementations first. Fixes #37714. + +2003-07-04 Miguel de Icaza + + * expression.cs (MemberAccess.ResolveMemberAccess): Events are + defined recursively; but since we modify the input parameters + (left is set to `this' temporarily), we reset this value if the + left_is_explicit is false, which gives the original semantics to + the code. + + * literal.cs (NullPointer): new class used to represent a null + literal in a pointer context. + + * convert.cs (Convert.ImplicitReferenceConversion): Is the target + type is a pointer, use a NullPointer object instead of a + NullLiteral. Closes 43687 + + (ExplicitConversion): Convert pointer values using + the conv opcode to the proper type. + + * ecore.cs (New): change ValueTypeVariable property into a method, + that returns whether the valuetype is suitable for being used. + + * expression.cs (Binary.DoNumericPromotions): Only return if we + the int constant was a valid uint, and we can return both left and + right as uints. If not, we continue processing, to trigger the + type conversion. This fixes 39018. + + * statement.cs (Block.EmitMeta): During constant resolution, set + the CurrentBlock property on the emitcontext, so that we resolve + constants propertly. + +2003-07-02 Martin Baulig + + * codegen.cs (EmitContext.NeedExplicitReturn): New public variable. + (EmitContext.EmitTopBlock): Emit an explicit return if it's set. + + * statement.cs (Try.Resolve): Set ec.NeedExplicitReturn rather + than emitting it here. + + * statement.cs: Fixed some more flow analysis bugs. + +2003-07-02 Martin Baulig + + * class.cs (MethodData.Define): When implementing interface + methods, set Final unless we're Virtual. + + * decl.cs (MemberCore.CheckMethodAgainstBase): Make the CS0506 + check work for interface methods. + +2003-07-01 Martin Baulig + + * ecore.cs (EmitContext.This): Replaced this property with a + GetThis() method which takes a Location argument. This ensures + that we get the correct error location for a CS0188. + +2003-07-01 Miguel de Icaza + + * ecore.cs: (Convert.ConvertIntLiteral): Add test for + ImplicitStandardConversion. + + * class.cs (TypeContainer.GetClassBases): Small bug fix for 45649. + +2003-07-01 Zoltan Varga + + * expression.cs (ResolveOperator): Fix Concat (string, string, string) + optimization. + +2003-06-30 Miguel de Icaza + + * class.cs (Constructor.Define): Turn off initlocals for unsafe + constructors. + + (MethodData.Define): Turn off initlocals for unsafe methods. + +2003-06-29 Miguel de Icaza + + * decl.cs (DeclSpace.CheckAccessLevel): Make this routine + complete; Fixes #37521. + + * delegate.cs: Use Modifiers.TypeAttr to compute the + TypeAttributes, instead of rolling our own. This makes the flags + correct for the delegates. + +2003-06-28 Miguel de Icaza + + * class.cs (Constructor.Define): Set the private flag for static + constructors as well. + + * cs-parser.jay (statement_expression): Set the return value to + null, to avoid a crash when we catch an error. + +2003-06-24 Miguel de Icaza + + * cs-parser.jay: Applied patch from Jackson that adds support for + extern and unsafe modifiers to destructor declarations. + + * expression.cs: Report error 21 if the user is trying to index a + System.Array. + + * driver.cs: Add an error message, suggested by the bug report. + + * class.cs (TypeContainer.Emit): Only call EmitFieldInitializers + if we do not have a ": this ()" constructor initializer. Fixes 45149 + +2003-06-14 Miguel de Icaza + + * namespace.cs: Add some information to reduce FAQs. + +2003-06-13 Miguel de Icaza + + * cfold.cs (BinaryFold): BitwiseAnd, BitwiseOr: handle other + underlying enumeration types. Fixes #43915. + + * expression.cs: Treat ushort/short as legal values to be used in + bitwise operations. + +Wed Jun 4 13:19:04 CEST 2003 Paolo Molaro + + * delegate.cs: transfer custom attributes for paramenters from + the delegate declaration to Invoke and BeginInvoke. + +Tue Jun 3 11:11:08 CEST 2003 Paolo Molaro + + * attribute.cs: handle custom marshalers and emit marshal info + for fields, too. + +2003-05-28 Hector E. Gomez Morales + + * makefile.gnu: Added anonymous.cs to the compiler sources. + +2003-05-28 Miguel de Icaza + + * iterators.cs: Change the name of the proxy class to include two + underscores. + + * cs-parser.jay: Update grammar to include anonymous methods. + + * anonymous.cs: new file. + +2003-05-27 Miguel de Icaza + + * class.cs (Field.Define): Add missing test for pointers and + safety. + +2003-05-27 Ravi Pratap + + * expression.cs (ArrayAccess.GetStoreOpCode): For System.IntPtr, + we use the stobj opcode. + + (ArrayCreation.EmitDynamicInitializers): Revert Miguel's patch + since it wasn't the correct fix. + + It still is puzzling that we are required to use stobj for IntPtr + which seems to be a ValueType. + +2003-05-26 Miguel de Icaza + + * ecore.cs (SimpleName.SimpleNameResolve): Consider using aliases + during regular simple name resolution. Now, the trick is that + instead of returning for processing the simplename, we do a + TypeManager.LookupType (ie, a rooted lookup as opposed to a + contextual lookup type). If a match is found, return that, if + not, return for further composition. + + This fixes long-standing 30485. + + * expression.cs (ArrayCreation.EmitDynamicInitializers): When + using the address to initialize an object, do an Stobj instead of + using the regular Stelem. + + (IndexerAccess.Emit, IndexerAccess.EmitAssign): + Pass `is_base_indexer' to Invocation.EmitCall instead of false. + Because if we are a BaseIndexerAccess that value will be true. + Fixes 43643. + + * statement.cs (GotoCase.Resolve): Return after reporting an + error, do not attempt to continue. + + * expression.cs (PointerArithmetic.Emit): If our operand is a + long, convert our constants to match the operand before + multiplying. Convert to I type before adding. Fixes 43670. + +2003-05-14 Ravi Pratap + + * enum.cs (ImplicitConversionExists) : Rename to + ImplicitEnumConversionExists to remove ambiguity. + + * ecore.cs (NullCast): New type of cast expression class which + basically is very similar to EmptyCast with the difference being + it still is a constant since it is used only to cast a null to + something else + (eg. (string) null) + + * convert.cs (ImplicitReferenceConversion): When casting a null + literal, we return a NullCast. + + * literal.cs (NullLiteralTyped): Remove - I don't see why this + should be around anymore. + + The renaming (reported was slightly wrong). Corrections: + + ConvertImplicitStandard -> ImplicitConversionStandard + ConvertExplicitStandard -> ExplicitConversionStandard + + * expression.cs (StaticCallExpr.MakeSimpleCall): Resolve arguments + before passing them in ! + + * convert.cs (ImplicitConversionStandard): When comparing for + equal expr and target types, ensure that expr is not a + NullLiteral. + + In general, we must not be checking (expr_type == + target_type) in the top level conversion methods + (ImplicitConversion, ExplicitConversion etc). This checking is + done in the methods that they delegate to. + +2003-05-20 Miguel de Icaza + + * convert.cs: Move Error_CannotConvertType, + ImplicitReferenceConversion, ImplicitReferenceConversionExists, + ImplicitNumericConversion, ImplicitConversionExists, + ImplicitUserConversionExists, StandardConversionExists, + FindMostEncompassedType, FindMostSpecificSource, + FindMostSpecificTarget, ImplicitUserConversion, + ExplicitUserConversion, GetConversionOperators, + UserDefinedConversion, ConvertImplicit, ConvertImplicitStandard, + TryImplicitIntConversion, Error_CannotConvertImplicit, + ConvertImplicitRequired, ConvertNumericExplicit, + ExplicitReferenceConversionExists, ConvertReferenceExplicit, + ConvertExplicit, ConvertExplicitStandard from the ecore.cs into + its own file. + + Perform the following renames: + + StandardConversionExists -> ImplicitStandardConversionExists + ConvertImplicit -> ImplicitConversion + ConvertImplicitStandard -> ImplicitStandardConversion + TryImplicitIntConversion -> ImplicitIntConversion + ConvertImplicitRequired -> ImplicitConversionRequired + ConvertNumericExplicit -> ExplicitNumericConversion + ConvertReferenceExplicit -> ExplicitReferenceConversion + ConvertExplicit -> ExplicitConversion + ConvertExplicitStandard -> ExplicitStandardConversion + +2003-05-19 Martin Baulig + + * statement.cs (TypeInfo.StructInfo): Made this type protected. + (TypeInfo): Added support for structs having structs as fields. + + * ecore.cs (FieldExpr): Implement IVariable. + (FieldExpr.DoResolve): Call VariableInfo.GetSubStruct() to get the + VariableInfo for the field. + +2003-05-18 Martin Baulig + + * expression.cs (This.DoResolve): Report a CS0027 if we're + emitting a field initializer. + +2003-05-18 Martin Baulig + + * expression.cs (This.ResolveBase): New public function. + (This.DoResolve): Check for CS0188. + + * codegen.cs (EmitContext.This): Just call This.ResolveBase(), not + This.Resolve(). + + * ecore.cs (MethodGroupExpr.DoResolve): Set the + `instance_expression' to null if we don't have any non-static + methods. + +2003-05-18 Martin Baulig + + Reworked the way how local variables and parameters are handled by + the flow analysis code. + + * statement.cs (TypeInfo, VariableMap): New public classes. + (VariableInfo): New public class. This is now responsible for + checking whether a variable has been assigned. It is used for + parameters and local variables. + (Block.EmitMeta): Take the InternalParameters as argument; compute + the layout of the flow vectors here. + (Block.LocalMap, Block.ParameterMap): New public properties. + (FlowBranching): The .ctor doesn't get the InternalParameters + anymore since Block.EmitMeta() now computes the layout of the flow + vector. + (MyStructInfo): This class is now known as `StructInfo' and nested + in `TypeInfo'; we don't access this directly anymore. + + * ecore.cs (IVariable): Added `VariableInfo VariableInfo' + property and removed IsAssigned(), IsFieldAssigned(), + SetAssigned() and SetFieldAssigned(); we now call them on the + VariableInfo so we don't need to duplicate this code everywhere. + + * expression.cs (ParameterReference): Added `Block block' argument + to the .ctor. + (LocalVariableReference, ParameterReference, This): The new + VariableInfo class is now responsible for all the definite + assignment stuff. + + * codegen.cs (EmitContext.IsVariableAssigned, SetVariableAssigned, + IsParameterAssigned, SetParameterAssigned): Removed. + +2003-05-18 Martin Baulig + + * typemanager.cs (InitCoreTypes): Try calling + SetCorlibTypeBuilders() with 4 args; if that fails, fall back to + the 3-args-version. Corlib now also needs our `void_type'. + (GetMethod): Added overloaded version which takes an optional + `bool report_errors' to allow lookups of optional methods. + +2003-05-12 Martin Baulig + + * statement.cs (VariableInfo): Renamed to LocalInfo since it's + only used for locals and not for parameters. + +2003-05-12 Miguel de Icaza + + * support.cs (InternalParameters.ParameterType): Return the + ExternalType of the parameter. + + * parameter.cs (Parameter.ExternalType): drop the two arguments, + they were unused. + +2003-05-11 Miguel de Icaza + + * class.cs (MethodData.Define): Do not set the `newslot' on + interface members, if they are also flagged as "override". + + * expression.cs (UnaryMutator.EmitCode): Simple workaround to emit + better code for ++i and i++. This only works for static fields + and local variables. + + * typemanager.cs (LookupDeclSpace): Add new method, sometimes we + want to pull the DeclSpace out of the builder_to_declspace instead + of the TypeBuilder (like in TypeContainer.FindMembers). + + * class.cs (TypeContainer.FindMembers): Use LookupDeclSpace + instead of LookupTypeContainer. Fixes the crash on .NET for + looking up interface members. + + * const.cs: Create our own emit context during the Definition + stage, so that constants are evaluated in the proper context, when + a recursive definition happens. + +2003-05-11 Martin Baulig + + * statement.cs (Block.CreateSwitchBlock): New method. Creates a + new block for a switch section. + (Block.AddLabel, Block.LookupLabel): If we're a switch section, do + the adding/lookup in the switch block. Fixes #39828. + +2003-05-09 Miguel de Icaza + + * expression.cs (UnaryMutator.LoadOneAndEmitOp): Missing + functionality: I needed to convert the data after I had performed + the add/sub operation into the operands type size. + + * ecore.cs (ImplicitReferenceConversion): When boxing an interface + pass the type for the box operation, otherwise the resulting + object would have been of type object. + + (BoxedCast): Add constructor to specify the type to box as. + +2003-05-07 Miguel de Icaza + + * iterators.cs: I was reusing the `count' variable inadvertently, + take steps to not allow this to happen. + +2003-05-06 Miguel de Icaza + + * attribute.cs (Attribute.Resolve): Params attributes are encoded + by creating an array at the point where the params starts and + putting all those arguments there, then adjusting the size of the + array. + +2003-05-05 Miguel de Icaza + + * expression.cs (New.AddressOf): Implement interface + IMemoryLocation. This is used when the `new' operator is used in + the context of an invocation to a method on a value type. + + See http://bugzilla.ximian.com/show_bug.cgi?id=#42390 for an + example. + + * namespace.cs: Also check the using aliases here. + + * driver.cs: Move the test for using validity after the types have + been entered, so we do a single pass that also includes the using + aliases. + + * statement.cs (Try.Resolve): Avoid crashing if there is a failure + in the regular case. CreateSiblingForFinally is doing extra + error checking. + + * attribute.cs (GetAttributeArgumentExpression): Store the result + on an out value, and use the return value to indicate failure + instead of using null (which is a valid return for Constant.GetValue). + + * statement.cs: Perform the analysis flow for the increment + portion after the statement, because this will be the real flow of + execution. Fixes #42385 + + * codegen.cs (EmitContext.EmitArgument, + EmitContext.EmitStoreArgument): New helper functions when the + RemapToProxy flag is set. + + * expression.cs (ParameterReference.EmitLdarg): Expose this useful + function. + + Add support for remapping parameters. + + * iterators.cs: Propagate parameter values; Store parameter + values in the proxy classes. + +2003-05-04 Miguel de Icaza + + * ecore.cs (FieldExpr): Fix an obvious bug. static fields do not + need a proxy reference; I do not know what I was thinking + + * cs-parser.jay (constructor_initializer): catch another error, + and display nice message. + + (field_declaration): catch void field declaration + to flag a better error. + + * class.cs (MemberBase.CheckBase): Report an error instead of a + warning if a new protected member is declared in a struct. + (Field.Define): catch the error of readonly/volatile. + + * ecore.cs (FieldExpr.EmitAssign): reuse the field lookup. + + (FieldExpr.AddressOf): ditto. Catch error where the address of a + volatile variable is taken + +2003-05-02 Miguel de Icaza + + * statement.cs (Fixed.Resolve): Report an error if we are not in + an unsafe context. + +2003-05-01 Miguel de Icaza + + * typemanager.cs: reuse the code that handles type clashes for + delegates and enumerations. + + * class.cs (Report28): Always report. + + * expression.cs (EncodeAsAttribute): Allow nulls here. + +2003-04-28 Miguel de Icaza + + * attribute.cs (Attribute.GetAttributeArgumentExpression): Moved + the functionality for testing whether an expression is valid for + an attribute here. Also handle the case of arrays of elements + being stored. + + * expression.cs (ArrayCreation.EncodeAsAttribute): Add support for + encoding a linear array into an array of objects that are suitable + to be passed to an CustomAttributeBuilder. + + * delegate.cs: Check unsafe types being used outside of an Unsafe context. + + * ecore.cs: (FieldExpr): Handle field remapping here. + + * iteratators.cs: Pass the instance variable (if the method is an + instance method) to the constructors, so we can access the field + variables on the class. + + TODO: Test this with structs. I think the THIS variable on + structs might have to be a pointer, and not a refenrece + +2003-04-27 Miguel de Icaza + + * codegen.cs (EmitContext.Mapvariable): Adds a mechanism to map + local variables to fields in a proxy class. + + * iterators.cs (PopulateProxy): Rename our internal fields to + . + Create a field if we are an instance method, so we can + reference our parent container variables. + (MapVariable): Called back from the EmitContext code to enter a + new variable to field mapping into the proxy class (we just create + a FieldBuilder). + + * expression.cs + (LocalVariableReference.{Emit,EmitAssign,AddressOf}): Add support + for using the remapped locals to fields. + + I placed the code here, because that gives the same semantics to + local variables, and only changes the Emit code. + + * statement.cs (Fixed.Resolve): it is not allowed to have fixed + statements inside iterators. + (VariableInfo): Add a FieldBuilder for the cases when we are + remapping local variables to fields in a proxy class + + * ecore.cs (SimpleNameResolve): Avoid testing two times for + current_block != null. + + * statement.cs (Swithc.SimpleSwitchEmit): Removed code that did + not cope with strings, as it has been moved to the + TableSwitchEmit. Fixed bug in switch generation. + + * expression.cs (New.DoResolve): Provide more context for the user + when reporting an error. + + * ecore.cs (Expression.LoadFromPtr): Use ldind_i when loading + pointers. + + * expression.cs (MemberAccess.DoResolve): When we get a type back, + check the permissions for it. Note than in a type-resolution + context the check was already present in DeclSpace.ResolveType, + but was missing from the MemberAccess. + + (ArrayCreation.CheckIndices): warn if the user has + more nested levels of expressions, but there are no more + dimensions specified. Avoids crash on bug 41906. + +2003-04-26 Miguel de Icaza + + * statement.cs (Block): replace Implicit bool, for a generic + flags. + New flag: `Unchecked'. This is used during the EmitMeta phase + (which is out-of-line with the regular Resolve/Emit process for a + statement, as this is done ahead of time, but still gets a chance + to call constant resolve). + + (Block.Flags): new enum for adding a new flag. + + (Block.EmitMeta): track the state of unchecked. + + (Unchecked): Set the "UnChecked" flags on any blocks we enclose, + to enable constant resolution to work there as well. + +2003-04-22 Miguel de Icaza + + * typemanager.cs (ienumerable_type): Also look up + System.Collections.IEnumerable. + +2003-04-21 Miguel de Icaza + + TODO: Test more than one conditional per method. + + * class.cs (Indexer.Define): Report the location where the user is + referencing the unsupported feature. + + (MethodData): Overload the use of `conditionals' to + minimize the creation of needless ArrayLists. This saves roughly + 212kb on my machine. + + (Method): Implement the new IIteratorContainer interface. + (Method.SetYields): Implement the method by setting the ModFlags + to contain METHOD_YIELDS. + + * expression.cs (Unary.ResolveOperator): Use expr_type, not Expr, + which just got set to null. + + * iterators.cs: New file. + + (Yield, YieldBreak): New statements. + + * statement.cs (Return.Resolve): Flag an error if we are used in + an iterator method. + + * codegen.cs (InIterator): New flag set if the code is being + compiled in an iterator method. + + * modifiers.cs: New flag METHOD_YIELDS. This modifier is an + internal modifier, and we just use it to avoid adding extra + fields, as this is seldom used. + + * cs-parser.jay: Add yield_statement (yield and yield break). + + * driver.cs: New flag -v2 to turn on version 2 features. + + * cs-tokenizer.cs (Tokenizer): Add yield and __yield to the + hashtable when v2 is enabled. + +2003-04-20 Miguel de Icaza + + * typemanager.cs (TypeManager.NamespaceClash): Use to check if + there is already a namespace defined with this name. + + (TypeManager.InitCoreTypes): Remove the temporary workaround, as + people upgraded their corlibs. + + (TypeManager.CoreLookupType): Use LookupTypeDirect, as we + always use fully qualified types, no need to use the compiler + front end. + + (TypeManager.IsNamespace): Use binarysearch. + + * class.cs (AddClass, AddStruct, AddInterface, AddEvent, + AddDelegate): I did not quite use the new IsValid API properly: I + have to pass the short-name and the fullname. I was passing only + the basename instead of the fullname sometimes. + + (TypeContainer.DefineType): call NamespaceClash. + + * interface.cs (Interface.DefineType): use NamespaceClash before + defining the type. + + * delegate.cs (Delegate.DefineType): use NamespaceClash before + defining the type. + + * enum.cs: (Enum.DefineType): use NamespaceClash before + defining the type. + + * typemanager.cs (: 3-line patch that gives us some tasty 11% + speed increase. First, use the negative_hits cache when we get a + negative. Second, add the type with its full original name + instead of the new . and + encoded name (reflection uses + to + separate type from a nested type). Use LookupTypeReflection + directly which bypasses the type->name hashtable (that we already + know does not contain the type. + + * decl.cs (DeclSpace.ResolveTypeExpr): track the + location/container type. + + * driver.cs: When passing utf8, use directly the UTF8Encoding. + +2003-04-19 Miguel de Icaza + + * decl.cs (ResolveTypeExpr): Mirror check acess here too. + + * delegate.cs (NewDelegate.Resolve): Test whether an instance + method is being referenced in the method group from a static + context, and report error 120 if so. + + * expression.cs, ecore.cs (Error_UnexpectedKind): New name for + Error118. + + * typemanager.cs: Add intermediate namespaces (if a namespace A.B + is created, we create the A namespace). + + * cs-parser.jay: A namespace also introduces a DeclarationFound. + Fixes #41591 + +2003-04-18 Miguel de Icaza + + * typemanager.cs (GetReferenceType, GetPointerType): In .NET each + invocation to ModuleBuilder.GetType with the same values will + return a new type instance, so we need to cache its return + values. + + * expression.cs (Binary.ResolveOperator): Only allow the compare + operators on enums if they are of the same type. + + * ecore.cs (Expression.ImplicitReferenceConversion): handle target + types of ValueType on their own case. Before we were giving them + the same treatment as objects. + + * decl.cs (DeclSpace.IsValid): IsValid takes the short name and + fullname. Short name is used to compare against container name. + Fullname is used to check against defined namespace names. + + * class.cs (AddProperty, AddField, AddClass, AddStruct, AddEnum, + AddDelegate, AddEvent): Pass new parameter to DeclSpace.IsValid + + (Method.CheckBase): Call parent. + (MemberBase.CheckBase): Check for protected members on sealed + classes. + (PropertyBase.CheckBase): Call parent. + (Field.Define): Call parent. + + * report.cs: Negative error codes are now mapped to 8000 - code, + so that the display is render more nicely. + + * typemanager.cs: Do not use try/catch, instead report a regular + error. + + (GetPointerType, GetReferenceType): These methods provide + mechanisms to obtain the T* and T& from a T. We had the code + previously scattered around the code base, and it also used + TypeManager.LookupType that would go through plenty of caches. + This one goes directly to the type source. + + In some places we did the Type.GetType followed by + ModuleBuilder.GetType, but not in others, so this unifies the + processing as well. + + * namespace.cs (VerifyUsing): Perform a non-lazy approach to using + statements now that we have namespace information. + + * typemanager.cs (IsNamespace): New method, returns whether the + string presented is a namespace or not. + + (ComputeNamespaces): New public entry point, computes the list of + available namespaces, using the GetNamespaces API call in Mono, or + the slower version in MS.NET. + + Now before we start the semantic analysis phase, we have a + complete list of namespaces including everything that the user has + provided. + + Deleted old code to cache namespaces in .nsc files. + +2003-04-17 Miguel de Icaza + + * class.cs: (TypeContainer.DefineDefaultConstructor): Use the + class/struct location definition Location for the implicit + constructor location. + + (Operator.Define): Use the location of the operator for the + implicit Method definition. + + (Constructor.Emit): use the constructor location for the implicit + base initializer constructor. + + * ecore.cs: Remove ITypeExpression. This interface is now gone, + and the Expression class now contains two new methods: + + ResolveAsTypeStep and ResolveAsTypeTerminal. This is used to + isolate type lookup from the rest of the resolution process. + + Since we use Expressions to hold type definitions due to the way + we parse the input we have historically overloaded Resolve to + perform the Type lookups if a special flag is passed. Now this is + eliminated and two methods take their place. + + The differences in the two methods between xStep and xTerminal is + that xStep is involved in our current lookup system that uses + SimpleNames to compose a name, while xTerminal is used just to + catch the case where the simplename lookup failed. + +2003-04-16 Miguel de Icaza + + * expression.cs (ResolveMemberAccess): Remove redundant code. + TypeExpr expressions are always born fully resolved. + + * interface.cs (PopulateMethod): Do not lookup the types twice. + We were doing it once during SemanticAnalysis and once during + PopulateMethod. + + * cs-parser.jay: Due to our hack in the grammar, things like A.B[] + in local variable type definitions, were being returned as a + SimpleName (we decomposed everything into a string), that is + because primary_expression was being used instead of a type in the + grammar (reduce/reduce conflicts). + + The part that was wrong is that we converted the expression into a + string (an oversimplification in one hand, compounded with primary + expressions doing string concatenation). + + So things like: + + A.B.C [] x; + + Would return "A.B.C[]" as a SimpleName. This stopped things like + using clauses from working on this particular context. And a type + was being matched directly against "A.B.C[]". + + We now use the correct approach, and allow for ComposedCast to be + part of the unary expression. So the "A.B.C []" become a composed + cast of "A.B.C" (as a nested group of MemberAccess with a + SimpleName at the end) plus the rank composition "[]". + + Also fixes 35567 + +2003-04-10 Miguel de Icaza + + * decl.cs (CheckAccessLevel): Implement the NestedPrivate rules + for the access level checking. + + * class.cs: Cosmetic changes. Renamed `TypeContainer parent' to + `TypeContainer container', because I kept getting confused when I + was debugging this code. + + * expression.cs (Indexers): Instead of tracking getters/setters, + we now track them in parallel. We create one arraylist less, but + most importantly it is possible now for the LValue code to find a + matching get for a set. + + (IndexerAccess.DoResolveLValue): Update the code. + GetIndexersForType has been modified already to extract all the + indexers from a type. The code assumed it did not. + + Also make the code set the correct return type for the indexer. + This was fixed a long time ago for properties, but was missing for + indexers. It used to be void_type. + + (Binary.Emit): Test first for doubles instead of + floats, as they are more common. + + (Binary.EmitBranchable): Use the .un version of the branch opcodes + when dealing with floats and the <=, >= operators. This fixes bug + #39314 + + * statement.cs (Foreach.EmitArrayForeach): bug fix: The code used + to load the array value by emitting a load on the foreach variable + type. This was incorrect. + + We now emit the code to load an element using the the array + variable type, and then we emit the conversion operator. + + Fixed #40176 + +2003-04-10 Zoltan Varga + + * attribute.cs: Avoid allocation of ArrayLists in the common case. + +2003-04-09 Miguel de Icaza + + * class.cs (MethodSignature.InheritableMemberSignatureCompare): + test for protection before we test for signatures. + + (MethodSignature.ToString): implement. + + * expression.cs (Unary.TryReduceNegative): Add missing minus sign + to the case where we reduced into a LongConstant. + + * decl.cs (CheckAccessLevel): If the type is an array, we can not + depend on whether the information is acurrate, because the + Microsoft runtime will always claim that the array type is public, + regardless of the real state. + + If the type is a pointer, another problem happens: the type is + reported as non-public in Microsoft. + + In both cases we have to call CheckAccessLevel recursively with + the underlying type as the argument to be tested. + +2003-04-08 Miguel de Icaza + + * assign.cs (Assign.Emit): If we are dealing with a compound + assignment expression, we should use the code path that stores the + intermediate result in a temporary value. This fixes #40903. + + *expression.cs (Indirection.ToString): Provide ToString method for + debugging. + +2003-04-08 Zoltan Varga + + * class.cs: Null out fields holding references to Block objects so + they can be garbage collected. + + * expression.cs (OverloadResolve): Remove unused local. + +2003-04-07 Martin Baulig + + * codegen.cs (EmitContext.CurrentFile): New public field. + (EmitContext.Mark): Use the CurrentFile to check whether the + location is in the correct file. + (EmitContext.EmitTopBlock): Initialize CurrentFile here. + +2003-04-07 Martin Baulig + + * ecore.cs (Expression.ResolveBoolean): Don't call ec.Mark(). + + * codegen.cs (EmitContext.EmitTopBlock): Don't call Mark() on the + location. [FIXME: The location argument which gets passed to this + method is sometimes wrong!] + +2003-04-07 Nick Drochak + + * codegen.cs: Be more verbose when we can't find the symbol writer dll. + +2003-04-07 Miguel de Icaza + + * expression.cs (Indirection.EmitAssign): We were using the + temporary, but returning immediately instead of continuing the + EmitAssing flow. + +2003-04-06 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Don't report an error + if it's a nested child, but also deriving from the outer class. + See test 190.cs. + + * typemanager.cs (IsNestedChildOf): Make this work if it's a + nested child, but also deriving from the outer class. See + test-190.cs. + (FilterWithClosure): We may access private members of the outer + class if we're a nested child and deriving from the outer class. + (RealMemberLookup): Only set `closure_private_ok' if the + `original_bf' contained BindingFlags.NonPublic. + +2003-04-05 Martin Baulig + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #40670. + +2003-04-02 Miguel de Icaza + + * class.cs (Event.Define): Do not allow abstract events to have + initializers. + +2003-04-01 Miguel de Icaza + + * cs-parser.jay: Add error productions for ADD/REMOVE missing a + block in event declarations. + + * ecore.cs (FieldExpr.AddressOf): If our instance expression is a + value type, get its address. + + * expression.cs (Is.Emit): For action `LeaveOnStack' we were + leaving a class on the stack instead of a boolean value (int + 0/1). Change the code so we compare against null, and then the + result against zero. + + * class.cs (TypeContainer.GetClassBases): We were checking for the + parent class being sealed too late. + + * expression.cs (Binary.Emit): For <= and >= when dealing with + floating point values, use cgt.un and clt.un instead of cgt and + clt alone. + +2003-04-01 Zoltan Varga + + * statement.cs: Apply the same optimization as MS: skip the + GetEnumerator returning an IEnumerator, and use the one returning a + CharEnumerator instead. This allows us to avoid the try-finally block + and the boxing. + +2003-03-31 Gaurav Vaish + + * cs-parser.jay: Attributes cannot be applied to + namespaces. Fixes #40473 + +2003-03-31 Gonzalo Paniagua Javier + + * class.cs: + (Add*): check if the name is valid using the full name for constants, + fields, properties and events. + +2003-03-28 Miguel de Icaza + + * enum.cs (Enum.DefineType, Enum.IsValidEnumConstant): Also allow + char constants to be part of the enumeration. + + * expression.cs (Conditional.DoResolve): Add support for operator + true. Implements the missing functionality from 14.12 + + * class.cs (TypeContainer.CheckPairedOperators): Report error for missmatch on + operator true/false as required by the spec. + + * expression.cs (Unary.ResolveOperator): In LogicalNot, do an + implicit conversion to boolean. + + * statement.cs (Statement.ResolveBoolean): A boolean expression is + also one where the type implements `operator true'. + + * ecore.cs (Expression.GetOperatorTrue): New helper routine to + get an expression that will invoke operator true based on an + expression. + + (GetConversionOperators): Removed the hack that called op_True + here. + + (Expression.ResolveBoolean): Move this from Statement. + +2003-03-17 Miguel de Icaza + + * ecore.cs (FieldExpr): do not allow initialization of initonly + fields on derived classes + +2003-03-13 Martin Baulig + + * statement.cs (Block.Emit): Call ig.BeginScope() and + ig.EndScope() when compiling with debugging info; call + LocalBuilder.SetLocalSymInfo _after_ opening the scope. + +2003-03-08 Miguel de Icaza + + * expression.cs (Indexers): Do not construct immediately, allow + for new members to be appended as we go. Fixes 38143 + +2003-03-07 Gonzalo Paniagua Javier + + * expression.cs: save/restore context when resolving an unchecked + expression. + +2003-03-05 Miguel de Icaza + + * cfold.cs: Catch division by zero in modulus operator during + constant folding. + +2003-03-03 Miguel de Icaza + + * interface.cs (Interface.DefineMembers): Avoid defining members + twice. + +2003-02-27 Miguel de Icaza + + * driver.cs: handle the +/- options for -noconfig + + * statement.cs (Unckeched.Resolve): Also track the state of + unchecked in the Resolve phase. + +2003-02-27 Martin Baulig + + * ecore.cs (Expression.MemberLookup): Don't create a + MethodGroupExpr for something which is not a method. Fixes #38291. + +2003-02-25 Miguel de Icaza + + * class.cs (MemberBase.CheckParameters): Also check that the type + is unmanaged if it is a pointer. + + * expression.cs (SizeOf.Resolve): Add location information. + + * statement.cs (Block.EmitMeta): Flag error (208) if a pointer to + a managed type is declared. + + * expression.cs (Invocation.VerifyArgumentsCompat): Check for the + parameter modifiers as well. Fixes bug 38606 + + * class.cs: Very sad. Am backing out the speed up changes + introduced by the ArrayList -> Array in the TypeContainer, as they + were not actually that much faster, and introduced a bug (no error + reports on duplicated methods). + + * assign.cs (CompoundAssign.DoLResolve): Resolve the original + source first, this will guarantee that we have a valid expression + before calling in lower levels functions that will require a + resolved object. Then use this original_source in the + target.ResolveLValue instead of the original source that was + passed to us. + + Another change. Use target.Resolve instead of LValueResolve. + Although we are resolving for LValues, we will let the Assign code + take care of that (it will be called again from Resolve). This + basically allows code like this: + + class X { X operator + (X x, object o) {} X this [int idx] { get; set; } } + class Y { void A (X x) { x [0] += o; } + + The problem was that the indexer was trying to resolve for + set_Item (idx, object o) and never finding one. The real set_Item + was set_Item (idx, X). By delaying the process we get the right + semantics. + + Fixes bug 36505 + +2003-02-23 Martin Baulig + + * statement.cs (Block.Emit): Override this and set ec.CurrentBlock + while calling DoEmit (). + + * codegen.cs (EmitContext.Mark): Don't mark locations in other + source files; if you use the #line directive inside a method, the + compiler stops emitting line numbers for the debugger until it + reaches the end of the method or another #line directive which + restores the original file. + +2003-02-23 Martin Baulig + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Fix bug #37708. + +2003-02-23 Martin Baulig + + * statement.cs (Block.AddChildVariableNames): We need to call this + recursively, not just for our immediate children. + +2003-02-23 Martin Baulig + + * class.cs (Event.Define): Always make the field private, like csc does. + + * typemanager.cs (TypeManager.RealMemberLookup): Make events + actually work, fixes bug #37521. + +2003-02-23 Miguel de Icaza + + * delegate.cs: When creating the various temporary "Parameters" + classes, make sure that we call the ComputeAndDefineParameterTypes + on those new parameters (just like we do with the formal ones), to + allow them to be resolved in the context of the DeclSpace. + + This fixes the bug that Dick observed in Bugzilla #38530. + +2003-02-22 Miguel de Icaza + + * expression.cs (ResolveMemberAccess): When resolving a constant, + do not attempt to pull a constant if the value was not able to + generate a valid constant. + + * const.cs (LookupConstantValue): Do not report more errors than required. + +2003-02-19 Gonzalo Paniagua Javier + + * expression.cs: fixes bug #38328. + +2003-02-18 Miguel de Icaza + + * class.cs: Changed all the various members that can be part of a + class from being an ArrayList to be an Array of the right type. + During the DefineType type_list, interface_list, delegate_list and + enum_list are turned into types, interfaces, delegates and enums + arrays. + + And during the member population, indexer_list, event_list, + constant_list, field_list, instance_constructor_list, method_list, + operator_list and property_list are turned into their real arrays. + + Although we could probably perform this operation earlier, for + good error reporting we need to keep the lists and remove the + lists for longer than required. + + This optimization was triggered by Paolo profiling the compiler + speed on the output of `gen-sample-program.pl' perl script. + + * decl.cs (DeclSpace.ResolveType): Set the ContainerType, so we do + not crash in methods like MemberLookupFailed that use this field. + + This problem arises when the compiler fails to resolve a type + during interface type definition for example. + +2003-02-18 Miguel de Icaza + + * expression.cs (Indexers.GetIndexersForType): Interfaces do not + inherit from System.Object, so we have to stop at null, not only + when reaching System.Object. + +2003-02-17 Miguel de Icaza + + * expression.cs: (Indexers.GetIndexersForType): Martin's fix used + DeclaredOnly because the parent indexer might have had a different + name, but did not loop until the top of the hierarchy was reached. + + The problem this one fixes is 35492: when a class implemented an + indexer from an interface, we were getting the interface method + (which was abstract) and we were flagging an error (can not invoke + abstract method). + + This also keeps bug 33089 functioning, and test-148 functioning. + + * typemanager.cs (IsSpecialMethod): The correct way of figuring + out if a method is special is to see if it is declared in a + property or event, or whether it is one of the predefined operator + names. This should fix correctly #36804. + +2003-02-15 Miguel de Icaza + + The goal here is to remove the dependency on EmptyCast.Peel (). + Killing it completely. + + The problem is that currently in a number of places where + constants are expected, we have to "probe" for an EmptyCast, and + Peel, which is not the correct thing to do, as this will be + repetitive and will likely lead to errors. + + The idea is to remove any EmptyCasts that are used in casts that + can be reduced to constants, so we only have to cope with + constants. + + This bug hunt was triggered by Bug 37363 and the desire to remove + the duplicate pattern where we were "peeling" emptycasts to check + whether they were constants. Now constants will always be + constants. + + * ecore.cs: Use an enumconstant here instead of wrapping with + EmptyCast. + + * expression.cs (Cast.TryReduce): Ah, the tricky EnumConstant was + throwing me off. By handling this we can get rid of a few hacks. + + * statement.cs (Switch): Removed Peel() code. + +2003-02-14 Miguel de Icaza + + * class.cs: Location information for error 508 + + * expression.cs (New.DoResolve): Add a guard against double + resolution of an expression. + + The New DoResolve might be called twice when initializing field + expressions (see EmitFieldInitializers, the call to + GetInitializerExpression will perform a resolve on the expression, + and later the assign will trigger another resolution + + This leads to bugs (#37014) + + * delegate.cs: The signature for EndInvoke should contain any ref + or out parameters as well. We were not doing this in the past. + + * class.cs (Field.Define): Do not overwrite the type definition + inside the `volatile' group. Turns out that volatile enumerations + were changing the type here to perform a validity test, which + broke conversions. + +2003-02-12 Miguel de Icaza + + * ecore.cs (FieldExpr.AddressOf): In the particular case of This + and structs, we do not want to load the instance variable + + (ImplicitReferenceConversion, ImplicitReferenceConversionExists): + enum_type has to be handled like an object reference (implicit + conversions exists from this to object), but the regular IsClass + and IsValueType tests will never return true for this one. + + Also we use TypeManager.IsValueType instead of type.IsValueType, + just for consistency with the rest of the code (this is only + needed if we ever use the construct exposed by test-180.cs inside + corlib, which we dont today). + +2003-02-12 Zoltan Varga + + * attribute.cs (ApplyAttributes): apply all MethodImplAttributes, not + just InternalCall. + +2003-02-09 Martin Baulig + + * namespace.cs (Namespace..ctor): Added SourceFile argument. + (Namespace.DefineNamespaces): New static public method; this is + called when we're compiling with debugging to add all namespaces + to the symbol file. + + * tree.cs (Tree.RecordNamespace): Added SourceFile argument and + pass it to the Namespace's .ctor. + + * symbolwriter.cs (SymbolWriter.OpenMethod): Added TypeContainer + and MethodBase arguments; pass the namespace ID to the symwriter; + pass the MethodBase instead of the token to the symwriter. + (SymbolWriter.DefineNamespace): New method to add a namespace to + the symbol file. + +2003-02-09 Martin Baulig + + * symbolwriter.cs: New file. This is a wrapper around + ISymbolWriter with a cleaner API. We'll dynamically Invoke() + methods here in near future. + +2003-02-09 Martin Baulig + + * codegen.cs (EmitContext.Mark): Just pass the arguments to + ILGenerator.MarkSequencePoint() which are actually used by the + symbol writer. + +2003-02-09 Martin Baulig + + * location.cs (SourceFile): New public sealed class. This + contains the name and an index which is used in the location's token. + (Location): Reserve an appropriate number of bits in the token for + the source file instead of walking over that list, this gives us a + really huge performance improvement when compiling with debugging. + + * driver.cs (Driver.parse, Driver.tokenize_file): Take a + `SourceFile' argument instead of a string. + (Driver.ProcessFile): Add all the files via Location.AddFile(), + but don't parse/tokenize here, we need to generate the list of all + source files before we do that. + (Driver.ProcessFiles): New static function. Parses/tokenizes all + the files. + + * cs-parser.jay (CSharpParser): Take a `SourceFile' argument + instead of a string. + + * cs-tokenizer.cs (Tokenizer): Take `SourceFile' argument instead + of a string. + +2003-02-09 Martin Baulig + + * cs-tokenizer.cs (Tokenizer.PreProcessLine): Also reset the + filename on `#line default'. + +Sat Feb 8 17:03:16 CET 2003 Paolo Molaro + + * statement.cs: don't clear the pinned var when the fixed statement + returns from the method (fixes bug#37752). + +Sat Feb 8 12:58:06 CET 2003 Paolo Molaro + + * typemanager.cs: fix from mathpup@mylinuxisp.com (Marcus Urban) + to IsValueType. + +2003-02-07 Martin Baulig + + * driver.cs: Removed the `--debug-args' command line argument. + + * codegen.cs (CodeGen.SaveSymbols): Removed, this is now done + automatically by the AsssemblyBuilder. + (CodeGen.InitializeSymbolWriter): We don't need to call any + initialization function on the symbol writer anymore. This method + doesn't take any arguments. + +2003-02-03 Miguel de Icaza + + * driver.cs: (AddAssemblyAndDeps, LoadAssembly): Enter the types + from referenced assemblies as well. + +2003-02-02 Martin Baulig + + * class.cs (MethodData.Emit): Generate debugging info for external methods. + +2003-02-02 Martin Baulig + + * class.cs (Constructor.Emit): Open the symbol writer before + emitting the constructor initializer. + (ConstructorInitializer.Emit): Call ec.Mark() to allow + single-stepping through constructor initializers. + +2003-01-30 Miguel de Icaza + + * class.cs: Handle error 549: do not allow virtual methods in + sealed classes. + +2003-02-01 Jackson Harper + + * decl.cs: Check access levels when resolving types + +2003-01-31 Jackson Harper + + * statement.cs: Add parameters and locals set in catch blocks that might + return to set vector + +2003-01-29 Miguel de Icaza + + * class.cs (Operator): Set the SpecialName flags for operators. + + * expression.cs (Invocation.DoResolve): Only block calls to + accessors and operators on SpecialName methods. + + (Cast.TryReduce): Handle conversions from char constants. + + +Tue Jan 28 17:30:57 CET 2003 Paolo Molaro + + * statement.cs: small memory and time optimization in FlowBranching. + +2003-01-28 Pedro Mart + + * expression.cs (IndexerAccess.DoResolveLValue): Resolve the same + problem that the last fix but in the other sid (Set). + + * expression.cs (IndexerAccess.DoResolve): Fix a problem with a null + access when there is no indexer in the hierarchy. + +2003-01-27 Jackson Harper + + * class.cs: Combine some if statements. + +2003-01-27 Gonzalo Paniagua Javier + + * driver.cs: fixed bug #37187. + +2003-01-27 Pedro Martinez Juliá + + * expression.cs (IndexerAccess.DoResolve): Before trying to resolve + any indexer, it's needed to build a list with all the indexers in the + hierarchy (AllGetters), else we have problems. Fixes #35653. + +2003-01-23 Miguel de Icaza + + * class.cs (MethodData.Define): It is wrong for an interface + implementation to be static in both cases: explicit and implicit. + We were only handling this in one case. + + Improve the if situation there to not have negations. + + * class.cs (Field.Define): Turns out that we do not need to check + the unsafe bit on field definition, only on usage. Remove the test. + +2003-01-22 Gonzalo Paniagua Javier + + * driver.cs: use assembly.Location instead of Codebase (the latest + patch made mcs fail when using MS assemblies). + +2003-01-21 Tim Haynes + + * driver.cs: use DirectorySeparatorChar instead of a hardcoded "/" to + get the path to *corlib.dll. + +2003-01-21 Nick Drochak + + * cs-tokenizer.cs: + * pending.cs: + * typemanager.cs: Remove compiler warnings + +2003-01-20 Duncan Mak + + * AssemblyInfo.cs: Bump the version number to 0.19. + +2003-01-20 Gonzalo Paniagua Javier + + * cs-tokenizer.cs: little fixes to line numbering when #line is used. + +2003-01-18 Zoltan Varga + + * class.cs (Constructor::Emit): Emit debugging info for constructors. + +2003-01-17 Miguel de Icaza + + * cs-parser.jay: Small fix: we were not comparing the constructor + name correctly. Thanks to Zoltan for the initial pointer. + +2003-01-16 Jackson Harper + + * cs-tokenizer.cs: Set file name when specified with #line + +2003-01-15 Miguel de Icaza + + * cs-parser.jay: Only perform the constructor checks here if we + are named like the class; This will help provider a better + error. The constructor path is taken when a type definition is + not found, but most likely the user forgot to add the type, so + report that rather than the constructor error. + +Tue Jan 14 10:36:49 CET 2003 Paolo Molaro + + * class.cs, rootcontext.cs: small changes to avoid unnecessary memory + allocations. + +2003-01-13 Jackson Harper + + * cs-parser.jay: Add cleanup call. + +2003-01-13 Duncan Mak + + * cs-tokenizer.cs (Cleanup): Rename to 'cleanup' to make it more + consistent with other methods. + +2003-01-13 Jackson Harper + + * cs-tokenizer.cs: Add Cleanup method, also fix #region error messages. + +Sun Jan 12 19:58:42 CET 2003 Paolo Molaro + + * attribute.cs: only set GuidAttr to true when we have a + GuidAttribute. + +2003-01-09 Gonzalo Paniagua Javier + + * ecore.cs: + * expression.cs: + * typemanager.cs: fixes to allow mcs compile corlib with the new + Type.IsSubclassOf fix. + +2003-01-08 Miguel de Icaza + + * expression.cs (LocalVariableReference.DoResolve): Classify a + constant as a value, not as a variable. Also, set the type for + the variable. + + * cs-parser.jay (fixed_statement): take a type instead of a + pointer_type, so we can produce a better error message later. + + * statement.cs (Fixed.Resolve): Flag types that are not pointers + as an error. + + (For.DoEmit): Make inifinite loops have a + non-conditional branch back. + + (Fixed.DoEmit): First populate the pinned variables, then emit the + statement, then clear the variables. Before I was emitting the + code once for each fixed piece. + + +2003-01-08 Martin Baulig + + * statement.cs (FlowBranching.MergeChild): A break in a + SWITCH_SECTION does not leave a loop. Fixes #36155. + +2003-01-08 Martin Baulig + + * statement.cs (FlowBranching.CheckOutParameters): `struct_params' + lives in the same number space than `param_map'. Fixes #36154. + +2003-01-07 Miguel de Icaza + + * cs-parser.jay (constructor_declaration): Set the + Constructor.ModFlags before probing for it. This makes the + compiler report 514, 515 and 132 (the code was there, but got + broken). + + * statement.cs (Goto.Resolve): Set `Returns' to ALWAYS. + (GotoDefault.Resolve): Set `Returns' to ALWAYS. + (GotoCase.Resolve): Set `Returns' to ALWAYS. + +Tue Jan 7 18:32:24 CET 2003 Paolo Molaro + + * enum.cs: create the enum static fields using the enum type. + +Tue Jan 7 18:23:44 CET 2003 Paolo Molaro + + * class.cs: don't try to create the ParamBuilder for the return + type if it's not needed (and handle it breaking for the ms runtime + anyway). + +2003-01-06 Jackson Harper + + * cs-tokenizer.cs: Add REGION flag to #region directives, and add checks to make sure that regions are being poped correctly + +2002-12-29 Miguel de Icaza + + * cs-tokenizer.cs (get_cmd_arg): Fixups to allow \r to terminate + the command. This showed up while compiling the JANET source + code, which used \r as its only newline separator. + +2002-12-28 Miguel de Icaza + + * class.cs (Method.Define): If we are an operator (because it + reuses our code), then set the SpecialName and HideBySig. #36128 + +2002-12-22 Miguel de Icaza + + * ecore.cs (FieldExpr.DoResolve): Instead of throwing an + exception, report error 120 `object reference required'. + + * driver.cs: Add --pause option, used during to measure the size + of the process as it goes with --timestamp. + + * expression.cs (Invocation.DoResolve): Do not allow methods with + SpecialName to be invoked. + +2002-12-21 Miguel de Icaza + + * cs-tokenizer.cs: Small fix to the parser: compute the ascii + number before adding it. + +2002-12-21 Ravi Pratap + + * ecore.cs (StandardImplicitConversion): When in an unsafe + context, we allow conversion between void * to any other pointer + type. This fixes bug #35973. + +2002-12-20 Jackson Harper + + * codegen.cs: Use Path.GetFileNameWithoutExtension so an exception + is not thrown when extensionless outputs are used + +2002-12-20 Gonzalo Paniagua Javier + + * rootcontext.cs: fixed compilation of corlib. + +2002-12-19 Miguel de Icaza + + * attribute.cs (Attributes.Contains): Add new method. + + * class.cs (MethodCore.LabelParameters): if the parameter is an + `out' parameter, check that no attribute `[In]' has been passed. + + * enum.cs: Handle the `value__' name in an enumeration. + +2002-12-14 Jaroslaw Kowalski + + * decl.cs: Added special case to allow overrides on "protected + internal" methods + +2002-12-18 Ravi Pratap + + * attribute.cs (Attributes.AddAttributeSection): Rename to this + since it makes much more sense. + + (Attributes.ctor): Don't require a Location parameter. + + * rootcontext.cs (AddGlobalAttributeSection): Rename again. + + * attribute.cs (ApplyAttributes): Remove extra Location parameters + since we already have that information per attribute. + + * everywhere : make appropriate changes. + + * class.cs (LabelParameters): Write the code which actually + applies attributes to the return type. We can't do this on the MS + .NET runtime so we flag a warning in the case an exception is + thrown. + +2002-12-18 Miguel de Icaza + + * const.cs: Handle implicit null conversions here too. + +2002-12-17 Ravi Pratap + + * class.cs (MethodCore.LabelParameters): Remove the extra + Type [] parameter since it is completely unnecessary. Instead + pass in the method's attributes so that we can extract + the "return" attribute. + +2002-12-17 Miguel de Icaza + + * cs-parser.jay (parse): Use Report.Error to flag errors instead + of ignoring it and letting the compile continue. + + * typemanager.cs (ChangeType): use an extra argument to return an + error condition instead of throwing an exception. + +2002-12-15 Miguel de Icaza + + * expression.cs (Unary.TryReduce): mimic the code for the regular + code path. Perform an implicit cast in the cases where we can + implicitly convert to one of the integral types, and then reduce + based on that constant. This fixes bug #35483. + +2002-12-14 Gonzalo Paniagua Javier + + * typemanager.cs: fixed cut & paste error in GetRemoveMethod. + +2002-12-13 Gonzalo Paniagua Javier + + * namespace.cs: fixed bug #35489. + +2002-12-12 Miguel de Icaza + + * class.cs: Remove some dead code. + + * cs-parser.jay: Estimate the number of methods needed + (RootContext.MethodCount); + + * cs-tokenizer.cs: Use char arrays for parsing identifiers and + numbers instead of StringBuilders. + + * support.cs (PtrHashtable): Add constructor with initial size; + We can now reduce reallocations of the method table. + +2002-12-10 Ravi Pratap + + * attribute.cs (ApplyAttributes): Keep track of the emitted + attributes on a per-target basis. This fixes bug #35413. + +2002-12-10 Miguel de Icaza + + * driver.cs (MainDriver): On rotor encoding 28591 does not exist, + default to the Windows 1252 encoding. + + (UnixParseOption): Support version, thanks to Alp for the missing + pointer. + + * AssemblyInfo.cs: Add nice assembly information. + + * cs-tokenizer.cs: Add fix from Felix to the #if/#else handler + (bug 35169). + + * cs-parser.jay: Allow a trailing comma before the close bracked + in the attribute_section production. + + * ecore.cs (FieldExpr.AddressOf): Until I figure out why the + address of the instance was being taken, I will take this out, + because we take the address of the object immediately here. + +2002-12-09 Ravi Pratap + + * typemanager.cs (AreMultipleAllowed): Take care of the most + obvious case where attribute type is not in the current assembly - + stupid me ;-) + +2002-12-08 Miguel de Icaza + + * ecore.cs (SimpleName.DoResolve): First perform lookups on using + definitions, instead of doing that afterwards. + + Also we use a nice little hack, depending on the constructor, we + know if we are a "composed" name or a simple name. Hence, we + avoid the IndexOf test, and we avoid + + * codegen.cs: Add code to assist in a bug reporter to track down + the source of a compiler crash. + +2002-12-07 Ravi Pratap + + * attribute.cs (Attribute.ApplyAttributes) : Keep track of which attribute + types have been emitted for a given element and flag an error + if something which does not have AllowMultiple set is used more + than once. + + * typemanager.cs (RegisterAttributeAllowMultiple): Keep track of + attribute types and their corresponding AllowMultiple properties + + (AreMultipleAllowed): Check the property for a given type. + + * attribute.cs (Attribute.ApplyAttributes): Register the AllowMultiple + property in the case we have a TypeContainer. + + (Attributes.AddAttribute): Detect duplicates and just skip on + adding them. This trivial fix catches a pretty gross error in our + attribute emission - global attributes were being emitted twice! + + Bugzilla bug #33187 is now fixed. + +2002-12-06 Miguel de Icaza + + * cs-tokenizer.cs (pp_expr): Properly recurse here (use pp_expr + instead of pp_and). + + * expression.cs (Binary.ResolveOperator): I can only use the + Concat (string, string, string) and Concat (string, string, + string, string) if the child is actually a concatenation of + strings. + +2002-12-04 Miguel de Icaza + + * cs-tokenizer.cs: Small fix, because decimal_digits is used in a + context where we need a 2-character lookahead. + + * pending.cs (PendingImplementation): Rework so we can keep track + of interface types all the time, and flag those which were + implemented by parents as optional. + +2002-12-03 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Use + String.Concat(string,string,string) or + String.Concat(string,string,string,string) when possible. + + * typemanager: More helper methods. + + +Tue Dec 3 19:32:04 CET 2002 Paolo Molaro + + * pending.cs: remove the bogus return from GetMissingInterfaces() + (see the 2002-11-06 entry: the mono runtime is now fixed in cvs). + +2002-12-02 Gonzalo Paniagua Javier + + * namespace.cs: avoid duplicated 'using xxx' being added to + using_clauses. This prevents mcs from issuing and 'ambiguous type' error + when we get more than one 'using' statement for the same namespace. + Report a CS0105 warning for it. + +2002-11-30 Miguel de Icaza + + * cs-tokenizer.cs (consume_identifier): use read directly, instead + of calling getChar/putback, uses internal knowledge of it. + + (xtoken): Reorder tokenizer so most common patterns are checked + first. This reduces the compilation time in another 5% (from 8.11s + average to 7.73s for bootstrapping mcs on my Mobile p4/1.8ghz). + + The parsing time is 22% of the compilation in mcs, and from that + 64% is spent on the tokenization process. + + I tried using a binary search for keywords, but this is slower + than the hashtable. Another option would be to do a couple of + things: + + * Not use a StringBuilder, instead use an array of chars, + with a set value. Notice that this way we could catch + the 645 error without having to do it *afterwards*. + + * We could write a hand-parser to avoid the hashtable + compares altogether. + + The identifier consumption process takes 37% of the tokenization + time. Another 15% is spent on is_number. 56% of the time spent + on is_number is spent on Int64.Parse: + + * We could probably choose based on the string length to + use Int32.Parse or Int64.Parse and avoid all the 64-bit + computations. + + Another 3% is spend on wrapping `xtoken' in the `token' function. + + Handle 0xa0 as whitespace (#34752) + +2002-11-26 Miguel de Icaza + + * typemanager.cs (IsCLRType): New routine to tell whether a type + is one of the builtin types. + + Maybe it needs to use TypeCodes to be faster. Maybe we could use + typecode in more places instead of doing pointer comparissions. + We could leverage some knowledge about the way the typecodes are + laid out. + + New code to cache namespaces in assemblies, it is currently not + invoked, to be used soon. + + * decl.cs (DeclSpace.MakeFQN): Simple optimization. + + * expression.cs (Binary.ResolveOperator): specially handle + strings, and do not perform user-defined operator overloading for + built-in types. + +2002-11-24 Miguel de Icaza + + * cs-tokenizer.cs: Avoid calling Char.IsDigit which is an + internalcall as it is a pretty simple operation; Avoid whenever + possible to call Char.IsLetter. + + (consume_identifier): Cut by half the number of + hashtable calls by merging the is_keyword and GetKeyword behavior. + + Do not short-circuit, because if we do, we + report errors (ie, #if false && true would produce an invalid + directive error); + + +2002-11-24 Martin Baulig + + * expression.cs (Cast.TryReduce): If we're in checked syntax, + check constant ranges and report a CS0221. Fixes #33186. + +2002-11-24 Martin Baulig + + * cs-parser.jay: Make this work for uninitialized variable + declarations in the `for' initializer. Fixes #32416. + +2002-11-24 Martin Baulig + + * ecore.cs (Expression.ConvertExplicit): Make casting from/to + System.Enum actually work. Fixes bug #32269, added verify-6.cs. + +2002-11-24 Martin Baulig + + * expression.cs (Binary.DoNumericPromotions): Added `check_user_conv' + argument; if true, we also check for user-defined conversions. + This is only needed if both arguments are of a user-defined type. + Fixes #30443, added test-175.cs. + (Binary.ForceConversion): Pass the location argument to ConvertImplicit. + + * ecore.cs (Expression.ImplicitUserConversionExists): New method. + +2002-11-24 Martin Baulig + + * expression.cs (ArrayAccess.GetStoreOpcode): New public static + function to get the store opcode. + (Invocation.EmitParams): Call ArrayAccess.GetStoreOpcode() and + only emit the Ldelema if the store opcode is Stobj. You must run + both test-34 and test-167 to test this. Fixes #34529. + +2002-11-23 Martin Baulig + + * ecore.cs (Expression.MemberLookup): Added additional + `qualifier_type' argument which is used when we're being called + from MemberAccess.DoResolve() and null if we're called from a + SimpleName lookup. + (Expression.MemberLookupFailed): New method to report errors; this + does the CS1540 check and reports the correct error message. + + * typemanager.cs (MemberLookup): Added additional `qualifier_type' + argument for the CS1540 check and redone the way how we're dealing + with private members. See the comment in the source code for details. + (FilterWithClosure): Reverted this back to revision 1.197; renamed + `closure_start_type' to `closure_qualifier_type' and check whether + it's not null. It was not this filter being broken, it was just + being called with the wrong arguments. + + * expression.cs (MemberAccess.DoResolve): use MemberLookupFinal() + and pass it the correct `qualifier_type'; this also does the error + handling for us. + +2002-11-22 Miguel de Icaza + + * expression.cs (Invocation.EmitParams): If the we are dealing + with a non-built-in value type, load its address as well. + + (ArrayCreation): Use a a pretty constant instead + of the hardcoded value 2. Use 6 instead of 2 for the number of + static initializers. + + (ArrayCreation.EmitDynamicInitializers): Peel enumerations, + because they are not really value types, just glorified integers. + + * driver.cs: Do not append .exe, the CSC compiler does not do it. + + * ecore.cs: Remove redundant code for enumerations, make them use + the same code path as everything else, fixes the casting issue + with enumerations in Windows.Forms. + + * attribute.cs: Do only cast to string if it is a string, the + validation happens later. + + * typemanager.cs: Temproary hack to avoid a bootstrap issue until + people upgrade their corlibs. + + * ecore.cs: Oops, enumerations were not following the entire code path + +2002-11-21 Miguel de Icaza + + * typemanager.cs (FilterWithClosure): Commented out the test for + 1540 in typemanager.cs, as it has problems when accessing + protected methods from a parent class (see test-174.cs). + + * attribute.cs (Attribute.ValidateGuid): new method. + (Attribute.Resolve): Use above. + +2002-11-19 Miguel de Icaza + + * enum.cs: In FindMembers, perform a recursive lookup for values. (34308) + + * ecore.cs (SimpleName.SimpleNameResolve): Remove the special + handling for enumerations, as we only needed the TypeContainer + functionality to begin with (this is required for the fix below to + work for enums that reference constants in a container class for + example). + + * codegen.cs (EmitContext): Make TypeContainer a DeclSpace. + + * enum.cs (Enum.Define): Use `this' instead of parent, so we have + a valid TypeBuilder to perform lookups on.o + + * class.cs (InheritableMemberSignatureCompare): Use true in the + call to GetGetMethod and GetSetMethod, because we are comparing + the signature, and we need to get the methods *even* if they are + private. + + (PropertyBase.CheckBase): ditto. + + * statement.cs (Switch.ResolveAndReduce, Block.EmitMeta, + GotoCase.Resolve): Use Peel on EmpytCasts. + + * ecore.cs (EmptyCast): drop child, add Peel method. + +2002-11-17 Martin Baulig + + * ecore.cs (EmptyCast.Child): New public property. + + * statement.cs (SwitchLabel.ResolveAndReduce): Check whether the + label resolved to an EmptyCast. Fixes #34162. + (GotoCase.Resolve): Likewise. + (Block.EmitMeta): Likewise. + +2002-11-17 Martin Baulig + + * expression.cs (Invocation.BetterConversion): Prefer int over + uint; short over ushort; long over ulong for integer literals. + Use ImplicitConversionExists instead of StandardConversionExists + since we also need to check for user-defined implicit conversions. + Fixes #34165. Added test-173.cs. + +2002-11-16 Martin Baulig + + * expression.cs (Binary.EmitBranchable): Eliminate comparisions + with the `true' and `false' literals. Fixes #33151. + +2002-11-16 Martin Baulig + + * typemanager.cs (RealMemberLookup): Reverted Miguel's patch from + October 22nd; don't do the cs1540 check for static members. + + * ecore.cs (PropertyExpr.ResolveAccessors): Rewrote this; we're + now using our own filter here and doing the cs1540 check again. + +2002-11-16 Martin Baulig + + * support.cs (InternalParameters): Don't crash if we don't have + any fixed parameters. Fixes #33532. + +2002-11-16 Martin Baulig + + * decl.cs (MemberCache.AddMethods): Use BindingFlags.FlattenHierarchy + when looking up static methods to make this work on Windows. + Fixes #33773. + +2002-11-16 Martin Baulig + + * ecore.cs (PropertyExpr.VerifyAssignable): Check whether we have + a setter rather than using PropertyInfo.CanWrite. + +2002-11-15 Nick Drochak + + * class.cs: Allow acces to block member by subclasses. Fixes build + breaker. + +2002-11-14 Martin Baulig + + * class.cs (Constructor.Emit): Added the extern/block check. + Fixes bug #33678. + +2002-11-14 Martin Baulig + + * expression.cs (IndexerAccess.DoResolve): Do a DeclaredOnly + iteration while looking for indexers, this is needed because the + indexer may have a different name in our base classes. Fixed the + error reporting (no indexers at all, not get accessor, no + overloaded match). Fixes bug #33089. + (IndexerAccess.DoResolveLValue): Likewise. + +2002-11-14 Martin Baulig + + * class.cs (PropertyBase.CheckBase): Make this work for multiple + indexers. Fixes the first part of bug #33089. + (MethodSignature.InheritableMemberSignatureCompare): Added support + for properties. + +2002-11-13 Ravi Pratap + + * attribute.cs (Attribute.Resolve): Catch the + NullReferenceException and report it since it isn't supposed to + happen. + +2002-11-12 Miguel de Icaza + + * expression.cs (Binary.EmitBranchable): Also handle the cases for + LogicalOr and LogicalAnd that can benefit from recursively + handling EmitBranchable. The code now should be nice for Paolo. + +2002-11-08 Miguel de Icaza + + * typemanager.cs (LookupType): Added a negative-hit hashtable for + the Type lookups, as we perform quite a number of lookups on + non-Types. This can be removed once we can deterministically tell + whether we have a type or a namespace in advance. + + But this might require special hacks from our corlib. + + * TODO: updated. + + * ecore.cs (TryImplicitIntConversion): Handle conversions to float + and double which avoids a conversion from an integer to a double. + + * expression.cs: tiny optimization, avoid calling IsConstant, + because it effectively performs the lookup twice. + +2002-11-06 Miguel de Icaza + + But a bogus return here to keep the semantics of the old code + until the Mono runtime is fixed. + + * pending.cs (GetMissingInterfaces): New method used to remove all + the interfaces that are already implemented by our parent + classes from the list of pending methods. + + * interface.cs: Add checks for calls after ResolveTypeExpr. + +2002-11-05 Miguel de Icaza + + * class.cs (Class.Emit): Report warning 67: event not used if the + warning level is beyond 3. + + * ecore.cs (Expression.ConvertExplicit): Missed a check for expr + being a NullLiteral. + + * cs-parser.jay: Fix, Gonzalo reverted the order of the rank + specifiers. + + * class.cs (TypeContainer.GetClassBases): Cover a missing code + path that might fail if a type can not be resolved. + + * expression.cs (Binary.Emit): Emit unsigned versions of the + operators. + + * driver.cs: use error 5. + +2002-11-02 Gonzalo Paniagua Javier + + * cs-parser.jay: simplified a rule and 5 SR conflicts dissapeared. + +2002-11-01 Miguel de Icaza + + * cs-parser.jay (switch_section): A beautiful patch from Martin + Baulig that fixed 33094. + +2002-10-31 Miguel de Icaza + + * ecore.cs (PropertyExpr.DoResolveLValue, PropertyExpr.DoResolve): + Check whether the base is abstract and report an error if so. + + * expression.cs (IndexerAccess.DoResolveLValue, + IndexerAccess.DoResolve): ditto. + + (Invocation.DoResolve): ditto. + + (Invocation.FullMethodDesc): Improve the report string. + + * statement.cs (Block): Eliminate IsVariableDefined as it is + basically just a wrapper for GetVariableInfo. + + * ecore.cs (SimpleName): Use new + + * support.cs (ReflectionParamter.ParameterType): We unwrap the + type, as we return the actual parameter ref/unref state on a + different call. + +2002-10-30 Miguel de Icaza + + * support.cs: Return proper flags REF/OUT fixing the previous + commit. + + * expression.cs: Reverted last patch, that was wrong. Is_ref is + not used to mean `ref' but `ref or out' in ParameterReference + + * delegate.cs (FullDelegateDesc): use ParameterDesc to get the + full type signature instead of calling TypeManger.CSharpName + ourselves. + + * support.cs (InternalParameters.ParameterDesc): Do not compare + directly to the modflags, because REF/OUT will actually be bitsets + if set. + + * delegate.cs (VerifyMethod): Check also the modifiers. + + * cs-tokenizer.cs: Fix bug where floating point values with an + exponent where a sign was missing was ignored. + + * driver.cs: Allow multiple assemblies to be specified in a single + /r: argument + +2002-10-28 Miguel de Icaza + + * cs-parser.jay: Ugly. We had to add a multiplicative_expression, + because identifiers after a parenthesis would end up in this kind + of production, and we needed to desamiguate it for having casts + like: + + (UserDefinedType *) xxx + +2002-10-24 Miguel de Icaza + + * typemanager.cs (RealMemberLookup): when we deal with a subclass, + we should set on the Bindingflags.NonPublic, but not turn on + private_ok. private_ok controls whether a Private member is + returned (this is chekced on the filter routine), while the + BindingFlags.NonPublic just controls whether private/protected + will be allowed. This fixes the problem part of the problem of + private properties being allowed to be used in derived classes. + + * expression.cs (BaseAccess): Provide an DoResolveLValue method, + so we can call the children DoResolveLValue method (this will + properly signal errors on lvalue assignments to base properties) + + * ecore.cs (PropertyExpr.ResolveAccessors): If both setter and + getter are null, and we have a property info, we know that this + happened because the lookup failed, so we report an error 122 for + protection level violation. + + We also silently return if setter and getter are null in the + resolve functions, this condition only happens if we have flagged + the error before. This is the other half of the problem. + + (PropertyExpr.ResolveAccessors): Turns out that PropertyInfo does + not have accessibility information, that is why we were returning + true in the filter function in typemanager.cs. + + To properly report 122 (property is inaccessible because of its + protection level) correctly, we report this error in ResolveAccess + by failing if both the setter and the getter are lacking (ie, the + lookup failed). + + DoResolve and DoLResolve have been modified to check for both + setter/getter being null and returning silently, the reason being + that I did not want to put the knowledge about this error in upper + layers, like: + + int old = Report.Errors; + x = new PropertyExpr (...); + if (old != Report.Errors) + return null; + else + return x; + + So the property expr is returned, but it is invalid, so the error + will be flagged during the resolve process. + + * class.cs: Remove InheritablePropertySignatureCompare from the + class, as we no longer depend on the property signature to compute + whether it is possible to implement a method or not. + + The reason is that calling PropertyInfo.GetGetMethod will return + null (in .NET, in Mono it works, and we should change this), in + cases where the Get Method does not exist in that particular + class. + + So this code: + + class X { public virtual int A { get { return 1; } } } + class Y : X { } + class Z : Y { public override int A { get { return 2; } } } + + Would fail in Z because the parent (Y) would not have the property + defined. So we avoid this completely now (because the alternative + fix was ugly and slow), and we now depend exclusively on the + method names. + + (PropertyBase.CheckBase): Use a method-base mechanism to find our + reference method, instead of using the property. + + * typemanager.cs (GetPropertyGetter, GetPropertySetter): These + routines are gone now. + + * typemanager.cs (GetPropertyGetter, GetPropertySetter): swap the + names, they were incorrectly named. + + * cs-tokenizer.cs: Return are more gentle token on failure. + + * pending.cs (PendingImplementation.InterfaceMethod): This routine + had an out-of-sync index variable, which caused it to remove from + the list of pending methods the wrong method sometimes. + +2002-10-22 Miguel de Icaza + + * ecore.cs (PropertyExpr): Do not use PropertyInfo.CanRead, + CanWrite, because those refer to this particular instance of the + property, and do not take into account the fact that we can + override single members of a property. + + Constructor requires an EmitContext. The resolution process does + not happen here, but we need to compute the accessors before, + because the resolution does not always happen for properties. + + * typemanager.cs (RealMemberLookup): Set private_ok if we are a + subclass, before we did not update this flag, but we did update + bindingflags. + + (GetAccessors): Drop this routine, as it did not work in the + presence of partially overwritten set/get methods. + + Notice that this broke the cs1540 detection, but that will require + more thinking. + +2002-10-22 Gonzalo Paniagua Javier + + * class.cs: + * codegen.cs: + * driver.cs: issue a warning instead of an error if we don't support + debugging for the platform. Also ignore a couple of errors that may + arise when trying to write the symbols. Undo my previous patch. + +2002-10-22 Gonzalo Paniagua Javier + + * driver.cs: ignore /debug switch except for Unix platforms. + +2002-10-23 Nick Drochak + + * makefile: Remove mcs2.exe and mcs3.exe on 'make clean' + +2002-10-21 Miguel de Icaza + + * driver.cs: Do not make mcs-debug conditional, so we do not break + builds that use it. + + * statement.cs (UsageVector.MergeChildren): I would like Martin to + review this patch. But basically after all the children variables + have been merged, the value of "Breaks" was not being set to + new_breaks for Switch blocks. I think that it should be set after + it has executed. Currently I set this to the value of new_breaks, + but only if new_breaks is FlowReturn.ALWAYS, which is a bit + conservative, but I do not understand this code very well. + + I did not break anything in the build, so that is good ;-) + + * cs-tokenizer.cs: Also allow \r in comments as a line separator. + +2002-10-20 Mark Crichton + + * cfold.cs: Fixed compile blocker. Really fixed it this time. + +2002-10-20 Nick Drochak + + * cfold.cs: Fixed compile blocker. + +2002-10-20 Miguel de Icaza + + * driver.cs: I was chekcing the key, not the file. + +2002-10-19 Ravi Pratap + + * ecore.cs (UserDefinedConversion): Get rid of the bogus error + message that we were generating - we just need to silently return + a null. + +2002-10-19 Miguel de Icaza + + * class.cs (Event.Define): Change my previous commit, as this + breaks the debugger. This is a temporary hack, as it seems like + the compiler is generating events incorrectly to begin with. + + * expression.cs (Binary.ResolveOperator): Added support for + "U operator - (E x, E y)" + + * cfold.cs (BinaryFold): Added support for "U operator - (E x, E + y)". + + * ecore.cs (FieldExpr.AddressOf): We had a special code path for + init-only variables, but this path did not take into account that + there might be also instance readonly variables. Correct this + problem. + + This fixes bug 32253 + + * delegate.cs (NewDelegate.DoResolve): Catch creation of unsafe + delegates as well. + + * driver.cs: Change the extension for modules to `netmodule' + + * cs-parser.jay: Improved slightly the location tracking for + the debugger symbols. + + * class.cs (Event.Define): Use Modifiers.FieldAttr on the + modifiers that were specified instead of the hardcoded value + (FamAndAssem). This was basically ignoring the static modifier, + and others. Fixes 32429. + + * statement.cs (Switch.SimpleSwitchEmit): Simplified the code, and + fixed a bug in the process (32476) + + * expression.cs (ArrayAccess.EmitAssign): Patch from + hwang_rob@yahoo.ca that fixes bug 31834.3 + +2002-10-18 Miguel de Icaza + + * driver.cs: Make the module extension .netmodule. + +2002-10-16 Miguel de Icaza + + * driver.cs: Report an error if the resource file is not found + instead of crashing. + + * ecore.cs (PropertyExpr.EmitAssign): Pass IsBase instead of + false, like Emit does. + +2002-10-16 Nick Drochak + + * typemanager.cs: Remove unused private member. Also reported mcs + bug to report this as a warning like csc. + +2002-10-15 Martin Baulig + + * statement.cs (Statement.Emit): Made this a virtual method; emits + the line number info and calls DoEmit(). + (Statement.DoEmit): New protected abstract method, formerly knows + as Statement.Emit(). + + * codegen.cs (EmitContext.Mark): Check whether we have a symbol writer. + +2002-10-11 Miguel de Icaza + + * class.cs: Following the comment from 2002-09-26 to AddMethod, I + have fixed a remaining problem: not every AddXXXX was adding a + fully qualified name. + + Now everyone registers a fully qualified name in the DeclSpace as + being defined instead of the partial name. + + Downsides: we are slower than we need to be due to the excess + copies and the names being registered this way. + + The reason for this is that we currently depend (on the corlib + bootstrap for instance) that types are fully qualified, because + we dump all the types in the namespace, and we should really have + types inserted into the proper namespace, so we can only store the + basenames in the defined_names array. + +2002-10-10 Martin Baulig + + * expression.cs (ArrayAccess.EmitStoreOpcode): Reverted the patch + from bug #31834, see the bug report for a testcase which is + miscompiled. + +2002-10-10 Martin Baulig + + * codegen.cs (EmitContext.Breaks): Removed, we're now using the + flow analysis code for this. + + * statement.cs (Do, While, For): Tell the flow analysis code about + infinite loops. + (FlowBranching.UsageVector): Added support for infinite loops. + (Block.Resolve): Moved the dead code elimination here and use flow + analysis to do it. + +2002-10-09 Miguel de Icaza + + * class.cs (Field.Define): Catch cycles on struct type + definitions. + + * typemanager.cs (IsUnmanagedtype): Do not recursively check + fields if the fields are static. We only need to check instance + fields. + + * expression.cs (As.DoResolve): Test for reference type. + + * statement.cs (Using.ResolveExpression): Use + ConvertImplicitRequired, not ConvertImplicit which reports an + error on failture + (Using.ResolveLocalVariableDecls): ditto. + + * expression.cs (Binary.ResolveOperator): Report errors in a few + places where we had to. + + * typemanager.cs (IsUnmanagedtype): Finish implementation. + +2002-10-08 Miguel de Icaza + + * expression.cs: Use StoreFromPtr instead of extracting the type + and then trying to use Stelem. Patch is from hwang_rob@yahoo.ca + + * ecore.cs (ImplicitReferenceConversion): It is possible to assign + an enumeration value to a System.Enum, but System.Enum is not a + value type, but an class type, so we need to box. + + (Expression.ConvertExplicit): One codepath could return + errors but not flag them. Fix this. Fixes #31853 + + * parameter.cs (Resolve): Do not allow void as a parameter type. + +2002-10-06 Martin Baulig + + * statemenc.cs (FlowBranching.SetParameterAssigned): Don't crash + if it's a class type and not a struct. Fixes #31815. + +2002-10-06 Martin Baulig + + * statement.cs: Reworked the flow analysis code a bit to make it + usable for dead code elimination. + +2002-10-06 Gonzalo Paniagua Javier + + * cs-parser.jay: allow empty source files. Fixes bug #31781. + +2002-10-04 Miguel de Icaza + + * expression.cs (ComposedCast.DoResolveType): A quick workaround + to fix the test 165, will investigate deeper. + +2002-10-04 Martin Baulig + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Make + finally blocks actually work. + (Try.Resolve): We don't need to create a sibling for `finally' if + there is no finally block. + +2002-10-04 Martin Baulig + + * class.cs (Constructor.Define): The default accessibility for a + non-default constructor is private, not public. + +2002-10-04 Miguel de Icaza + + * class.cs (Constructor): Make AllowedModifiers public, add + EXTERN. + + * cs-parser.jay: Perform the modifiers test here, as the + constructor for the Constructor class usually receives a zero + because of the way we create it (first we create, later we + customize, and we were never checking the modifiers). + + * typemanager.cs (Typemanager.LookupTypeDirect): This new function + is a version of LookupTypeReflection that includes the type-name + cache. This can be used as a fast path for functions that know + the fully qualified name and are only calling into *.GetType() to + obtain a composed type. + + This is also used by TypeManager.LookupType during its type + composition. + + (LookupType): We now also track the real type name, as sometimes + we can get a quey for the real type name from things like + ComposedCast. This fixes bug 31422. + + * expression.cs (ComposedCast.Resolve): Since we are obtaining a + complete type fullname, it does not have to go through the type + resolution system to obtain the composed version of the type (for + obtaining arrays or pointers). + + (Conditional.Emit): Use the EmitBoolExpression to + generate nicer code, as requested by Paolo. + + (ArrayCreation.CheckIndices): Use the patch from + hwang_rob@yahoo.ca to validate the array initializers. + +2002-10-03 Miguel de Icaza + + * class.cs (ConstructorInitializer.Emit): simplify code by using + Invocation.EmitCall, and at the same time, fix the bugs in calling + parent constructors that took variable arguments. + + * ecore.cs (Expression.ConvertNumericExplicit, + Expression.ImplicitNumericConversion): Remove the code that + manually wrapped decimal (InternalTypeConstructor call is now gone + as well). + + * expression.cs (Cast.TryReduce): Also handle decimal types when + trying to perform a constant fold on the type. + + * typemanager.cs (IsUnmanagedtype): Partially implemented. + + * parameter.cs: Removed ResolveAndDefine, as it was not needed, as + that only turned off an error report, and did nothing else. + +2002-10-02 Miguel de Icaza + + * driver.cs: Handle and ignore /fullpaths + +2002-10-01 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Catch the case where + DoNumericPromotions returns true, + + (Binary.DoNumericPromotions): Simplify the code, and the tests. + +2002-09-27 Miguel de Icaza + + * ecore.cs (EventExpr.Emit): Instead of emitting an exception, + report error 70. + +2002-09-26 Miguel de Icaza + + * ecore.cs (ConvertNumericExplicit): It is not enough that the + conversion exists, but it is also required that the conversion be + performed. This manifested in "(Type64Enum) 2". + + * class.cs (TypeManager.AddMethod): The fix is not to change + AddEnum, because that one was using a fully qualified name (every + DeclSpace derivative does), but to change the AddMethod routine + that was using an un-namespaced name. This now correctly reports + the duplicated name. + + Revert patch until I can properly fix it. The issue + is that we have a shared Type space across all namespaces + currently, which is wrong. + + Options include making the Namespace a DeclSpace, and merge + current_namespace/current_container in the parser. + +2002-09-25 Miguel de Icaza + + * cs-parser.jay: Improve error reporting when we get a different + kind of expression in local_variable_type and + local_variable_pointer_type. + + Propagate this to avoid missleading errors being reported. + + * ecore.cs (ImplicitReferenceConversion): treat + TypeManager.value_type as a target just like object_type. As + code like this: + + ValueType v = 1; + + Is valid, and needs to result in the int 1 being boxed before it + is assigned to the value type v. + + * class.cs (TypeContainer.AddEnum): Use the basename, not the name + to validate the enumeration name. + + * expression.cs (ArrayAccess.EmitAssign): Mimic the same test from + EmitDynamicInitializers for the criteria to use Ldelema. Thanks + to hwang_rob@yahoo.ca for finding the bug and providing a patch. + + * ecore.cs (TryImplicitIntConversion): When doing an + implicit-enumeration-conversion, check if the type is 64-bits and + perform a conversion before passing to EnumConstant. + +2002-09-23 Miguel de Icaza + + * decl.cs (Error_AmbiguousTypeReference); New routine used to + report ambiguous type references. Unlike the MS version, we + report what the ambiguity is. Innovation at work ;-) + + (DeclSpace.FindType): Require a location argument to + display when we display an ambiguous error. + + * ecore.cs: (SimpleName.DoResolveType): Pass location to FindType. + + * interface.cs (GetInterfaceTypeByName): Pass location to FindType. + + * expression.cs (EmitDynamicInitializers): Apply patch from + hwang_rob@yahoo.ca that fixes the order in which we emit our + initializers. + +2002-09-21 Martin Baulig + + * delegate.cs (Delegate.VerifyApplicability): Make this work if the + delegate takes no arguments. + +2002-09-20 Miguel de Icaza + + * constant.cs: Use Conv_U8 instead of Conv_I8 when loading longs + from integers. + + * expression.cs: Extract the underlying type. + + * ecore.cs (StoreFromPtr): Use TypeManager.IsEnumType instad of IsEnum + + * decl.cs (FindType): Sorry about this, fixed the type lookup bug. + +2002-09-19 Miguel de Icaza + + * class.cs (TypeContainer.DefineType): We can not use the nice + PackingSize with the size set to 1 DefineType method, because it + will not allow us to define the interfaces that the struct + implements. + + This completes the fixing of bug 27287 + + * ecore.cs (Expresion.ImplicitReferenceConversion): `class-type S' + means also structs. This fixes part of the problem. + (Expresion.ImplicitReferenceConversionExists): ditto. + + * decl.cs (DeclSparce.ResolveType): Only report the type-not-found + error if there were no errors reported during the type lookup + process, to avoid duplicates or redundant errors. Without this + you would get an ambiguous errors plus a type not found. We have + beaten the user enough with the first error. + + (DeclSparce.FindType): Emit a warning if we have an ambiguous + reference. + + * ecore.cs (SimpleName.DoResolveType): If an error is emitted + during the resolution process, stop the lookup, this avoids + repeated error reports (same error twice). + + * rootcontext.cs: Emit a warning if we have an ambiguous reference. + + * typemanager.cs (LookupType): Redo the type lookup code to match + the needs of System.Reflection. + + The issue is that System.Reflection requires references to nested + types to begin with a "+" sign instead of a dot. So toplevel + types look like: "NameSpace.TopLevelClass", and nested ones look + like "Namespace.TopLevelClass+Nested", with arbitrary nesting + levels. + +2002-09-19 Martin Baulig + + * codegen.cs (EmitContext.EmitTopBlock): If control flow analysis + says that a method always returns or always throws an exception, + don't report the CS0161. + + * statement.cs (FlowBranching.UsageVector.MergeChildren): Always + set `Returns = new_returns'. + +2002-09-19 Martin Baulig + + * expression.cs (MemberAccess.ResolveMemberAccess): When resolving + to an enum constant, check for a CS0176. + +2002-09-18 Miguel de Icaza + + * class.cs (TypeContainer.CheckPairedOperators): Now we check + for operators that must be in pairs and report errors. + + * ecore.cs (SimpleName.DoResolveType): During the initial type + resolution process, when we define types recursively, we must + check first for types in our current scope before we perform + lookups in the enclosing scopes. + + * expression.cs (MakeByteBlob): Handle Decimal blobs. + + (Invocation.VerifyArgumentsCompat): Call + TypeManager.TypeToCoreType on the parameter_type.GetElementType. + I thought we were supposed to always call this, but there are a + few places in the code where we dont do it. + +2002-09-17 Miguel de Icaza + + * driver.cs: Add support in -linkres and -resource to specify the + name of the identifier. + +2002-09-16 Miguel de Icaza + + * ecore.cs (StandardConversionExists): Sync with the conversion + code: allow anything-* to void* conversions. + + (FindMostSpecificSource): Use an Expression argument + instead of a Type, because we might be handed over a Literal which + gets a few more implicit conversions that plain types do not. So + this information was being lost. + + Also, we drop the temporary type-holder expression when not + required. + +2002-09-17 Martin Baulig + + * class.cs (PropertyBase.CheckBase): Don't check the base class if + this is an explicit interface implementation. + +2002-09-17 Martin Baulig + + * class.cs (PropertyBase.CheckBase): Make this work for indexers with + different `IndexerName' attributes. + + * expression.cs (BaseIndexerAccess): Rewrote this class to use IndexerAccess. + (IndexerAccess): Added special protected ctor for BaseIndexerAccess and + virtual CommonResolve(). + +2002-09-16 Miguel de Icaza + + * enum.cs (LookupEnumValue): Use the EnumConstant declared type, + and convert that to the UnderlyingType. + + * statement.cs (Foreach.Resolve): Indexers are just like variables + or PropertyAccesses. + + * cs-tokenizer.cs (consume_string): Track line numbers and columns + inside quoted strings, we were not doing this before. + +2002-09-16 Martin Baulig + + * ecore.cs (MethodGroupExpr.DoResolve): If we have an instance expression, + resolve it. This is needed for the definite assignment check of the + instance expression, fixes bug #29846. + (PropertyExpr.DoResolve, EventExpr.DoResolve): Likewise. + +2002-09-16 Nick Drochak + + * parameter.cs: Fix compile error. Cannot reference static member + from an instance object. Is this an mcs bug? + +2002-09-14 Martin Baulig + + * decl.cs (MemberCache.SetupCacheForInterface): Don't add an interface + multiple times. Fixes bug #30295, added test-166.cs. + +2002-09-14 Martin Baulig + + * statement.cs (Block.Emit): Don't emit unreachable code. + (Switch.SimpleSwitchEmit, Switch.TableSwitchEmit): Check for missing + `break' statements. + (Goto.Emit, Continue.Emit): Set ec.Breaks = true. + +2002-09-14 Martin Baulig + + * parameter.cs (Parameter.Attributes): Make this work if Modifier.ISBYREF + is set. + +2002-09-14 Martin Baulig + + * typemanager.cs (TypeManager.IsNestedChildOf): This must return false + if `type == parent' since in this case `type.IsSubclassOf (parent)' will + be false on the ms runtime. + +2002-09-13 Martin Baulig + + * ecore.cs (SimpleName.SimpleNameResolve): Include the member name in + the CS0038 error message. + +2002-09-12 Miguel de Icaza + + * expression.cs (CheckedExpr, UnCheckedExpr): If we have a + constant inside, return it. + +2002-09-12 Martin Baulig + + * cfold.cs (ConstantFold.DoConstantNumericPromotions): Check whether an + implicit conversion can be done between enum types. + + * enum.cs (Enum.LookupEnumValue): If the value is an EnumConstant, + check whether an implicit conversion to the current enum's UnderlyingType + exists and report an error if not. + + * codegen.cs (CodeGen.Init): Delete the symbol file when compiling + without debugging support. + + * delegate.cs (Delegate.CloseDelegate): Removed, use CloseType instead. + Fixes bug #30235. Thanks to Ricardo Fernández Pascual. + +2002-09-12 Martin Baulig + + * typemanager.cs (TypeManager.IsNestedChildOf): New method. + + * ecore.cs (IMemberExpr.DeclaringType): New property. + (SimpleName.SimpleNameResolve): Check whether we're accessing a + nonstatic member of an outer type (CS0038). + +2002-09-11 Miguel de Icaza + + * driver.cs: Activate the using-error detector at warning level + 4 (at least for MS-compatible APIs). + + * namespace.cs (VerifyUsing): Small buglett fix. + + * pending.cs (PendingImplementation): pass the container pointer. + + * interface.cs (GetMethods): Allow for recursive definition. Long + term, I would like to move every type to support recursive + definitions, not the current ordering mechanism that we have right + now. + + The situation is this: Attributes are handled before interfaces, + so we can apply attributes to interfaces. But some attributes + implement interfaces, we will now handle the simple cases + (recursive definitions will just get an error). + + * parameter.cs: Only invalidate types at the end if we fail to + lookup all types. + +2002-09-09 Martin Baulig + + * ecore.cs (PropertyExpr.Emit): Also check for + TypeManager.system_int_array_get_length so this'll also work when + compiling corlib. Fixes #30003. + +2002-09-09 Martin Baulig + + * expression.cs (ArrayCreation.MakeByteBlob): Added support for enums + and throw an exception if we can't get the type's size. Fixed #30040, + added test-165.cs. + +2002-09-09 Martin Baulig + + * ecore.cs (PropertyExpr.DoResolve): Added check for static properies. + + * expression.cs (SizeOf.DoResolve): Sizeof is only allowed in unsafe + context. Fixes bug #30027. + + * delegate.cs (NewDelegate.Emit): Use OpCodes.Ldvirtftn for + virtual functions. Fixes bug #30043, added test-164.cs. + +2002-09-08 Ravi Pratap + + * attribute.cs : Fix a small NullRef crash thanks to my stupidity. + +2002-09-08 Nick Drochak + + * driver.cs: Use an object to get the windows codepage since it's not a + static property. + +2002-09-08 Miguel de Icaza + + * statement.cs (For.Emit): for infinite loops (test == null) + return whether there is a break inside, not always "true". + + * namespace.cs (UsingEntry): New struct to hold the name of the + using definition, the location where it is defined, and whether it + has been used in a successful type lookup. + + * rootcontext.cs (NamespaceLookup): Use UsingEntries instead of + strings. + + * decl.cs: ditto. + +2002-09-06 Ravi Pratap + + * attribute.cs : Fix incorrect code which relied on catching + a NullReferenceException to detect a null being passed in + where an object was expected. + +2002-09-06 Miguel de Icaza + + * statement.cs (Try): flag the catch variable as assigned + + * expression.cs (Cast): Simplified by using ResolveType instead of + manually resolving. + + * statement.cs (Catch): Fix bug by using ResolveType. + +2002-09-06 Ravi Pratap + + * expression.cs (BetterConversion): Special case for when we have + a NullLiteral as the argument and we have to choose between string + and object types - we choose string the way csc does. + + * attribute.cs (Attribute.Resolve): Catch the + NullReferenceException and report error #182 since the Mono + runtime no more has the bug and having this exception raised means + we tried to select a constructor which takes an object and is + passed a null. + +2002-09-05 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Flag a nicer error + message (1502, 1503) when we can't locate a method after overload + resolution. This is much more informative and closes the bug + Miguel reported. + + * interface.cs (PopulateMethod): Return if there are no argument + types. Fixes a NullReferenceException bug. + + * attribute.cs (Attribute.Resolve): Ensure we allow TypeOf + expressions too. Previously we were checking only in one place for + positional arguments leaving out named arguments. + + * ecore.cs (ImplicitNumericConversion): Conversion from underlying + type to the enum type is not allowed. Remove code corresponding to + that. + + (ConvertNumericExplicit): Allow explicit conversions from + the underlying type to enum type. This precisely follows the spec + and closes a bug filed by Gonzalo. + +2002-09-04 Gonzalo Paniagua Javier + + * compiler.csproj: + * compiler.csproj.user: patch from Adam Chester (achester@bigpond.com). + +2002-09-03 Miguel de Icaza + + * statement.cs (SwitchLabel.ResolveAndReduce): In the string case, + it was important that we stored the right value after the + reduction in `converted'. + +2002-09-04 Martin Baulig + + * location.cs (Location.SymbolDocument): Use full pathnames for the + source files. + +2002-08-30 Miguel de Icaza + + * expression.cs (ComposedCast): Use DeclSparce.ResolveType instead + of the expression resolve mechanism, because that will catch the + SimpleName error failures. + + (Conditional): If we can not resolve the + expression, return, do not crash. + +2002-08-29 Gonzalo Paniagua Javier + + * cs-tokenizer.cs: + (location): display token name instead of its number. + +2002-08-28 Martin Baulig + + * expression.cs (Binary.ResolveOperator): Don't silently return + but return an error if an operator cannot be applied between two + enum types. + +2002-08-28 Martin Baulig + + * class.cs (Constructor.Define): Set the permission attributes + correctly instead of making all constructors public. + +2002-08-28 Martin Baulig + + * ecore.cs (Expression.DoResolve): Do a TypeManager.MemberLook + for private members before reporting a CS0103; if we find anything, + it's a CS0122. + +2002-08-28 Martin Baulig + + * typemanager.cs (TypeManager.FilterWithClosure): It's not enough + to check whether `closure_start_type == closure_invocation_type', + we also need to check whether `m.DeclaringType == closure_invocation_type' + before bypassing the permission checks. We might be accessing + protected/private members from the base class. + (TypeManager.RealMemberLookup): Only set private_ok if private + members were requested via BindingFlags.NonPublic. + + * ecore.cs (MethodGroupExpr.IsExplicitImpl): New property. + + * expression.cs (MemberAccess.ResolveMemberAccess): Set + MethodGroupExpr.IsExplicitImpl if appropriate. + (Invocation.DoResolve): Don't report the CS0120 for explicit + interface implementations. + +2002-08-27 Martin Baulig + + * expression.cs (Invocation.DoResolve): If this is a static + method and we don't have an InstanceExpression, we must report + a CS0120. + +2002-08-25 Martin Baulig + + * expression.cs (Binary.ResolveOperator): Don't allow `!=' and + `==' between a valuetype and an object. + +2002-08-25 Miguel de Icaza + + * ecore.cs (TypeExpr): Provide a ToString method. + +2002-08-24 Martin Baulig + + * codegen.cs (CodeGen.InitMonoSymbolWriter): The symbol file is + now called proggie.dbg and it's a binary file. + +2002-08-23 Martin Baulig + + * decl.cs (MemberCache.AddMethods): Ignore varargs methods. + +2002-08-23 Martin Baulig + + * struct.cs (MyStructInfo.ctor): Make this work with empty + structs; it's not allowed to use foreach() on null. + +2002-08-23 Martin Baulig + + * codegen.cs (CodeGen.InitMonoSymbolWriter): Tell the symbol + writer the full pathname of the generated assembly. + +2002-08-23 Martin Baulig + + * statements.cs (FlowBranching.UsageVector.MergeChildren): + A `finally' block never returns or breaks; improved handling of + unreachable code. + +2002-08-23 Martin Baulig + + * statement.cs (Throw.Resolve): Allow `throw null'. + +2002-08-23 Martin Baulig + + * expression.cs (MemberAccess.ResolveMemberAccess): If this is an + EventExpr, don't do a DeclaredOnly MemberLookup, but check whether + `ee.EventInfo.DeclaringType == ec.ContainerType'. The + MemberLookup would return a wrong event if this is an explicit + interface implementation and the class has an event with the same + name. + +2002-08-23 Martin Baulig + + * statement.cs (Block.AddChildVariableNames): New public method. + (Block.AddChildVariableName): Likewise. + (Block.IsVariableNameUsedInChildBlock): Likewise. + (Block.AddVariable): Check whether a variable name has already + been used in a child block. + + * cs-parser.jay (declare_local_variables): Mark all variable names + from the current block as being used in a child block in the + implicit block. + +2002-08-23 Martin Baulig + + * codegen.cs (CodeGen.InitializeSymbolWriter): Abort if we can't + find the symbol writer. + + * driver.cs: csc also allows the arguments to /define being + separated by commas, not only by semicolons. + +2002-08-23 Martin Baulig + + * interface.cs (Interface.GetMembers): Added static check for events. + +2002-08-15 Martin Baulig + + * class.cs (MethodData.EmitDestructor): In the Expression.MemberLookup + call, use ec.ContainerType.BaseType as queried_type and invocation_type. + + * ecore.cs (Expression.MemberLookup): Added documentation and explained + why the MethodData.EmitDestructor() change was necessary. + +2002-08-20 Martin Baulig + + * class.cs (TypeContainer.FindMembers): Added static check for events. + + * decl.cs (MemberCache.AddMembers): Handle events like normal members. + + * typemanager.cs (TypeHandle.GetMembers): When queried for events only, + use Type.GetEvents(), not Type.FindMembers(). + +2002-08-20 Martin Baulig + + * decl.cs (MemberCache): Added a special method cache which will + be used for method-only searched. This ensures that a method + search will return a MethodInfo with the correct ReflectedType for + inherited methods. + +2002-08-20 Martin Baulig + + * decl.cs (DeclSpace.FindMembers): Made this public. + +2002-08-20 Gonzalo Paniagua Javier + + * delegate.cs: fixed build on windows. + [FIXME: Filed as bug #29150: MCS must report these errors.] + +2002-08-19 Ravi Pratap + + * ecore.cs (StandardConversionExists): Return a false + if we are trying to convert the void type to anything else + since that is not allowed. + + * delegate.cs (DelegateInvocation.DoResolve): Ensure that + we flag error 70 in the event an event is trying to be accessed + directly from outside the declaring type. + +2002-08-20 Martin Baulig + + * typemanager.cs, decl.cs: Moved MemberList, IMemberContainer and + MemberCache from typemanager.cs to decl.cs. + +2002-08-19 Martin Baulig + + * class.cs (TypeContainer): Implement IMemberContainer. + (TypeContainer.DefineMembers): Create the MemberCache. + (TypeContainer.FindMembers): Do better BindingFlags checking; only + return public members if BindingFlags.Public was given, check + whether members are static. + +2002-08-16 Martin Baulig + + * decl.cs (DeclSpace.Define): Splitted this in Define and + DefineMembers. DefineMembers is called first and initializes the + MemberCache. + + * rootcontext.cs (RootContext.DefineMembers): New function. Calls + DefineMembers() on all our DeclSpaces. + + * class.cs (TypeContainer.Define): Moved all code to DefineMembers(), + but call DefineMembers() on all nested interfaces. We call their + Define() in our new Define() function. + + * interface.cs (Interface): Implement IMemberContainer. + (Interface.Define): Moved all code except the attribute stuf to + DefineMembers(). + (Interface.DefineMembers): Initialize the member cache. + + * typemanager.cs (IMemberFinder): Removed this interface, we don't + need this anymore since we can use MemberCache.FindMembers directly. + +2002-08-19 Martin Baulig + + * typemanager.cs (MemberCache): When creating the cache for an + interface type, add all inherited members. + (TypeManager.MemberLookup_FindMembers): Changed `ref bool searching' + to `out bool used_cache' and documented it. + (TypeManager.MemberLookup): If we already used the cache in the first + iteration, we don't need to do the interfaces check. + +2002-08-19 Martin Baulig + + * decl.cs (DeclSpace.FindMembers): New abstract method. Moved this + here from IMemberFinder and don't implement this interface anymore. + (DeclSpace.MemberCache): Moved here from IMemberFinder. + + * typemanager.cs (IMemberFinder): This interface is now only used by + classes which actually support the member cache. + (TypeManager.builder_to_member_finder): Renamed to builder_to_declspace + since we only put DeclSpaces into this Hashtable. + (MemberLookup_FindMembers): Use `builder_to_declspace' if the type is + a dynamic type and TypeHandle.GetTypeHandle() otherwise. + +2002-08-16 Martin Baulig + + * typemanager.cs (ICachingMemberFinder): Removed. + (IMemberFinder.MemberCache): New property. + (TypeManager.FindMembers): Merged this with RealFindMembers(). + This function will never be called from TypeManager.MemberLookup() + so we can't use the cache here, just the IMemberFinder. + (TypeManager.MemberLookup_FindMembers): Check whether the + IMemberFinder has a MemberCache and call the cache's FindMembers + function. + (MemberCache): Rewrote larger parts of this yet another time and + cleaned it up a bit. + +2002-08-15 Miguel de Icaza + + * driver.cs (LoadArgs): Support quoting. + + (Usage): Show the CSC-like command line arguments. + + Improved a few error messages. + +2002-08-15 Martin Baulig + + * typemanager.cs (IMemberContainer.Type): New property. + (IMemberContainer.IsInterface): New property. + + The following changes are conditional to BROKEN_RUNTIME, which is + defined at the top of the file. + + * typemanager.cs (MemberCache.MemberCache): Don't add the base + class'es members, but add all members from TypeHandle.ObjectType + if we're an interface. + (MemberCache.AddMembers): Set the Declared flag if member.DeclaringType + is the current type. + (MemberCache.CacheEntry.Container): Removed this field. + (TypeHandle.GetMembers): Include inherited members. + +2002-08-14 Gonzalo Paniagua Javier + + * typemanager.cs: fixed compilation and added a comment on a field that + is never used. + +2002-08-15 Martin Baulig + + * class.cs (ConstructorInitializer.Resolve): In the + Expression.MemberLookup call, use the queried_type as + invocation_type. + + * typemanager.cs (IMemberContainer.GetMembers): Removed the `bool + declared' attribute, it's always true. + (IMemberContainer.Parent, IMemberContainer.Name): New properties. + (TypeManager.MemberLookup_FindMembers): [FIXME FIXME FIXME] Added + temporary wrapper for FindMembers which tells MemberLookup whether + members from the base classes are included in the return value. + This will go away soon. + (TypeManager.MemberLookup): Use this temporary hack here; once the + new MemberCache is completed, we don't need to do the DeclaredOnly + looping here anymore since the MemberCache will take care of this. + (TypeManager.IsSubclassOrNestedChildOf): Allow `type == parent'. + (MemberCache): When creating the MemberCache for a class, get + members from the current class and all its base classes. + (MemberCache.CacheEntry.Container): New field. This is a + temporary hack until the Mono runtime is fixed to distinguish + between ReflectedType and DeclaringType. It allows us to use MCS + with both the MS runtime and the unfixed Mono runtime without + problems and without accecting performance. + (MemberCache.SearchMembers): The DeclaredOnly looping from + TypeManager.MemberLookup is now done here. + +2002-08-14 Martin Baulig + + * statement.cs (MyStructInfo.MyStructInfo): Don't call + Type.GetFields on dynamic types but get the fields from the + corresponding TypeContainer. + (MyStructInfo.GetStructInfo): Added check for enum types. + + * typemanager.cs (MemberList.IsSynchronized): Implemented. + (MemberList.SyncRoot): Implemented. + (TypeManager.FilterWithClosure): No need to check permissions if + closure_start_type == closure_invocation_type, don't crash if + closure_invocation_type is null. + +2002-08-13 Martin Baulig + + Rewrote TypeContainer.FindMembers to use a member cache. This + gives us a speed increase of about 35% for the self-hosting MCS + build and of about 15-20% for the class libs (both on GNU/Linux). + + * report.cs (Timer): New class to get enhanced profiling. This + whole class is "TIMER" conditional since it remarkably slows down + compilation speed. + + * class.cs (MemberList): New class. This is an IList wrapper + which we're now using instead of passing MemberInfo[]'s around to + avoid copying this array unnecessarily. + (IMemberFinder.FindMember): Return a MemberList, not a MemberInfo []. + (ICachingMemberFinder, IMemberContainer): New interface. + (TypeManager.FilterWithClosure): If `criteria' is null, the name + has already been checked, otherwise use it for the name comparision. + (TypeManager.FindMembers): Renamed to RealMemberFinder and + provided wrapper which tries to use ICachingMemberFinder.FindMembers + if possible. Returns a MemberList, not a MemberInfo []. + (TypeHandle): New class, implements IMemberContainer. We create + one instance of this class per type, it contains a MemberCache + which is used to do the member lookups. + (MemberCache): New class. Each instance of this class contains + all members of a type and a name-based hash table. + (MemberCache.FindMembers): This is our new member lookup + function. First, it looks up all members of the requested name in + the hash table. Then, it walks this list and sorts out all + applicable members and returns them. + +2002-08-13 Martin Baulig + + In addition to a nice code cleanup, this gives us a performance + increase of about 1.4% on GNU/Linux - not much, but it's already + half a second for the self-hosting MCS compilation. + + * typemanager.cs (IMemberFinder): New interface. It is used by + TypeManager.FindMembers to call FindMembers on a TypeContainer, + Enum, Delegate or Interface. + (TypeManager.finder_to_member_finder): New PtrHashtable. + (TypeManager.finder_to_container): Removed. + (TypeManager.finder_to_delegate): Removed. + (TypeManager.finder_to_interface): Removed. + (TypeManager.finder_to_enum): Removed. + + * interface.cs (Interface): Implement IMemberFinder. + + * delegate.cs (Delegate): Implement IMemberFinder. + + * enum.cs (Enum): Implement IMemberFinder. + + * class.cs (TypeContainer): Implement IMemberFinder. + +2002-08-12 Martin Baulig + + * ecore.cs (TypeExpr.DoResolveType): Mark this as virtual. + +2002-08-12 Martin Baulig + + * ecore.cs (ITypeExpression): New interface for expressions which + resolve to a type. + (TypeExpression): Renamed to TypeLookupExpression. + (Expression.DoResolve): If we're doing a types-only lookup, the + expression must implement the ITypeExpression interface and we + call DoResolveType() on it. + (SimpleName): Implement the new ITypeExpression interface. + (SimpleName.SimpleNameResolve): Removed the ec.OnlyLookupTypes + hack, the situation that we're only looking up types can't happen + anymore when this method is called. Moved the type lookup code to + DoResolveType() and call it. + (SimpleName.DoResolveType): This ITypeExpression interface method + is now doing the types-only lookup. + (TypeExpr, TypeLookupExpression): Implement ITypeExpression. + (ResolveFlags): Added MaskExprClass. + + * expression.cs (MemberAccess): Implement the ITypeExpression + interface. + (MemberAccess.DoResolve): Added support for a types-only lookup + when we're called via ITypeExpression.DoResolveType(). + (ComposedCast): Implement the ITypeExpression interface. + + * codegen.cs (EmitContext.OnlyLookupTypes): Removed. Call + Expression.Resolve() with ResolveFlags.Type instead. + +2002-08-12 Martin Baulig + + * interface.cs (Interface.Define): Apply attributes. + + * attribute.cs (Attribute.ApplyAttributes): Added support for + interface attributes. + +2002-08-11 Martin Baulig + + * statement.cs (Block.Emit): Only check the "this" variable if we + do not always throw an exception. + + * ecore.cs (PropertyExpr.DoResolveLValue): Implemented, check + whether the property has a set accessor. + +2002-08-11 Martin Baulig + + Added control flow analysis support for structs. + + * ecore.cs (ResolveFlags): Added `DisableFlowAnalysis' to resolve + with control flow analysis turned off. + (IVariable): New interface. + (SimpleName.SimpleNameResolve): If MemberAccess.ResolveMemberAccess + returns an IMemberExpr, call DoResolve/DoResolveLValue on it. + (FieldExpr.DoResolve): Resolve the instance expression with flow + analysis turned off and do the definite assignment check after the + resolving when we know what the expression will resolve to. + + * expression.cs (LocalVariableReference, ParameterReference): + Implement the new IVariable interface, only call the flow analysis + code if ec.DoFlowAnalysis is true. + (This): Added constructor which takes a Block argument. Implement + the new IVariable interface. + (MemberAccess.DoResolve, MemberAccess.DoResolveLValue): Call + DoResolve/DoResolveLValue on the result of ResolveMemberLookup(). + This does the definite assignment checks for struct members. + + * class.cs (Constructor.Emit): If this is a non-static `struct' + constructor which doesn't have any initializer, call + Block.AddThisVariable() to tell the flow analysis code that all + struct elements must be initialized before control returns from + the constructor. + + * statement.cs (MyStructInfo): New public class. + (UsageVector.this [VariableInfo vi]): Added `int field_idx' + argument to this indexer. If non-zero, check an individual struct + member, not the whole struct. + (FlowBranching.CheckOutParameters): Check struct members. + (FlowBranching.IsVariableAssigned, SetVariableAssigned): Added + overloaded versions of these methods which take an additional + `int field_idx' argument to check struct members. + (FlowBranching.IsParameterAssigned, SetParameterAssigned): Added + overloaded versions of these methods which take an additional + `string field_name' argument to check struct member.s + (VariableInfo): Implement the IVariable interface. + (VariableInfo.StructInfo): New public property. Returns the + MyStructInfo instance of the variable if it's a struct or null. + (Block.AddThisVariable): New public method. This is called from + Constructor.Emit() for non-static `struct' constructor which do + not have any initializer. It creates a special variable for the + "this" instance variable which will be checked by the flow + analysis code to ensure that all of the struct's fields are + initialized before control returns from the constructor. + (UsageVector): Added support for struct members. If a + variable/parameter is a struct with N members, we reserve a slot + in the usage vector for each member. A struct is considered fully + initialized if either the struct itself (slot 0) or all its + members are initialized. + +2002-08-08 Martin Baulig + + * driver.cs (Driver.MainDriver): Only report an error CS5001 + if there were no compilation errors. + + * codegen.cs (EmitContext.EmitContext): Use the DeclSpace's + `UnsafeContext' property to determine whether the parent is in + unsafe context rather than checking the parent's ModFlags: + classes nested in an unsafe class are unsafe as well. + +2002-08-08 Martin Baulig + + * statement.cs (UsageVector.MergeChildren): Distinguish between + `Breaks' and `Returns' everywhere, don't set `Breaks' anymore if + we return. Added test17() and test18() to test-154.cs. + +2002-08-08 Martin Baulig + + * typemanager.cs (TypeManager.FilterWithClosure): If we have + Family access, make sure the invoking type isn't a subclass of the + queried type (that'd be a CS1540). + + * ecore.cs (Expression.MemberLookup): Added overloaded version of + this method which takes an additional `Type invocation_type'. + + * expression.cs (BaseAccess.DoResolve): Use the base type as + invocation and query type. + (MemberAccess.DoResolve): If the lookup failed and we're about to + report a CS0122, try a lookup with the ec.ContainerType - if this + succeeds, we must report a CS1540. + +2002-08-08 Martin Baulig + + * ecore.cs (IMemberExpr): Added `bool IsInstance' property. + (MethodGroupExpr): Implement the IMemberExpr interface. + + * expression (MemberAccess.ResolveMemberAccess): No need to have + any special code for MethodGroupExprs anymore, they're now + IMemberExprs. + +2002-08-08 Martin Baulig + + * typemanager.cs (TypeManager.FilterWithClosure): Check Assembly, + Family, FamANDAssem and FamORAssem permissions. + (TypeManager.IsSubclassOrNestedChildOf): New public method. + +2002-08-08 Martin Baulig + + * statement.cs (FlowBranchingType): Added LOOP_BLOCK. + (UsageVector.MergeChildren): `break' breaks unless we're in a switch + or loop block. + +Thu Aug 8 10:28:07 CEST 2002 Paolo Molaro + + * driver.cs: implemented /resource option to embed managed resources. + +2002-08-07 Martin Baulig + + * class.cs (FieldBase.Initializer): Renamed to `init' and made private. + (FieldBase.HasFieldInitializer): New public property. + (FieldBase.GetInitializerExpression): New public method. Resolves and + returns the field initializer and makes sure it is only resolved once. + (TypeContainer.EmitFieldInitializers): Call + FieldBase.GetInitializerExpression to get the initializer, this ensures + that it isn't resolved multiple times. + + * codegen.cs (EmitContext): Added `bool IsFieldInitialier'. This tells + the resolving process (SimpleName/MemberLookup) that we're currently + emitting a field initializer (which must not access any instance members, + this is an error CS0236). + + * ecore.cs (SimpleName.Error_ObjectRefRequired): Added EmitContext + argument, if the `IsFieldInitializer' flag is set, we must report and + error CS0236 and not an error CS0120. + +2002-08-07 Martin Baulig + + * ecore.cs (IMemberExpr): New public interface. + (FieldExpr, PropertyExpr, EventExpr): Implement IMemberExpr. + (SimpleName.SimpleNameResolve): Call MemberAccess.ResolveMemberAccess + if the expression is an IMemberExpr. + + * expression.cs (MemberAccess.ResolveMemberAccess): Allow `left' + to be null, implicitly default to `this' if we're non-static in + this case. Simplified the code a lot by using the new IMemberExpr + interface. Also fixed bug #28176 here. + +2002-08-06 Martin Baulig + + * cs-parser.jay (SimpleLookup): Removed. We need to create + ParameterReferences during semantic analysis so that we can do a + type-only search when resolving Cast, TypeOf and SizeOf. + (block): Pass the `current_local_parameters' to the Block's + constructor. + + * class.cs (ConstructorInitializer): Added `Parameters parameters' + argument to the constructor. + (ConstructorInitializer.Resolve): Create a temporary implicit + block with the parameters. + + * ecore.cs (SimpleName.SimpleNameResolve): Resolve parameter + references here if we aren't doing a type-only search. + + * statement.cs (Block): Added constructor which takes a + `Parameters parameters' argument. + (Block.Parameters): New public property. + + * support.cs (InternalParameters.Parameters): Renamed `parameters' + to `Parameters' and made it public readonly. + +2002-08-06 Martin Baulig + + * ecore.cs (Expression.Warning): Made this public as well. + + * report.cs (Report.Debug): Print the contents of collections. + +2002-08-06 Martin Baulig + + * ecore.cs (Expression.ResolveFlags): New [Flags] enum. This is + used to tell Resolve() which kinds of expressions it may return. + (Expression.Resolve): Added overloaded version of this method which + takes a `ResolveFlags flags' argument. This can be used to tell + Resolve() which kinds of expressions it may return. Reports a + CS0118 on error. + (Expression.ResolveWithSimpleName): Removed, use Resolve() with + ResolveFlags.SimpleName. + (Expression.Error118): Added overloaded version of this method which + takes a `ResolveFlags flags' argument. It uses the flags to determine + which kinds of expressions are allowed. + + * expression.cs (Argument.ResolveMethodGroup): New public method. + Resolves an argument, but allows a MethodGroup to be returned. + This is used when invoking a delegate. + + * TODO: Updated a bit. + +2002-08-06 Gonzalo Paniagua Javier + + Fixed compilation with csc. + + * ecore.cs: Expression.Error made public. Is this correct? Should + Warning be made public too? + + * expression.cs: use ea.Location instead of ea.loc. + [FIXME: Filed as bug #28607: MCS must report these errors.] + +2002-08-06 Martin Baulig + + * ecore.cs (Expression.loc): Moved the location here instead of + duplicating it in all derived classes. + (Expression.Location): New public property. + (Expression.Error, Expression.Warning): Made them non-static and + removed the location argument. + (Expression.Warning): Added overloaded version which takes an + `int level' argument. + (Expression.Error118): Make this non-static and removed the + expression and location arguments. + (TypeExpr): Added location argument to the constructor. + + * expression.cs (StaticCallExpr): Added location argument to + the constructor. + (Indirection, PointerArithmetic): Likewise. + (CheckedExpr, UnCheckedExpr): Likewise. + (ArrayAccess, IndexerAccess, UserCast, ArrayPtr): Likewise. + (StringPtr): Likewise. + + +2002-08-05 Martin Baulig + + * expression.cs (BaseAccess.DoResolve): Actually report errors. + + * assign.cs (Assign.DoResolve): Check whether the source + expression is a value or variable. + + * statement.cs (Try.Resolve): Set ec.InTry/InCatch/InFinally + while resolving the corresponding blocks. + + * interface.cs (Interface.GetInterfaceTypeByName): Actually report + an error, don't silently return null. + + * statement.cs (Block.AddVariable): Do the error reporting here + and distinguish between CS0128 and CS0136. + (Block.DoResolve): Report all unused labels (warning CS0164). + (LabeledStatement): Pass the location to the constructor. + (LabeledStatement.HasBeenReferenced): New property. + (LabeledStatement.Resolve): Set it to true here. + + * statement.cs (Return.Emit): Return success even after reporting + a type mismatch error (CS0126 or CS0127), this is what csc does and + it avoids confusing the users with any consecutive errors. + +2002-08-05 Martin Baulig + + * enum.cs (Enum.LookupEnumValue): Catch circular definitions. + + * const.cs (Const.LookupConstantValue): Catch circular definitions. + + * expression.cs (MemberAccess.DoResolve): Silently return if an + error has already been reported. + + * ecore.cs (Expression.MemberLookupFinal): Silently return if an + error has already been reported. + +2002-08-05 Martin Baulig + + * statement.cs (UsageVector): Only initialize the `parameters' + vector if we actually have any "out" parameters. + +2002-08-05 Martin Baulig + + * expression.cs (Binary.ResolveOperator): When combining delegates, + they must have the same type. + +2002-08-05 Martin Baulig + + * typemanager.cs (TypeManager.GetArgumentTypes): Don't call + PropertyInfo.GetIndexParameters() on dynamic types, this doesn't + work with the ms runtime and we also don't need it: if we're a + PropertyBuilder and not in the `indexer_arguments' hash, then we + are a property and not an indexer. + + * class.cs (TypeContainer.AsAccessible): Use Type.IsArray, + Type.IsPointer and Type.IsByRef instead of Type.HasElementType + since the latter one doesn't work with the ms runtime. + +2002-08-03 Martin Baulig + + Fixed bugs #27998 and #22735. + + * class.cs (Method.IsOperator): New public field. + (Method.CheckBase): Report CS0111 if there's already a method + with the same parameters in the current class. Report CS0508 when + attempting to change the return type of an inherited method. + (MethodData.Emit): Report CS0179 if a method doesn't have a body + and it's not marked abstract or extern. + (PropertyBase): New abstract base class for Property and Indexer. + (PropertyBase.CheckBase): Moved here from Property and made it work + for indexers. + (PropertyBase.Emit): Moved here from Property.Emit, Indexer.Emit is + the same so we can reuse it there. + (Property, Indexer): Derive from PropertyBase. + (MethodSignature.inheritable_property_signature_filter): New delegate + to find properties and indexers. + + * decl.cs (MemberCore.CheckMethodAgainstBase): Added `string name' + argument and improved error reporting. + + * parameter.cs (Parameters.GetEmptyReadOnlyParameters): Renamed to + EmptyReadOnlyParameters and made it a property. + + * typemanager.cs (TypeManager.GetArgumentTypes): Added overloaded + version of this method which takes a `PropertyInfo indexer'. + (TypeManager.RegisterIndexer): New method. + + * class.cs: Added myself as author of this file :-) + +2002-08-03 Gonzalo Paniagua Javier + + * class.cs: fixed compilation on windoze. + +2002-08-03 Martin Baulig + + * interface.cs (Interface.GetInterfaceBases): Check whether all + base interfaces are at least as accessible than the current one. + + * class.cs (TypeContainer.GetClassBases): Check whether base types + are at least as accessible than the current type. + (TypeContainer.AsAccessible): Implemented and made non-static. + (MemberBase.CheckParameters): Report errors if the accessibility + checks fail. + + * delegate.cs (Delegate.Delegate): The default visibility is + internal for top-level types and private for nested types. + (Delegate.Define): Report errors if the accessibility checks fail. + + * enum.cs (Enum.Enum): The default visibility is internal for + top-level types and private for nested types. + (Enum.DefineType): Compute the correct visibility. + + * modifiers.cs (Modifiers.TypeAttr): Added a version of this + function which takes a `bool is_toplevel' instead of a TypeContainer. + + * typemanager.cs (TypeManager.IsBuiltinType): `void' is also a + builtin type. + +2002-08-02 Martin Baulig + + * expression.cs (LocalVariableReferenc): Added constructor which + takes additional `VariableInfo vi' and `bool is_readonly' arguments. + (LocalVariableReference.IsReadOnly): New property. + (LocalVariableReference.DoResolveLValue): Report a CS1604 if the + variable is readonly, use our own readonly flag to do this; you can + use the new constructor to get a writable reference to a read-only + variable. + + * cs-parser.jay (foreach_statement, using_statement): Get a writable + reference to the local variable. + +2002-08-01 Miguel de Icaza + + * rootcontext.cs (ResolveCore): Also include System.Exception + + * statement.cs (Block.Emit): Do not emit the dead-code warnings if + we reach an EmptyStatement. + + (Catch.DoResolve, Throw.DoResolve): Throwing the System.Exception + is also fine. + + * expression.cs (Binary.ResolveOperator): Check error result in + two places. + + use brtrue/brfalse directly and avoid compares to null. + +2002-08-02 Martin Baulig + + * class.cs (TypeContainer.Define): Define all nested interfaces here. + Fixes bug #28407, added test-155.cs. + +2002-08-01 Martin Baulig + + * class.cs (Event.EmitDefaultMethod): Make this work with static + events. Fixes #28311, added verify-3.cs. + +2002-08-01 Martin Baulig + + * statement.cs (ForeachHelperMethods): Added `enumerator_type' and + `is_disposable' fields. + (Foreach.GetEnumeratorFilter): Set `hm.enumerator_type' and + `hm.is_disposable' if we're using the collection pattern. + (Foreach.EmitCollectionForeach): Use the correct type for the + enumerator's local variable, only emit the try/finally block if + necessary (fixes #27713). + +2002-08-01 Martin Baulig + + * ecore.cs (Expression.report118): Renamed to Error118 and made + it public static. + + * statement.cs (Throw.Resolve): Check whether the expression is of + the correct type (CS0118) and whether the type derives from + System.Exception (CS0155). + (Catch.Resolve): New method. Do the type lookup here and check + whether it derives from System.Exception (CS0155). + (Catch.CatchType, Catch.IsGeneral): New public properties. + + * typemanager.cs (TypeManager.exception_type): Added. + +2002-07-31 Miguel de Icaza + + * driver.cs: Updated About function. + +2002-07-31 Martin Baulig + + Implemented Control Flow Analysis. + + * codegen.cs (EmitContext.DoFlowAnalysis): New public variable. + (EmitContext.CurrentBranching): Added. + (EmitContext.StartFlowBranching): Added. + (EmitContext.EndFlowBranching): Added. + (EmitContext.KillFlowBranching): Added. + (EmitContext.IsVariableAssigned): Added. + (EmitContext.SetVariableAssigned): Added. + (EmitContext.IsParameterAssigned): Added. + (EmitContext.SetParameterAssigned): Added. + (EmitContext.EmitTopBlock): Added `InternalParameters ip' argument. + Added control flow analysis stuff here. + + * expression.cs (Unary.DoResolve): If the operator is Oper.AddressOf, + resolve the expression as lvalue. + (LocalVariableReference.DoResolve): Check whether the variable has + already been assigned. + (ParameterReference.DoResolveLValue): Override lvalue resolve to mark + the parameter as assigned here. + (ParameterReference.DoResolve): Check whether the parameter has already + been assigned. + (Argument.Resolve): If it's a `ref' or `out' argument, resolve the + expression as lvalue. + + * statement.cs (FlowBranching): New class for the flow analysis code. + (Goto): Resolve the label in Resolve, not in Emit; added flow analysis. + (LabeledStatement.IsDefined): New public property. + (LabeledStatement.AddUsageVector): New public method to tell flow + analyis that the label may be reached via a forward jump. + (GotoCase): Lookup and resolve the label in Resolve, not in Emit; added + flow analysis. + (VariableInfo.Number): New public field. This is used by flow analysis + to number all locals of a block. + (Block.CountVariables): New public property. This is the number of + local variables in this block (including the locals from all parent + blocks). + (Block.EmitMeta): Number all the variables. + + * statement.cs: Added flow analysis support to all classes. + +2002-07-31 Martin Baulig + + * driver.cs: Added "--mcs-debug" argument if MCS_DEBUG is defined. + To get debugging messages, compile mcs with /define:MCS_DEBUG and + then use this argument. + + * report.cs (Report.Debug): Renamed to conditional to "MCS_DEBUG". + + * makefile.gnu (MCS_FLAGS): Include $(MCS_DEFINES), the user may + use this to specify /define options. + +2002-07-29 Martin Baulig + + * statement.cs (Fixed): Moved all code that does variable lookups + and resolvings from Emit to Resolve. + + * statement.cs (For): Moved all code that does variable lookups + and resolvings from Emit to Resolve. + + * statement.cs (Using): Moved all code that does variable lookups + and resolvings from Emit to Resolve. + +2002-07-29 Martin Baulig + + * attribute.cs (Attribute.Resolve): Explicitly catch a + System.NullReferenceException when creating the + CustromAttributeBuilder and report a different warning message. + +2002-07-29 Martin Baulig + + * support.cs (ParameterData.ParameterName): Added method to + get the name of a parameter. + + * typemanager.cs (TypeManager.IsValueType): New public method. + +2002-07-29 Martin Baulig + + * parameter.cs (Parameter.Modifier): Added `ISBYREF = 8'. This + is a flag which specifies that it's either ref or out. + (Parameter.GetParameterInfo (DeclSpace, int, out bool)): Changed + the out parameter to `out Parameter.Modifier mod', also set the + Parameter.Modifier.ISBYREF flag on it if it's either ref or out. + + * support.cs (InternalParameters.ParameterModifier): Distinguish + between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the + Parameter.Modifier.ISBYREF flag if it's either ref or out. + + * expression.cs (Argument.GetParameterModifier): Distinguish + between Parameter.Modifier.OUT and Parameter.Modifier.REF, set the + Parameter.Modifier.ISBYREF flag if it's either ref or out. + +2002-07-29 Martin Baulig + + * expression.cs (ParameterReference.ParameterReference): Added + `Location loc' argument to the constructor. + + * cs-parser.jay: Pass location to ParameterReference. + +2002-07-28 Miguel de Icaza + + * statement.cs (Try): Initialize the location. + + * cs-parser.jay: pass location to Try. + + * expression.cs (Unary.Reduce): Change the prototype to return + whether a constant fold could be performed or not. The result is + returned in an out parameters. In the case of Indirection and + AddressOf, we want to perform the full tests. + +2002-07-26 Miguel de Icaza + + * statement.cs (Statement.Emit): Flag dead code. + +2002-07-27 Andrew Birkett + + * expression.cs (Unary.Reduce): Handle AddressOf and Indirection. + +2002-07-27 Martin Baulig + + * class.cs (MethodData.Define): Put back call to + TypeManager.AddMethod(), accidentally commented this out. + + * report.cs (Debug): New public method to print debugging information, + this is `[Conditional ("DEBUG")]'. + +2002-07-26 Martin Baulig + + * cs-parser.jay (CSharpParser): Added `Stack switch_stack'. + (switch_statement): Push the current_block to the switch_stack and + pop it again when we're done with the switch. + (switch_section): The new block is a child of the current_block. + Fixes bug #24007, added test-152.cs. + +2002-07-27 Martin Baulig + + * expression.cs (Invocation.EmitArguments): When calling a varargs + function with only its fixed arguments, we need to pass an empty + array. + +2002-07-27 Martin Baulig + + Mono 0.13 has been released. + +2002-07-25 Miguel de Icaza + + * driver.cs: Rename --resource to --linkres, because that is what + we do currently, we dont support --resource yet. + + * cs-tokenizer.cs: Fix test for reporting endif mismatches. + +2002-07-25 Martin Baulig + + * class.cs (MethodData): New public class. This is a `method builder' + class for a method or one accessor of a Property/Indexer/Event. + (MethodData.GetMethodFlags): Moved here from MemberBase. + (MethodData.ApplyAttributes): Likewise. + (MethodData.ApplyObsoleteAttribute): Likewise. + (MethodData.ApplyConditionalAttribute): Likewise. + (MethodData.ApplyDllImportAttribute): Likewise. + (MethodData.CheckAbstractAndExternal): Likewise. + (MethodData.Define): Formerly knows as MemberBase.DefineMethod(). + (MethodData.Emit): Formerly known as Method.Emit(). + (MemberBase): Moved everything which was specific to a single + accessor/method to MethodData. + (Method): Create a new MethodData and call Define() and Emit() on it. + (Property, Indexer, Event): Create a new MethodData objects for each + accessor and call Define() and Emit() on them. + +2002-07-25 Martin Baulig + + Made MethodCore derive from MemberBase to reuse the code from there. + MemberBase now also checks for attributes. + + * class.cs (MethodCore): Derive from MemberBase, not MemberCore. + (MemberBase.GetMethodFlags): Moved here from class Method and marked + as virtual. + (MemberBase.DefineAccessor): Renamed to DefineMethod(), added + `CallingConventions cc' and `Attributes opt_attrs' arguments. + (MemberBase.ApplyAttributes): New virtual method; applies the + attributes to a method or accessor. + (MemberBase.ApplyObsoleteAttribute): New protected virtual method. + (MemberBase.ApplyConditionalAttribute): Likewise. + (MemberBase.ApplyDllImportAttribute): Likewise. + (MemberBase.CheckAbstractAndExternal): Likewise. + (MethodCore.ParameterTypes): This is now a property instead of a + method, it's initialized from DoDefineParameters(). + (MethodCore.ParameterInfo): Removed the set accessor. + (MethodCore.DoDefineParameters): New protected virtual method to + initialize ParameterTypes and ParameterInfo. + (Method.GetReturnType): We can now simply return the MemberType. + (Method.GetMethodFlags): Override the MemberBase version and add + the conditional flags. + (Method.CheckBase): Moved some code from Define() here, call + DoDefineParameters() here. + (Method.Define): Use DoDefine() and DefineMethod() from MemberBase + here to avoid some larger code duplication. + (Property.Emit, Indexer.Emit): Call CheckAbstractAndExternal() to + ensure that abstract and external accessors don't declare a body. + + * attribute.cs (Attribute.GetValidPieces): Make this actually work: + `System.Attribute.GetCustomAttributes (attr.Type)' does a recursive + lookup in the attribute's parent classes, so we need to abort as soon + as we found the first match. + (Attribute.Obsolete_GetObsoleteMessage): Return the empty string if + the attribute has no arguments. + + * typemanager.cs (TypeManager.AddMethod): Now takes a MemberBase instead + of a Method. + +2002-07-24 Gonzalo Paniagua Javier + + * cs-parser.jay: reverted previous patch. + +2002-07-24 Gonzalo Paniagua Javier + + * cs-parser.jay: fixed bug #22119. + +2002-07-24 Gonzalo Paniagua Javier + + * attribute.cs: fixed compilation. The error was: + "attribute.cs(571,17): error CS0177: The out parameter 'is_error' must + be assigned to before control leaves the current method." + [FIXME: Filed as bug #28186: MCS must report this error.] + +2002-07-25 Martin Baulig + + * attribute.cs (Attribute.Conditional_GetConditionName): New static + method to pull the condition name ouf of a Conditional attribute. + (Attribute.Obsolete_GetObsoleteMessage): New static method to pull + the obsolete message and error flag out of an Obsolete attribute. + + * class.cs (Method.GetMethodFlags): New public method to get the + TypeManager.MethodFlags for this method. + (Method.ApplyConditionalAttribute, Method.ApplyObsoleteAttribute): New + private methods. + (Method.Define): Get and apply the Obsolete and Conditional attributes; + if we're overriding a virtual function, set the new private variable + `parent_method'; call the new TypeManager.AddMethod(). + + * typemanager.cs (TypeManager.AddMethod): New static method. Stores + the MethodBuilder and the Method in a PtrHashtable. + (TypeManager.builder_to_method): Added for this purpose. + (TypeManager.MethodFlags): Added IsObsoleteError. + (TypeManager.GetMethodFlags): Added `Location loc' argument. Lookup + Obsolete and Conditional arguments in MethodBuilders. If we discover + an Obsolete attribute, emit an appropriate warning 618 / error 619 with + the message from the attribute. + +2002-07-24 Martin Baulig + + * cs-tokenizer.cs: Eat up trailing whitespaces and one-line comments in + preprocessor directives, ensure that the argument to #define/#undef is + exactly one identifier and that it's actually an identifier. + + Some weeks ago I did a `#define DEBUG 1' myself and wondered why this + did not work .... + +2002-07-24 Martin Baulig + + * statement.cs (Foreach.ForeachHelperMethods): Added `Type element_type', + initialize it to TypeManager.object_type in the constructor. + (Foreach.GetEnumeratorFilter): Set `hm.element_type' to the return type + of the `hm.get_current' method if we're using the collection pattern. + (Foreach.EmitCollectionForeach): Use `hm.element_type' as the source type + for the explicit conversion to make it work when we're using the collection + pattern and the `Current' property has a different return type than `object'. + Fixes #27713. + +2002-07-24 Martin Baulig + + * delegate.cs (Delegate.VerifyMethod): Simply return null if the method + does not match, but don't report any errors. This method is called in + order for all methods in a MethodGroupExpr until a matching method is + found, so we don't want to bail out if the first method doesn't match. + (NewDelegate.DoResolve): If none of the methods in the MethodGroupExpr + matches, report the 123. Fixes #28070. + +2002-07-24 Martin Baulig + + * expression.cs (ArrayAccess.EmitStoreOpcode): Moved the + TypeManager.TypeToCoreType() to the top of the method so the + following equality checks will work. Fixes #28107. + +2002-07-24 Martin Baulig + + * cfold.cs (ConstantFold.DoConstantNumericPromotions): "If either + operand is of type uint, and the other operand is of type sbyte, + short or int, the operands are converted to type long." - + Actually do what this comment already told us. Fixes bug #28106, + added test-150.cs. + +2002-07-24 Martin Baulig + + * class.cs (MethodBase): New abstract class. This is now a base + class for Property, Indexer and Event to avoid some code duplication + in their Define() and DefineMethods() methods. + (MethodBase.DoDefine, MethodBase.DefineAccessor): Provide virtual + generic methods for Define() and DefineMethods(). + (FieldBase): Derive from MemberBase, not MemberCore. + (Property): Derive from MemberBase, not MemberCore. + (Property.DefineMethod): Moved all the code from this method to the + new MethodBase.DefineAccessor(), just call it with appropriate + argumetnts. + (Property.Define): Call the new Property.DoDefine(), this does some + sanity checks and we don't need to duplicate the code everywhere. + (Event): Derive from MemberBase, not MemberCore. + (Event.Define): Use the new MethodBase.DefineAccessor() to define the + accessors, this will also make them work with interface events. + (Indexer): Derive from MemberBase, not MemberCore. + (Indexer.DefineMethod): Removed, call MethodBase.DefineAccessor() insstead. + (Indexer.Define): Use the new MethodBase functions. + + * interface.cs (InterfaceEvent.InterfaceEvent): Added `Location loc' + argument to the constructor. + (Interface.FindMembers): Added support for interface events. + (Interface.PopluateEvent): Implemented. + + Added test-149.cs for this. This also fixes bugs #26067 and #24256. + +2002-07-22 Miguel de Icaza + + * class.cs (TypeContainer.AddMethod): Adding methods do not use IsValid, + but this is required to check for a method name being the same as + the containing class. + + Handle this now. + +2002-07-22 Gonzalo Paniagua Javier + + * interface.cs: initialize variable. + +2002-07-23 Martin Baulig + + Implemented the IndexerName attribute in interfaces. + + * class.cs (TypeContainer.DefineIndexers): Don't set the indexer + name if this is an explicit interface implementation. + (Indexer.InterfaceIndexerName): New public variable. If we're + implementing an interface indexer, this is the IndexerName in that + interface. Otherwise, it's the IndexerName. + (Indexer.DefineMethod): If we're implementing interface indexer, + set InterfaceIndexerName. Use the new Pending.IsInterfaceIndexer + and Pending.ImplementIndexer methods. + (Indexer.Define): Also define the PropertyBuilder if we're + implementing an interface indexer and this is neither an explicit + interface implementation nor do the IndexerName match the one in + the interface. + + * pending.cs (TypeAndMethods): Added `MethodInfo [] need_proxy'. + If a method is defined here, then we always need to create a proxy + for it. This is used when implementing interface indexers. + (Pending.IsInterfaceIndexer): New public method. + (Pending.ImplementIndexer): New public method. + (Pending.InterfaceMethod): Added `MethodInfo need_proxy' argument. + This is used when implementing interface indexers to define a proxy + if necessary. + (Pending.VerifyPendingMethods): Look in the `need_proxy' array and + define a proxy if necessary. + + * interface.cs (Interface.IndexerName): New public variable. + (Interface.PopulateIndexer): Set the IndexerName. + (Interface.DefineIndexers): New private method. Populate all the + indexers and make sure their IndexerNames match. + + * typemanager.cs (IndexerPropertyName): Added support for interface + indexers. + +2002-07-22 Martin Baulig + + * codegen.cs (EmitContext.HasReturnLabel): New public variable. + (EmitContext.EmitTopBlock): Always mark the ReturnLabel and emit a + ret if HasReturnLabel. + (EmitContext.TryCatchLevel, LoopBeginTryCatchLevel): New public + variables. + + * statement.cs (Do.Emit, While.Emit, For.Emit, Foreach.Emit): Save + and set the ec.LoopBeginTryCatchLevel. + (Try.Emit): Increment the ec.TryCatchLevel while emitting the block. + (Continue.Emit): If the ec.LoopBeginTryCatchLevel is smaller than + the current ec.TryCatchLevel, the branch goes out of an exception + block. In this case, we need to use Leave and not Br. + +2002-07-22 Martin Baulig + + * statement.cs (Try.Emit): Emit an explicit ret after the end of the + block unless the block does not always return or it is contained in + another try { ... } catch { ... } block. Fixes bug #26506. + Added verify-1.cs to the test suite. + +2002-07-22 Martin Baulig + + * statement.cs (Switch.TableSwitchEmit): If we don't have a default, + then we do not always return. Fixes bug #24985. + +2002-07-22 Martin Baulig + + * expression.cs (Invocation.OverloadedResolve): Do the BetterFunction() + lookup on a per-class level; ie. walk up the class hierarchy until we + found at least one applicable method, then choose the best among them. + Fixes bug #24463 and test-29.cs. + +2002-07-22 Martin Baulig + + * typemanager.cs (TypeManager.ArrayContainsMethod): Don't check the + return types of the methods. The return type is not part of the + signature and we must not check it to make the `new' modifier work. + Fixes bug #27999, also added test-147.cs. + (TypeManager.TypeToCoreType): Added TypeManager.type_type. + + * expression.cs (Invocation.DoResolve): Call TypeManager.TypeToCoreType() + on the method's return type. + +2002-07-21 Martin Baulig + + * assign.cs: Make this work if the rightmost source is a constant and + we need to do an implicit type conversion. Also adding a few more tests + to test-38.cs which should have caught this. + + * makefile.gnu: Disable debugging, there's already the mcs-mono2.exe + target in the makefile for this. The makefile.gnu is primarily intended + for end-users who don't want to debug the compiler. + +2002-07-21 Martin Baulig + + * assign.cs: Improved the Assign class so it can now handle embedded + assignments (X = Y = Z = something). As a side-effect this'll now also + consume less local variables. test-38.cs now passes with MCS, added + a few new test cases to that test. + +2002-07-20 Martin Baulig + + * expression.cs (Binary.EmitBranchable): Emit correct unsigned branch + instructions. Fixes bug #27977, also added test-146.cs. + +2002-07-19 Gonzalo Paniagua Javier + + * cs-tokenizer.cs: fixed getHex (). + +2002-07-19 Martin Baulig + + * expression.cs (Invocation.EmitParams): Use TypeManager.LookupType(), + not Type.GetType() to lookup the array type. This is needed when + we're constructing an array of a user-defined type. + (ArrayAccess.EmitDynamicInitializers): Only emit the Ldelema for + single-dimensional arrays, but also for single-dimensial arrays of + type decimal. + +2002-07-19 Martin Baulig + + * expression.cs (New.DoEmit): Create a new LocalTemporary each time + this function is called, it's not allowed to share LocalBuilders + among ILGenerators. + +2002-07-19 Martin Baulig + + * expression.cs (Argument.Resolve): Report an error 118 when trying + to pass a type as argument. + +2002-07-18 Martin Baulig + + * ecore.cs (Expression.ImplicitNumericConversion): Don't emit a + Conv_R_Un for the signed `long' type. + +2002-07-15 Miguel de Icaza + + * expression.cs (MemberAccess.DoResolve): Do not reuse the field + `expr' for the temporary result, as that will fail if we do + multiple resolves on the same expression. + +2002-07-05 Miguel de Icaza + + * ecore.cs (SimpleNameResolve): Use ec.DeclSpace instead of + ec.TypeContainer for looking up aliases. + + * class.cs (TypeContainer): Remove LookupAlias from here. + + * decl.cs (DeclSpace); Move here. + +2002-07-01 Miguel de Icaza + + * class.cs (FindMembers): Only call filter if the constructor + bulider is not null. + + Also handle delegates in `NestedTypes' now. Now we will perform + type lookups using the standard resolution process. This also + fixes a bug. + + * decl.cs (DeclSpace.ResolveType): New type resolution routine. + This uses Expressions (the limited kind that can be parsed by the + tree) instead of strings. + + * expression.cs (ComposedCast.ToString): Implement, used to flag + errors since now we have to render expressions. + + (ArrayCreation): Kill FormElementType. Use ComposedCasts in + FormArrayType. + + * ecore.cs (SimpleName.ToString): ditto. + + * cs-parser.jay: Instead of using strings to assemble types, use + Expressions to assemble the type (using SimpleName, ComposedCast, + MemberAccess). This should fix the type lookups in declarations, + because we were using a different code path for this. + + * statement.cs (Block.Resolve): Continue processing statements + even when there is an error. + +2002-07-17 Miguel de Icaza + + * class.cs (Event.Define): Also remove the `remove' method from + the list of pending items. + + * expression.cs (ParameterReference): Use ldarg.N (0..3) to + generate more compact code. + +2002-07-17 Martin Baulig + + * const.cs (Const.LookupConstantValue): Add support for constant + `unchecked' and `checked' expressions. + Also adding test case test-140.cs for this. + +2002-07-17 Martin Baulig + + * statement.cs (Foreach.GetEnumeratorFilter): When compiling corlib, + check whether mi.ReturnType implements the IEnumerator interface; the + `==' and the IsAssignableFrom() will fail in this situation. + +2002-07-16 Ravi Pratap + + * ecore.cs (SimpleName.SimpleNameResolve) : Apply Gonzalo's fix + here too. + +2002-07-16 Gonzalo Paniagua Javier + + * expression.cs: fixed bug #27811. + +2002-07-14 Miguel de Icaza + + * expression.cs (ParameterReference.AddressOf): Patch from Paolo + Molaro: when we are a ref, the value already contains a pointer + value, do not take the address of it. + +2002-07-14 Rafael Teixeira + * removed mb-parser.jay and mb-tokenizer.cs + +Sat Jul 13 19:38:03 CEST 2002 Paolo Molaro + + * expression.cs: check against the building corlib void type. + +Sat Jul 13 19:35:58 CEST 2002 Paolo Molaro + + * ecore.cs: fix for valuetype static readonly fields: when + initializing them, we need their address, not the address of a copy. + +Sat Jul 13 17:32:53 CEST 2002 Paolo Molaro + + * typemanager.cs: register also enum_type in corlib. + +Sat Jul 13 15:59:47 CEST 2002 Paolo Molaro + + * class.cs: allow calling this (but not base) initializers in structs. + +Sat Jul 13 15:12:06 CEST 2002 Paolo Molaro + + * ecore.cs: make sure we compare against the building base types + in GetTypeSize (). + +Sat Jul 13 15:10:32 CEST 2002 Paolo Molaro + + * typemanager.cs: fix TypeToCoreType() to handle void and object + (corlib gets no more typerefs after this change). + +2002-07-12 Miguel de Icaza + + * expression.cs (ArrayCreation.EmitArrayArguments): use + Conv.Ovf.U4 for unsigned and Conv.Ovf.I4 for signed. + + (ArrayAccess.LoadArrayAndArguments): Use Conv_Ovf_I and + Conv_Ovf_I_Un for the array arguments. Even if C# allows longs as + array indexes, the runtime actually forbids them. + + * ecore.cs (ExpressionToArrayArgument): Move the conversion code + for array arguments here. + + * expression.cs (EmitLoadOpcode): System.Char is a U2, use that + instead of the default for ValueTypes. + + (New.DoEmit): Use IsValueType instead of + IsSubclassOf (value_type) + (New.DoResolve): ditto. + (Invocation.EmitCall): ditto. + + * assign.cs (Assign): ditto. + + * statement.cs (Unsafe): Ok, so I got the semantics wrong. + Statements *are* currently doing part of their resolution during + Emit. + + Expressions do always resolve during resolve, but statements are + only required to propagate resolution to their children. + +2002-07-11 Miguel de Icaza + + * driver.cs (CSCParseOption): Finish the /r: and /lib: support. + + (LoadAssembly): Do not add the dll if it is already specified + + (MainDriver): Add the System directory to the link path at the end, + after all the other -L arguments. + + * expression.cs (ArrayAccess.EmitLoadOpcode): I was using the + wrong opcode for loading bytes and bools (ldelem.i1 instead of + ldelem.u1) and using the opposite for sbytes. + + This fixes Digger, and we can finally run it. + + * driver.cs (UnixParseOption): Move the option parsing here. + (CSCParseOption): Implement CSC-like parsing of options. + + We now support both modes of operation, the old Unix way, and the + new CSC-like way. This should help those who wanted to make cross + platform makefiles. + + The only thing broken is that /r:, /reference: and /lib: are not + implemented, because I want to make those have the same semantics + as the CSC compiler has, and kill once and for all the confussion + around this. Will be doing this tomorrow. + + * statement.cs (Unsafe.Resolve): The state is checked during + resolve, not emit, so we have to set the flags for IsUnsfe here. + +2002-07-10 Miguel de Icaza + + * expression.cs (MemberAccess.ResolveMemberAccess): Since we can + not catch the Error_ObjectRefRequired in SimpleName (as it is + possible to have a class/instance variable name that later gets + deambiguated), we have to check this here. + +2002-07-10 Ravi Pratap + + * class.cs (TypeContainer.GetFieldFromEvent): Move away from here, + make static and put into Expression. + + (Event.Define): Register the private field of the event with the + TypeManager so that GetFieldFromEvent can get at it. + + (TypeManager.RegisterPrivateFieldOfEvent): Implement to + keep track of the private field associated with an event which + has no accessors. + + (TypeManager.GetPrivateFieldOfEvent): Implement to get at the + private field. + + * ecore.cs (GetFieldFromEvent): RE-write to use the above methods. + +2002-07-10 Miguel de Icaza + + * expression.cs (Binary.EmitBranchable): this routine emits the + Binary expression in a branchable context. This basically means: + we need to branch somewhere, not just get the value on the stack. + + This works together with Statement.EmitBoolExpression. + + * statement.cs (Statement.EmitBoolExpression): Use + EmitBranchable. + +2002-07-09 Miguel de Icaza + + * statement.cs (For): Reduce the number of jumps in loops. + + (For): Implement loop inversion for the For statement. + + (Break): We can be breaking out of a Try/Catch controlled section + (foreach might have an implicit try/catch clause), so we need to + use Leave instead of Br. + + * ecore.cs (FieldExpr.AddressOf): Fix for test-139 (augmented + now). If the instace expression supports IMemoryLocation, we use + the AddressOf method from the IMemoryLocation to extract the + address instead of emitting the instance. + + This showed up with `This', as we were emitting the instance + always (Emit) instead of the Address of This. Particularly + interesting when This is a value type, as we dont want the Emit + effect (which was to load the object). + +2002-07-08 Miguel de Icaza + + * attribute.cs: Pass the entry point to the DefinePInvokeMethod + + * statement.cs (Checked): Set the CheckedState during the resolve + process too, as the ConvCast operations track the checked state on + the resolve process, and not emit. + + * cs-parser.jay (namespace_member_declaration): Flag that we have + found a declaration when we do. This is used to flag error 1529 + + * driver.cs: Report ok when we display the help only. + +2002-07-06 Andrew Birkett + + * cs-tokenizer.cs (xtoken): Improve handling of string literals. + +2002-07-04 Miguel de Icaza + + * cs-tokenizer.cs (define): We also have to track locally the + defines. AllDefines is just used for the Conditional Attribute, + but we also need the local defines for the current source code. + +2002-07-03 Miguel de Icaza + + * statement.cs (While, For, Do): These loops can exit through a + Break statement, use this information to tell whether the + statement is the last piece of code. + + (Break): Flag that we break. + + * codegen.cs (EmitContexts): New `Breaks' state variable. + +2002-07-03 Martin Baulig + + * class.cs (TypeContainer.MethodModifiersValid): Allow override + modifiers in method declarations in structs. Otherwise, you won't + be able to override things like Object.Equals(). + +2002-07-02 Miguel de Icaza + + * class.cs (Method, Property, Indexer): Do not allow the public + modifier to be used in explicit interface implementations. + + (TypeContainer.MethodModifiersValid): Catch virtual, abstract and + override modifiers in method declarations in structs + +2002-07-02 Andrew Birkett + + * cs-tokenizer.cs (adjust_int, adjust_real): Do not abort on + integer or real overflow, report an error + +2002-07-02 Martin Baulig + + * typemanager.cs (TypeManager.InitCoreTypes): When compiling + corlib, dynamically call AssemblyBuilder.SetCorlibTypeBuilders() + to tell the runtime about our newly created System.Object and + System.ValueType types. + +2002-07-02 Miguel de Icaza + + * expression.cs (This): Use Stobj/Ldobj when we are a member of a + struct instead of Ldarg/Starg. + +2002-07-02 Martin Baulig + + * expression.cs (Indirection.Indirection): Call + TypeManager.TypeToCoreType() on `expr.Type.GetElementType ()'. + +2002-07-02 Martin Baulig + + * expression.cs (ArrayAccess.EmitStoreOpcode): If the type is a + ValueType, call TypeManager.TypeToCoreType() on it. + (Invocations.EmitParams): Call TypeManager.TypeToCoreType() on + the OpCodes.Newarr argument. + +2002-07-02 Martin Baulig + + * expression.cs (Invocation.EmitCall): When compiling corlib, + replace all calls to the system's System.Array type to calls to + the newly created one. + + * typemanager.cs (TypeManager.InitCodeHelpers): Added a few more + System.Array methods. + (TypeManager.InitCoreTypes): When compiling corlib, get the methods + from the system's System.Array type which must be replaced. + +Tue Jul 2 19:05:05 CEST 2002 Paolo Molaro + + * typemanager.cs: load unverifiable_code_ctor so we can build + corlib using the correct type. Avoid using GetTypeCode() with + TypeBuilders. + * rootcontext.cs: uses TypeManager.unverifiable_code_ctor and + TypeManager.object_type to allow building corlib. + +Tue Jul 2 19:03:19 CEST 2002 Paolo Molaro + + * ecore.cs: handle System.Enum separately in LoadFromPtr(). + +2002-07-01 Martin Baulig + + * class.cs: Make the last change actually work, we need to check + whether `ifaces != null' to avoid a crash. + +Mon Jul 1 16:15:03 CEST 2002 Paolo Molaro + + * class.cs: when we build structs without fields that implement + interfaces, we need to add the interfaces separately, since there is + no API to both set the size and add the interfaces at type creation + time. + +Mon Jul 1 14:50:47 CEST 2002 Paolo Molaro + + * expression.cs: the dimension arguments to the array constructors + need to be converted if they are a long. + +Mon Jul 1 12:26:12 CEST 2002 Paolo Molaro + + * class.cs: don't emit ldarg.0 if there is no parent constructor + (fixes showstopper for corlib). + +2002-06-29 Martin Baulig + + MCS now compiles corlib on GNU/Linux :-) + + * attribute.cs (Attribute.ApplyAttributes): Treat Accessors like Method, + ie. check for MethodImplOptions.InternalCall. + + * class.cs (TypeContainer.DefineType): When compiling corlib, both parent + and TypeManager.attribute_type are null, so we must explicitly check + whether parent is not null to find out whether it's an attribute type. + (Property.Emit): Always call Attribute.ApplyAttributes() on the GetBuilder + and SetBuilder, not only if the property is neither abstract nor external. + This is necessary to set the MethodImplOptions on the accessor methods. + (Indexer.Emit): Call Attribute.ApplyAttributes() on the GetBuilder and + SetBuilder, see Property.Emit(). + + * rootcontext.cs (RootContext.PopulateTypes): When compiling corlib, don't + populate "System.Object", "System.ValueType" and "System.Attribute" since + they've already been populated from BootCorlib_PopulateCoreTypes(). + +2002-06-29 Martin Baulig + + * ecore.cs (Expression.ImplicitReferenceConversionExists): If expr + is the NullLiteral, we also need to make sure that target_type is not + an enum type. + +2002-06-29 Martin Baulig + + * rootcontext.cs (RootContext.ResolveCore): We must initialize + `TypeManager.multicast_delegate_type' and `TypeManager.delegate_type' + before calling BootstrapCorlib_ResolveDelegate (). + +2002-06-27 Gonzalo Paniagua Javier + + * statement.cs: fixed build-breaker. All tests passed ok. + +2002-06-27 Martin Baulig + + * typemanager.cs (TypeManager.VerifyUnManaged): Added explicit check + for System.Decimal when compiling corlib. + +2002-06-27 Martin Baulig + + * statement.cs (Switch.TableSwitchEmit): Make this work with empty + switch blocks which contain nothing but a default clause. + +2002-06-26 Andrew + + * ../errors/cs1501-3.cs: Added new test for struct ctr typechecks. + +2002-06-27 Martin Baulig + + * ecore.cs (PropertyExpr.PropertyExpr): Call + TypeManager.TypeToCoreType() on the `pi.PropertyType'. + + * typemanager.cs (TypeManager.TypeToCoreType): Return if the type + is already a TypeBuilder. + +2002-06-27 Martin Baulig + + * ecore.cs (Expression.ImplicitReferenceConversionExists): Use + `target_type == TypeManager.array_type', not IsAssignableFrom() in + the "from an array-type to System.Array" case. This makes it work + when compiling corlib. + +2002-06-27 Martin Baulig + + * ecore.cs (Expression.SimpleNameResolve): If the expression is a + non-static PropertyExpr, set its InstanceExpression. This makes + the `ICollection.Count' property work in System/Array.cs. + +2002-06-25 Andrew Birkett + + * driver.cs: Made error handling more consistent. Errors now + tracked by Report class, so many methods which used to return int + now return void. Main() now prints success/failure and + errors/warnings message. + + Renamed '--probe' compiler argument to '--expect-error'. Removed + the magic number return values (123 and 124). Now, if the + expected error occurs, the compiler exits with success (exit value + 0). If the compilation completes without seeing that particular + error, the compiler exits with failure (exit value 1). The + makefile in mcs/errors has been changed to handle the new behaviour. + + * report.cs: Made 'expected error' number a property and renamed + it from 'Probe' to 'ExpectedError'. + + * genericparser.cs: Removed error handling support, since it is + now all done by Report class. + + * cs-parser.jay, mb-parser.jay: Errors are tracked by Report + class, so parse() no longer returns an int. + + * namespace.cs: Use Report.Error instead of GenericParser.error + +2002-06-22 Miguel de Icaza + + * class.cs (TypeContainer.AddMethod, TypeContainer.AddIndexer, + TypeContainer.AddOperator): At the front of the list put the + explicit implementations, so they get resolved/defined first. + +2002-06-21 Miguel de Icaza + + * class.cs (TypeContainer.VerifyImplements): Verifies that a given + interface type is implemented by this TypeContainer. Used during + explicit interface implementation. + + (Property.Define, Indexer.Define, Method.Define): Validate that + the given interface in the explicit implementation is one of the + base classes for the containing type. + + Also if we are explicitly implementing an interface, but there is + no match in the pending implementation table, report an error. + + (Property.Define): Only define the property if we are + not explicitly implementing a property from an interface. Use the + correct name also for those properties (the same CSC uses, + although that is really not needed). + + (Property.Emit): Do not emit attributes for explicitly implemented + properties, as there is no TypeBuilder. + + (Indexer.Emit): ditto. + + Hiding then means that we do not really *implement* a pending + implementation, which makes code fail. + +2002-06-22 Martin Baulig + + * ecore.cs (Expression.Constantify): Call TypeManager.TypeToCoreType() on + the return value of Object.GetType(). [FIXME: we need to do this whenever + we get a type back from the reflection library]. + +Fri Jun 21 13:37:57 CEST 2002 Paolo Molaro + + * typemanager.cs: make ExpandInterfaces() slip duplicated interfaces. + +2002-06-20 Miguel de Icaza + + * attribute.cs: Return null if we can not look up the type. + + * class.cs (TypeContainer.GetClassBases): Use ExpandInterfaces on + the interface types found. + + * interface.cs (Interface.GetInterfaceBases): Use ExpandInterfaces on the + interface types found. + + * typemanager.cs (GetInterfaces): Make this routine returns alll + the interfaces and work around the lame differences between + System.Type and System.Reflection.Emit.TypeBuilder in the results + result for GetInterfaces. + + (ExpandInterfaces): Given an array of interface types, expand and + eliminate repeated ocurrences of an interface. This expands in + context like: IA; IB : IA; IC : IA, IB; the interface "IC" to + be IA, IB, IC. + +2002-06-21 Martin Baulig + + * typemanager.cs (TypeManager.EnumToUnderlying): It's now safe to call this function + on System.Enum. + +2002-06-21 Martin Baulig + + * typemanager.cs (TypeManager.TypeToCoreType): New function. When compiling corlib + and called with one of the core types, return the corresponding typebuilder for + that type. + + * expression.cs (ArrayAccess.DoResolve): Call TypeManager.TypeToCoreType() on the + element type. + +2002-06-21 Martin Baulig + + * ecore.cs (Expression.ExplicitReferenceConversionExists): Use + `target_type.IsArray' instead of `target_type.IsSubclassOf (TypeManager.array_type)'. + (Expression.ConvertReferenceExplicit): Likewise. + + * expression.cs (ElementAccess.DoResolve): Likewise. + (ElementAccess.DoResolveLValue): Likewise. + +2002-06-10 Martin Baulig + + * interface.cs (Interface.PopulateIndexer): When creating the setter, we need to + add the "value" parameter to the parameter list. + + * statement.cs (Fixed.Emit): Pass the return value of the child block's Emit() + to our caller. + +2002-06-19 Miguel de Icaza + + * expression.cs (ArrayCreation.ExpressionToArrayArgument): Convert + the argument to an int, uint, long or ulong, per the spec. Also + catch negative constants in array creation. + +Thu Jun 20 17:56:48 CEST 2002 Paolo Molaro + + * class.cs: do not allow the same interface to appear twice in + the definition list. + +Wed Jun 19 22:33:37 CEST 2002 Paolo Molaro + + * ecore.cs: don't use ldlen with System.Array. + +Wed Jun 19 20:57:40 CEST 2002 Paolo Molaro + + * ecore.cs: stobj requires a type argument. Handle indirect stores on enums. + +Wed Jun 19 20:17:59 CEST 2002 Paolo Molaro + + * modifiers.cs: produce correct field attributes for protected + internal. Easy fix so miguel can work on ther harder stuff:-) + +2002-06-18 Miguel de Icaza + + * pending.cs: New file. Move the code from class.cs here. + Support clearning the pending flag for all methods (when not doing + explicit interface implementation). + +Tue Jun 18 10:36:22 CEST 2002 Paolo Molaro + + * rootcontext.cs: added a couple more types needed to bootstrap. + +2002-06-17 Miguel de Icaza + + * typemanager.cs (GetConstructor): Use DeclaredOnly to look the + constructor in the type, instead of any constructor in the type + hierarchy. Thanks to Paolo for finding this bug (it showed up as + a bug in the Mono runtime when applying the params attribute). + +2002-06-16 Rafael Teixeira + * changed namespace.cs to use "GenericParser.error(...)" instead of "CSharpParser.error(...)" + +2002-06-14 Rachel Hestilow + + * expression.cs (Unary.ResolveOperator): Use TypeManager + to resolve the type. + +2002-06-13 Ravi Pratap + + * cs-parser.jay (enum_member_declaration): Pass in the attributes + attached. + + * enum.cs (AddEnumMember): Add support to store the attributes associated + with each member too. + + * attribute.cs (CheckAttribute, ApplyAttributes): Update to handle + field builders too - this takes care of the enum member case. + +2002-06-10 Rachel Hestilow + + * typemanager.cs (TypeManager.VerifyUnManaged): Allow + address-of operator on both value types and pointers. + +2002-06-10 Martin Baulig + + * interface.cs (Interface.PopulateIndexer): Add the indexer's + PropertyBuilder to the `property_builders' list. + + * expression.cs (Indexers.GetIndexersForTypeOrInterface): New private method. + (Indexers.GetIndexersForType): Call GetIndexersForTypeOrInterface() on the + `lookup_type' and all its interfaces. Unfortunately, Type.FindMembers() won't + find any indexers which are inherited from an interface. + +2002-06-09 Martin Baulig + + * const.cs (Const.LookupConstantValue): Convert `Expr' to a literal of + the same type as the constant if necessary. There's also a test-130.cs + for this. + + * enum.cs (Enum.ChangeEnumType): Moved to typemanager.cs and made public. + + * typemanager.cs (TypeManager.ChangeType): Previously known as + Enum.ChangeEnumType(). + +2002-06-09 Martin Baulig + + * expression.cs (Cast.TryReduce): Added support for consts. + +2002-06-08 Ravi Pratap + + * class.cs (Accessor): Hold attributes information so we can pass + it along. + + * cs-parser.jay (get_accessor_declaration, set_accessor_declaration): + Modify to pass in attributes attached to the methods. + + (add_accessor_declaration, remove_accessor_declaration): Ditto. + + * attribute.cs (ApplyAttributes, CheckAttribute): Update accordingly + to handle the Accessor kind :-) + + * class.cs (Property.Emit, Event.Emit): Apply attributes to the accessors + +2002-06-08 Martin Baulig + + * expression.cs (Unary.TryReduceNegative): Added support for + ULongConstants. + +2002-06-08 Martin Baulig + + * enum.cs (Enum.LookupEnumValue): Don't report an error if the + name can't be found in the `defined_names' - the caller will do a + MemberLookup in this case and thus find methods in System.Enum + such as Enum.IsDefined(). + +2002-06-08 Martin Baulig + + * enum.cs (Enum.ChangeEnumType): This is a custom version of + Convert.ChangeType() which works with TypeBuilder created types. + (Enum.LookupEnumValue, Enum.Define): Use it here. + + * class.cs (TypeContainer.RegisterRequiredImplementations): Added + `TypeBuilder.BaseType != null' check. + (TypeContainer.FindMembers): Only lookup parent members if we + actually have a parent. + (Method.EmitDestructor): Added `ec.ContainerType.BaseType != null' check. + (ConstructorInitializer.Resolve): Likewise. + + * interface.cs (Interface.FindMembers): Added + `TypeBuilder.BaseType != null' check. + + * rootcontext.cs (RootContext.ResolveCore): Added + "System.Runtime.CompilerServices.IndexerNameAttribute" to + classes_second_stage. + + * typemanager.cs (TypeManager.InitCoreTypes): Don't initialize + debug_type and trace_type when compiling with --nostdlib. + +2002-06-07 Martin Baulig + + * class.cs (TypeContainer): Added `have_nonstatic_fields' field. + (AddField): Set it to true when adding a non-static field. + (DefineType): Use `have_nonstatic_fields' to find out whether we + have non-static fields, not `Fields != null'. + +2002-06-02 Miguel de Icaza + + * ecore.cs (SimpleNameResolve): Removed simple bug (we were + dereferencing a null on the static-field code path) + +2002-05-30 Martin Baulig + + * codegen.cs (InitMonoSymbolWriter): Added `string[] args' argument + to take command line arguments. Use reflection to call the new + custom `Initialize' function on the symbol writer and pass it the + command line arguments. + + * driver.cs (--debug-args): New command line argument to pass command + line arguments to the symbol writer. + +2002-05-28 Miguel de Icaza + + * assign.cs (DoResolve): Forgot to do the implicit conversion to + the target type for indexers and properties. Thanks to Joe for + catching this. + +2002-05-27 Miguel de Icaza + + * typemanager.cs (MethodFlags): returns the method flags + (Obsolete/ShouldIgnore) that control warning emission and whether + the invocation should be made, or ignored. + + * expression.cs (Invocation.Emit): Remove previous hack, we should + not do this on matching a base type, we should do this based on an attribute + + Only emit calls to System.Diagnostics.Debug and + System.Diagnostics.Trace if the TRACE and DEBUG defines are passed + on the command line. + + * rootcontext.cs: Global settings for tracing and debugging. + + * cs-tokenizer.cs (define): New utility function to track + defines. Set the global settings for TRACE and DEBUG if found. + +2002-05-25 Ravi Pratap + + * interface.cs (Populate*): Pass in the TypeContainer as well as + the DeclSpace as parameters so that we can create EmitContexts and + then use that to apply attributes etc. + + (PopulateMethod, PopulateEvent, PopulateProperty) + (PopulateIndexer): Apply attributes everywhere. + + * attribute.cs (CheckAttribute): Include InterfaceMethod, InterfaceEvent + etc. + + (ApplyAttributes): Update accordingly. + + We now apply interface attributes for all members too. + +2002-05-26 Miguel de Icaza + + * class.cs (Indexer.Define); Correctly check if we are explicit + implementation (instead of checking the Name for a ".", we + directly look up if the InterfaceType was specified). + + Delay the creation of the PropertyBuilder. + + Only create the PropertyBuilder if we are not an explicit + interface implementation. This means that explicit interface + implementation members do not participate in regular function + lookups, and hence fixes another major ambiguity problem in + overload resolution (that was the visible effect). + + (DefineMethod): Return whether we are doing an interface + implementation. + + * typemanager.cs: Temporary hack until we get attributes in + interfaces (Ravi is working on that) and we get IndexerName + support in interfaces. + + * interface.cs: Register the indexers as properties. + + * attribute.cs (Attribute.Resolve): Catch the error, and emit a + warning, I have verified that this is a bug in the .NET runtime + (JavaScript suffers of the same problem). + + * typemanager.cs (MemberLookup): When looking up members for + interfaces, the parent of an interface is the implicit + System.Object (so we succeed in searches of Object methods in an + interface method invocation. Example: IEnumerable x; x.ToString + ()) + +2002-05-25 Miguel de Icaza + + * class.cs (Event): Events should also register if they do + implement the methods that an interface requires. + + * typemanager.cs (MemberLookup); use the new GetInterfaces + method. + + (GetInterfaces): The code used to lookup interfaces for a type is + used in more than one place, factor it here. + + * driver.cs: Track the errors at the bottom of the file, we kept + on going. + + * delegate.cs (NewDelegate.Emit): We have to emit a null as the + instance if the method we are calling is static! + +2002-05-24 Miguel de Icaza + + * attribute.cs (ApplyAttributes): Make this function filter out + the IndexerName attribute (as that attribute in reality is never + applied) and return the string constant for the IndexerName + attribute. + + * class.cs (TypeContainer.Emit): Validate that all the indexers + have the same IndexerName attribute, and if so, set the + DefaultName attribute on the class. + + * typemanager.cs: The return value might contain other stuff (not + only methods). For instance, consider a method with an "Item" + property and an Item method. + + * class.cs: If there is a problem with the parameter types, + return. + +2002-05-24 Ravi Pratap + + * ecore.cs (ImplicitConversionExists): Wrapper function which also + looks at user defined conversion after making a call to + StandardConversionExists - we need this for overload resolution. + + * expression.cs : Update accordingly the various method calls. + + This fixes 2 bugs filed against implicit user defined conversions + +2002-05-22 Miguel de Icaza + + * statement.cs: Track the result of the assignment. + +2002-05-21 Miguel de Icaza + + * expression.cs (MemberAccess): Improved error reporting for + inaccessible members. + +2002-05-22 Martin Baulig + + * makefile (mcs-mono2.exe): New target. This is mcs compiled with + itself with debugging support. + +2002-05-22 Martin Baulig + + * typemanager.cs ("System.Runtime.InteropServices.StructLayoutAttribute"): + Removed, this isn't needed anymore. + +2002-05-20 Martin Baulig + + * typemanager.cs (InitEnumUnderlyingTypes): "System.Char" can't + be underlying type for an enum. + +2002-05-20 Miguel de Icaza + + * typemanager.cs (InitEnumUnderlyingTypes): New helper function + that splits out the loading of just the core types. + + * rootcontext.cs (ResolveCore): Split the struct resolution in + two, so we can load the enumeration underlying types before any + enums are used. + + * expression.cs (Is): Bandaid until we fix properly Switch (see + bug #24985 for details). + + * typemanager.cs (ImplementsInterface): The hashtable will contain + a null if there are no interfaces implemented. + +2002-05-18 Miguel de Icaza + + * cs-parser.jay (indexer_declarator): It is fine to have array + parameters + +2002-05-17 Miguel de Icaza + + * typemanager.cs: (RegisterBuilder): New function used to register + TypeBuilders that implement interfaces. Since + TypeBuilder.GetInterfaces (as usual) does not work with lame + Reflection.Emit. + (AddUserType): register interfaces. + + (ImplementsInterface): Use the builder_to_ifaces hash if we are + dealing with TypeBuilder. Also, arrays are showing up as + SymbolTypes, which are not TypeBuilders, but whose GetInterfaces + methods can not be invoked on them! + + * ecore.cs (ExplicitReferenceConversionExists): Made public. + (ImplicitReferenceConversionExists): Split out from + StandardConversionExists. + + * expression.cs (As): We were only implementing one of the three + cases for the as operator. We now implement them all. + (Is): Implement the various other cases for Is as well. + + * typemanager.cs (CACHE): New define used to control if we want or + not the FindMembers cache. Seems to have a negative impact on + performance currently + + (MemberLookup): Nested types have full acess to + enclosing type members + + Remove code that coped with instance/static returns for events, we + now catch this in RealFindMembers. + + (RealFindMembers): only perform static lookup if the instance + lookup did not return a type or an event. + +2002-05-17 Miguel de Icaza + + * assign.cs (CompoundAssign): We pass more semantic information + now to Compound Assignments than we did before: now we have all + the information at hand, and now we resolve the target *before* we + do the expression expansion, which allows the "CacheValue" method + to have the effect we intended (before, a [x] += 1 would generate + two differen ArrayAccess expressions from the ElementAccess, + during the resolution process). + + (CompoundAssign.DoResolve): Resolve target and original_source here. + +2002-05-16 Miguel de Icaza + + * expression.cs (ArrayAccess): dropped debugging information. + + * typemanager.cs: Small bug fix: I was always returning i_members, + instead of one of i_members or s_members (depending on which had + the content). + + * assign.cs (IAssignMethod.CacheTemporaries): New method. This + method is invoked before any code generation takes place, and it + is a mechanism to inform that the expression will be invoked more + than once, and that the method should use temporary values to + avoid having side effects + + (Assign.Emit): Call CacheTemporaries in the IAssignMethod. + + * ecore.cs (Expression.CacheTemporaries): Provide empty default + implementation. + + * expression.cs (Indirection, ArrayAccess): Add support for + CacheTemporaries in these two bad boys. + + * ecore.cs (LoadFromPtr): figure out on our own if we need to use + ldobj or ldind_ref. + (StoreFromPtr): Handle stobj as well. + + * expression.cs (UnaryMutator): Share more code. + + * typemanager.cs (FindMembers): Thanks to Paolo for tracking this + down: I was not tracking the Filter function as well, which + was affecting the results of the cache. + +2002-05-15 Miguel de Icaza + + * attribute.cs: Remove the hack to handle the CharSet property on + StructLayouts. + +2002-05-14 Miguel de Icaza + + * attribute.cs (DoResolve): More uglyness, we now only try to + resolve the attribute partially, to extract the CharSet + information (only if we are a StructLayout attribute). Otherwise + + (GetExtraTypeInfo): Add some code to conditionally kill in the + future this. I am more and more convinced that the .NET + framework has special code to handle the attribute setting on + certain elements. + + * expression.cs (IsParamsMethodApplicable): Revert my previous + foreach change here, it was wrong. + +2002-05-13 Miguel de Icaza + + * cs-tokenizer.cs: (pp_primary): Eat the ')' at the end. + (pp_expr): do not abort on unknown input, just return. + (eval): abort if there are pending chars. + + * attribute.cs (Attribute.Resolve): Positional parameters are + optional. Deal with that case. + + * class.cs (DefineType): Call Attribute.GetExtraTypeInfo to fetch + the Ansi/Unicode/Auto information for the type. + + (TypeContainer.DefineType): instantiate the EmitContext here, as + we will be using it during the type definition (to resolve + attributes) and during the emit phase. + + * attribute.cs (Attribute.GetExtraTypeInfo): This routine is used + to pull type information out of the attributes + + (Attribute.Resolve): track the constructor builder, and allow for + multiple invocations (structs and classes will use this). + + * ecore.cs (MemberLookupFinal): new version with all the + parameters customizable. + + * expression.cs (New.DoResolve): Use MemberLookupFinal to locate + constructors. Return if the result value is null (as the error + would have been flagged already by MemberLookupFinal) + + Do not allow instances of abstract classes or interfaces to be + created. + + * class.cs: (MethodSignature.InheritableMemberSignatureCompare): + We have to compare the assembly property here when dealing with + FamANDAssem and Assembly access modifiers, because we might be + creating an assembly from *modules* (that means that we are not + getting TypeBuilders for types defined in other modules that are + part of this assembly). + + (Method.Emit): If the method is marked abstract and has a body, + emit an error. + + (TypeContainer.DefineMembers): If both the defined member and the + parent name match are methods, then do not emit any warnings: let + the Method.Define routine take care of flagging warnings. But if + there is a mismatch (method overrides something else, or method is + overriwritten by something, then emit warning). + + (MethodSignature.MemberSignatureCompare): If the sig.ret_type is + set to null, this means `do not check for the return type on the + signature'. + + (Method.Define): set the return type for the method signature to + null, so that we get methods with the same name and parameters and + different return types. This is used to flag warning 114 (you are + hiding a method, and you probably want to use the new/override + keywords instead). + + * typemanager.cs (MemberLookup): Implemented proper access + control, closing a long standing set of bug reports. The problem + was that the Framework only has two bits: Public and NonPublic, + and NonPublic includes private and protected methods, but we need + to enforce the FamANDAssem, FamOrAssem and Family. + +2002-05-11 Miguel de Icaza + + * statement.cs (GotoCase): Return true: Ammounts to giving up + knowledge on whether we return or not, and letting the other case + be responsible for it. + +2002-05-10 Miguel de Icaza + + * driver.cs: Do not load directories for each file processed, only + do it if there is a pattern. + + * ecore.cs: Report readonly assigns here as well, as we might have + been resolved only by MemberAccess. + + (SimpleName.SimpleNameResolve): Also be useful for LValue + resolution. We need this to propagate assign to local readonly variables + + * typemanager.cs: Use a ptrhashtable for the criteria, because we + do not want to reuse potential criteria memory. + + * class.cs (MyEventBuilder): Set reflected_type; + + * ecore.cs (Constantify): Added support for constifying bools. + + (RootContext.LookupType): Added a cache for values looked up in + the declaration space. + + * typemanager.cs (FindMembers): Now is a front-end to + RealFindMembers, and provides a two-level hashtable-based cache to + the request. + + 15% performance improvement: from 22.5 to 19.2 seconds. + + * expression.cs (IsParamsMethodApplicable): use foreach. + (Invocation.DoResolve): ditto. + (New.DoResolve): ditto. + (ArrayCreation.DoResolve): ditto. + + * ecore.cs (FindMostEncompassingType): use foreach. + + * delegate.cs (NewDelegate.DoResolve): Use foreach + + * ecore.cs (Expression.FindMostSpecificSource): Use foreach. + (RemoveMethods): use foreach. + + * expression.cs (Invocation.MakeUnionSet): Optimization: Use two + nested foreach statements instead of for, and also break out of + the inner loop once a match is found. + + (Invocation.OverloadResolve): Use foreach, simplify the code. + +2002-05-08 Miguel de Icaza + + * cfold.cs (BinaryFold): During an enumeration evaluation context, + we actually unwrap the expression to allow for extra information + to be extracted. + + * expression.cs: Use Shr_Un on unsigned operations. + +2002-05-08 Ravi Pratap + + * ecore.cs (FindMostEncompass*): Fix trivial bug where the set of + applicable operators was not being considered correctly. This closes + the bug Miguel reported. + +Wed May 8 16:40:50 CEST 2002 Paolo Molaro + + * attribute.cs: check that the type derives from System.Attribute + and report the correct error in that case (moved the duplicate code to + its own method, too). + +Wed May 8 11:50:31 CEST 2002 Paolo Molaro + + * attribute.cs: lookup attribute type name as the spec says: first the + bare attribute name and then name + "Attribute" (nant compiles with + mcs after this fix). + +2002-05-07 Miguel de Icaza + + * expression.cs (Unary.TryReduceNegative): Ah! Tricky! Tricky! + Because of the way we parse things, we should try to see if a + UIntConstant can fit in an integer. + +2002-05-07 Ravi Pratap + + * ecore.cs (GetConversionOperators): Do not pick up op_True operators + when we are in an explicit context. + + (ConvertReferenceExplicit): When converting from Iface type S to Class + T make sure the rules are implemented as an OR. + + * parameter.cs (ParameterType): Make it a property for now although the + purpose really isn't anything immediate. + + * expression.cs (Is*Applicable): Do better checking on the parameter type + of a ref/out parameter. The ones from the system assemblies are already + marked with the correct type so we don't need to do any correction. + + * ecore.cs (StandardConversionExists): Conversion from Interface types to + the object type is standard too so include that. + +2002-05-06 Miguel de Icaza + + * ecore.cs (StandardConversionExists): Augment with missing code: + deal with IntConstant, LongConstants and Enumerations. + + * assign.cs: Report the error, instead of failing silently + + * rootcontext.cs (AddGlobalAttributes): Track attributes on the + typecontainer that they are declared, because the + typecontainer/namespace will have the list of using clauses that + need to be applied. + + Assembly Attributes were escaping the normal registration + mechanism. + + (EmitCode): Apply attributes within an EmitContext that represents + the container they were declared on. + + * cs-parser.jay: Track bases for structs. How did I get this wrong? + +2002-05-06 Ravi Pratap + + * ecore.cs (FindMostEncompassingType, FindMostEncompassedType): + Revamp completely - make much cleaner as we now operate only + on a set of Types. + + (FindMostSpecificSource, FindMostSpecificTarget): New methods + to implement the logic detailed in the spec more correctly. + + (UserDefinedConversion): Update accordingly. + +2002-05-06 Miguel de Icaza + + * statement.cs: Return flow analysis information up. + + * cs-tokenizer.cs (adjust_real): Share code between LITERAL_DOUBLE + and the default. + + (token): Do not consume an extra character before calling + decimal_digits. + +2002-05-06 Piers Haken + + * cs-parser.jay: add 'override' attribute to System.Object.Finalize + +2002-05-06 Miguel de Icaza + + * class.cs (Constructor.Emit): Set the IsStatic flag in the + EmitContext during the instance constructor initializer + resolution, to stop access to instance variables. + + This is mandated by the spec, last paragraph of the `constructor + initializers' section. + +2002-05-05 Miguel de Icaza + + * cs-parser.jay, class.cs (Accessor): new class used to represent + an accessor (get or set). In the past we used `null' to represent + a missing accessor. But this is ambiguous because there was no + way to tell in abstract indexers/properties if one of them was + specified. + + Now there is a way of addressing that. + + * expression.cs (Indexers.GetIndexersForType): Use TypeManager.MemberLookup + instead of FindMembers. + + * class.cs (TypeContainer.EmitFieldInitializer): Do not typecast + the result of Assign.Resolve as Assign, but rather as ExpressionStatement. + + * attribute.cs: Treat indexers and properties as the same in terms + of applying attributes + + * ecore.cs (FindMostEncompassedType): Use statically initialized + EmptyExpressions()s like we do elsewhere to avoid creating useless + objects (and we take this out of the tight loop). + + (GetConversionOperators): Move the code to extract the actual + operators to a separate routine to clean things up. + +2002-05-04 Miguel de Icaza + + * ecore.cs (FieldExpr): Remove un-needed tests for null, since now + events are always registered FieldBuilders. + + * class.cs (FieldBase): New class shared by Fields + + * delegate.cs: If we are a toplevel delegate, use our full name. + If we are a nested delegate, then only use our tail name. + +2002-05-02 Ravi Pratap + + * expression.cs (IsApplicable): Ensure that we add the "&" to + ref/out types before comparing it with the type of the argument. + + (IsParamsMethodApplicable): Ditto. + + (Argument.Type): Use TypeManager.LookupType instead of Type.GetType - + silly me ;-) + + * delegate.cs : Handle the case when we have more than one applicable + method. Flag an error only when we finish checking all. + +2002-05-02 Miguel de Icaza + + * expression.cs: Add support for boolean static initializers. + +2002-05-01 Miguel de Icaza + + * attribute.cs: Use proper cast for Events, since we use a MyEventBuilder. + + * parameter.cs (ComputeParameterTypes, + ComputeAndDefineParameterTypes): Better error handling: now we + clear the `types' cache if we fail during any of the type lookups. + We also return the status code correctly to our caller + + * delegate.cs: If we fail to define a delegate, abort the extra + steps. + + * expression.cs (Binary.ResolveOperator): for + operator==(object,object) and operator !=(object, object) we also + have to verify that there is an implicit conversion from one to + the other. + + (ArrayAccess.DoResolve): Array Access can operate on + non-variables. + +2002-04-30 Miguel de Icaza + + * assign.cs (CompoundAssign): A new class used as a "flag" that + the assignment actually is happening as part of a compound + assignment operator. + + During compound assignment, a few new rules exist to enable things + like: + + byte b |= 1 + 2 + + From the spec: + + x op= y can be evaluated as x = (T) (x op y) (ie, an explicit cast + to the type of x) if y is implicitly convertible to the type of x, + and the operator is a builtin operator and the return type of the + operator is explicitly convertible to the type of x. + + * rootcontext.cs: Reset warning level to 2. 4 catches various + "interesting" features in mcs, we must clean this up at some + point, but currently am trying to kill other bugs ;-) + + * ecore.cs (SimpleName.SimpleNameResolve): Perform member lookups + in container classes as well. + + * expression.cs (Binary.ResolveOperator): Handle string case + before anything else (as operator overloading does emit an error + before doing anything else). + + This code could go away when we move to a table driven model, but + i could not come up with a good plan last night. + +2002-04-30 Lawrence Pit + + * typemanager.cs (CSharpName): reimplementation using regex. + * class.cs: added null check for fields in Emit + * rootcontext.cs: set warninglevel to 4 + +2002-04-29 Miguel de Icaza + + * typemanager.cs (CSharpName): reimplemented with Lupus + suggestion. + +2002-04-28 Miguel de Icaza + + * statement.cs (If): correclty implement Resolve, because we were + not catching sem errors in there. The same process is needed + everywhere else. + (Return, StatementExpression, For, While, Do, Throw, Lock): Implement Resolve + + + (Statement.Warning_DeadCodeFound): Factorize code. + (While): Report dead code here too. + + (Statement): Added Resolve virtual method to allow + for resolution split from the emit code. + +2002-04-26 Miguel de Icaza + + * statement.cs (EmitBoolExpression): No longer try to resolve the + expression here. + (MakeBoolean): New utility function that resolve, implicitly + converts to boolean and tags the expression. + + + (If, Do): Implement dead code elimination. + (While): Implement loop inversion + + (Do, While, For, If): Resolve the expression prior to calling our + code generation. + +2002-04-22 Lawrence Pit + + * class.cs: + - added method Report28 (warning: program has more than one entry point) + - added method IsEntryPoint, implements paragraph 10.1 of the spec + - modified method Method.Define, the part at the end of the method + + * rootcontext.cs: added static public Location EntryPointLocation; + + * ../errors/cs0028.cs : Add test case for the above warning. + + * typemanager.cs: + - modified method CSharpName to allow arrays of primitive type to + be printed nicely (e.g. instead of System.Int32[][] it now prints + int[][]) + - added method CSharpSignature: returns the signature of a method + in string format to be used in reporting errors, warnings, etc. + + * support.cs: InternalParameters.ParameterDesc variable tmp initialized + with String.Empty. + +2002-04-26 Ravi Pratap + + * delegate.cs (Define): Fix extremely silly bug where I was + setting the type of the 'object' parameter of the BeginInvoke + method to System.IAsyncResult instead of System.Object ;-) + +2002-04-26 Miguel de Icaza + + * class.cs (ConstructorInitializer.Resolve): Also use DeclaredOnly + here. + + (Constructor.Emit): return if we fail to initialize the + constructor. Another door closed! + + * expression.cs (New.DoResolve): Improve error message (from -6 to + 1501). Use DeclaredOnly lookup to find the exact constructor. + + * typemanager.cs (MemberLookup): If DeclaredOnly is set, do not + loop. This is useful. + + * cs-parser.jay: Adjust the default parameters so that destructors + have the proper signature. + +2002-04-26 Martin Baulig + + * driver.cs (LoadAssembly): If `assembly' contains any characters + which are only valid in path names and not in assembly names + (currently slash, backslash and point), use Assembly.LoadFrom () + instead of Assembly.Load () on the `assembly' (before iteration + over the link_paths). + +2002-04-26 Martin Baulig + + * cs-tokenizer.cs (is_hex): Correctly handle lowercase chars. + +2002-04-25 Miguel de Icaza + + * class.cs (Property): use the new typemanager.MemberLookup + + (TypeContainer.MemberLookup): Implement using the + TypeManager.MemberLookup now. + + * typemanager.cs: Make MemberLookup a function of the TypeManager, + and return MemberInfos, so that these can be used without an + EmitContext (what we had before). + +2002-04-24 Miguel de Icaza + + * expression.cs: Fix the case where the argument to params if the + type of the params. I omitted handling this before. Fixed + +2002-04-22 Miguel de Icaza + + * driver.cs: Call BootCorlib_PopulateCoreType + + * class.cs (Property.CheckBase): Check for properties only, not + for all members. + + * interface.cs: Temporary hack: try/catch around the + CustomAttributeBuilder, because I am getting an exception that I + do not understand. + + * rootcontext.cs (BootCorlib_PopulateCoreType): Populate some + types whose definitions are required to be there (attributes are + defined before standard types). + + Compute definitions as we boot the various types, as they are used + immediately (value_type class will need object_type, but if we do + not initialize object_type, we will pass a null, which will let + the runtime pick the System.Object from the existing corlib, which + is not what we want). + +2002-04-22 Patrik Torstensson + + * cs-tokenizer.cs: fixed a number of trim() issues. + +2002-04-22 Ravi Pratap + + * expression.cs (Argument.Type): Ensure that we return the correct + type when we have out or ref parameters [in which case we + append a "&"]. + +2002-04-22 Miguel de Icaza + + * class.cs (Property, Indexer): Allow extern modifier in there. + + * typemanager.cs (InitBaseTypes): Initializes object_type and + value_type, since those will be used early on during the bootstrap + process to compile corlib. + + (InitCoreTypes): Move code from here to InitBaseTypes. + +2002-04-21 Miguel de Icaza + + * ecore.cs (PropertyExpr): Optimize calls to Array::get_Length on + single-dimension arrays as using the ldlen opcode. + + Daniel Lewis discovered this optimization. + + * typemanager.cs: Add signature for System.Array::get_Length + +2002-04-20 Gonzalo Paniagua Javier + + * statement.cs: report the error when the foreach does not apply to an + array nor a collection. + +2002-04-19 Miguel de Icaza + + * expression.cs: Add implicit conversions to the operator ~. + + * constant.cs (DecimalConstant.Emit): Emit decimal value. + + * typemanager.cs: Locate the decimal constructor. + +2002-04-17 Gonzalo Paniagua Javier + + * attribute.cs: use the new property of TypeOf. + * expression.cs: added 'get' property around typearg. + + These changes fix a build breaker reported by NickD. Is this the + correct way to fix? If not, please, revert my changes and make it + work :-). + +2002-04-17 Miguel de Icaza + + * attribute.cs: Add support for typeof in attribute invocations. + I am not sure that this is right though. + +2002-04-14 Duncan Mak + + * cfold.cs (BinaryFold): Catch DivideByZeroException in the + Binary.Operator.Division case. + +2002-04-13 Ravi Pratap + + * class.cs (DefineType): Ensure that we do a proper check on + attribute types and also register it with the TypeManager. + + (TypeContainer.Targets): The default for attribute types is + AttributeTargets.All. + + * attribute.cs (ApplyAttributes): Registering the attribute type + is done elsewhere, not when we discover we have a Usage attribute. + +2002-04-12 Ravi Pratap + + * expression.cs (VerifyArgumentsCompat): Implement Miguel's suggestion + and get rid of is_delegate parameter. + + * everywhere : update. + +2002-04-12 Ravi Pratap + + * cs-parser.jay (compilation_unit): Revamp completely to use + some new ideas that I got from Rhys' grammar to solve the problems + with assembly level attributes. + + (outer_declaration): New grammar production. + + (attribute_sections): Add. + + (opt_attributes): Base on attribute_sections + + (namespace_declaration): Allow opt_attributes to tackle the case + when we have assembly level attributes - we are clever in this + regard now ;-) + + * attribute.cs (ApplyAttributes): Do not worry about assembly + attributes in the non-global context. + + * rootcontext.cs (AddGlobalAttributes): Go back to using this + instead of SetGlobalAttributes. + + * class.cs, rootcontext.cs : Ensure we define and generate + attribute types before anything else. + + * attribute.cs (CheckAttribute and GetValidPlaces): Handle the exception + and flag the new error -20 for the case when the attribute type + does not have valid targets specified. csc does not catch this. + + * ../errors/errors.txt : update for error # -20 + +2002-04-11 Ravi Pratap + + * support.cs (InternalParameters.ParameterModifier): Do some null + checking and return sane values. + + * class.cs (Method.Define): If we are a PInvoke method, ensure + that we are static and extern. Report error # 601 + + * ../errors/cs0601.cs : Add test case for the above error. + +2002-04-07 Ravi Pratap + + * rootcontext.cs (attribute_types): We need to keep type of + all attribute types separately and emit code for them first. + + (RegisterAttribute) : Implement. + + * class.cs (DefineType): Check if the current Type is a custom + attribute type and register it accordingly. + + * rootcontext.cs (AddGlobalAttributes): Fix silly bug where we were + adding the first attribute twice and rename to + + (SetGlobalAttributes): this. + + * rootcontext.cs (NamespaceLookup): Run through the aliases too and perform + lookups. + + * attribute.cs (ApplyAttributes): Take an additional argument telling us + if we are processing global arguments. Hmm, I am unsure of this. + +2002-04-12 Gonzalo Paniagua Javier + + * expression.cs: added static array of strings to avoid calling + Enum.ToString () for Operator in Binary. Significant recover of + performance. + +2002-04-10 Miguel de Icaza + + * class.cs (FindMembers): Allow the Builders of the various + members to be null. If they are skip them. This only happens + during the PInvoke declaration. + +2002-04-09 Miguel de Icaza + + * parameter.cs (Parameters.ComputeParameterTypes): Flag the + failure, so we do not keep going afterwards. + + * expression.cs: (Invocation.OverloadResolve): I believe Ravi + wanted to pass `false' as the `is_delegate' argument. If this is + the case, why not use delegate_type == null to mean `is_delegate = + false' and anything else as is_delegate = true. + +Tue Apr 9 05:40:12 2002 Piers Haken + + * statement.cs: fixed SimpleSwitchEmit to make 'goto case' goto the + code for the section, not the beginning of the tests. + +2002-04-08 Miguel de Icaza + + * cfold.cs: Handle operator + (Enum x, Underlying x) + + * expression.cs (Binary): same. Warn about errors where we have + Enum/Enum in operator + as well. + +Mon Apr 8 06:29:03 2002 Piers Haken + + * statement.cs: + - added support for switch(bool) + - optimize loading of I8/U8 constants (ldc.i4, iconv_i8) + - add TableSwitchEmit() to handle table-based switch statements + +2002-04-05 Ravi Pratap + + * expression.cs (Invocation.OverloadResolve): Factor out code which + does parameter compatibility checking with arguments so that we can + re-use the code even from Delegate.VerifyApplicability + + (VerifyArgumentsCompat): Move above code here. + + * delegate.cs (VerifyApplicability): Get rid of duplicate code + and instead make a call to the above method. + +2002-03-31 Ravi Pratap + + * typemanager.cs (attribute_type): Corresponds to System.Attribute. + We use it to keep track of classes which are attribute types. + +2002-04-02 Miguel de Icaza + + * delegate.cs (Delegate.Define): Correctly define the types in the + presence of fixed and array parameters. + + * class.cs (TypeContainers.FindMembers): Use NonPublic flag while + doing FindMembers. + + * ecore.cs (Expression.MemberLookup): Reset binding flags to not + include NonPublic after the first iteration. + + * class.cs (Indexer.CheckBase): Only check if both parents are + non-null. + + * cs-parser.jay (accessor_body): If empty, set to null. + + * ecore.cs (SimpleName.SimpleNameResolve): We did not have the + same code path here to resolve constants names that we did have in + MemberAccess.DoResolve. There is too much code duplicated here. + +2002-04-01 Miguel de Icaza + + * statement.cs, makefile: Drop Statementcollection and just use ArrayLists + + * ecore.cs: Optimize UserDefinedConversion by minimizing the calls + to MakeUnionSet. + + * cs-tokenizer.cs: Reuse a single StringBuilder for assembling + tokens, numbers and strings. + + * ecore.cs (MethodGroupExpr): Make Emit warn about missing + parenthesis. + + * delegate.cs: Use ComputeAndDefineParameterTypes for both the + asyncronous parameters and the regular parameters. + + * codegen.cs (CodeGen.Init): Use the constructor that allows us to + specify the target directory. + + * expression.cs: (This.DoResolve): Simplify + (As.Emit): Optimize, do not generate IsInst if the expression is + always of the given type. + + (Is.DoResolve): Bug fix, we were reporting both always/never for + the is expression. + + * (Invocation.MakeUnionSet): Simplify vastly and optimize, we were + creating too many unnecessary arrays. + +2002-03-31 Miguel de Icaza + + * class.cs (EmitFieldInitializer): Use Assign expression to assign + fields instead of rolling our own initializer. Takes care of all + implicit conversions, and drops unnecessary static checks/argument. + +2002-03-31 Dick Porter + + * driver.cs: use the GetDirectories() return values properly, and + use "/" as path separator. + +2002-03-30 Miguel de Icaza + + * expression.cs (Unary): Optimize - - expr into expr. + (Binary): Optimize a + (-b) into a -b. + + * codegen.cs (CodeGen): Made all methods static. + +2002-03-29 Miguel de Icaza + + * rootcontext.cs: + + * decl.cs: Rename `definition' into `TypeBuilder' and drop the + TypeBuilder property. + + * cs-parser.jay: Drop the use of RecordXXX and use RecordDecl + instead. + + * tree.cs: Removed the various RecordXXXX, and replaced with a + single RecordDecl. Removed all the accessor methods, and just + left a single access point Type + + * enum.cs: Rename DefineEnum to DefineType. + + * decl.cs: New abstract method `DefineType' used to unify the + Defines for Enumerations, Interfaces, TypeContainers and + Delegates. + + (FindType): Moved LookupInterfaceOrClass here. Moved the + LookupBaseClasses method that used to live in class.cs and + interface.cs here, and renamed to FindType. + + * delegate.cs: Implement DefineType. Take advantage of the + refactored pattern for locating the parent builder without taking + the parent_builder argument (which we know does not work if we are + nested, and triggering a toplevel definition). + +2002-03-28 Miguel de Icaza + + * decl.cs (MemberCore.CheckMethodAgainstBase): Test if the + accessibility of a member has changed during override and report + an error if so. + + * class.cs (Method.Define, Property.Define): Only complain on + overrides if the method is private, any other accessibility is + fine (and since we just checked the permission is the same, we are + good to go). + + * cs-tokenizer.cs: only line, region, endregion, if, endif, else + and elif are processed always. The other pre-processing + directives are only processed if we are "taking" the path + +2002-03-29 Martin Baulig + + * class.cs (Method.Emit): Only emit symbolic debugging info if the + current location is not Null. + + * codegen.cs (CodeGen.SaveSymbols): Split out symbol writing code into + a separate method so we can profile it. + + * driver.cs (ShowTime): We need to use `(int) span.TotalSeconds' since + `span.Seconds' are just seconds, but no minutes or hours. + (MainDriver): Profile the CodeGen.SaveSymbols calls. + +2002-03-28 Miguel de Icaza + + * class.cs (Method.Define), (Property.Define), (Indexer.Define): + Remove the gratuitous set of Final: + + // If an interface implementation, then we can set Final. + if (((flags & MethodAttributes.Abstract) == 0) && + implementing.DeclaringType.IsInterface) + flags |= MethodAttributes.Final; + + I do not know what I was smoking when I used that. + + + * cs-parser.jay, delegate.cs: Make Delegate be a DeclSpace, first + step into fixing the name resolution issues for delegates and + unifying the toplevel name resolution. + +2002-03-28 Martin Baulig + + * class.cs (Method.Emit): If we have a symbol writer, call its + OpenMethod(), CloseMethod() and SetMethodSourceRange() methods to + tell it about the current method. + + * codegen.cs (EmitContext.Mark): New public method. Tell the symbol + writer that we're going to emit the first byte of IL code for a new + statement (a new source line). + (EmitContext.EmitTopBlock): If we have a symbol writer, call + EmitContext.Mark() before emitting any code. + + * location.cs (SymbolDocument): Return null when we're Null. + + * statement.cs (Statement): Moved the `Location loc' variable here. + (Statement.EmitBoolExpression): If we have a symbol writer, call + ec.Mark() before emitting any code to tell it that we're at the + beginning of a new statement. + (StatementExpression): Added `Location' argument to the constructor. + (Block): Added public readonly variable `StartLocation' and public + variable `EndLocation'. The latter is to be set using SetEndLocation(). + (Block): Added constructor which takes a start and end location. + (Block.SetEndLocation): New method. This sets the end location. + (Block.EmitMeta): If we have a symbol writer, tell it the names of the + local variables we create. + (Block.Emit): If we have a symbol writer, call ec.Mark() before emitting + each statement and do also mark the begin and end of the block. + + * cs-parser.jay (block : OPEN_BRACE): Use the new `Block' constructor to + tell it the current lexer.Location, use Location.Null for the end of the + block. + (block : OPEN_BRACE opt_statement_list CLOSE_BRACE): When closing the + current block, set its end location using SetEndLocation(). + (statement_expression): StatementExpression constructor now takes the + lexer.Location as additional argument. + (for_statement, declare_local_variables): Likewise. + (declare_local_variables): When creating a new implicit block, use the + new Block constructor and pass it the lexer.Location. + +2002-03-28 Miguel de Icaza + + * ecore.cs (Expression.MemberLookup): On interfaces, lookup + members also on the parent interfaces recursively. + +2002-03-27 Miguel de Icaza + + * report.cs: Use new formats, since Gonzalo finished the missing + bits. + + * expression.cs (Binary.ResolveOperator): added missing operator| + operator& and operator^ for bool/bool. + + * cs-parser.jay: CheckDef now takes a Location argument that is + used to report errors more precisly (instead of reporting the end + of a definition, we try to track something which is a lot closer + to the source of the problem). + + * cs-tokenizer.cs: Track global token use, so we can properly flag + the use of #define/#undef after the first token has been seen. + + Also, rename the reportXXXX to Error_DescriptiveName + + * decl.cs (DeclSpace.IsTopLevel): Move property here from + TypeContainer, so that Enum and Interface can use this too. + + * class.cs (TypeContainer.LookupInterfaceOrClass, + GetInterfaceOrClass, GetClassBases, DefineType): Drop the + `builder' argument. Typically this was used to pass the parent + builder (a ModuleBuilder or a TypeBuilder from whoever triggered + the definition). + + The problem is that a nested class could trigger the definition of + a toplevel class, and the builder would be obviously wrong in that + case. + + So we drop this argument, and we compute dynamically the + TypeBuilder/ModuleBuilder (the correct information was available + to us anyways from DeclSpace.Parent) + + * interface.cs (Interface.DefineInterface): Drop builder + parameter cleanup like class.cs + + * enum.cs (Enum.DefineEnum): Drop builder parameter. Clean up + like class.cs + + * statement.cs (Switch.EmitObjectInteger): Emit short/ushort + values. + + (Try.Emit): Propagate the returns value from the statement. + + (Return.Emit): Even if we are leavning + + * driver.cs: Catch IOExpcetion for Directory.GetFiles as well. + + * modifiers.cs: Fix the computation of MethodAttributes flags. + +Tue Mar 26 21:14:36 CET 2002 Paolo Molaro + + * driver.cs: allow compilation of files that start with '/'. + Add a default case when checking the argument of --target. + +2002-03-25 Miguel de Icaza + + * interface.cs: Implement the same search algorithm for types in + the interface code. + + * delegate.cs: Do not allow multiple definition. + + * Recovered ChangeLog that got accidentally amputated + + * interface.cs (Interface.DefineInterface): Prevent from double definitions. + + * rootcontext.cs: Load manually enum to allow core classes to + contain enumerations. + + * enum.cs, ecore.cs, driver.cs, attribute.cs, class.cs, expression.cs: + Update to new static methods in TypeManager. + + * typemanager.cs (GetMethod, GetConstructor): Use our + implementation of FindMembers to find the members, since during + corlib compilation, the types are TypeBuilders and GetMethod and + GetConstructor do not work. + + Make all methods in TypeManager static. + + (InitCodeHelpers): Split the functionality from + the InitCodeTypes function. + + * driver.cs: Call InitCodeHelpers after we have populated the + types. + + * cs-parser.jay (delegate_declaration): we did not used to compute + the delegate name correctly for void delegates. + +2002-03-24 Miguel de Icaza + + * rootcontext.cs (RootContext): Init the interface_resolve_order + and type_container_resolve_order always. + + (ResolveCore, BootstrapCorlib_ResolveClass, + BootstrapCorlib_ResolveStruct): New functions to bootstrap the + compiler when compiling with --nostdlib + + * class.cs (TypeContainer.DefineType): Check that our parent is + not null. This test is most important when we are bootstraping + the core types. + + * codegen.cs: Split out the symbol writing code. + +2002-03-25 Martin Baulig + + * driver.cs (-g): Made -g an alias for --debug. + +2002-03-24 Martin Baulig + + * codegen.cs (SymbolWriter): New public variable. Returns the + current symbol writer. + (CodeGen): Added `bool want_debugging_support' argument to the + constructor. If true, tell the ModuleBuild that we want debugging + support and ask it for the ISymbolWriter. + (Save): If we have a symbol writer, call it's Close() method after + saving the assembly. + + * driver.c (--debug): New command line argument to create a + debugger information file. + + * location.cs (SymbolDocument): New public property. Returns an + ISymbolDocumentWriter object for the current source file or null + if we don't have a symbol writer. + +2002-03-21 Miguel de Icaza + + * driver.cs (LoadAssembly): Correctly return when all the paths + have been tried and not before. + + * statement.cs (Switch.Emit): return the actual coverage for this + statement (returns/not-returns) + + (Switch.SimpleSwitchEmit): Do not generate jumps to the end of the + switch of the statement if we are the last switch section. That + kills two problems: try/catch problems (we used to emit an empty + nop at the end) and switch statements where all branches would + return. + +2002-03-19 Miguel de Icaza + + * driver.cs: Add default assemblies (the equivalent to the + Microsoft CSC.RSP file) + + * cs-tokenizer.cs: When updating `cols and setting it to zero, + also update tokens_seen and set it to false. + + * driver.cs: Implement --recurse for Mike. + + * driver.cs (SplitPathAndPattern): Small bug fix, I was not + correctly splitting out the paths. + +2002-03-18 Miguel de Icaza + + * interface.cs (Interface.PopulateProperty): Instead of using + `parent' as the declaration space for the set parameters, use + `this' + + * support.cs (InternalParameters): InternalParameters constructor + takes a DeclSpace instead of a TypeContainer. + + * expression.cs (ArrayCreation.EmitDynamicInitializers): If value + types are being initialized, load the address of it before calling + the function. + + (New): Provide a mechanism to disable the generation of local + value type temporaries when the caller will be providing us with + an address to store it. + + (ArrayCreation.EmitDynamicInitializers): Use it. + +2002-03-17 Miguel de Icaza + + * expression.cs (Invocation.EmitArguments): Only probe for array + property if there is more than one argument. Sorry about that. + + * class.cs (Invocation.EmitArguments): Fix to emit arguments for + empty param arrays. + + * class.cs (Method.LabelParameters): Fix incorrect code path that + prevented the `ParamArrayAttribute' from being applied to the + params attribute. + +2002-03-16 Miguel de Icaza + + * support.cs (ReflectionParameters): Correctly compute whether the + last argument is a params array. Fixes the problem with + string.Split ('a') + + * typemanager.cs: Make the assemblies array always be non-null + (empty, but non-null) + + * tree.cs (RecordDecl): New function that abstracts the recording + of names. This reports error 101, and provides a pointer to the + previous declaration. Fixes a crash in the compiler. + + * cs-parser.jay (constructor_declaration): Update to new grammar, + and provide a constructor_body that can be empty. + +2002-03-15 Miguel de Icaza + + * driver.cs: Add support for --resources. + + * expression.cs: (FetchGetMethod, FetchAddressMethod, EmitAssign): + Make all types for the various array helper methods be integer. + + * ecore.cs (Expression.ConvertNumericExplicit): Pass the + CheckState to ConvCast. + + (ConvCast): Now it takes a `checked' state argument, to avoid + depending on the emit context for the conversion, and just using + the resolve time setting. + + * expression.cs (ArrayCreation.EmitArrayArguments): New function, + instead of Invocation.EmitArguments. We do not emit the original + arguments, instead we emit those which have been converted to + unsigned int expressions. + + * statement.cs (Block.EmitMeta): Drop tracking of indexes. + + * codegen.cs: ditto. + + * expression.cs (LocalVariableReference): Drop the use of the + Store function that depended on the variable index. + + * statement.cs (VariableInfo): Drop the `Idx' property from this + class, as this is not taking into account the indexes for + temporaries tat we generate during the execution, getting the + indexes wrong. + + * class.cs: First emit class initializers, then call the parent + constructor. + + * expression.cs (Binary): Fix opcode emision. + (UnaryMutator.EmitCode): Support checked code generation + + * ecore.cs (MemberLookup): TypeManager.FindMembers will return + matches for events for both the Static and Instance scans, + pointing to the same element. Fix that. + +2002-03-14 Miguel de Icaza + + * rootcontext.cs (ResolveTree): Always set the + interface_resolve_order, because nested interfaces will be calling + into us. + + * class.cs (GetInterfaceOrClass): Track the same resolution + process used by TypeManager.LookupType. This fixes the nested + type lookups in class declarations (separate path from + LookupType). + + (TypeContainer.DefineType): Also define nested interfaces. + (TypeContainer.RegisterOrder): New public function used to + register the order in which child interfaces need to be closed. + + Nested interfaces need to be closed after their parents have been + created. + + * interface.cs (InterfaceAttr): Put all the logic for computing + the interface attribute here. + + (DefineInterface): Register our interface order with the + RootContext or with the TypeContainer depending on the case. + +2002-03-12 Miguel de Icaza + + * cs-parser.jay: rework foreach statement to work with the new + changes to the policy on SimpleNames. + + * report.cs: support Stacktrace on warnings as well. + + * makefile: drop --unsafe and /unsafe from the compile. + +2002-03-13 Ravi Pratap + + * ecore.cs (StandardConversionExists): Modify to take an Expression + as the first parameter. Ensure we do null -> reference type conversion + checking. + + * Everywhere : update calls accordingly, making use of MyEmptyExpr to store + temporary Expression objects. + +Wed Mar 13 12:32:40 CET 2002 Paolo Molaro + + * interface.cs: workaround bug in method overloading resolution + (there is already a bugzilla bug for it). + +2002-03-12 Miguel de Icaza + + We could also solve this problem by having a separate path for + performing type lookups, instead of DoResolve, we could have a + ResolveType entry point, and only participating pieces of the + production (simplename, deref, array) would implement this. + + * codegen.cs (EmitContext): New field OnlyLookupTypes used to + signal SimpleName to only resolve type names and not attempt to + resolve anything else. + + * expression.cs (Cast): Set the flag. + + * ecore.cs (SimpleName): Use the OnlyLookupTypes flag + + * class.cs: Only report 108 if there is no `new' modifier. + + * cs-parser.jay: rework foreach statement to work with the new + changes to the policy on SimpleNames. + + * report.cs: support Stacktrace on warnings as well. + + * makefile: drop --unsafe and /unsafe from the compile. + +2002-03-11 Miguel de Icaza + + * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable + lookups here, instead of doing that at parse time. This means + that our grammar will not introduce `LocalVariableReferences' as + expressions at this point. That solves the problem of code like + this: + + class X { + static void Main () + { int X = 1; + { X x = null }}} + + This is only half the fix. The full fix requires parameters to + also be handled in this way. + + * Everywhere: Use ec.DeclSpace on calls to LookupType, as this + makes the use more obvious of the DeclSpace. The + ec.TypeContainer.TypeBuilder is now only used to pull the + TypeBuilder for it. + + My theory is that I can get rid of the TypeBuilder completely from + the EmitContext, and have typecasts where it is used (from + DeclSpace to where it matters). + + The only pending problem is that the code that implements Aliases + is on TypeContainer, and probably should go in DeclSpace. + + * ecore.cs (SimpleName.SimpleNameResolve): Perform local variable + lookups here, instead of doing that at parse time. This means + that our grammar will not introduce `LocalVariableReferences' as + expressions at this point. That solves the problem of code like + this: + + class X { + static void Main () + { int X = 1; + { X x = null }}} + + This is only half the fix. The full fix requires parameters to + also be handled in this way. + + * class.cs (Property.DefineMethod): When implementing an interface + method, set newslot, when implementing an abstract method, do not + set the flag (before we tried never setting it, or always setting + it, which is the difference). + (Indexer.DefineMethod): same. + (Method.DefineMethod): same. + + * ecore.cs: Only set the status used flag if we get back a Field. + + * attribute.cs: Temporary hack, so Paolo can keep working. + +2002-03-08 Ravi Pratap + + * attribute.cs (Attribute.UnmanagedType): This is to keep track of + the unmanaged type in the case we have a MarshalAs attribute. + + (Resolve): Handle the case when we are parsing the special MarshalAs + attribute [we need to store the unmanaged type to use later] + + * typemanager.cs (marshal_as_attr_type): Built in type for the + MarshalAs Attribute. + + * attribute.cs (ApplyAttributes): Recognize the MarshalAs attribute + on parameters and accordingly set the marshalling info. + +2002-03-09 Miguel de Icaza + + * class.cs: Optimizing slightly by removing redundant code after + we switched to the `NoTypes' return value. + (Property.DefineMethod): use NoTypes here too. + + This fixes the bug I introduced in my last batch of changes. + +2002-03-05 Ravi Pratap + + * tree.cs (RecordEnum): Add. We now keep track of enums too. + + * class.cs (LookupInterfaceOrClass): Check against the list of recorded + Enums since those are types too. + + * cs-parser.jay (enum_declaration): Record enums as we parse them. + + * enum.cs (DefineEnum): Return if the TypeBuilder has already been defined + thanks to a call during the lookup process. + +2002-03-07 Miguel de Icaza + + * statement.cs (Foreach): Lots of work to accomodate a particular + kind of foreach statement that I had not kept in mind. It is + possible to have foreachs on classes that provide a GetEnumerator + method that return objects that implement the "pattern" for using + a foreach, there is no need to support GetEnumerator + specifically. + + This is needed to compile nant. + + * decl.cs: Only report 114 if the member is not `Finalize' and if + the warning level is at least 2. + + * class.cs: Moved the compare function from Method to + MethodSignature. + + (MethodSignature.InheritableMemberSignatureCompare): Add new + filter function that is used to extract inheritable methods from a + class. + + (Method.Define): Use the new `inheritable_method_signature_filter' + delegate + + * cs-tokenizer.cs (get_cmd_arg): Do not add white space to the + command. + +2002-03-06 Miguel de Icaza + + * ecore.cs (Expression.ConvertReferenceExplicit): Removed dead code. + + * cs-parser.jay: Add opt_semicolon to the interface declaration. + + * expression.cs: Pass location information to + ConvertImplicitStandard. + + * class.cs: Added debugging code to track return values from + interfaces. + +2002-03-05 Miguel de Icaza + + * expression.cs (Is.DoResolve): If either side of the `is' is an + interface, do not flag the warning. + + * ecore.cs (ImplicitReferenceConversion): We need a separate test + for interfaces + + * report.cs: Allow for --fatal to be used with --probe. + + * typemanager.cs (NoTypes): Move the definition for the empty Type + array here. + + * class.cs (TypeContainer.FindMembers): Also look for methods defined by + properties. + (TypeContainer.DefineProxy): New function used to proxy to parent + implementations when implementing interfaces. + (TypeContainer.ParentImplements): used to lookup if our parent + implements a public function that is required by an interface. + (TypeContainer.VerifyPendingMethods): Hook this up. + + * typemanager.cs (TypeManager, AddModule, AddAssembly): Make the + `modules' and `assemblies' arraylists into arrays. We only grow + these are the very early start up of the program, so this improves + the speedof LookupType (nicely measured). + + * expression.cs (MakeByteBlob): Replaced unsafe code with + BitConverter, as suggested by Paolo. + + * cfold.cs (ConstantFold.Binary): Special case: perform constant + folding of string concatenation, but if either side is a string, + and the other is not, then return null, and let the runtime use + the concatenation on the string plus the object (using + `Object.ToString'). + +2002-03-04 Miguel de Icaza + + Constant Folding has been implemented now. + + * expression.cs (Unary.Reduce): Do not throw an exception, catch + the error instead on types that are not supported in one's + complement. + + * constant.cs (Constant and all children): New set of functions to + perform implict and explicit conversions. + + * ecore.cs (EnumConstant): Implement the new functions to perform + conversion by proxying to the child expression. + + * codegen.cs: (ConstantCheckState): Constant evaluation has its + own separate setting that can not be turned off from the command + line using --unchecked or --checked and is only controlled using + the checked/unchecked statements and expressions. This setting is + used by the constant folder to flag errors. + + * expression.cs (CheckedExpr, UncheckedExpr): Set the + ConstantCheckState as well. + + During Resolve, they also have to flag the state, because the + constant folder runs completely in the Resolve phase. + + * statement.cs (Checked, Unchecked): Set the ConstantCheckState as + well. + +2002-03-01 Miguel de Icaza + + * cfold.cs: New file, this file contains the constant folder. + + * ecore.cs (IMemoryLocation.AddressOf): Now takes an extra + argument to track whether we are using the resulting address to + load or store a value and provide better error messages. + + (FieldExpr.Emit, FieldExpr.EmitAssign, FieldExpr.AddressOf): Use + new AddressOf arguments. + + * statement.cs (Foreach.EmitCollectionForeach): Update + + * expression.cs (Argument.Emit): Call AddressOf with proper + arguments to track usage. + + (New.DoEmit): Call AddressOf with new arguments. + + (Unary.Emit): Adjust AddressOf call. + +2002-03-01 Ravi Pratap + + * cs-parser.jay (member_access): Change the case for pre-defined types + to use a MemberAccess instead of a SimpleName. Thanks to Felix again for + this suggestion. + + * class.cs (Operator::Emit): If we are abstract or extern, we don't have + a method body. + + * attribute.cs (CheckAttribute, ApplyAttribute): Ensure that we treat operators + essentially like methods and apply attributes like MethodImplOptions to them too. + + * ecore.cs (SimpleName.SimpleNameResolve): Perform a check on ec.TypeContainer.TypeBuilder + not being null. + + * codegen.cs (EmitContext): The constructor now takes in an extra argument specifying the + DeclSpace as the distinction is important. We provide sane defaults as usually the TypeContainer + is the DeclSpace. + + * Update code everywhere accordingly. + + * ecore.cs : Change references to ec.TypeContainer to ec.DeclSpace where appropriate. + + * cs-parser.jay (enum_declaration): Set the current namespace of the enum. + +2002-02-28 Ravi Pratap + + * rootcontext.cs (LookupType): As we cycle through the chain of namespaces + try performing lookups against those instead of jumping straight into using + the 'using' clauses. + + (ImplicitParent): Add. Thanks to Felix Arrese-Igor for this idea. + + (LookupType): Perform lookups in implicit parents too. + + * class.cs (GetInterfaceOrClass): Modify to perform the exact same lookup + sequence as RootContext.LookupType. + + * rootcontext.cs (NamespaceLookup): Split out code from LookupType which tries + the various cases of namespace lookups into this method. + +2002-03-01 Miguel de Icaza + + * cs-parser.jay: Add support for [Attribute ()] (empty arguments + in positional arguments) + + * class.cs (Operator): Update the AllowedModifiers to contain + extern. + + * cs-parser.jay: Update operator declaration to allow for the + operator body to be empty. + + * cs-tokenizer.cs: Added '\u' unicode support in strings and hex + values. + +2002-02-27 Miguel de Icaza + + * class.cs (Method.Emit): Label parameters. + + * driver.cs: Return 1 or 0 as the program exit code. + +2002-02-26 Miguel de Icaza + + * expression.cs: Special case the `null' object when trying to + auto-compute the type, as anything can be explicitly converted to + that. + + * ecore.cs (Expression.ConvertExplicit): Bug fix, thanks for + spotting this Paolo. + + (Expression.ImplicitNumericConversion): Perform comparissions of + the type using the underlying type in the case of an enumeration + rather than using the enumeration type for the compare. + + Cope with the underlying == type case, which is not possible to + catch before. + + (Expression.ConvertNumericExplicit): Perform comparissions of + the type using the underlying type in the case of an enumeration + rather than using the enumeration type for the compare. + + * driver.cs: If the user does not supply an extension, assume .exe + + * cs-parser.jay (if_statement): Rewrote so that we can track the + location for the if statement. + + * expression.cs (Binary.ConstantFold): Only concat strings when + the operation is "+", not everything ;-) + + * statement.cs (Statement.EmitBoolExpression): Take a location + argument. + (If, While, Do): Track location. + + * expression.cs (Binary.ResolveOperator): In the object + string + case, I was missing a call to ConvertImplicit + +2002-02-25 Ravi Pratap + + * parameter.cs (Parameter.ExternalType): Take in extra DeclSpace and + Location arguments. Ensure we use RootContext.LookupType to do our work + and not try to do a direct Type.GetType and ModuleBuilder.GetType + + * interface.cs (PopulateMethod): Handle the type of the parameter being + null gracefully. + + * expression.cs (Invocation.BetterFunction): Handle the case when we + have a params method with no fixed arguments and a call is made with no + arguments. + +2002-02-25 Miguel de Icaza + + * cs-tokenizer.cs: Add support for the quote-escape-sequence in + the verbatim-string-literal + + * support.cs (InternalParameters.ParameterModifier): handle null + fixed parameters. + (InternalParameters.ParameterType): ditto. + + * parameter.cs (VerifyArgs): Also check if the fixed parameter is + duplicating the name of the variable parameter. + (GetParameterByName): Fix bug where we were not looking up array + paramters if they were the only present (thanks Paolo!). + (GetParameterInfo): We only have an empty set of types if both + fixed and array are set to null. + (GetParameterInfo-idx): Handle FixedParameter == null + + * cs-parser.jay: Handle the case where there is no catch + statements (missing null test). + +2002-02-22 Miguel de Icaza + + * driver.cs (MainDriver): Be conservative on our command line + handling. + + Catch DirectoryNotFoundException when calling GetFiles. + + (SplitPathAndPattern): Used to split the input specification into + a path and a pattern that we can feed to Directory.GetFiles. + +2002-02-21 Miguel de Icaza + + * statement.cs (Fixed): Implement the last case of the Fixed + statement (string handling). + + * expression.cs (StringPtr): New class used to return a char * to + a string; Used by the Fixed statement. + + * typemanager.cs: Add char_ptr_type. Add get_OffsetToStringData method. + + * expression.cs (Binary.ResolveOperator): Remove redundant + MemberLookup pn parent type. + Optimize union call, we do not need a union if the types are the same. + (Unary.ResolveOperator): REmove redundant MemberLookup on parent + type. + + Specialize the use of MemberLookup everywhere, instead of using + the default settings. + + (StackAlloc): Implement stackalloc keyword. + + * cs-parser.jay: Add rule to parse stackalloc. + + * driver.cs: Handle /h, /help, /? + + * expression.cs (MakeByteBlob): Removed the hacks we had in place + before we supported unsafe code. + + * makefile: add --unsafe to the self compilation of mcs. + +2002-02-20 Miguel de Icaza + + * expression.cs (PointerArithmetic): New class that is used to + perform pointer arithmetic. + (Binary.Resolve): Handle pointer arithmetic + Handle pointer comparission. + (ArrayPtr): Utility expression class that is used to take the + address of an array. + + (ElementAccess): Implement array access for pointers + + * statement.cs (Fixed): Implement fixed statement for arrays, we + are missing one more case before we are done. + + * expression.cs (Indirection): Implement EmitAssign and set the + ExprClass to Variable. This allows pointer dereferences to be + treated as variables, and to have values assigned to them. + + * ecore.cs (Expression.StoreFromPtr): New utility function to + store values dereferencing. + +2002-02-20 Ravi Pratap + + * expression.cs (Binary.ResolveOperator): Ensure that we are + not trying to operate on a void type - this fixes the reported + bug. + + * decl.cs (CheckMethodAgainstBase): Do not allow overriding if + the parent implementation is sealed. + + * ../errors/cs0239.cs : Add. + + * attribute.cs (ApplyAttributes): Handle Modulebuilders too. + + * typemanager.cs (unverifiable_code_type): Corresponds to + System.Security.UnverifiableCodeAttribute. We need to emit this for modules + which have unsafe code in them. + + * rootcontext.cs (EmitCode): Emit the above attribute when we are in an + unsafe context. + +2002-02-19 Miguel de Icaza + + * cs-tokenizer.cs: Add support for @"litreal strings" + + Make tokenizer accept pre-processor directives + on any column (remove the old C-like limitation). + + * rootcontext.cs (EmitCode): Emit any global attributes. + (AddGlobalAttributes): Used to keep track of assembly attributes. + + * attribute.cs (ApplyAttributes): Support AssemblyAttributes. + + * cs-parser.jay: Add support for global attributes. + +2002-02-17 Miguel de Icaza + + * expression.cs (Indirection): New helper class. Unary will + create Indirection classes to be able to implement the + IMemoryLocation interface on it. + +2002-02-16 Miguel de Icaza + + * cs-parser.jay (fixed_statement): reference the right statement. + + * statement.cs (Fixed.Emit): Finish implementing the fixed + statement for the &x case. + +2002-02-14 Miguel de Icaza + + * class.cs (Property.Define, Method.Define): Remove newslot when + `implementing'. + + * modifiers.cs: My use of NewSlot when `Abstract' was set was + wrong. NewSlot should only be used if the `new' keyword is present. + + * driver.cs (GetSystemDir): Use CodeBase instead of FullName for + locating our system dir. Sorry about this. + +2002-02-13 Miguel de Icaza + + * driver.cs (GetSystemDir): Compute correctly the location of our + system assemblies. I was using the compiler directory instead of + the library directory. + +2002-02-13 Ravi Pratap + + * expression.cs (BetterFunction): Put back in what Miguel commented out + since it is the correct fix. The problem is elsewhere ;-) + + (IsParamsMethodApplicable): Fix bug where we were not checking that the fixed + parameters of the parms method are themselves compatible or not ! + + (StandardConversionExists): Fix very dangerous bug where we were forgetting + to check that a class implements an interface before saying that an implicit + conversion was allowed. Use ImplementsInterface to do the checking. + +2002-02-13 Miguel de Icaza + + * class.cs (Method.Define): Track whether we are an explicit + implementation or not. And only call DefineMethodOverride if we + are an explicit implementation. + + (Property.DefineMethod): Ditto. + +2002-02-11 Ravi Pratap + + * expression.cs (BetterFunction): Catch hideous bug which was + preventing us from detecting ambiguous calls due to implicit casts i.e + cs0121. + +2002-01-29 Miguel de Icaza + + * support.cs (Pair): Remove un-needed method. I figured why I was + getting the error in cs-parser.jay, the variable in a foreach loop + is readonly, and the compiler does not really treat this as a variable. + + * cs-parser.jay (fixed_statement): Fix grammar. Use ASSIGN + instead of EQUALS in grammar. + + * typemanager.cs (VerifyUnmanaged): Report correct error (208) + + * expression.cs (Unary.DoResolve): Check whether the argument is + managed or not. + +2002-01-28 Miguel de Icaza + + * support.cs: Api for Pair to set a value. Despite the fact that + the variables are public the MS C# compiler refuses to compile + code that accesses the field if the variable is part of a foreach + statement. + + * statement.cs (Fixed): Begin implementation of the fixed + statement. + + (Block.AddVariable): Return the VariableInfo on success and null + on failure instead of true/false. + + * cs-parser.jay (foreach): Catch errors on variables already + defined (we were ignoring this value before) and properly unwind + the block hierarchy + + (fixed_statement): grammar for the fixed statement. + +2002-01-25 Miguel de Icaza + + * expression.cs (UnaryMutator.IsIncrementableNumber): Allow also + pointer types to be incretemented. + + (SizeOf): Implement. + + * cs-parser.jay (pointer_member_access): Implement + expr->IDENTIFIER production. + + * expression.cs (IndexerAccess.DoResolve, ArrayAccess.DoResolve, + MemberAccess.DoResolve, Invocation.DoResolve): Check for pointers + on safe contexts. + + (Unary): Implement indirection. + + * ecore.cs (Expression.UnsafeError): Reports error 214 (pointer + use in non-unsafe context). + + (SimpleName.DoResolve): Check for pointers in field access on safe + contexts. + + (Expression.LoadFromPtr): Factor the load-indirect code in this + function. This was duplicated in UnboxCast and ParameterReference + +2002-01-24 Miguel de Icaza + + * expression.cs (ComposedCast): report an error if a pointer cast + is used in a safe region. + + * ecore.cs (Expression.ConvertExplicit): Add rules for implicit + pointer type casts in unsafe context. + + * codegen.cs (EmitContext): Set up IsUnsafe. + + * cs-parser.jay (non_expression_type): Add productions for pointer + casts. + + * expression.cs (Invocation.EmitCall): Remove chunk of buggy + code. We should not use force into static mode if the method is + not virtual. Fixes bug in MIS + + * statement.cs (Do.Emit, While.Emit, For.Emit, + Statement.EmitBoolExpression): Add support to Do and While to + propagate infinite loop as `I do return' semantics. + + Improve the For case to also test for boolean constants. + + * attribute.cs (Attribute.ApplyAttributes): Add ParameterBuilder + to the list of attributes we can add. + + Remove `EmitContext' argument. + + * class.cs (Method.Define): Apply parameter attributes. + (Constructor.Define): Apply parameter attributes. + (MethodCore.LabelParameters): Move here the core of labeling + parameters. + + * support.cs (ReflectionParameters.ParameterModifier, + InternalParameters.ParameterModifier): Use IsByRef on the type and + only return the OUT bit for these parameters instead of in/out/ref + flags. + + This is because I miss-understood things. The ParameterInfo.IsIn + and IsOut represent whether the parameter has the [In] and [Out] + attributes set. + +2002-01-22 Miguel de Icaza + + * ecore.cs (FieldExpr.Emit): Release temporaries. + + * assign.cs (LocalTemporary.Release): new function. + + * codegen.cs (EmitContext.GetTemporaryStorage, + EmitContext.FreeTemporaryStorage): Rework the way we deal with + temporary storage. Now we can "put back" localbuilders when we + are done with them + +2002-01-21 Miguel de Icaza + + * ecore.cs (FieldExpr.Emit): Handle initonly fields specially: we + need to make a copy of the variable to generate verifiable code. + +2002-01-19 Miguel de Icaza + + * driver.cs: Compute dynamically the system directory. + + * ecore.cs (CopyNewMethods): reworked, exposed, made public. + Slower, but more generally useful. Used by the abstract + registering implementation. + + * expression.cs (ResolveMemberAccess): Reorder the way we evaluate + the rules for the special rule on Type/instances. First check if + we have the same name, and if so, try that special static path + rather than the instance path. + +2002-01-18 Miguel de Icaza + + * cs-parser.jay: Emit 642 (warning: possible empty statement) for + for, while and if. + + * class.cs (TypeBuilder.DefineType): Do not allow inheritance from + Enum, ValueType, Delegate or Array for non-corlib compiles. + + * cs-tokenizer.cs: Catch long identifiers (645) + + * typemanager.cs (IndexerPropetyName): Ravi never tested this + piece of code. + + * class.cs (TypeContainer.RegisterRequiredImplementations): Bug + fix, we were returning too early, so we were not registering + pending methods from abstract classes. + + Do not register pending methods if the class is abstract. + + * expression.cs (Conditional.DoResolve): Report circular implicit + conversions when we neecd to compute it for conditional + expressions. + + (Is.DoResolve): If the expression is always of the provided type, + flag warning 183. If the expression can not ever be of the + provided type flag warning 184. + + * class.cs: Catch 169 as well. + + * ecore.cs (FieldExpr): For now in AddressOf mark as assigned and + read. + +2002-01-18 Nick Drochak + + * makefile: remove path to beta2 csc.exe. path to csc.exe must be in PATH instead. + +2002-01-17 Miguel de Icaza + + * interface.cs: (PopulateMethod): Check for pointers being defined + only if the unsafe context is active. + (PopulateProperty): ditto. + (PopulateIndexer): ditto. + + * class.cs (Method, Method.Define): Allow `unsafe' modifier to be + specified. If pointers are present, make sure that they are + present in an unsafe context. + (Constructor, Constructor.Define): ditto. + (Field, Field.Define): ditto. + (Property, Property.Define): ditto. + (Event, Event.Define): ditto. + + * interface.cs (Interface.GetInterfaceTypeByName): Only lookup the + hashtable if there are classes or structs defined. + + * expression.cs (LocalVariableReference.DoResolve): Simplify this + code, as the constant resolution moved. + + * statement.cs (Block.EmitMeta): Resolve all constants as we emit + the metadata, so we can flag error 133. + + * decl.cs (MemberCore.UnsafeOK): New function to test that a + pointer is being declared in an unsafe context. + +2002-01-16 Miguel de Icaza + + * modifiers.cs (Modifiers.Check): Require a Location argument. + Report error 227 for Unsafe use. + + * typemanager.cs: Remove IsPointerType, we should be using Type.IsPointer + + * statement.cs (For.Emit): If the test is null, then report that + we do `return', as we wont reach anything afterwards. + + (Switch.SwitchGoverningType): Track the expression that matched + the conversion. + + * driver.cs: Allow negative numbers as an error code to flag. + + * cs-parser.jay: Handle 1551. + + * namespace.cs: Add 1537 checking (repeated using alias namespaces). + +2002-01-15 Miguel de Icaza + + * cs-parser.jay: Report 1518 (type declaration can only contain + class, struct, interface, enum or delegate) + + (switch_label): Report 1523 (keywords `case' or `default' must + preced code) + + (opt_switch_sections): Report 1522 (empty switch) + + * driver.cs: Report 1515 (response file specified multiple times) + Report 1516 (Source file specified multiple times). + + * expression.cs (Argument.Resolve): Signal 1510 + + (BaseAccess.Resolve, BaseIndexer.Resolve): Signal 1511 (base + access not allowed in static code) + +2002-01-11 Ravi Pratap + + * typemanager.cs (IsPointerType): Utility method which we are going + to need a lot. + + * ecore.cs (ImplicitReferenceConversion): A pointer type cannot be cast to + the object type, so we take care of that. + + * expression.cs (FullMethodDesc): Also include the return type in descriptions. + + * support.cs (ParameterDesc): Fix minor bug which was causing params tags to be + added to non-params parameters :-) + + * typemanager.cs (CSharpName): Include 'void' type too. + + (void_ptr_type): Include in the set of core types. + + * ecore.cs (ConvertImplicit): Make use of ConvertImplicitStandard instead of + duplicating code. + + (ConvertImplicitStandard): Handle standard implicit pointer conversions when we have + an unsafe context. + + * cs-parser.jay (local_variable_pointer_type): Add support for 'void *' as I had + completely forgotten about it. + +2002-01-10 Ravi Pratap + + * cs-parser.jay (pointer_type): Add. This begins our implementation + of parsing rules for unsafe code. + + (unsafe_statement): Implement. + + (embedded_statement): Modify to include the above. + + * statement.cs (Unsafe): Implement new class for unsafe blocks. + + * codegen.cs (EmitContext.InUnsafe): Add. This determines + if the current context is an unsafe one. + + * cs-parser.jay (local_variable_pointer_type): Since local variable types + are handled differently, we need separate rules for them. + + (local_variable_declaration): Update to use local_variable_pointer_type + to allow variable declarations of unmanaged pointer types. + + * expression.cs (Unary.ResolveOperator): Ensure that the '&' operator is used only + in unsafe contexts. + + * ../errors/cs0214.cs : Add. + +2002-01-16 Nick Drochak + + * makefile: remove 'response' file when cleaning. + +2002-01-15 Miguel de Icaza + + * cs-parser.jay: Report 1524. + +2002-01-14 Miguel de Icaza + + * typemanager.cs (RegisterMethod): drop checking if we have + registered this from here + +2002-01-12 Miguel de Icaza + + * class.cs (Method.EmitDestructor): Implement calling our base + destructor. + + * statement.cs (Try.Emit): Fix to reset the InFinally to the old + value of InFinally. + + * codegen.cs (EmitContext.EmitTopBlock): Destructors will call + this routine and will wrap the call in a try/catch block. Deal + with the case. + +2002-01-11 Miguel de Icaza + + * ecore.cs (Expression.MemberLookup): instead of taking a + parameter `same_type' that was used to tell whether we could + access private members we compute our containing type from the + EmitContext. + + (FieldExpr): Added partial support for volatile fields. This does + not work for volatile fields exposed from assemblies, as I can not + figure out how to extract the modreq from it. + + Updated all the source files to use this. + + * codegen.cs (EmitContext): Compute ContainerType ahead of time, + because it is referenced by MemberLookup very often. + +2002-01-09 Ravi Pratap + + * typemanager.cs (IndexerPropertyName): If we have a TypeBuilder, use + TypeBuilder.GetCustomAttributes to retrieve what we need. + + Get rid of redundant default_member_attr_type as this is the same as + default_member_type which already exists. + + * interface.cs, attribute.cs : Update accordingly. + +2002-01-08 Miguel de Icaza + + * typemanager.cs: Enable IndexerPropertyName again. It does not + work for TYpeBuilders though. Ravi, can you please fix this? + + * cs-tokenizer.cs: Accept _ as a name in pp-expressions. + + * expression.cs (Argument.Emit): Handle the case of ref objects + being passed to ref functions; + + (ParameterReference.EmitLoad): Loads the content of the pointer + without dereferencing. + +2002-01-07 Miguel de Icaza + + * cs-tokenizer.cs: Implemented the pre-processing expressions. + +2002-01-08 Ravi Pratap + + * class.cs (Indexer.DefineMethod): Incorporate the interface + type in the name of the method if we are doing explicit interface + implementation. + + * expression.cs (ConversionExists): Remove as it is completely obsolete. + + (BetterConversion): Fix extremely trivial bug where we were referring to + ConversionExists instead of StandardConversionExists ! Hooray, things are fine + again ! + + * ../errors/bug16.cs : Add although we have fixed it. + +2002-01-07 Miguel de Icaza + + * expression.cs (BaseIndexer): Begin implementation. + + * class.cs (TypeContainer.IsInterfaceMethod): Bug fix. + + * cs-parser.jay (indexer_declarator): Use qualified_identifier + production directly to remove a shift/reduce, and implement + explicit interface implementation. + + * cs-tokenizer.cs: Fix tokenizer, it was consuming one extra char + after a floating point suffix. + + * expression.cs (DoNumericPromotions): Improved the conversion for + uint/uint. If we have a constant, we avoid doing a typecast to a + larger type. + + * class.cs (Indexer): Implement explicit interface implementation + for indexers. + +Sat Jan 5 16:08:23 CET 2002 Paolo Molaro + + * class.cs: make the default instance constructor public and hidebysig. + +2001-01-03 Ravi Pratap + + * interface.cs (EmitDefaultMemberAttr): Make this helper method static + so we can call it from elsewhere. + + * class.cs (TypeContainer.Emit): Emit the attribute here too. The rule is that + we emit it internally if the class has a defined indexer; otherwise the user + emits it by decorating the class definition with the DefaultMemberAttribute. + + * attribute.cs (ApplyAttributes): Perform checks to see that the DefaultMember + attribute is not used on a type which defines an indexer. + + * cs-tokenizer.cs (get_cmd_arg): Ensure we trim whitespace and also include the tab + character when we skip whitespace. + + * ../errors/cs0646.cs : Add. + +2002-01-03 Miguel de Icaza + + * ecore.cs (SimpleName.ResolveSimpleName): Report error 120 + again. + + * makefile: Add practical target `mcs3.exe' which builds the third + generation compiler. + + * expression.cs (New): Fix structures constructor calling. + + * class.cs (Property, Method, Indexer): Emit Final flag on the + method if we are an interface implementation and we are not + abstract. + + * ecore.cs (PropertyExpr): New public field `IsBase', tells + whether this property is referencing a `base' method. + + * expression.cs (Invocation.EmitCall): take an extra argument: + is_base, this is used to determine whether the `call' or + `callvirt' opcode should be used. + + + * delegate.cs: update EmitCall. + + * class.cs (Method.Define): Set NewSlot for the cases where we are + not implementing an interface method. + + (Property.Define): ditto. + +2002-01-02 Miguel de Icaza + + * cs-tokenizer.cs: (Tokenizer.escape): Escape '\r' as '\r' not as + 'r'. Allows mcs to parse itself fully. + +2002-01-02 Ravi Pratap + + * expression.cs (ArrayCreation.num_automatic_initializers): Keep track + of the number of initializers that require the InitializeArray method. + + (CheckIndices): Store the Expression in all cases - not the plain value. Also + update the above field where necessary. + + (MakeByteBlob): Update accordingly. + + (DoEmit): Call EmitStaticInitializers only if the number of initializers is + greater than 2. + + (EmitDynamicInitializers): Update in accordance with the new optimization. + + (ArrayAccess.EmitStoreOpcode): Include char type along with short and ushort - the + same OpCode applies. + + * cs-parser.jay : Fix some glaring errors I introduced. + +2002-01-01 Ravi Pratap + + * parameters.cs (AddVariable, AddConstant): Pass in current_local_parameters + so that we can check for name clashes there too. + + * typemanager.cs (default_member_attr_type): The attribute that we need to emit + for interface indexers. + + * interfaces.cs (Define): Emit the default member attribute. + + * expression.cs (MakeByteBlob): Fix extremely trivial bug where the wrong + variable was being referred to while setting the value ;-) + +2002-01-01 Miguel de Icaza + + * expression.cs (MakeByteBlob): Optimize: we do not need to fill + byte-by-byte information when we know the data is zero. + + Make the block always a multiple of 4, because + DefineInitializedData has a bug. + + * assign.cs: Fix, we should assign from the temporary, not from + the source. + + * expression.cs (MakeByteBlob): Fix my incorrect code. + +2001-12-31 Miguel de Icaza + + * typemanager.cs (EnumToUnderlying): This function is used to get + the underlying type from an enumeration, because it does not + always work. + + * constant.cs: Use the I4_S form for values between -128 and 127. + + * statement.cs (Block.LookupLabel): Looks up a label. + (Block): Drop support for labeled blocks. + + (LabeledStatement): New kind of statement that represents a label + only. + + (Goto): Finally implement this bad boy. + + * cs-parser.jay: Update to reflect new mechanism to implement + labels. + +2001-12-30 Miguel de Icaza + + * codegen.cs (EmitContext.This): a codegen property that keeps the + a single instance of this instead of creating many different this + instances. + + * delegate.cs (Delegate.DoResolve): Update to use the property; + + * ecore.cs (SimpleName.SimpleNameResolve): Ditto + + * expression.cs (BaseAccess.DoResolve): Ditto. + +2001-12-29 Ravi Pratap + + * typemanager.cs (methodimpl_attr_type): Add to hold the type + corresponding to System.Runtime.CompilerServices.MethodImplAttribute. + + (InitCoreTypes): Update accordingly. + + * attribute.cs (Resolve): Remember if the attribute is a MethodImplAttribute + so we can quickly store the state. + + (ApplyAttributes): Set the correct implementation flags + for InternalCall methods. + +2001-12-29 Miguel de Icaza + + * expression.cs (EmitCall): if a method is not virtual, then do + not use callvirt on it. + + (ArrayAccess.EmitAssign): storing non-builtin value types (ie, + user defined stuff) requires the use of stobj, which takes an + address on the stack instead of an array and an index. So emit + the Ldelema operation for it. + + (EmitStoreOpcode): Use stobj for valuetypes. + + (UnaryMutator.EmitCode): Use the right 1 value depending on + whether we are dealing with int64/uint64, float or doubles. + + * class.cs (TypeContainer.AddConstructor): Fix the logic to define + constructors that I implemented last night. + + (Constructor.IsDefault): Fix to work properly for static + constructors. + + * cs-parser.jay (CheckDef): report method signature errors. + Update error number 103 to be 132. + + * decl.cs: New AdditionResult enumeration value: MethodExists. + Although we do this check for methods later on in the semantic + analysis, catching repeated default constructors is so easy that + we catch these here. + + * expression.cs (Binary.DoNumericPromotions): Fix the uint64 type + promotions code. + + (ParameterReference.EmitAssign, Emit): handle + bools as bytes. + + (ArrayAccess.EmitLoadOpcode): Handle bool type here. + (ArrayAccess.EmitStoreOpcode): ditto. + + * cs-tokenizer.cs (is_punct): Eliminated empty computation. + + * expression.cs (MakeByteBlob): Complete all the missing types + (uint, short, ushort, byte, sbyte) + + * class.cs: Only init instance field initializers on instance + constructors. + + Rename `constructors' to instance_constructors. + + (TypeContainer.AddConstructor): Only add constructors to the list + if it is not static. + + Make sure that we handle default_static_constructor independently + everywhere where we handle instance_constructors + +2001-12-28 Miguel de Icaza + + * class.cs: Do not lookup or create a base initializer for a + static constructor. + + (ConstructorInitializer.Resolve): use the proper type to lookup + for constructors. + + * cs-parser.jay: Report error 1585 (modifiers between type and name). + + * enum.cs, interface.cs: Remove CloseType, this is taken care by + in DeclSpace. + + * decl.cs: CloseType is now an virtual method, the default + implementation just closes this type. + +2001-12-28 Ravi Pratap + + * attribute.cs (DefinePInvokeMethod): Set the implementation flags + to PreserveSig by default. Also emit HideBySig on such methods. + + Basically, set the defaults to standard values. + + * expression.cs (Invocation.BetterFunction): We need to make sure that for each + argument, if candidate is better, it can't be worse than the best ! + + (Invocation): Re-write bits to differentiate between methods being + applicable in their expanded form and their normal form - for params + methods of course. + + Get rid of use_standard everywhere as only standard conversions are allowed + in overload resolution. + + More spec conformance. + +2001-12-27 Miguel de Icaza + + * driver.cs: Add --timestamp, to see where the compiler spends + most of its time. + + * ecore.cs (SimpleName.DoResolve): Do not create an implicit + `this' in static code. + + (SimpleName.DoResolve): Implement in terms of a helper function + that allows static-references to be passed upstream to + MemberAccess. + + (Expression.ResolveWithSimpleName): Resolve specially simple + names when called by MemberAccess to implement the special + semantics. + + (Expression.ImplicitReferenceConversion): Handle conversions from + Null to reference types before others, as Null's type is + System.Object. + + * expression.cs (Invocation.EmitCall): Handle the special case of + calling methods declared on a reference type from a ValueType + (Base classes System.Object and System.Enum) + + (MemberAccess.Resolve): Only perform lookups on Enumerations if + the left hand side is a TypeExpr, not on every enumeration. + + (Binary.Resolve): If types are reference types, then do a cast to + object on operators != and == of both arguments. + + * typemanager.cs (FindMembers): Extract instance and static + members if requested. + + * interface.cs (PopulateProperty): Use void_type instead of null + as the return type for the setter method. + + (PopulateIndexer): ditto. + +2001-12-27 Ravi Pratap + + * support.cs (ReflectionParameters): Fix minor bug where we + were examining the wrong parameter for the ParamArray attribute. + + Cope with requests for the type of the parameter at position + greater than the params parameter's. We now return the element + type of the params array as that makes more sense. + + * expression.cs (Invocation.IsParamsMethodApplicable): Update + accordingly as we no longer have to extract the element type + ourselves. + + (Invocation.OverloadResolve): Update. + +2001-12-27 Miguel de Icaza + + * statement.cs (Foreach.GetEnumeratorFilter): Do not compare + against IEnumerator, test whether the return value is a descendant + of the IEnumerator interface. + + * class.cs (Indexer.Define): Use an auxiliary method to implement + the other bits of the method definition. Begin support for + explicit interface implementation. + + (Property.DefineMethod): Use TypeManager.void_type instead of null + for an empty return value. + +2001-12-26 Miguel de Icaza + + * expression.cs (MemberAccess.ResolveMemberAccess): if we are + dealing with a FieldExpr which is composed of a FieldBuilder, in + the code path we did extract the constant, but we should have + obtained the underlying value to be able to cast it (otherwise we + end up in an infinite loop, this is what Ravi was running into). + + (ArrayCreation.UpdateIndices): Arrays might be empty. + + (MemberAccess.ResolveMemberAccess): Add support for section + 14.5.4.1 that deals with the special case of E.I when E is a type + and something else, that I can be a reference to a static member. + + (ArrayCreation.MakeByteBlob): It is not an error to not be able to + handle a particular array type to create byte blobs, it is just + something we dont generate byteblobs for. + + * cs-tokenizer.cs (get_cmd_arg): Ignore \r in commands and + arguments. + + * location.cs (Push): remove the key from the hashtable that we + are about to add. This happens for empty files. + + * driver.cs: Dispose files after we have parsed them. + + (tokenize): new function that only runs the tokenizer on its + input, for speed testing. + +2001-12-26 Ravi Pratap + + * class.cs (Event.Define): Define the private field only if there + are no accessors defined. + + * expression.cs (ResolveMemberAccess): If there is no associated + field with the event, that means we have an event defined with its + own accessors and we should flag error cs0070 since transforming + ourselves into a field is not valid in that case. + + * ecore.cs (SimpleName.DoResolve): Same as above. + + * attribute.cs (DefinePInvokeMethod): Set the default calling convention + and charset to sane values. + +2001-12-25 Ravi Pratap + + * assign.cs (DoResolve): Perform check on events only if they + are being accessed outside the declaring type. + + * cs-parser.jay (event_declarations): Update rules to correctly + set the type of the implicit parameter etc. + + (add_accessor, remove_accessor): Set current local parameters. + + * expression.cs (Binary): For delegate addition and subtraction, + cast the return value from the method into the appropriate delegate + type. + +2001-12-24 Ravi Pratap + + * typemanager.cs (RegisterDelegateData, GetDelegateData): Get rid + of these as the workaround is unnecessary. + + * delegate.cs (NewDelegate.DoResolve): Get rid of bits which registered + delegate data - none of that is needed at all. + + Re-write bits to extract the instance expression and the delegate method + correctly. + + * expression.cs (Binary.ResolveOperator): Handle the '-' binary operator + on delegates too. + + * attribute.cs (ApplyAttributes): New method to take care of common tasks + of attaching attributes instead of duplicating code everywhere. + + * everywhere : Update code to do attribute emission using the above method. + +2001-12-23 Miguel de Icaza + + * expression.cs (IsParamsMethodApplicable): if there are not + parameters, return immediately. + + * ecore.cs: The 0 literal can be implicity converted to an enum + type. + + (SimpleName.DoResolve): First lookup the type, then lookup the + members. + + (FieldExpr.Emit): If the InstanceExpression is a ValueType, we + want to get its address. If the InstanceExpression is not + addressable, store the result in a temporary variable, then get + the address of it. + + * codegen.cs: Only display 219 errors on warning level or above. + + * expression.cs (ArrayAccess): Make it implement the + IMemoryLocation interface. + + (Binary.DoResolve): handle the operator == (object a, object b) + and operator != (object a, object b) without incurring into a + BoxedCast (because 5 != o should never be performed). + + Handle binary enumerator operators. + + (EmitLoadOpcode): Use Ldelema if the object we are loading is a + value type, otherwise use Ldelem_ref. + + Use precomputed names; + + (AddressOf): Implement address of + + * cs-parser.jay (labeled_statement): Fix recursive block + addition by reworking the production. + + * expression.cs (New.DoEmit): New has a special case: + + If we are dealing with a ValueType, we have a few + situations to deal with: + + * The target of New is a ValueType variable, that is + easy, we just pass this as the variable reference + + * The target of New is being passed as an argument, + to a boxing operation or a function that takes a + ValueType. + + In this case, we need to create a temporary variable + that is the argument of New. + + +2001-12-23 Ravi Pratap + + * rootcontext.cs (LookupType): Check that current_type is not null before + going about looking at nested types. + + * ecore.cs (EventExpr.EmitAddOrRemove): Rename from EmitAssign as we do + not implement the IAssignMethod interface any more. + + * expression.cs (MemberAccess.ResolveMemberAccess): Handle EventExprs specially + where we tranform them into FieldExprs if they are being resolved from within + the declaring type. + + * ecore.cs (SimpleName.DoResolve): Do the same here. + + * assign.cs (DoResolve, Emit): Clean up code considerably. + + * ../errors/bug10.cs : Add. + + * ../errors/cs0070.cs : Add. + + * typemanager.cs : Use PtrHashtable for Delegate data hashtable etc. + + * assign.cs : Get rid of EventIsLocal everywhere. + +2001-12-23 Miguel de Icaza + + * ecore.cs (ConvertIntLiteral): finished the implementation. + + * statement.cs (SwitchLabel): Convert the value we are using as a + key before looking up the table. + +2001-12-22 Miguel de Icaza + + * codegen.cs (EmitTopBlock): Require a Location argument now. + + * cs-parser.jay (constructor_declarator): We need to setup + current_local_parameters before we parse the + opt_constructor_initializer, to allow the variables to be bound + to the constructor arguments. + + * rootcontext.cs (LookupType): First lookup nested classes in our + class and our parents before we go looking outside our class. + + * expression.cs (ConstantFold): Extract/debox the values at the + beginnning. + + * rootcontext.cs (EmitCode): Resolve the constants first before we + resolve the types. This is not really needed, but it helps debugging. + + * statement.cs: report location. + + * cs-parser.jay: pass location to throw statement. + + * driver.cs: Small bug fix. + + * report.cs: Updated format to be 4-zero filled digits. + +2001-12-22 Ravi Pratap + + * expression.cs (CheckIndices): Fix minor bug where the wrong + variable was being referred to ;-) + + (DoEmit): Do not call EmitStaticInitializers when the + underlying type is System.Object. + +2001-12-21 Ravi Pratap + + * ecore.cs (EventExpr.Resolve): Implement to correctly set the type + and do the usual workaround for SRE. + + * class.cs (MyEventBuilder.EventType): New member to get at the type + of the event, quickly. + + * expression.cs (Binary.ResolveOperator): Handle delegate addition. + + * assign.cs (Assign.DoResolve): Handle the case when the target + is an EventExpr and perform the necessary checks. + + * ecore.cs (EventExpr.EmitAssign): Implement the IAssignMethod + interface. + + (SimpleName.MemberStaticCheck): Include check for EventExpr. + + (EventExpr): Set the type in the constructor itself since we + are meant to be born fully resolved. + + (EventExpr.Define): Revert code I wrote earlier. + + * delegate.cs (NewDelegate.Resolve): Handle the case when the MethodGroup's + instance expression is null. The instance expression is a This in that case + or a null, depending on whether it is a static method or not. + + Also flag an error if the reference to a method is ambiguous i.e the MethodGroupExpr + refers to more than one method. + + * assign.cs (DoResolve): Check whether the event belongs to the same Type container + and accordingly flag errors. + +2001-12-21 Miguel de Icaza + + * statement.cs (Throw.Emit): Add support for re-throwing exceptions. + +2001-12-22 Miguel de Icaza + + * location.cs (ToString): Provide useful rutine. + +2001-12-21 Miguel de Icaza + + * ecore.cs (Expression.ConvertIntLiteral): Do not return Constant + objects, return the actual integral boxed. + + * statement.cs (SwitchLabel): define an ILLabel for each + SwitchLabel. + + (Switch.CheckSwitch): If the value is a Literal, extract + the underlying literal. + + Also in the unused hashtable we had, add the SwitchLabel so we can + quickly look this value up. + + * constant.cs: Implement a bunch of new constants. Rewrite + Literal based on this. Made changes everywhere to adapt to this. + + * expression.cs (Expression.MakeByteBlob): Optimize routine by + dereferencing array only once, and also copes with enumrations. + + bytes are two bytes wide, not one. + + (Cast): Perform constant conversions. + + * ecore.cs (TryImplicitIntConversion): Return literals instead of + wrappers to the literals here. + + * expression.cs (DoNumericPromotions): long literals can converted + to ulong implicity (this is taken care of elsewhere, but I was + missing this spot). + + * ecore.cs (Expression.Literalize): Make the return type Literal, + to improve type checking. + + * rootcontext.cs: Lookup for nested classes in our class hierarchy. + +2001-12-20 Miguel de Icaza + + * literal.cs: Revert code from ravi that checked the bounds. The + bounds are sane by the definition of the type itself. + + * typemanager.cs: Fix implementation of ImplementsInterface. We + need to actually look up in our parent hierarchy for interfaces + implemented. + + * const.cs: Use the underlying type for enumerations + + * delegate.cs: Compute the basename for the delegate creation, + that should fix the delegate test case, and restore the correct + Type Lookup semantics in rootcontext + + * rootcontext.cs: Revert Ravi's last patch. The correct way of + referencing a nested type with the Reflection API is using the "+" + sign. + + * cs-parser.jay: Do not require EOF token at the end. + +2001-12-20 Ravi Pratap + + * rootcontext.cs (LookupType): Concatenate type names with + a '.' instead of a '+' The test suite passes again. + + * enum.cs (Enum.DefineEnum): Set RTSpecialName on the 'value__' + field of the enumeration. + + * expression.cs (MemberAccess.ResolveMemberAccess): Add support for + the case when the member is an EventExpr. + + * ecore.cs (EventExpr.InstanceExpression): Every event which is not + static has an associated instance expression. + + * typemanager.cs (RegisterEvent): The usual workaround, now for events. + + (GetAddMethod, GetRemoveMethod): Workarounds, as usual. + + * class.cs (Event.Define): Register event and perform appropriate checks + for error #111. + + We define the Add and Remove methods even if the use provides none because + in that case, we provide default implementations ourselves. + + Define a private field of the type of the event. This is done by the CSC compiler + and we should be doing it too ;-) + + * typemanager.cs (delegate_combine_delegate_delegate, delegate_remove_delegate_delegate): + More methods we use in code we generate. + + (multicast_delegate_type, delegate_type): Two separate types since the distinction + is important. + + (InitCoreTypes): Update accordingly for the above. + + * class.cs (Event.Emit): Generate code for default accessors that we provide + + (EmitDefaultMethod): Do the job in the above. + + * delegate.cs (DefineDelegate): Use TypeManager.multicast_delegate_type in the + appropriate place. + +2001-12-20 Miguel de Icaza + + * class.cs (Indexer.Define): Fix bug, we were setting both Get/Set + builders even if we were missing one. + + * interface.cs, class.cs, enum.cs: When calling DefineNestedType + pass the Basename as our class name instead of the Name. The + basename will be correctly composed for us. + + * parameter.cs (Paramters): Now takes a Location argument. + + * decl.cs (DeclSpace.LookupType): Removed convenience function and + make all the code call directly LookupType in RootContext and take + this chance to pass the Location information everywhere. + + * Everywhere: pass Location information. + +2001-12-19 Miguel de Icaza + + * class.cs (Constructor.Define): Updated way of detecting the + length of the parameters. + + (TypeContainer.DefineType): Use basename as the type name for + nested types. + + (TypeContainer.Define): Do not recursively define types here, as + definition is taken care in order by the RootContext. + + * tree.cs: Keep track of namespaces in a per-file basis. + + * parameter.cs (Parameter.ComputeSignature): Update to use + DeclSpace. + + (Parameters.GetSignature): ditto. + + * interface.cs (InterfaceMethod.GetSignature): Take a DeclSpace + instead of a TypeContainer. + + (Interface.SemanticAnalysis): Use `this' instead of our parent to + resolve names. Because we need to be resolve in our context, not + our parents. + + * driver.cs: Implement response files. + + * class.cs (TypeContainer.DefineType): If we are defined, do not + redefine ourselves. + + (Event.Emit): Emit the code for add/remove handlers. + (Event.Define): Save the MethodBuilders for add/remove. + + * typemanager.cs: Use pair here too. + + * cs-parser.jay: Replaced use of DictionaryEntry for Pair because + DictionaryEntry requires the first argument to be non-null. + + (enum_declaration): Compute full name for registering the + enumeration. + + (delegate_declaration): Instead of using + formal_parameter_list, use opt_formal_parameter_list as the list + can be empty. + + * cs-tokenizer.cs (PropertyParsing): renamed from `properties' + (EventParsing): New property that controls whether `add' and + `remove' are returned as tokens or identifiers (for events); + +2001-12-19 Ravi Pratap + + * class.cs (Event.Define): Revamp use of EventBuilder completely. We now + use MyEventBuilder only and let it wrap the real builder for us. + + (MyEventBuilder): Revamp constructor etc. + + Implement all operations that we perform on EventBuilder in precisely the same + way here too. + + (FindMembers): Update to use the EventBuilder member. + + (Event.Emit): Update accordingly. + +2001-12-18 Ravi Pratap + + * class.cs (MyEventBuilder.Set*): Chain to the underlying builder + by calling the appropriate methods. + + (GetCustomAttributes): Make stubs as they cannot possibly do anything + useful. + + (Event.Emit): Use MyEventBuilder everywhere - even to set attributes. + +2001-12-17 Ravi Pratap + + * delegate.cs (Delegate.Populate): Check that the return type + and various parameters types are indeed accessible. + + * class.cs (Constructor.Define): Same here. + + (Field.Define): Ditto. + + (Event.Define): Ditto. + + (Operator.Define): Check that the underlying Method defined itself + correctly - so it's MethodBuilder should not be null. + + * delegate.cs (DelegateInvocation.DoResolve): Bale out if the type of the Instance + expression happens to be null. + + * class.cs (MyEventBuilder): Workaround for SRE lameness. Implement various abstract + members but as of now we don't seem to be able to do anything really useful with it. + + (FindMembers): Handle events separately by returning the MyEventBuilder of the event, + not the EventBuilder. + +2001-12-18 Miguel de Icaza + + * cs-tokenizer.cs: Add support for defines. + Add support for #if, #elif, #else, #endif + + (eval_var): evaluates a variable. + (eval): stubbed for evaluating functions. + + * cs-parser.jay: Pass the defines information + + * driver.cs: Add --define command line option. + + * decl.cs: Move MemberCore here. + + Make it the base class for DeclSpace. This allows us to catch and + report 108 and 109 for everything now. + + * class.cs (TypeContainer.Define): Extract all the members + before populating and emit the warning 108 (new keyword required + to override) instead of having each member implement this. + + (MemberCore.Define): New abstract method, we will be using this in + the warning reporting engine in Populate. + + (Operator.Define): Adjust to new MemberCore protocol. + + * const.cs (Const): This does not derive from Expression, it is a + temporary object we use to create fields, it is a MemberCore. + + * class.cs (Method.Define): Allow the entry point to be in a + specific class. + + * driver.cs: Rewrite the argument handler to clean it up a bit. + + * rootcontext.cs: Made it just an auxiliary namespace feature by + making everything static. + + * driver.cs: Adapt code to use RootContext type name instead of + instance variable. + + * delegate.cs: Remove RootContext argument. + + * class.cs: (Struct, TypeContainer, Class): Remove RootContext + argument. + + * class.cs (Event.Define): The lookup can fail. + + * cs-tokenizer.cs: Begin implementation of pre-procesor. + + * expression.cs: Resolve the this instance before invoking the code. + +2001-12-17 Miguel de Icaza + + * cs-parser.jay: Add a production in element_access that allows + the thing to become a "type" reference. This way we can parse + things like "(string [])" as a type. + + Note that this still does not handle the more complex rules of + casts. + + + * delegate.cs (Delegate.Populate): Register the delegage constructor builder here. + + * ecore.cs: (CopyNewMethods): new utility function used to + assemble the list of methods from running FindMembers. + + (MemberLookup): Rework FindMembers so that + +2001-12-16 Miguel de Icaza + + * class.cs (TypeContainer): Remove Delegates who fail to be + defined. + + * delegate.cs (Populate): Verify that we dont get null return + values. TODO: Check for AsAccessible. + + * cs-parser.jay: Use basename to emit error 574 (destructor should + have the same name as container class), not the full name. + + * cs-tokenizer.cs (adjust_int): Fit the integer in the best + possible representation. + + Also implements integer type suffixes U and L. + +2001-12-15 Miguel de Icaza + + * expression.cs (ArrayCreation.DoResolve): We need to do the + argument resolution *always*. + + * decl.cs: Make this hold the namespace. Hold the root context as + well. + (LookupType): Move here. + + * enum.cs, class.cs, interface.cs: Adapt to new hierarchy. + + * location.cs (Row, Name): Fixed the code, it was always returning + references to the first file. + + * interface.cs: Register properties defined through interfaces. + + * driver.cs: Add support for globbing on the command line + + * class.cs (Field): Make it derive from MemberCore as well. + (Event): ditto. + +2001-12-15 Ravi Pratap + + * class.cs (Event::Define): Check that the type of the event is a delegate + type else flag error #66. + + Also, re-use TypeContainer.MethodModifiersValid here too as the rules are the + same. + + * attribute.cs (DefinePInvokeMethod): Handle named arguments and process + values of EntryPoint, CharSet etc etc. + + Pass in the values to TypeBuilder.DefinePInvokeMethod; determine Type etc neatly. + + * class.cs (FindMembers): If a method is in transit, its MethodBuilder will + be null and we should ignore this. I am not sure if this is really clean. Apparently, + there's no way of avoiding hitting this because the call is coming from SimpleName.DoResolve, + which needs this to do its work. + + * ../errors/cs0066.cs : Add. + +2001-12-14 Miguel de Icaza + + * typemanager.cs: (GetPropertyGetter, GetPropertyGetter): New + helper functions. + + * class.cs: (MethodSignature.MethodSignature): Removed hack that + clears out the parameters field. + (MemberSignatureCompare): Cleanup + + (MemberCore): New base class used to share code between MethodCore + and Property. + + (RegisterRequiredImplementations) BindingFlags.Public requires + either BindingFlags.Instace or Static. Use instance here. + + (Property): Refactored code to cope better with the full spec. + + * parameter.cs (GetParameterInfo): Return an empty array instead + of null on error. + + * class.cs (Property): Abstract or extern properties have no bodies. + + * parameter.cs (GetParameterInfo): return a zero-sized array. + + * class.cs (TypeContainer.MethodModifiersValid): Move all the + method modifier validation to the typecontainer so we can reuse + this on properties. + + (MethodCore.ParameterTypes): return an empty sized array of types. + + (Property.Define): Test property modifier validity. + + Add tests for sealed/override too. + + (Method.Emit): abstract or extern methods have no bodies. + +2001-12-14 Ravi Pratap + + * class.cs (Method.IsPInvoke): Get rid of it as it is an expensive + thing. + + (Method::Define, ::Emit): Modify accordingly. + + * expression.cs (Invocation::OverloadResolve): Handle error # 121. + + (ArrayCreation::MakeByteBlob): Handle floats and doubles. + + * makefile: Pass in /unsafe. + +2001-12-13 Miguel de Icaza + + * class.cs (MakeKey): Kill routine. + + * class.cs (TypeContainer.Define): Correctly define explicit + method implementations (they require the full interface name plus + the method name). + + * typemanager.cs: Deply the PtrHashtable here and stop using the + lame keys. Things work so much better. + + This of course broke everyone who depended on `RegisterMethod' to + do the `test for existance' test. This has to be done elsewhere. + + * support.cs (PtrHashtable): A hashtable that avoid comparing with + the object stupid Equals method (because, that like fails all over + the place). We still do not use it. + + * class.cs (TypeContainer.SetRequiredInterface, + TypeContainer.RequireMethods): Killed these two routines and moved + all the functionality to RegisterRequiredImplementations. + + (TypeContainer.RegisterRequiredImplementations): This routine now + registers all the implementations required in an array for the + interfaces and abstract methods. We use an array of structures + which can be computed ahead of time to reduce memory usage and we + also assume that lookups are cheap as most classes will not + implement too many interfaces. + + We also avoid creating too many MethodSignatures. + + (TypeContainer.IsInterfaceMethod): Update and optionally does not + clear the "pending" bit if we find that there are problems with + the declaration. + + (TypeContainer.VerifyPendingMethods): Update to report errors of + methods that look like implementations but are not. + + (TypeContainer.Define): Add support for explicit interface method + implementation. + +2001-12-12 Miguel de Icaza + + * typemanager.cs: Keep track of the parameters here instead of + being a feature of the TypeContainer. + + * class.cs: Drop the registration of parameters here, as + InterfaceMethods are also interface declarations. + + * delegate.cs: Register methods with the TypeManager not only with + the TypeContainer. This code was buggy. + + * interface.cs: Full registation here. + +2001-12-11 Miguel de Icaza + + * expression.cs: Remove reducer for binary expressions, it can not + be done this way. + + * const.cs: Put here the code that used to go into constant.cs + + * constant.cs: Put here the code for constants, this is a new base + class for Literals. + + * literal.cs: Make Literal derive from Constant. + +2001-12-09 Miguel de Icaza + + * statement.cs (Return.Emit): Report error 157 if the user + attempts to return from a finally block. + + (Return.Emit): Instead of emitting a return, jump to the end of + the function. + + * codegen.cs (EmitContext): ReturnValue, ReturnLabel: new + LocalBuilder to store the result of the function. ReturnLabel is + the target where we jump. + + +2001-12-09 Radek Doulik + + * cs-parser.jay: remember alias in current namespace + + * ecore.cs (SimpleName::DoResolve): use aliases for types or + namespaces + + * class.cs (LookupAlias): lookup alias in my_namespace + + * namespace.cs (UsingAlias): add alias, namespace_or_type pair to + aliases hashtable + (LookupAlias): lookup alias in this and if needed in parent + namespaces + +2001-12-08 Miguel de Icaza + + * support.cs: + + * rootcontext.cs: (ModuleBuilder) Made static, first step into + making things static. I need this to avoid passing the + TypeContainer when calling ParameterType. + + * support.cs (InternalParameters.ParameterType): Remove ugly hack + that did string manipulation to compute the type and then call + GetType. Use Parameter.ParameterType instead. + + * cs-tokenizer.cs: Consume the suffix for floating values. + + * expression.cs (ParameterReference): figure out whether this is a + reference parameter or not. Kill an extra variable by computing + the arg_idx during emission. + + * parameter.cs (Parameters.GetParameterInfo): New overloaded + function that returns whether a parameter is an out/ref value or not. + + (Parameter.ParameterType): The type of the parameter (base, + without ref/out applied). + + (Parameter.Resolve): Perform resolution here. + (Parameter.ExternalType): The full type (with ref/out applied). + + * statement.cs (Using.Emit, Using.EmitExpression): Implement + support for expressions on the using statement. + +2001-12-07 Miguel de Icaza + + * statement.cs (Using.EmitLocalVariableDecls): Split the + localvariable handling of the using statement. + + (Block.EmitMeta): Keep track of variable count across blocks. We + were reusing slots on separate branches of blocks. + + (Try.Emit): Emit the general code block, we were not emitting it. + + Check the type of the declaration to be an IDisposable or + something that can be implicity converted to it. + + Emit conversions if required. + + * ecore.cs (EmptyExpression): New utility class. + (Expression.ImplicitConversionExists): New utility function. + +2001-12-06 Miguel de Icaza + + * statement.cs (Using): Implement. + + * expression.cs (LocalVariableReference): Support read only variables. + + * statement.cs: Remove the explicit emit for the Leave opcode. + (VariableInfo): Add a readonly field. + +2001-12-05 Miguel de Icaza + + * ecore.cs (ConvCast): new class used to encapsulate the various + explicit integer conversions that works in both checked and + unchecked contexts. + + (Expression.ConvertNumericExplicit): Use new ConvCast class to + properly generate the overflow opcodes. + +2001-12-04 Miguel de Icaza + + * statement.cs: The correct type for the EmptyExpression is the + element_type, not the variable type. Ravi pointed this out. + +2001-12-04 Ravi Pratap + + * class.cs (Method::Define): Handle PInvoke methods specially + by using DefinePInvokeMethod instead of the usual one. + + * attribute.cs (DefinePInvokeMethod): Implement as this is what is called + above to do the task of extracting information and defining the method. + +2001-12-04 Ravi Pratap + + * expression.cs (ArrayCreation::EmitStaticInitializers): Get rid + of the condition for string type. + + (Emit): Move that here. + + (ArrayCreation::CheckIndices): Keep string literals in their expression + form. + + (EmitDynamicInitializers): Handle strings appropriately. + +2001-12-04 Miguel de Icaza + + * codegen.cs (EmitContext): Replace multiple variables with a + single pointer to the current Switch statement. + + * statement.cs (GotoDefault, Switch): Adjust to cleaned up + EmitContext. + +2001-12-03 Miguel de Icaza + + * statement.cs + + * statement.cs (GotoDefault), cs-parser.jay: Implement `goto + default'. + + (Foreach.Emit): Foreach on arrays was not setting + up the loop variables (for break/continue). + + (GotoCase): Semi-implented. + +2001-12-03 Ravi Pratap + + * attribute.cs (CheckAttribute): Handle system attributes by using + Attribute.GetAttributes to examine information we need. + + (GetValidPlaces): Same here. + + * class.cs (Method::Define): Catch invalid use of extern and abstract together. + + * typemanager.cs (dllimport_type): Core type for System.DllImportAttribute. + + * class.cs (Method.IsPinvoke): Used to determine if we are a PInvoke method. + + (Method::Define): Set appropriate flags if we have a DllImport attribute. + + (Method::Emit): Handle the case when we are a PInvoke method. + +2001-12-03 Miguel de Icaza + + * expression.cs: Use ResolveWithSimpleName on compound names. + +2001-12-02 Ravi Pratap + + * constant.cs (EmitConstant): Make sure we resolve the associated expression + before trying to reduce it. + + * typemanager.cs (RegisterConstant, LookupConstant): Implement. + + * constant.cs (LookupConstantValue): Implement. + + (EmitConstant): Use the above in emitting the constant. + + * expression.cs (MemberAccess::ResolveMemberAccess): Handle constants + that are user-defined by doing a LookupConstantValue on them. + + (SimpleName::DoResolve): When we have a FieldExpr, cope with constants + too, like above. + +2001-11-29 Miguel de Icaza + + * expression.cs (BaseAccess, BaseIndexer): Also split this out. + + (BaseAccess.DoResolve): Implement. + + (MemberAccess.DoResolve): Split this routine into a + ResolveMemberAccess routine that can be used independently + +2001-11-28 Miguel de Icaza + + * expression.cs (Probe, Is, As): Split Probe in two classes Is and + As that share bits of the implementation. Is returns a boolean, + while As returns the Type that is being probed. + +2001-12-01 Ravi Pratap + + * enum.cs (LookupEnumValue): Re-write various bits, return an object value + instead of a Literal - much easier. + + (EnumInTransit): Remove - utterly useless :-) + + (Populate): Re-write bits - remove duplicate code etc. The code is much neater now. + + * expression.cs (MemberLookup): Cope with user-defined enums when they are in transit. + + * enum.cs (LookupEnumValue): Auto-compute next values by going down the dependency + chain when we have no associated expression. + +2001-11-30 Ravi Pratap + + * constant.cs (Define): Use Location while reporting the errror. + + Also emit a warning when 'new' is used and there is no inherited + member to hide. + + * enum.cs (EnumInTransit): Used to tell if an enum type is in the process of being + populated. + + (LookupEnumValue): Implement to lookup an enum member's value and define it + if necessary. + + (Populate): Re-write accordingly to use the above routine. + +2001-11-27 Miguel de Icaza + + * expression.cs (This): Fix prototype for DoResolveLValue to + override the base class DoResolveLValue. + + * cs-parser.cs: Report errors cs574 and cs575 (destructor + declarations) + + * ecore.cs (FieldExpr.EmitAssign): Handle value types specially + (we need to load the address of the field here). This fixes + test-22. + + (FieldExpr.DoResolveLValue): Call the DoResolve + function to initialize the Instance expression. + + * statement.cs (Foreach.Emit): Fix the bug where we did not invoke + correctly the GetEnumerator operation on a value type. + + * cs-parser.jay: Add more simple parsing error catches. + + * statement.cs (Switch): Add support for string switches. + Handle null specially. + + * literal.cs (NullLiteral): Make NullLiteral objects singletons. + +2001-11-28 Ravi Pratap + + * cs-parser.jay (local_constant_declaration): Use declare_local_constant. + + (declare_local_constant): New helper function. + + * statement.cs (AddConstant): Keep a separate record of constants + + (IsConstant): Implement to determine if a variable is a constant. + + (GetConstantExpression): Implement. + + * expression.cs (LocalVariableReference): Handle the case when it is a constant. + + * statement.cs (IsVariableDefined): Re-write. + +2001-11-27 Ravi Pratap + + * class.cs (TypeContainer::FindMembers): Look for constants + in the case when we are looking for MemberTypes.Field + + * expression.cs (MemberAccess::DoResolve): Check that in the + case we are a FieldExpr and a Literal, we are not being accessed + by an instance reference. + + * cs-parser.jay (local_constant_declaration): Implement. + + (declaration_statement): Implement for constant declarations. + +2001-11-26 Miguel de Icaza + + * statement.cs (Switch): Catch double defaults. + + (Switch): More work on the switch() statement + implementation. It works for integral values now, need to finish + string support. + + +2001-11-24 Miguel de Icaza + + * ecore.cs (Expression.ConvertIntLiteral): New function to convert + integer literals into other integer literals. To be used by + switch. + +2001-11-24 Ravi Pratap + + * expression.cs (ArrayCreation): Get rid of ArrayExprs : we save + some memory. + + (EmitDynamicInitializers): Cope with the above since we extract data + directly from ArrayData now. + + (ExpectInitializers): Keep track of whether initializers are mandatory + or not. + + (Bounds): Make it a hashtable to prevent the same dimension being + recorded for every element in that dimension. + + (EmitDynamicInitializers): Fix bug which prevented the Set array method + from being found. + + Also fix bug which was causing the indices to be emitted in the reverse + order. + +2001-11-24 Miguel de Icaza + + * expression.cs (ArrayCreation): Implement the bits that Ravi left + unfinished. They do not work, because the underlying code is + sloppy. + +2001-11-22 Miguel de Icaza + + * cs-parser.jay: Remove bogus fixme. + + * statement.cs (Switch, SwitchSection, SwithLabel): Started work + on Switch statement. + +2001-11-23 Ravi Pratap + + * typemanager.cs (IsDelegateType, IsEnumType): Fix logic to determine + the same. + + * expression.cs (ArrayCreation::CheckIndices): Get rid of the require_constant + parameter. Apparently, any expression is allowed. + + (ValidateInitializers): Update accordingly. + + (CheckIndices): Fix some tricky bugs thanks to recursion. + + * delegate.cs (NewDelegate::DoResolve): Re-write large portions as + I was being completely brain-dead. + + (VerifyMethod, VerifyApplicability, VerifyDelegate): Make static + and re-write acordingly. + + (DelegateInvocation): Re-write accordingly. + + * expression.cs (ArrayCreation::Emit): Handle string initialization separately. + + (MakeByteBlob): Handle types more correctly. + + * expression.cs (ArrayCreation:Emit): Write preliminary code to do + initialization from expressions but it is incomplete because I am a complete + Dodo :-| + +2001-11-22 Miguel de Icaza + + * statement.cs (If.Emit): Fix a bug that generated incorrect code + on If. Basically, we have to return `true' (ie, we do return to + our caller) only if both branches of the if return. + + * expression.cs (Binary.Emit): LogicalOr and LogicalAnd are + short-circuit operators, handle them as short circuit operators. + + (Cast.DoResolve): Resolve type. + (Cast.Cast): Take an expression as the target type. + + * cs-parser.jay (cast_expression): Remove old hack that only + allowed a limited set of types to be handled. Now we take a + unary_expression and we resolve to a type during semantic + analysis. + + Use the grammar productions from Rhys to handle casts (this is + not complete like Rhys syntax yet, we fail to handle that corner + case that C# has regarding (-x), but we will get there. + +2001-11-22 Ravi Pratap + + * class.cs (EmitFieldInitializer): Take care of the case when we have a + field which is an array type. + + * cs-parser.jay (declare_local_variables): Support array initialization too. + + * typemanager.cs (MakeKey): Implement. + + (everywhere): Use the above appropriately. + + * cs-parser.jay (for_statement): Update for array initialization while + declaring variables. + + * ecore.cs : The error message was correct, it's the variable's names that + were misleading ;-) Make the code more readable. + + (MemberAccess::DoResolve): Fix the code which handles Enum literals to set + the correct type etc. + + (ConvertExplicit): Handle Enum types by examining the underlying type. + +2001-11-21 Ravi Pratap + + * parameter.cs (GetCallingConvention): Always return + CallingConventions.Standard for now. + +2001-11-22 Miguel de Icaza + + * expression.cs (Binary.ResolveOperator): Update the values of `l' + and `r' after calling DoNumericPromotions. + + * ecore.cs: Fix error message (the types were in the wrong order). + + * statement.cs (Foreach.ProbeCollectionType): Need to pass + BindingFlags.Instance as well + + * ecore.cs (Expression.TryImplicitIntConversion): Wrap the result + implicit int literal conversion in an empty cast so that we + propagate the right type upstream. + + (UnboxCast): new class used to unbox value types. + (Expression.ConvertExplicit): Add explicit type conversions done + by unboxing. + + (Expression.ImplicitNumericConversion): Oops, forgot to test for + the target type before applying the implicit LongLiterals to ULong + literal cast. + +2001-11-21 Miguel de Icaza + + * cs-parser.jay (for_statement): Reworked the way For works: now + we declare manually any variables that are introduced in + for_initializer to solve the problem of having out-of-band code + emition (that is what got for broken). + + (declaration_statement): Perform the actual variable declaration + that used to be done in local_variable_declaration here. + + (local_variable_declaration): Do not declare anything, just pass + the information on a DictionaryEntry + +2001-11-20 Ravi Pratap + + * expression.cs (ArrayCreation::CheckIndices): The story continues :-) Complete + re-write of the logic to now make it recursive. + + (UpdateIndices): Re-write accordingly. + + Store element data in a separate ArrayData list in the above methods. + + (MakeByteBlob): Implement to dump the array data into a byte array. + +2001-11-19 Ravi Pratap + + * expression.cs (ArrayCreation): Factor out some code from ValidateInitializers + into CheckIndices. + + * constant.cs (Define): Implement. + + (EmitConstant): Re-write fully. + + Pass in location info. + + * class.cs (Populate, Emit): Call Constant::Define and Constant::EmitConstant + respectively. + + * cs-parser.jay (constant_declarator): Use VariableDeclaration instead of + DictionaryEntry since we need location info too. + + (constant_declaration): Update accordingly. + + * expression.cs (ArrayCreation): Make ValidateInitializers simpler by factoring + code into another method : UpdateIndices. + +2001-11-18 Ravi Pratap + + * expression.cs (ArrayCreation::ValidateInitializers): Update to perform + some type checking etc. + +2001-11-17 Ravi Pratap + + * expression.cs (ArrayCreation::ValidateInitializers): Implement + bits to provide dimension info if the user skips doing that. + + Update second constructor to store the rank correctly. + +2001-11-16 Ravi Pratap + + * expression.cs (ArrayCreation::ValidateInitializers): Poke around + and try to implement. + + * ../errors/cs0150.cs : Add. + + * ../errors/cs0178.cs : Add. + +2001-11-16 Miguel de Icaza + + * statement.cs: Implement foreach on multi-dimensional arrays. + + * parameter.cs (Parameters.GetParameterByName): Also lookup the + name of the params argument. + + * expression.cs: Use EmitStoreOpcode to get the right opcode while + initializing the array. + + (ArrayAccess.EmitStoreOpcode): move the opcode generation here, so + we can use this elsewhere. + + * statement.cs: Finish implementation of foreach for single + dimension arrays. + + * cs-parser.jay: Use an out-of-band stack to pass information + around, I wonder why I need this. + + foreach_block: Make the new foreach_block the current_block. + + * parameter.cs (Parameters.GetEmptyReadOnlyParameters): New + function used to return a static Parameters structure. Used for + empty parameters, as those are created very frequently. + + * cs-parser.jay, class.cs: Use GetEmptyReadOnlyParameters + +2001-11-15 Ravi Pratap + + * interface.cs : Default modifier is private, not public. The + make verify test passes again. + +2001-11-15 Ravi Pratap + + * support.cs (ReflectionParameters): Fix logic to determine + whether the last parameter is a params one. Test 9 passes again. + + * delegate.cs (Populate): Register the builders we define with + RegisterParameterForBuilder. Test 19 passes again. + + * cs-parser.jay (property_declaration): Reference $6 instead + of $$ to get at the location. + + (indexer_declaration): Similar stuff. + + (attribute): Ditto. + + * class.cs (Property): Register parameters for the Get and Set methods + if they exist. Test 23 passes again. + + * expression.cs (ArrayCreation::Emit): Pass null for the method in the + call to EmitArguments as we are sure there aren't any params arguments. + Test 32 passes again. + + * suppor.cs (ParameterDesc, ParameterModifier): Fix trivial bug causing + IndexOutOfRangeException. + + * class.cs (Property::Define): Register property using TypeManager.RegisterProperty + Test 33 now passes again. + +2001-11-15 Miguel de Icaza + + * cs-parser.jay: Kill horrendous hack ($??? = lexer.Location) that + broke a bunch of things. Will have to come up with a better way + of tracking locations. + + * statement.cs: Implemented foreach for single dimension arrays. + +2001-11-09 Miguel de Icaza + + * enum.cs (Enum.Emit): Delay the lookup of loc until we run into + an error. This removes the lookup from the critical path. + + * cs-parser.jay: Removed use of temporary_loc, which is completely + broken. + +2001-11-14 Miguel de Icaza + + * support.cs (ReflectionParameters.ParameterModifier): Report + whether the argument is a PARAMS argument or not. + + * class.cs: Set the attribute `ParamArrayAttribute' on the + parameter argument. + + * typemanager.cs: Define param_array_type (ParamArrayAttribute) + and cons_param_array_attribute (ConstructorInfo for + ParamArrayAttribute)., + + * codegen.cs: Emit the return using the `Return' statement, that + way we can report the error correctly for missing return values. + + * class.cs (Method.Emit): Clean up. + + * expression.cs (Argument.Resolve): Take another argument: the + location where this argument is used. Notice that this is not + part of the "Argument" class as to reduce the size of the + structure (we know the approximate location anyways). + + Test if the argument is a variable-reference, if not, then + complain with a 206. + + (Argument.Emit): Emit addresses of variables. + + (Argument.FullDesc): Simplify. + + (Invocation.DoResolve): Update for Argument.Resolve. + + (ElementAccess.DoResolve): ditto. + + * delegate.cs (DelegateInvocation.Emit): Invocation of Invoke + method should be virtual, as this method is always virtual. + + (NewDelegate.DoResolve): Update for Argument.Resolve. + + * class.cs (ConstructorInitializer.DoResolve): ditto. + + * attribute.cs (Attribute.Resolve): ditto. + +2001-11-13 Miguel de Icaza + + * statement.cs (Foreach.Emit): Use EmitAssign instead of Store. + + * expression.cs (ParameterReference): Drop IStackStorage and implement + IAssignMethod instead. + + (LocalVariableReference): ditto. + + * ecore.cs (FieldExpr): Drop IStackStorage and implement + IAssignMethod instead. + +2001-11-13 Miguel de Icaza + + * parameter.cs, expression.cs, class.cs, ecore.cs: Made all + enumerations that are used in heavily used structures derive from + byte in a laughable and pathetic attempt to reduce memory usage. + This is the kind of pre-optimzations that you should not do at + home without adult supervision. + + * expression.cs (UnaryMutator): New class, used to handle ++ and + -- separatedly from the other unary operators. Cleans up the + code, and kills the ExpressionStatement dependency in Unary. + + (Unary): Removed `method' and `Arguments' from this class, making + it smaller, and moving it all to SimpleCall, so I can reuse this + code in other locations and avoid creating a lot of transient data + strucutres when not required. + + * cs-parser.jay: Adjust for new changes. + +2001-11-11 Miguel de Icaza + + * enum.cs (Enum.Populate): If there is a failure during + definition, return + + * cs-parser.jay (opt_enum_base): we used to catch type errors + here, but this is really incorrect. The type error should be + catched during semantic analysis. + +2001-12-11 Ravi Pratap + + * cs-parser.jay (operator_declarator, conversion_operator_declarator): Set + current_local_parameters as expected since I, in my stupidity, had forgotten + to do this :-) + + * attribute.cs (GetValidPlaces): Fix stupid bug. + + * class.cs (Method::Emit): Perform check on applicability of attributes. + + (Constructor::Emit): Ditto. + + (Field::Emit): Ditto. + + (Field.Location): Store location information. + + (Property, Event, Indexer, Operator): Ditto. + + * cs-parser.jay (field_declaration): Pass in location for each field. + + * ../errors/cs0592.cs : Add. + +2001-11-12 Ravi Pratap + + * typemanager.cs (attribute_usage_type): New static member for System.AttributeUsage. + + (InitCoreTypes): Update accordingly. + + (RegisterAttrType, LookupAttr): Implement. + + * attribute.cs (Attribute.Targets, AllowMultiple, Inherited): New fields to hold + info about the same. + + (Resolve): Update to populate the above as necessary. + + (Error592): Helper. + + (GetValidPlaces): Helper to the above. + + (CheckAttribute): Implement to perform validity of attributes on declarative elements. + + * class.cs (TypeContainer::Emit): Update attribute emission code to perform checking etc. + +2001-11-12 Ravi Pratap + + * attribute.cs (Attribute::Resolve): Expand to handle named arguments too. + + * ../errors/cs0617.cs : Add. + +2001-11-11 Ravi Pratap + + * enum.cs (Emit): Rename to Populate to be more consistent with what + we expect it to do and when exactly it is called. + + * class.cs, rootcontext.cs : Update accordingly. + + * typemanager.cs (RegisterField, GetValue): Workarounds for the fact that + FieldInfo.GetValue does not work on dynamic types ! S.R.E lameness strikes again ! + + * enum.cs (Populate): Register fields with TypeManager.RegisterField. + + * expression.cs (MemberAccess.DoResolve): Adjust code to obtain the value + of a fieldinfo using the above, when dealing with a FieldBuilder. + +2001-11-10 Ravi Pratap + + * ../errors/cs0031.cs : Add. + + * ../errors/cs1008.cs : Add. + + * ../errrors/cs0543.cs : Add. + + * enum.cs (DefineEnum): Check the underlying type and report an error if not a valid + enum type. + + (FindMembers): Implement. + + * typemanager.cs (FindMembers): Re-write to call the appropriate methods for + enums and delegates too. + + (enum_types): Rename to builder_to_enum. + + (delegate_types): Rename to builder_to_delegate. + + * delegate.cs (FindMembers): Implement. + +2001-11-09 Ravi Pratap + + * typemanager.cs (IsEnumType): Implement. + + * enum.cs (Emit): Re-write parts to account for the underlying type + better and perform checking etc. + + (GetNextDefaultValue): Helper to ensure we don't overshoot max value + of the underlying type. + + * literal.cs (GetValue methods everywhere): Perform bounds checking and return + value + + * enum.cs (error31): Helper to report error #31. + + * cs-parser.jay (enum_declaration): Store location of each member too. + + * enum.cs (member_to_location): New hashtable. + + (AddEnumMember): Update location hashtable. + + (Emit): Use the location of each member while reporting errors. + +2001-11-09 Miguel de Icaza + + * cs-parser.jay: A for_initializer if is a + local_variable_declaration really ammount to have an implicit + block with the variable declaration and no initializer for for. + + * statement.cs (For.Emit): Cope with null initializers. + + This fixes the infinite loop on for initializers. + +2001-11-08 Miguel de Icaza + + * enum.cs: More cleanup. + + * ecore.cs: Remove dead code. + + * class.cs (Property.Emit): More simplification. + (Event.Emit): ditto. + + Reworked to have less levels of indentation. + +2001-11-08 Ravi Pratap + + * class.cs (Property): Emit attributes. + + (Field): Ditto. + + (Event): Ditto. + + (Indexer): Ditto. + + (Operator): Ditto. + + * enum.cs (Emit): Ditto. + + * rootcontext.cs (ResolveTree, EmitCode, CloseTypes): Do the same for + Enums too. + + * class.cs (Field, Event, etc.): Move attribute generation into the + Emit method everywhere. + + * enum.cs (Enum): Revamp to use the same definition semantics as delegates so + we have a DefineEnum, CloseEnum etc. The previous way of doing things was not right + as we had no way of defining nested enums ! + + * rootcontext.cs : Adjust code accordingly. + + * typemanager.cs (AddEnumType): To keep track of enum types separately. + +2001-11-07 Ravi Pratap + + * expression.cs (EvalConstantExpression): Move into ecore.cs + + * enum.cs (Enum): Rename some members and make them public and readonly + according to our convention. + + * modifiers.cs (EnumAttr): Implement as we need to set only visibility flags, + nothing else. + + * enum.cs (Enum::Define): Use the above instead of TypeAttr. + + (Enum::Emit): Write a simple version for now which doesn't try to compute + expressions. I shall modify this to be more robust in just a while. + + * class.cs (TypeContainer::Emit): Make sure we include Enums too. + + (TypeContainer::CloseType): Create the Enum types too. + + * attribute.cs (Resolve): Use the new Reduce method instead of EvalConstantExpression. + + * expression.cs (EvalConstantExpression): Get rid of completely. + + * enum.cs (Enum::Emit): Use the new expression reducer. Implement assigning + user-defined values and other cases. + + (IsValidEnumLiteral): Helper function. + + * expression.cs (ExprClassfromMemberInfo): Modify to not do any literalizing + out there in the case we had a literal FieldExpr. + + (MemberAccess:DoResolve): Do the literalizing of the FieldExpr here. + + (Literalize): Revamp a bit to take two arguments. + + (EnumLiteral): New class which derives from Literal to wrap enum literals. + +2001-11-06 Ravi Pratap + + * cs-parser.jay (compilation_unit): Remove extra opt_attributes for now. + + * expression.cs (ArrayCreation::ValidateInitializers): Implement. + + (Resolve): Use the above to ensure we have proper initializers. + +2001-11-05 Ravi Pratap + + * expression.cs (Expression::EvalConstantExpression): New method to + evaluate constant expressions. + + * attribute.cs (Attribute::Resolve): Modify bits to use the above function. + +2001-11-07 Miguel de Icaza + + * expression.cs (ArrayCreation.Emit): Some bits to initialize data + in an array. + + (Binary.ResolveOperator): Handle operator != (object a, object b) + and operator == (object a, object b); + + (Binary.DoNumericPromotions): Indicate whether the numeric + promotion was possible. + + (ArrayAccess.DoResolve, ArrayAccess.Emit, ArrayAccess.EmitAssign): + Implement. + + Made the ArrayAccess implement interface IAssignMethod instead of + IStackStore as the order in which arguments are passed reflects + this. + + * assign.cs: Instead of using expr.ExprClass to select the way of + assinging, probe for the IStackStore/IAssignMethod interfaces. + + * typemanager.cs: Load InitializeArray definition. + + * rootcontext.cs (RootContext.MakeStaticData): Used to define + static data that can be used to initialize arrays. + +2001-11-05 Miguel de Icaza + + * expression.cs: Handle operator== and operator!= for booleans. + + (Conditioal.Reduce): Implement reducer for the ?: operator. + + (Conditional.Resolve): Implement dead code elimination. + + (Binary.Resolve): Catch string literals and return a new + concatenated string. + + (Unary.Reduce): Implement reduction of unary expressions. + + * ecore.cs: Split out the expression core handling here. + + (Expression.Reduce): New method used to perform constant folding + and CSE. This is needed to support constant-expressions. + + * statement.cs (Statement.EmitBoolExpression): Pass true and false + targets, and optimize for !x. + +2001-11-04 Ravi Pratap + + * attribute.cs (Attribute::Resolve): Implement guts. Note that resolution + of an attribute gives us a CustomAttributeBuilder which we use accordingly to + set custom atttributes. + + * literal.cs (Literal::GetValue): New abstract method to return the actual + value of the literal, cast as an object. + + (*Literal): Implement GetValue method. + + * cs-parser.jay (positional_argument_list, named_argument_list): Add not just plain + expressions to the arraylist but objects of type Argument. + + * class.cs (TypeContainer::Emit): Emit our attributes too. + + (Method::Emit, Constructor::Emit): Ditto. + + * cs-parser.jay (constructor_declaration): Set attributes too, which we seemed + to be ignoring earlier. + +2001-11-03 Ravi Pratap + + * attribute.cs (AttributeSection::Define): Implement to do the business + of constructing a CustomAttributeBuilder. + + (Attribute): New trivial class. Increases readability of code. + + * cs-parser.jay : Update accordingly. + + (positional_argument_list, named_argument_list, named_argument): New rules + + (attribute_arguments): Use the above so that we are more correct. + +2001-11-02 Ravi Pratap + + * expression.cs (Invocation::IsParamsMethodApplicable): Implement + to perform all checks for a method with a params parameter. + + (Invocation::OverloadResolve): Update to use the above method and therefore + cope correctly with params method invocations. + + * support.cs (InternalParameters::ParameterDesc): Provide a desc for + params too. + + * class.cs (ConstructorInitializer::Resolve): Make sure we look for Non-public + constructors in our parent too because we can't afford to miss out on + protected ones ;-) + + * attribute.cs (AttributeSection): New name for the class Attribute + + Other trivial changes to improve readability. + + * cs-parser.jay (opt_attributes, attribute_section etc.): Modify to + use the new class names. + +2001-11-01 Ravi Pratap + + * class.cs (Method::Define): Complete definition for params types too + + (Indexer::Define): Ditto. + + * support.cs (InternalParameters::ParameterType, ParameterDesc, ParameterModifier): + Cope everywhere with a request for info about the array parameter. + +2001-11-01 Ravi Pratap + + * tree.cs (RecordNamespace): Fix up to check for the correct key. + + * cs-parser.jay (GetQualifiedIdentifier): New Helper method used in + local_variable_type to extract the string corresponding to the type. + + (local_variable_type): Fixup the action to use the new helper method. + + * codegen.cs : Get rid of RefOrOutParameter, it's not the right way to + go. + + * expression.cs : Clean out code which uses the above. + +2001-10-31 Ravi Pratap + + * typemanager.cs (RegisterMethod): Check if we already have an existing key + and bale out if necessary by returning a false. + + (RegisterProperty): Ditto. + + * class.cs (everywhere): Check the return value from TypeManager.RegisterMethod + and print out appropriate error messages. + + * interface.cs (everywhere): Ditto. + + * cs-parser.jay (property_declaration, event_declaration, indexer_declaration): Pass + location to constructor. + + * class.cs (Property, Event, Indexer): Update accordingly. + + * ../errors/cs111.cs : Added. + + * expression.cs (Invocation::IsApplicable): New static method to determine applicability + of a method, as laid down by the spec. + + (Invocation::OverloadResolve): Use the above method. + +2001-10-31 Ravi Pratap + + * support.cs (InternalParameters): Get rid of crap taking in duplicate info. We + now take a TypeContainer and a Parameters object. + + (ParameterData): Modify return type of ParameterModifier method to be + Parameter.Modifier and not a string. + + (ReflectionParameters, InternalParameters): Update accordingly. + + * expression.cs (Argument::GetParameterModifier): Same here. + + * support.cs (InternalParameters::ParameterType): Find a better way of determining + if we are a ref/out parameter. Actually, the type shouldn't be holding the '&' + symbol in it at all so maybe this is only for now. + +2001-10-30 Ravi Pratap + + * support.cs (InternalParameters): Constructor now takes an extra argument + which is the actual Parameters class. + + (ParameterDesc): Update to provide info on ref/out modifiers. + + * class.cs (everywhere): Update call to InternalParameters to pass in + the second argument too. + + * support.cs (ParameterData): Add ParameterModifier, which is a method + to return the modifier info [ref/out etc] + + (InternalParameters, ReflectionParameters): Implement the above. + + * expression.cs (Argument::ParameterModifier): Similar function to return + info about the argument's modifiers. + + (Invocation::OverloadResolve): Update to take into account matching modifiers + too. + + * class.cs (Indexer::Define): Actually define a Parameter object and put it onto + a new SetFormalParameters object which we pass to InternalParameters. + +2001-10-30 Ravi Pratap + + * expression.cs (NewArray): Merge into the ArrayCreation class. + +2001-10-29 Ravi Pratap + + * expression.cs (NewArray): Merge classes NewBuiltinArray and + NewUserdefinedArray into one as there wasn't much of a use in having + two separate ones. + + * expression.cs (Argument): Change field's name to ArgType from Type. + + (Type): New readonly property which returns the proper type, taking into + account ref/out modifiers. + + (everywhere): Adjust code accordingly for the above. + + * codegen.cs (EmitContext.RefOrOutParameter): New field to determine + whether we are emitting for a ref or out parameter. + + * expression.cs (Argument::Emit): Use the above field to set the state. + + (LocalVariableReference::Emit): Update to honour the flag and emit the + right stuff. + + * parameter.cs (Attributes): Set the correct flags for ref parameters. + + * expression.cs (Argument::FullDesc): New function to provide a full desc. + + * support.cs (ParameterData): Add method ParameterDesc to the interface. + + (ReflectionParameters, InternalParameters): Implement the above method. + + * expression.cs (Invocation::OverloadResolve): Use the new desc methods in + reporting errors. + + (Invocation::FullMethodDesc): Ditto. + +2001-10-29 Miguel de Icaza + + * cs-parser.jay: Add extra production for the second form of array + creation. + + * expression.cs (ArrayCreation): Update to reflect the above + change. + + * Small changes to prepare for Array initialization. + +2001-10-28 Miguel de Icaza + + * typemanager.cs (ImplementsInterface): interface might be null; + Deal with this problem; + + Also, we do store negative hits on the cache (null values), so use + this instead of calling t.GetInterfaces on the type everytime. + +2001-10-28 Ravi Pratap + + * typemanager.cs (IsBuiltinType): New method to help determine the same. + + * expression.cs (New::DoResolve): Get rid of array creation code and instead + split functionality out into different classes. + + (New::FormArrayType): Move into NewBuiltinArray. + + (Invocation::EmitArguments): Get rid of the MethodBase argument. Appears + quite useless. + + (NewBuiltinArray): New class to handle creation of built-in arrays. + + (NewBuiltinArray::DoResolve): Implement guts of array creation. Also take into + account creation of one-dimensional arrays. + + (::Emit): Implement to use Newarr and Newobj opcodes accordingly. + + (NewUserdefinedArray::DoResolve): Implement. + + * cs-parser.jay (local_variable_type): Fix up to add the rank to the variable too. + + * typemanager.cs (AddModule): Used to add a ModuleBuilder to the list of modules + we maintain inside the TypeManager. This is necessary to perform lookups on the + module builder. + + (LookupType): Update to perform GetType on the module builders too. + + * driver.cs (Driver): Add the ModuleBuilder to the list maintained by the TypeManager. + + * exprssion.cs (NewUserdefinedArray::Emit): Implement. + +2001-10-23 Ravi Pratap + + * expression.cs (New::DoResolve): Implement guts of array creation. + + (New::FormLookupType): Rename to FormArrayType and modify ever so slightly. + +2001-10-27 Miguel de Icaza + + * expression.cs: Fix bug I introduced lsat night that broke + Delegates. + + (Expression.Resolve): Report a 246 error (can not resolve name) + if we find a SimpleName in the stream. + + (Expression.ResolveLValue): Ditto. + + (Expression.ResolveWithSimpleName): This function is a variant of + ResolveName, this one allows SimpleNames to be returned without a + warning. The only consumer of SimpleNames is MemberAccess + +2001-10-26 Miguel de Icaza + + * expression.cs (Invocation::DoResolve): Catch SimpleNames that + might arrive here. I have my doubts that this is correct. + + * statement.cs (Lock): Implement lock statement. + + * cs-parser.jay: Small fixes to support `lock' and `using' + + * cs-tokenizer.cs: Remove extra space + + * driver.cs: New flag --checked, allows to turn on integer math + checking. + + * typemanger.cs: Load methodinfos for Threading.Monitor.Enter and + Threading.Monitor.Exit + +2001-10-23 Miguel de Icaza + + * expression.cs (IndexerAccess::DoResolveLValue): Set the + Expression Class to be IndexerAccess. + + Notice that Indexer::DoResolve sets the eclass to Value. + +2001-10-22 Miguel de Icaza + + * class.cs (TypeContainer::Emit): Emit code for indexers. + + * assign.cs (IAssignMethod): New interface implemented by Indexers + and Properties for handling assignment. + + (Assign::Emit): Simplify and reuse code. + + * expression.cs (IndexerAccess, PropertyExpr): Implement + IAssignMethod, clean up old code. + +2001-10-22 Ravi Pratap + + * typemanager.cs (ImplementsInterface): New method to determine if a type + implements a given interface. Provides a nice cache too. + + * expression.cs (ImplicitReferenceConversion): Update checks to use the above + method. + + (ConvertReferenceExplicit): Ditto. + + * delegate.cs (Delegate::Populate): Update to define the parameters on the + various methods, with correct names etc. + + * class.cs (Operator::OpType): New members Operator.UnaryPlus and + Operator.UnaryNegation. + + * cs-parser.jay (operator_declarator): Be a little clever in the case where + we have a unary plus or minus operator. + + * expression.cs (Unary): Rename memebers of Operator enum to UnaryPlus and + UnaryMinus. + + * everywhere : update accordingly. + + * everywhere : Change Negate and BitComplement to LogicalNot and OnesComplement + respectively. + + * class.cs (Method::Define): For the case where we are implementing a method + inherited from an interface, we need to set the MethodAttributes.Final flag too. + Also set MethodAttributes.NewSlot and MethodAttributes.HideBySig. + +2001-10-21 Ravi Pratap + + * interface.cs (FindMembers): Implement to work around S.R.E + lameness. + + * typemanager.cs (IsInterfaceType): Implement. + + (FindMembers): Update to handle interface types too. + + * expression.cs (ImplicitReferenceConversion): Re-write bits which + use IsAssignableFrom as that is not correct - it doesn't work. + + * delegate.cs (DelegateInvocation): Derive from ExpressionStatement + and accordingly override EmitStatement. + + * expression.cs (ConvertReferenceExplicit): Re-write similary, this time + using the correct logic :-) + +2001-10-19 Ravi Pratap + + * ../errors/cs-11.cs : Add to demonstrate error -11 + +2001-10-17 Miguel de Icaza + + * assign.cs (Assign::Resolve): Resolve right hand side first, and + then pass this as a hint to ResolveLValue. + + * expression.cs (FieldExpr): Add Location information + + (FieldExpr::LValueResolve): Report assignment to readonly + variable. + + (Expression::ExprClassFromMemberInfo): Pass location information. + + (Expression::ResolveLValue): Add new method that resolves an + LValue. + + (Expression::DoResolveLValue): Default invocation calls + DoResolve. + + (Indexers): New class used to keep track of indexers in a given + Type. + + (IStackStore): Renamed from LValue, as it did not really describe + what this did. Also ResolveLValue is gone from this interface and + now is part of Expression. + + (ElementAccess): Depending on the element access type + + * typemanager.cs: Add `indexer_name_type' as a Core type + (System.Runtime.CompilerServices.IndexerNameAttribute) + + * statement.cs (Goto): Take a location. + +2001-10-18 Ravi Pratap + + * delegate.cs (Delegate::VerifyDelegate): New method to verify + if two delegates are compatible. + + (NewDelegate::DoResolve): Update to take care of the case when + we instantiate a delegate from another delegate. + + * typemanager.cs (FindMembers): Don't even try to look up members + of Delegate types for now. + +2001-10-18 Ravi Pratap + + * delegate.cs (NewDelegate): New class to take care of delegate + instantiation. + + * expression.cs (New): Split the delegate related code out into + the NewDelegate class. + + * delegate.cs (DelegateInvocation): New class to handle delegate + invocation. + + * expression.cs (Invocation): Split out delegate related code into + the DelegateInvocation class. + +2001-10-17 Ravi Pratap + + * expression.cs (New::DoResolve): Implement delegate creation fully + and according to the spec. + + (New::DoEmit): Update to handle delegates differently. + + (Invocation::FullMethodDesc): Fix major stupid bug thanks to me + because of which we were printing out arguments in reverse order ! + + * delegate.cs (VerifyMethod): Implement to check if the given method + matches the delegate. + + (FullDelegateDesc): Implement. + + (VerifyApplicability): Implement. + + * expression.cs (Invocation::DoResolve): Update to accordingly handle + delegate invocations too. + + (Invocation::Emit): Ditto. + + * ../errors/cs1593.cs : Added. + + * ../errors/cs1594.cs : Added. + + * delegate.cs (InstanceExpression, TargetMethod): New properties. + +2001-10-16 Ravi Pratap + + * typemanager.cs (intptr_type): Core type for System.IntPtr + + (InitCoreTypes): Update for the same. + + (iasyncresult_type, asynccallback_type): Ditto. + + * delegate.cs (Populate): Fix to use System.Intptr as it is indeed + correct. + + * typemanager.cs (AddDelegateType): Store a pointer to the Delegate class + too. + + * delegate.cs (ConstructorBuilder, InvokeBuilder, ...): New members to hold + the builders for the 4 members of a delegate type :-) + + (Populate): Define the BeginInvoke and EndInvoke methods on the delegate + type. + + * expression.cs (New::DoResolve): Implement guts for delegate creation. + + * ../errors/errors.txt : Update for an error (-11) which only we catch :-) + +2001-10-15 Miguel de Icaza + + * statement.cs (Break::Emit): Implement. + (Continue::Emit): Implement. + + (For::Emit): Track old being/end loops; Set Begin loop, ack end loop + (While::Emit): Track old being/end loops; Set Begin loop, ack end loop + (Do::Emit): Track old being/end loops; Set Begin loop, ack end loop + (Foreach::Emit): Track old being/end loops; Set Begin loop, ack + end loop + + * codegen.cs (EmitContext::LoopEnd, EmitContext::LoopBegin): New + properties that track the label for the current loop (begin of the + loop and end of the loop). + +2001-10-15 Ravi Pratap + + * delegate.cs (Emit): Get rid of it as there doesn't seem to be any ostensible + use of emitting anything at all. + + * class.cs, rootcontext.cs : Get rid of calls to the same. + + * delegate.cs (DefineDelegate): Make sure the class we define is also sealed. + + (Populate): Define the constructor correctly and set the implementation + attributes. + + * typemanager.cs (delegate_types): New hashtable to hold delegates that + have been defined. + + (AddDelegateType): Implement. + + (IsDelegateType): Implement helper method. + + * delegate.cs (DefineDelegate): Use AddDelegateType instead of AddUserType. + + * expression.cs (New::DoResolve): Check if we are trying to instantiate a delegate type + and accordingly handle it. + + * delegate.cs (Populate): Take TypeContainer argument. + Implement bits to define the Invoke method. However, I still haven't figured out + how to take care of the native int bit :-( + + * cs-parser.jay (delegate_declaration): Fixed the bug that I had introduced :-) + Qualify the name of the delegate, not its return type ! + + * expression.cs (ImplicitReferenceConversion): Implement guts of implicit array + conversion. + + (StandardConversionExists): Checking for array types turns out to be recursive. + + (ConvertReferenceExplicit): Implement array conversion. + + (ExplicitReferenceConversionExists): New method to determine precisely that :-) + +2001-10-12 Ravi Pratap + + * cs-parser.jay (delegate_declaration): Store the fully qualified + name as it is a type declaration. + + * delegate.cs (ReturnType, Name): Rename members to these. Make them + readonly. + + (DefineDelegate): Renamed from Define. Does the same thing essentially, + as TypeContainer::DefineType. + + (Populate): Method in which all the definition of the various methods (Invoke) + etc is done. + + (Emit): Emit any code, if necessary. I am not sure about this really, but let's + see. + + (CloseDelegate): Finally creates the delegate. + + * class.cs (TypeContainer::DefineType): Update to define delegates. + (Populate, Emit and CloseType): Do the same thing here too. + + * rootcontext.cs (ResolveTree, PopulateTypes, EmitCode, CloseTypes): Include + delegates in all these operations. + +2001-10-14 Miguel de Icaza + + * expression.cs: LocalTemporary: a new expression used to + reference a temporary that has been created. + + * assign.cs: Handle PropertyAccess back here, so that we can + provide the proper semantic access to properties. + + * expression.cs (Expression::ConvertReferenceExplicit): Implement + a few more explicit conversions. + + * modifiers.cs: `NEW' modifier maps to HideBySig. + + * expression.cs (PropertyExpr): Make this into an + ExpressionStatement, and support the EmitStatement code path. + + Perform get/set error checking, clean up the interface. + + * assign.cs: recognize PropertyExprs as targets, and if so, turn + them into toplevel access objects. + +2001-10-12 Miguel de Icaza + + * expression.cs: PropertyExpr::PropertyExpr: use work around the + SRE. + + * typemanager.cs: Keep track here of our PropertyBuilders again to + work around lameness in SRE. + +2001-10-11 Miguel de Icaza + + * expression.cs (LValue::LValueResolve): New method in the + interface, used to perform a second resolution pass for LValues. + + (This::DoResolve): Catch the use of this in static methods. + + (This::LValueResolve): Implement. + + (This::Store): Remove warning, assigning to `this' in structures + is + + (Invocation::Emit): Deal with invocation of + methods on value types. We need to pass the address to structure + methods rather than the object itself. (The equivalent code to + emit "this" for structures leaves the entire structure on the + stack instead of a pointer to it). + + (ParameterReference::DoResolve): Compute the real index for the + argument based on whether the method takes or not a `this' pointer + (ie, the method is static). + + * codegen.cs (EmitContext::GetTemporaryStorage): Used to store + value types returned from functions when we need to invoke a + method on the sturcture. + + +2001-10-11 Ravi Pratap + + * class.cs (TypeContainer::DefineType): Method to actually do the business of + defining the type in the Modulebuilder or Typebuilder. This is to take + care of nested types which need to be defined on the TypeBuilder using + DefineNestedMethod. + + (TypeContainer::GetClassBases): Implement. Essentially the code from the + methods in RootContext, only ported to be part of TypeContainer. + + (TypeContainer::GetInterfaceOrClass): Ditto. + + (TypeContainer::LookupInterfaceOrClass, ::MakeFQN): Ditto. + + * interface.cs (Interface::DefineInterface): New method. Does exactly + what RootContext.CreateInterface did earlier, only it takes care of nested types + too. + + (Interface::GetInterfaces): Move from RootContext here and port. + + (Interface::GetInterfaceByName): Same here. + + * rootcontext.cs (ResolveTree): Re-write. + + (PopulateTypes): Re-write. + + * class.cs (TypeContainer::Populate): Populate nested types too. + (TypeContainer::Emit): Emit nested members too. + + * typemanager.cs (AddUserType): Do not make use of the FullName property, + instead just use the name argument passed in as it is already fully + qualified. + + (FindMembers): Check in the Builders to TypeContainer mapping instead of the name + to TypeContainer mapping to see if a type is user-defined. + + * class.cs (TypeContainer::CloseType): Implement. + + (TypeContainer::DefineDefaultConstructor): Use Basename, not Name while creating + the default constructor. + + (TypeContainer::Populate): Fix minor bug which led to creating default constructors + twice. + + (Constructor::IsDefault): Fix up logic to determine if it is the default constructor + + * interface.cs (CloseType): Create the type here. + + * rootcontext.cs (CloseTypes): Re-write to recursively close types by running through + the hierarchy. + + Remove all the methods which are now in TypeContainer. + +2001-10-10 Ravi Pratap + + * delegate.cs (Define): Re-write bits to define the delegate + correctly. + +2001-10-10 Miguel de Icaza + + * makefile: Renamed the compiler to `mcs.exe' instead of compiler.exe + + * expression.cs (ImplicitReferenceConversion): handle null as well + as a source to convert to any reference type. + + * statement.cs (Return): Perform any implicit conversions to + expected return type. + + Validate use of return statement. + + * codegen.cs (EmitContext): Pass the expected return type here. + + * class.cs (Method, Constructor, Property): Pass expected return + type to EmitContext. + +2001-10-09 Miguel de Icaza + + * expression.cs: Make DoResolve take an EmitContext instead of a + TypeContainer. + + Replaced `l' and `location' for `loc', for consistency. + + (Error, Warning): Remove unneeded Tc argument. + + * assign.cs, literal.cs, constant.cs: Update to new calling + convention. + + * codegen.cs: EmitContext now contains a flag indicating whether + code is being generated in a static method or not. + + * cs-parser.jay: DecomposeQI, new function that replaces the old + QualifiedIdentifier. Now we always decompose the assembled + strings from qualified_identifier productions into a group of + memberaccesses. + +2001-10-08 Miguel de Icaza + + * rootcontext.cs: Deal with field-less struct types correctly now + by passing the size option to Define Type. + + * class.cs: Removed hack that created one static field. + +2001-10-07 Miguel de Icaza + + * statement.cs: Moved most of the code generation here. + +2001-10-09 Ravi Pratap + + * expression.cs (New::DoResolve): Revert changes for array creation, doesn't + seem very right. + + (ElementAccess): Remove useless bits for now - keep checks as the spec + says. + +2001-10-08 Ravi Pratap + + * expression.cs (ElementAccess::DoResolve): Remove my crap code + and start performing checks according to the spec. + +2001-10-07 Ravi Pratap + + * cs-parser.jay (type_suffix*): Remove - they are redundant. Use + rank_specifiers instead. + + (rank_specifiers): Change the order in which the rank specifiers are stored + + (local_variable_declaration): Use opt_rank_specifier instead of type_suffixes. + + * expression.cs (ElementAccess): Implement the LValue interface too. + +2001-10-06 Ravi Pratap + + * expression.cs (ConvertExplicitStandard): Add. Same as ConvertExplicit + except that user defined conversions are not included. + + (UserDefinedConversion): Update to use the ConvertExplicitStandard to + perform the conversion of the return type, if necessary. + + (New::DoResolve): Check whether we are creating an array or an object + and accordingly do the needful. + + (New::Emit): Same here. + + (New::DoResolve): Implement guts of array creation. + + (New::FormLookupType): Helper function. + +2001-10-07 Miguel de Icaza + + * codegen.cs: Removed most of the code generation here, and move the + corresponding code generation bits to the statement classes. + + Added support for try/catch/finalize and throw. + + * cs-parser.jay: Added support for try/catch/finalize. + + * class.cs: Catch static methods having the flags override, + virtual or abstract. + + * expression.cs (UserCast): This user cast was not really doing + what it was supposed to do. Which is to be born in fully resolved + state. Parts of the resolution were being performed at Emit time! + + Fixed this code. + +2001-10-05 Miguel de Icaza + + * expression.cs: Implicity convert the result from UserCast. + +2001-10-05 Ravi Pratap + + * expression.cs (Expression::FindMostEncompassingType): Fix bug which + prevented it from working correctly. + + (ConvertExplicit): Make the first try, a call to ConvertImplicitStandard, not + merely ConvertImplicit. + +2001-10-05 Miguel de Icaza + + * typemanager.cs: Make the LookupTypeContainer function static, + and not per-instance. + + * class.cs: Make static FindMembers (the one that takes a Type + argument). + + * codegen.cs: Add EmitForeach here. + + * cs-parser.jay: Make foreach a toplevel object instead of the + inline expansion, as we need to perform semantic analysis on it. + +2001-10-05 Ravi Pratap + + * expression.cs (Expression::ImplicitUserConversion): Rename to + UserDefinedConversion. + + (Expression::UserDefinedConversion): Take an extra argument specifying + whether we look for explicit user conversions too. + + (Expression::ImplicitUserConversion): Make it a call to UserDefinedConversion. + + (UserDefinedConversion): Incorporate support for user defined explicit conversions. + + (ExplicitUserConversion): Make it a call to UserDefinedConversion + with the appropriate arguments. + + * cs-parser.jay (cast_expression): Record location too. + + * expression.cs (Cast): Record location info. + + (Expression::ConvertExplicit): Take location argument. + + (UserImplicitCast): Change name to UserCast. Take an extra constructor argument + to determine if we are doing explicit conversions. + + (UserCast::Emit): Update accordingly. + + (Expression::ConvertExplicit): Report an error if everything fails. + + * ../errors/cs0030.cs : Add. + +2001-10-04 Miguel de Icaza + + * modifiers.cs: If the ABSTRACT keyword is present, also set the + virtual and newslot bits. + + * class.cs (TypeContainer::RegisterRequiredImplementations): + Record methods we need. + + (TypeContainer::MakeKey): Helper function to make keys for + MethodBases, since the Methodbase key is useless. + + (TypeContainer::Populate): Call RegisterRequiredImplementations + before defining the methods. + + Create a mapping for method_builders_to_methods ahead of time + instead of inside a tight loop. + + (::RequireMethods): Accept an object as the data to set into the + hashtable so we can report interface vs abstract method mismatch. + +2001-10-03 Miguel de Icaza + + * report.cs: Make all of it static. + + * rootcontext.cs: Drop object_type and value_type computations, as + we have those in the TypeManager anyways. + + Drop report instance variable too, now it is a global. + + * driver.cs: Use try/catch on command line handling. + + Add --probe option to debug the error reporting system with a test + suite. + + * report.cs: Add support for exiting program when a probe + condition is reached. + +2001-10-03 Ravi Pratap + + * expression.cs (Binary::DoNumericPromotions): Fix the case when + we do a forcible conversion regardless of type, to check if + ForceConversion returns a null. + + (Binary::error19): Use location to report error. + + (Unary::error23): Use location here too. + + * ../errors/cs0019.cs : Check in. + + * ../errors/cs0023.cs : Check in. + + * expression.cs (Expression.MemberLookup): Return null for a rather esoteric + case of a non-null MethodInfo object with a length of 0 ! + + (Binary::ResolveOperator): Flag error if overload resolution fails to find + an applicable member - according to the spec :-) + Also fix logic to find members in base types. + + (Unary::ResolveOperator): Same here. + + (Unary::report23): Change name to error23 and make first argument a TypeContainer + as I was getting thoroughly confused between this and error19 :-) + + * expression.cs (Expression::ImplicitUserConversion): Re-write fully + (::FindMostEncompassedType): Implement. + (::FindMostEncompassingType): Implement. + (::StandardConversionExists): Implement. + + (UserImplicitCast): Re-vamp. We now need info about most specific + source and target types so that we can do the necessary conversions. + + (Invocation::MakeUnionSet): Completely re-write to make sure we form a proper + mathematical union with no duplicates. + +2001-10-03 Miguel de Icaza + + * rootcontext.cs (RootContext::PopulateTypes): Populate containers + in order from base classes to child classes, so that we can in + child classes look up in our parent for method names and + attributes (required for handling abstract, virtual, new, override + constructs: we need to instrospect our base class, and if we dont + populate the classes in order, the introspection might be + incorrect. For example, a method could query its parent before + the parent has any methods and would determine that the parent has + no abstract methods (while it could have had them)). + + (RootContext::CreateType): Record the order in which we define the + classes. + +2001-10-02 Miguel de Icaza + + * class.cs (TypeContainer::Populate): Also method definitions can + fail now, keep track of this. + + (TypeContainer::FindMembers): Implement support for + DeclaredOnly/noDeclaredOnly flag. + + (Constructor::Emit) Return the ConstructorBuilder. + + (Method::Emit) Return the MethodBuilder. + Check for abstract or virtual methods to be public. + + * rootcontext.cs (RootContext::CreateType): Register all the + abstract methods required for the class to be complete and the + interface methods that must be implemented. + + * cs-parser.jay: Report error 501 (method requires body if it is + not marked abstract or extern). + + * expression.cs (TypeOf::Emit): Implement. + + * typemanager.cs: runtime_handle_type, new global type. + + * class.cs (Property::Emit): Generate code for properties. + +2001-10-02 Ravi Pratap + + * expression.cs (Unary::ResolveOperator): Find operators on base type + too - we now conform exactly to the spec. + + (Binary::ResolveOperator): Same here. + + * class.cs (Operator::Define): Fix minor quirk in the tests. + + * ../errors/cs0215.cs : Added. + + * ../errors/cs0556.cs : Added. + + * ../errors/cs0555.cs : Added. + +2001-10-01 Miguel de Icaza + + * cs-tokenizer.cs: Reimplemented Location to be a struct with a + single integer which is really efficient + +2001-10-01 Ravi Pratap + + * expression.cs (Expression::ImplicitUserConversion): Use location + even in the case when we are examining True operators. + + * class.cs (Operator::Define): Perform extensive checks to conform + with the rules for operator overloading in the spec. + + * expression.cs (Expression::ImplicitReferenceConversion): Implement + some of the other conversions mentioned in the spec. + + * typemanager.cs (array_type): New static member for the System.Array built-in + type. + + (cloneable_interface): For System.ICloneable interface. + + * driver.cs (Driver::Driver): Initialize TypeManager's core types even before + we start resolving the tree and populating types. + + * ../errors/errors.txt : Update for error numbers -7, -8, -9, -10 + +2001-10-01 Miguel de Icaza + + * expression.cs (Expression::ExprClassFromMemberInfo, + Expression::Literalize): Create literal expressions from + FieldInfos which are literals. + + (ConvertNumericExplicit, ImplicitNumericConversion): Fix a few + type casts, because they were wrong. The test suite in tests + caught these ones. + + (ImplicitNumericConversion): ushort to ulong requires a widening + cast. + + Int32 constant to long requires widening cast as well. + + * literal.cs (LongLiteral::EmitLong): Do not generate i4 constants + for integers because the type on the stack is not i4. + +2001-09-30 Miguel de Icaza + + * expression.cs (report118): require location argument. + + * parameter.cs: Do not dereference potential null value. + + * class.cs: Catch methods that lack the `new' keyword when + overriding a name. Report warnings when `new' is used without + anything being there to override. + + * modifiers.cs: Handle `NEW' as MethodAttributes.NewSlot. + + * class.cs: Only add constructor to hashtable if it is non-null + (as now constructors can fail on define). + + (TypeManager, Class, Struct): Take location arguments. + + Catch field instance initialization in structs as errors. + + accepting_filter: a new filter for FindMembers that is static so + that we dont create an instance per invocation. + + (Constructor::Define): Catch errors where a struct constructor is + parameterless + + * cs-parser.jay: Pass location information for various new + constructs. + + * delegate.cs (Delegate): take a location argument. + + * driver.cs: Do not call EmitCode if there were problesm in the + Definition of the types, as many Builders wont be there. + + * decl.cs (Decl::Decl): Require a location argument. + + * cs-tokenizer.cs: Handle properly hex constants that can not fit + into integers, and find the most appropiate integer for it. + + * literal.cs: Implement ULongLiteral. + + * rootcontext.cs: Provide better information about the location of + failure when CreateType fails. + +2001-09-29 Miguel de Icaza + + * rootcontext.cs (RootContext::PopulateTypes): Populates structs + as well. + + * expression.cs (Binary::CheckShiftArguments): Add missing type + computation. + (Binary::ResolveOperator): Add type to the logical and and logical + or, Bitwise And/Or and Exclusive Or code paths, it was missing + before. + + (Binary::DoNumericPromotions): In the case where either argument + is ulong (and most signed types combined with ulong cause an + error) perform implicit integer constant conversions as well. + +2001-09-28 Miguel de Icaza + + * expression.cs (UserImplicitCast): Method should always be + non-null. + (Invocation::BetterConversion): Simplified test for IntLiteral. + + (Expression::ImplicitNumericConversion): Split this routine out. + Put the code that performs implicit constant integer conversions + here. + + (Expression::Resolve): Become a wrapper around DoResolve so we can + check eclass and type being set after resolve. + + (Invocation::Badness): Remove this dead function + + (Binary::ResolveOperator): Do not compute the expensive argumnets + unless we have a union for it. + + (Probe::Emit): Is needs to do an isinst and then + compare against null. + + (::CanConvert): Added Location argument. If the Location argument + is null (Location.Null), then we do not report errors. This is + used by the `probe' mechanism of the Explicit conversion. We do + not want to generate an error for something that the user + explicitly requested to be casted. But the pipeline for an + explicit cast first tests for potential implicit casts. + + So for now, if the Location is null, it means `Probe only' to + avoid adding another argument. Might have to revise this + strategy later. + + (ClassCast): New class used to type cast objects into arbitrary + classes (used in Explicit Reference Conversions). + + Implement `as' as well. + + Reverted all the patches from Ravi below: they were broken: + + * The use of `level' as a mechanism to stop recursive + invocations is wrong. That was there just to catch the + bug with a strack trace but not as a way of addressing + the problem. + + To fix the problem we have to *understand* what is going + on and the interactions and come up with a plan, not + just get things going. + + * The use of the type conversion cache that I proposed + last night had an open topic: How does this work across + protection domains. A user defined conversion might not + be public in the location where we are applying the + conversion, a different conversion might be selected + (ie, private A->B (better) but public B->A (worse), + inside A, A->B applies, but outside it, B->A will + apply). + + * On top of that (ie, even if the above is solved), + conversions in a cache need to be abstract. Ie, `To + convert from an Int to a Short use an OpcodeCast', not + `To convert from an Int to a Short use the OpcodeCast on + the variable 5' (which is what this patch was doing). + +2001-09-28 Ravi Pratap + + * expression.cs (Invocation::ConversionExists): Re-write to use + the conversion cache + + (Expression::ConvertImplicit): Automatic bailing out if level != 0. Also + cache all conversions done, not just user-defined ones. + + (Invocation::BetterConversion): The real culprit. Use ConversionExists + to determine if a conversion exists instead of acutually trying to + perform the conversion. It's faster too. + + (Expression::ConvertExplicit): Modify to use ConversionExists to check + and only then attempt the implicit conversion. + +2001-09-28 Ravi Pratap + + * expression.cs (ConvertImplicit): Use a cache for conversions + already found. Check level of recursion and bail out if necessary. + +2001-09-28 Miguel de Icaza + + * typemanager.cs (string_concat_string_string, string_concat_object_object): + Export standard methods that we expect for string operations. + + * statement.cs (Block::UsageWarning): Track usage of variables and + report the errors for not used variables. + + * expression.cs (Conditional::Resolve, ::Emit): Implement ?: + operator. + +2001-09-27 Miguel de Icaza + + * codegen.cs: remove unnneded code + + * expression.cs: Removed BuiltinTypeAccess class + + Fix the order in which implicit conversions are + done. + + The previous fixed dropped support for boxed conversions (adding a + test to the test suite now) + + (UserImplicitCast::CanConvert): Remove test for source being null, + that code is broken. We should not feed a null to begin with, if + we do, then we should track the bug where the problem originates + and not try to cover it up here. + + Return a resolved expression of type UserImplicitCast on success + rather than true/false. Ravi: this is what I was talking about, + the pattern is to use a static method as a "constructor" for + objects. + + Also, do not create arguments until the very last minute, + otherwise we always create the arguments even for lookups that + will never be performed. + + (UserImplicitCast::Resolve): Eliminate, objects of type + UserImplicitCast are born in a fully resolved state. + + * typemanager.cs (InitCoreTypes): Init also value_type + (System.ValueType). + + * expression.cs (Cast::Resolve): First resolve the child expression. + + (LValue): Add new method AddressOf to be used by + the `&' operator. + + Change the argument of Store to take an EmitContext instead of an + ILGenerator, because things like FieldExpr need to be able to call + their children expression to generate the instance code. + + (Expression::Error, Expression::Warning): Sugar functions for + reporting errors. + + (Expression::MemberLookup): Accept a TypeContainer instead of a + Report as the first argument. + + (Expression::ResolvePrimary): Killed. I still want to improve + this as currently the code is just not right. + + (Expression::ResolveMemberAccess): Simplify, but it is still + wrong. + + (Unary::Resolve): Catch errors in AddressOf operators. + + (LocalVariableReference::Emit, ::Store, ::AddressOf): typecast + index to a byte for the short-version, or the compiler will choose + the wrong Emit call, which generates the wrong data. + + (ParameterReference::Emit, ::Store): same. + + (FieldExpr::AddressOf): Implement. + + * typemanager.cs: TypeManager: made public variable instead of + property. + + * driver.cs: document --fatal. + + * report.cs (ErrorMessage, WarningMessage): new names for the old + Error and Warning classes. + + * cs-parser.jay (member_access): Turn built-in access to types + into a normal simplename + +2001-09-27 Ravi Pratap + + * expression.cs (Invocation::BetterConversion): Fix to cope + with q being null, since this was introducing a bug. + + * expression.cs (ConvertImplicit): Do built-in conversions first. + +2001-09-27 Ravi Pratap + + * expression.cs (UserImplicitCast::Resolve): Fix bug. + +2001-09-27 Ravi Pratap + + * class.cs (TypeContainer::AddConstructor): Fix a stupid bug + I had introduced long ago (what's new ?). + + * expression.cs (UserImplicitCast::CanConvert): Static method to do + the work of all the checking. + (ConvertImplicit): Call CanConvert and only then create object if necessary. + (UserImplicitCast::CanConvert, ::Resolve): Re-write. + + (Unary::Operator): Rename Add and Subtract to Addition and Subtraction because + that is the right way. + + (Invocation::MakeUnionSet): Convenience function to make unions of sets for + overloading resolution. Use everywhere instead of cutting and pasting code. + + (Binary::ResolveOperator): Use MakeUnionSet. + + (UserImplicitCast::CanConvert, ::Resolve): Update to take care of the case when + we have to convert to bool types. Not complete yet. + +2001-09-27 Miguel de Icaza + + * typemanager.cs (TypeManager::CSharpName): support ushort. + + * expression.cs (Expression::TryImplicitIntConversion): Attempts + to provide an expression that performsn an implicit constant int + conversion (section 6.1.6). + (Expression::ConvertImplicitRequired): Reworked to include + implicit constant expression conversions. + + (Expression::ConvertNumericExplicit): Finished. + + (Invocation::Emit): If InstanceExpression is null, then it means + that we perform a call on this. + +2001-09-26 Miguel de Icaza + + * expression.cs (Unary::Emit): Remove some dead code. + (Probe): Implement Resolve and Emit for `is'. + (Expression::ConvertImplicitRequired): Attempt to do constant + expression conversions here. Maybe should be moved to + ConvertImplicit, but I am not sure. + (Expression::ImplicitLongConstantConversionPossible, + Expression::ImplicitIntConstantConversionPossible): New functions + that tell whether is it possible to apply an implicit constant + expression conversion. + + (ConvertNumericExplicit): Started work on explicit numeric + conversions. + + * cs-parser.jay: Update operator constants. + + * parameter.cs (Parameters::GetParameterInfo): Hook up VerifyArgs + (Parameters::GetSignature): Hook up VerifyArgs here. + (Parameters::VerifyArgs): Verifies that no two arguments have the + same name. + + * class.cs (Operator): Update the operator names to reflect the + ones that the spec expects (as we are just stringizing the + operator names). + + * expression.cs (Unary::ResolveOperator): Fix bug: Use + MethodInfo's ReturnType instead of LookupMethodByBuilder as the + previous usage did only work for our methods. + (Expression::ConvertImplicit): Handle decimal implicit numeric + conversions as well. + (Expression::InternalTypeConstructor): Used to invoke constructors + on internal types for default promotions. + + (Unary::Emit): Implement special handling for the pre/post + increment/decrement for overloaded operators, as they need to have + the same semantics as the other operators. + + (Binary::ResolveOperator): ditto. + (Invocation::ConversionExists): ditto. + (UserImplicitCast::Resolve): ditto. + +2001-09-26 Ravi Pratap + + * expression.cs (Unary::Emit and Binary::Emit): If we have an overloaded + operator, return after emitting body. Regression tests pass again ! + + * expression.cs (ConvertImplicit): Take TypeContainer as first argument + (Unary::ForceConversion, Binary::ForceConversion): Ditto. + (Invocation::OverloadResolve): Ditto. + (Invocation::BetterFunction, BetterConversion, ConversionExists): Ditto. + + * everywhere : update calls to the above methods accordingly. + +2001-09-26 Miguel de Icaza + + * assign.cs (Assign): Make it inherit from ExpressionStatement. + + * expression.cs (ExpressionStatement): New base class used for + expressions that can appear in statements, so that we can provide + an alternate path to generate expression that do not leave a value + on the stack. + + (Expression::Emit, and all the derivatives): We no longer return + whether a value is left on the stack or not. Every expression + after being emitted leaves a single value on the stack. + + * codegen.cs (EmitContext::EmitStatementExpression): Use the + facilties of ExpressionStatement if possible. + + * cs-parser.jay: Update statement_expression. + +2001-09-25 Miguel de Icaza + + * driver.cs: Change the wording of message + +2001-09-25 Ravi Pratap + + * expression.cs (Binary::ResolveOperator): Had forgottten to set + the type of the expression to the return type of the method if + we have an overloaded operator match ! The regression tests pass again ! + (Unary::ResolveOperator): Ditto. + + * expression.cs (Invocation::ConversionExists): Correct the member lookup + to find "op_Implicit", not "implicit" ;-) + (UserImplicitCast): New class to take care of user-defined implicit conversions. + (ConvertImplicit, ForceConversion): Take TypeContainer argument + + * everywhere : Correct calls to the above accordingly. + + * expression.cs (UserImplicitCast::Resolve, ::Emit): Implement. + (ConvertImplicit): Do user-defined conversion if it exists. + +2001-09-24 Miguel de Icaza + + * assign.cs: track location. + (Resolve): Use implicit conversions on assignment. + + * literal.cs: Oops. Not good, Emit of short access values should + pass (Bytes) or the wrong argument will be selected. + + * expression.cs (Unary::Emit): Emit code for -expr. + + (Unary::ResolveOperator): Handle `Substract' for non-constants + (substract from zero from the non-constants). + Deal with Doubles as well. + + (Expression::ConvertImplicitRequired): New routine that reports an + error if no implicit conversion exists. + + (Invocation::OverloadResolve): Store the converted implicit + expressions if we make them + +2001-09-24 Ravi Pratap + + * class.cs (ConstructorInitializer): Take a Location argument. + (ConstructorBaseInitializer): Same here. + (ConstructorThisInitializer): Same here. + + * cs-parser.jay : Update all calls accordingly. + + * expression.cs (Unary, Binary, New): Take location argument. + Update accordingly everywhere. + + * cs-parser.jay : Update all calls to the above to take a location + argument. + + * class.cs : Ditto. + +2001-09-24 Ravi Pratap + + * expression.cs (Invocation::BetterFunction): Take TypeContainer argument + (Invocation::BetterConversion): Same here + (Invocation::ConversionExists): Ditto. + + (Invocation::ConversionExists): Implement. + +2001-09-22 Ravi Pratap + + * expression.cs (OverloadResolve): Improve some more to catch errors 1502 and 1503 + Also take an additional TypeContainer argument. + + * All over : Pass in TypeContainer as argument to OverloadResolve. + + * typemanager.cs (CSharpName): Update to check for the string type and return + that too. + + * expression.cs (Invocation::FullMethodDesc): New static method to return a string fully describing + a given method. + +2001-09-21 Ravi Pratap + + * expression.cs (Invocation::OverloadResolve): Re-write to conform more to the spec. + (Invocation::BetterFunction): Implement. + (Invocation::BetterConversion): Implement. + (Invocation::ConversionExists): Skeleton, no implementation yet. + + Okay, things work fine ! + +2001-09-21 Miguel de Icaza + + * typemanager.cs: declare and load enum_type, delegate_type and + void_type. + + * expression.cs (Expression::Emit): Now emit returns a value that + tells whether a value is left on the stack or not. This strategy + might be reveted tomorrow with a mechanism that would address + multiple assignments. + (Expression::report118): Utility routine to report mismatches on + the ExprClass. + + (Unary::Report23): Report impossible type/operator combination + utility function. + + (Unary::IsIncrementableNumber): Whether the type can be + incremented or decremented with add. + (Unary::ResolveOperator): Also allow enumerations to be bitwise + complemented. + (Unary::ResolveOperator): Implement ++, !, ~, + + (Invocation::Emit): Deal with new Emit convetion. + + * All Expression derivatives: Updated their Emit method to return + whether they leave values on the stack or not. + + * codegen.cs (CodeGen::EmitStatement): Pop values left on the + stack for expressions that are statements. + +2001-09-20 Miguel de Icaza + + * expression.cs (LValue): New interface. Must be implemented by + LValue objects. + (LocalVariableReference, ParameterReference, FieldExpr): Implement + LValue interface. + + * assign.cs (Assign::Emit, Assign::Resolve): Use new LValue + interface for generating code, simplifies the code. + +2001-09-20 Ravi Pratap + + * expression.cs (everywhere): Comment out return statements in ::Resolve + methods to avoid the warnings. + +2001-09-20 Miguel de Icaza + + * driver.cs (parse): Report error 2001 if we can not open the + source file. + + * expression.cs (SimpleName::ResolveSimpleName): Error if we can + not resolve it. + + * cs-parser.jay (QualifierIdentifier): Pass location to SimpleName + object. + + * statement.cs (Block::EmitMeta): Reuse the count across all the variables, + otherwise nested blocks end up with the same index. + + * codegen.cs (CodeGen::EmitTopBlock): Pass initial sequence + + * expression.cs: Instead of having FIXMEs in the Resolve + functions, throw exceptions so it is obvious that we are facing a + bug. + + * cs-parser.jay (invocation_expression): Pass Location information. + + * codegen.cs (CodeGen::Save, CodeGen::CodeGen, CodeGen::Basename): + Use a basename for those routines because .NET does not like paths + on them. + + * class.cs (TypeContainer::AddMethod): Do not call DefineName if the name was + already defined. + +2001-09-19 Miguel de Icaza + + * typemanager.cs (TypeManager::CoreLookupType): A function to make sure that we + are loading the correct data types (throws an exception if not). + (TypeManager::InitCoreTypes): Use CoreLookupType + + * expression.cs (Unary::ResolveOperator): return the child + expression for expressions which are just +expr. + (Unary::ResolveOperator): Return negative literals for -LITERAL + expressions (otherwise they are Unary {Literal}). + (Invocation::Badness): Take into account `Implicit constant + expression conversions'. + + * literal.cs (LongLiteral): Implement long literal class. + (IntLiteral): export the `Value' of the intliteral. + +2001-09-19 Ravi Pratap + + * expression.cs (Binary::Emit): Finally get the emission right ! Woo! + + * class.cs (Operator::Define): Change the methodname prefix to 'op_' + instead of 'Operator' + + * expression.cs (Binary::ResolveOperator): Update accordingly. + (Unary::Operator): Change names to 'Add' and 'Subtract' instead 'Plus' + and 'Minus' + + * cs-parser.jay (unary_expression): Update to use the new names. + + * gen-treedump.cs (GetUnary): Same here. + + * expression.cs (Unary::Resolve): Implement. + (Binary::ResolveOperator): Re-write bits to quietly continue if no overloaded + operators are found instead of making noise ;-) + (Unary::ResolveOperator): New method to do precisely the same thing which + Binary::ResolveOperator does for Binary expressions. + (Unary.method, .Arguments): Add. + (Unary::OperName): Implement. + (Unary::ForceConversion): Copy and Paste ! + + * class.cs (Operator::Define): Fix a small bug for the case when we have + a unary operator. + + * expression.cs (Unary::Emit): Implement. Need to find the right Opcodes + for the inbuilt operators. Only overloading works for now ;-) + +2001-09-18 Miguel de Icaza + + * expression.cs (CheckedExpr::Resolve, CheckedExpr::Emit, + UnCheckedExpr::Resolve, UnCheckedExpr::Emit): Implement. + + * expression.cs (This::Emit): Implement. + (This::Resolve): Implement. + (TypeOf:Resolve): Implement. + (Expression::ResolveSimpleName): Add an implicit this to instance + field references. + (MemberAccess::Resolve): Deal with Parameters and Fields. + Bind instance variable to Field expressions. + (FieldExpr::Instance): New field used to track the expression that + represents the object instance. + (FieldExpr::Resolve): Track potential errors from MemberLookup not + binding + (FieldExpr::Emit): Implement. + + * codegen.cs (EmitIf, EmitStatement, EmitBlock): Propagate whether + the last instruction contains a return opcode to avoid generating + the last `ret' instruction (this generates correct code, and it is + nice to pass the peverify output). + + * class.cs (TypeContainer::EmitFieldInitializers): Implement field + initializer for static and instance variables. + (Constructor::Emit): Allow initializer to be null in the case of + static constructors. Only emit initializer for instance + constructors. + + (TypeContainer::FindMembers): Return a null array if there are no + matches. + + Also fix the code for the MemberTypes.Method branch, as it was not + scanning that for operators (or tried to access null variables before). + + * assign.cs (Assign::Emit): Handle instance and static fields. + + * TODO: Updated. + + * driver.cs: Stop compilation if there are parse errors. + + * cs-parser.jay (constructor_declaration): Provide default base + initializer for non-static constructors. + (constructor_declarator): Do not provide a default base + initializers if none was specified. + Catch the fact that constructors should not have parameters. + + * class.cs: Do not emit parent class initializers for static + constructors, that should be flagged as an error. + +2001-09-18 Ravi Pratap + + * class.cs (RegisterMethodBuilder): Remove : it's unnecessary. + Move back code into TypeContainer::Populate. + +2001-09-18 Ravi Pratap + + * class.cs (TypeContainer::AddConstructor): Fix the check to + compare against Name, not Basename. + (Operator::OpType): Change Plus and Minus to Add and Subtract. + + * cs-parser.jay : Update accordingly. + + * class.cs (TypeContainer::FindMembers): For the case where we are searching + for methods, don't forget to look into the operators too. + (RegisterMethodBuilder): Helper method to take care of this for + methods, constructors and operators. + (Operator::Define): Completely revamp. + (Operator.OperatorMethod, MethodName): New fields. + (TypeContainer::Populate): Move the registering of builders into + RegisterMethodBuilder. + (Operator::Emit): Re-write. + + * expression.cs (Binary::Emit): Comment out code path to emit method + invocation stuff for the case when we have a user defined operator. I am + just not able to get it right ! + +2001-09-17 Miguel de Icaza + + * expression.cs (Expression::OverloadResolve): Drop TypeContainer + argument. + + (Expression::MemberLookup): Provide a version that allows to + specify the MemberTypes and BindingFlags. + + * statement.cs (Block::GetVariableInfo): Forgot to recurse here, + so it was not fetching variable information from outer blocks. + + * modifiers.cs: (Modifiers::TypeAttr): Invert condition on + Beforefieldinit as it was buggy. + + * rootcontext.cs (::LookupInterfaceOrClass): Removed an Error -200 + that Ravi put here. + + * class.cs (Constructor::Emit): Only emit if block is not null. + (TypeContainer::EmitDefaultConstructor): Removed routine, now we + deal with this by semantically definining it as if the user had + done it. + + (TypeContainer::FindMembers): Removed ad-hoc hack to deal with + constructors as we now "emit" them at a higher level. + + (TypeContainer::DefineDefaultConstructor): Used to define the + default constructors if none was provided. + + (ConstructorInitializer): Add methods Resolve and Emit. + + * expression.cs: Cast to ConstructorInfo instead of MethodInfo + +2001-09-17 Ravi Pratap + + * class.cs (TypeContainer::EmitDefaultConstructor): Register + the default constructor builder with our hashtable for methodbuilders + to methodcores. + + * expression.cs (Invocation::OverloadResolve): Add a check for pd == null + and argument_count is 0 in which case we have a match. + (Binary::ResolveOperator): More null checking and miscellaneous coding + style cleanup. + +2001-09-17 Ravi Pratap + + * rootcontext.cs (IsNameSpace): Compare against null. + + * everywhere : Correct spelling to 'Greater' and to 'Subtract' + + * class.cs (Operator::OpType): Change names to match the ones in Binary::Operator + and Unary::Operator. + + * cs-parser.jay (operator_declaration, CheckBinaryOperator, CheckUnaryOperator): Update + accordingly. + + * expression.cs (Binary::method): New member to hold the MethodBase for the case when + we have overloaded operators. + (Binary::ResolveOperator): Implement the part which does the operator overload + resolution. + + * class.cs (Operator::Emit): Implement. + (TypeContainer::Emit): Emit the operators we have too. + + * expression.cs (Binary::Emit): Update to emit the appropriate code for + the case when we have a user-defined operator. + +2001-09-17 Miguel de Icaza + + * rootcontext.cs: Fix bug: tree.Namespaces might be null. + +2001-09-16 Ravi Pratap + + * class.cs (EmitStaticFieldInitializers, EmitFieldInitializers): Make public. + (TypeContainer::EmitConstructor): Remove and move code into Contructor::Emit. + (Constructor::Emit): Implement. + (EmitStaticFieldInitializers, EmitFieldInitializers): Ensure we return immediately + if we have no work to do. + (TypeContainer::Emit): Pass in TypeContainer as argument to the constructor's + Emit method. + + * interface.cs (Interface::InterfaceAttr): Re-write to be more correct and complete. + (Interface::IsTopLevel): Add. Same as TypeContainer::IsTopLevel. + + * class.cs (TypeContainer::IsTopLevel): Modify to use parent.Parent instead + of parent.parent. + +2001-09-15 Ravi Pratap + + * tree.cs (Tree::namespaces): New hashtable to keep track of namespaces + in the source. + (Tree::RecordNamespace): Method to do what the name says ;-) + (Tree::Namespaces): Property to get at the namespaces hashtable. + + * cs-parser.jay (namespace_declaration): Call RecordNamespace to + keep track. + + * rootcontext.cs (IsNamespace): Fixed it :-) + +2001-09-14 Miguel de Icaza + + * class.cs (TypeContainer::FindMembers): Add support for + constructors. + (MethodCore): New class that encapsulates both the shared aspects + of a Constructor and a Method. + (Method, Constructor): Factored pieces into MethodCore. + + * driver.cs: Added --fatal which makes errors throw exceptions. + Load System assembly as well as part of the standard library. + + * report.cs: Allow throwing exceptions on errors for debugging. + + * modifiers.cs: Do not use `parent', instead use the real type + container to evaluate permission settings. + + * class.cs: Put Ravi's patch back in. He is right, and we will + have to cope with the + +2001-09-14 Ravi Pratap + + * modifiers.cs (TypeAttr, MethodAttr, FieldAttr): Map protected internal to + FamORAssem, not FamANDAssem. + +2001-09-14 Miguel de Icaza + + * driver.cs: Added --parse option that only parses its input files + and terminates. + + * class.cs: Reverted last change from Ravi to IsTopLevel. That is + incorrect. IsTopLevel is not used to tell whether an object is + root_types or not (that can be achieved by testing this == + root_types). But to see if this is a top-level *class* (not + necessarly our "toplevel" container). + +2001-09-14 Ravi Pratap + + * enum.cs (Enum::Define): Modify to call the Lookup method on the + parent instead of a direct call to GetType. + +2001-09-14 Ravi Pratap + + * class.cs (TypeContainer::TypeAttr): Remove property code and move it into + Modifiers.TypeAttr. This should just be a call to that method. + + * modifiers.cs (TypeAttr): Re-write and take an extra argument, the TypeContainer + object so that we can determine if we are top-level or not. + + * delegate.cs (Delegate::Define): Update call to TypeAttr method to pass in the + TypeContainer too. + + * enum.cs (Enum::Define): Ditto. + + * modifiers.cs (FieldAttr): Re-write. + + * class.cs (TypeContainer::IsTopLevel): Change accessibility to public. + (TypeContainer::HaveStaticConstructor): New property to provide access + to precisely that info. + + * modifiers.cs (MethodAttr): Re-write. + (EventAttr): Remove altogether as there seems to be no ostensible use for it. + + * class.cs (TypeContainer::IsTopLevel): Re-write. root_types doesn't seem to be the parent + of top-level types as claimed. + +2001-09-13 Miguel de Icaza + + * expression.cs (MemberLookup): Fruitless attempt to lookup + constructors. Maybe I need to emit default constructors? That + might be it (currently .NET emits this for me automatically). + (Invocation::OverloadResolve): Cope with Arguments == null. + (Invocation::EmitArguments): new function, shared by the new + constructor and us. + (Invocation::Emit): Handle static and instance methods. Emit + proper call instruction for virtual or non-virtual invocations. + (New::Emit): Implement. + (New::Resolve): Implement. + (MemberAccess:Resolve): Implement. + (MethodGroupExpr::InstanceExpression): used conforming to the spec + to track instances. + (FieldExpr::Resolve): Set type. + + * support.cs: Handle empty arguments. + + * cs-parser.jay (CompositeLookup, QualifierIdentifier, + SimpleLookup): Auxiliary routines to help parse a qualifier + identifier. + + Update qualifier_identifier rule. + + * codegen.cs: Removed debugging messages. + + * class.cs: Make this a global thing, this acts just as a "key" to + objects that we might have around. + + (Populate): Only initialize method_builders_to_methods once. + + * expression.cs (PropertyExpr): Initialize type from the + PropertyType. + + * codegen.cs (EmitContext::EmitBoolExpression): Use propper + Resolve pattern. Attempt to implicitly convert value to boolean. + Emit code. + + * expression.cs: Set the type for the int32/int32 argument case. + (Binary::ResolveOperator): Set the return type to boolean for + comparission operators + + * typemanager.cs: Remove debugging print code. + + (Invocation::Resolve): resolve type. + + * class.cs: Allocate a MemberInfo of the correct size, as the code + elsewhere depends on the test to reflect the correct contents. + + (Method::) Keep track of parameters, due to System.Reflection holes + + (TypeContainer::Populate): Keep track of MethodBuilders to Method + mapping here. + + (TypeContainer::FindMembers): Use ArrayList and then copy an array + of the exact size and return that. + + (Class::LookupMethodByBuilder): New function that maps + MethodBuilders to its methods. Required to locate the information + on methods because System.Reflection bit us again. + + * support.cs: New file, contains an interface ParameterData and + two implementations: ReflectionParameters and InternalParameters + used to access Parameter information. We will need to grow this + as required. + + * expression.cs (Invocation::GetParameterData): implement a cache + and a wrapper around the ParameterData creation for methods. + (Invocation::OverloadResolve): Use new code. + +2001-09-13 Ravi Pratap + + * class.cs (TypeContainer::EmitField): Remove and move into + (Field::Define): here and modify accordingly. + (Field.FieldBuilder): New member. + (TypeContainer::Populate): Update accordingly. + (TypeContainer::FindMembers): Implement. + +2001-09-13 Miguel de Icaza + + * statement.cs: (VariableInfo::VariableType): New field to be + initialized with the full type once it is resolved. + +2001-09-12 Miguel de Icaza + + * parameter.cs (GetParameterInfo): Use a type cache to compute + things only once, and to reuse this information + + * expression.cs (LocalVariableReference::Emit): Implement. + (OpcodeCast::Emit): fix. + + (ParameterReference::Resolve): Implement. + (ParameterReference::Emit): Implement. + + * cs-parser.jay: Fix bug introduced by Ravi, variable initializers + that are expressions need to stay as Expressions. + + * typemanager.cs (CSharpName): Returns the C# name of a type if + possible. + + * expression.cs (Expression::ConvertImplicit): New function that + implements implicit type conversions. + + (Expression::ImplicitReferenceConversion): Implements implicit + reference conversions. + + (EmptyCast): New type for transparent casts. + + (OpcodeCast): New type for casts of types that are performed with + a sequence of bytecodes. + + (BoxedCast): New type used for casting value types into reference + types. Emits a box opcode. + + (Binary::DoNumericPromotions): Implements numeric promotions of + and computation of the Binary::Type. + + (Binary::EmitBranchable): Optimization. + + (Binary::Emit): Implement code emission for expressions. + + * typemanager.cs (TypeManager): Added two new core types: sbyte + and byte. + +2001-09-12 Ravi Pratap + + * class.cs (TypeContainer::FindMembers): Method which does exactly + what Type.FindMembers does, only we don't have to use reflection. No + implementation yet. + + * typemanager.cs (typecontainers): New hashtable to hold the corresponding + typecontainer objects as we need to get at them. + (TypeManager::AddUserType): Overload to take an extra argument, the TypeContainer. + + * rootcontext.cs : Correspondingly modify called to AddUserType to pass the + typecontainer object. + + * expression.cs (MemberLookup): Modify signature to take a RootContext object instead + of just a Report object. + +2001-09-11 Ravi Pratap + + * class.cs (Event::Define): Go back to using the prefixes "add_" and + "remove_" + (TypeContainer::Populate): Now define the delegates of the type too. + (TypeContainer.Delegates): Property to access the list of delegates defined + in the type. + + * delegates.cs (Delegate::Define): Implement partially. + + * modifiers.cs (TypeAttr): Handle more flags. + +2001-09-11 Ravi Pratap + + * class.cs (Indexer::Define): Fix for loop iteration condition to be just < + and not <= + (Operator::Define): Re-write logic to get types by using the LookupType method + instead of blindly doing a Type.GetType ! How stupid can I get ;-) ? + (Indexer::Define): Ditto. + (Event::Define): Ditto. + (Property::Define): Ditto. + +2001-09-10 Ravi Pratap + + * class.cs (TypeContainer::Populate): Now define operators too. + (TypeContainer.Operators): New property to access the list of operators + in a type. + (Operator.OperatorMethodBuilder): New member to hold the method builder + for the operator we are defining. + (Operator::Define): Implement. + +2001-09-10 Ravi Pratap + + * class.cs (Event::Define): Make the prefixes of the accessor methods + addOn_ and removeOn_ + + * genericparser.cs (GenericParser::error): Overloaded method to handle the case + of the location being passed in too. Ideally, this should go later since all + error reporting should be done through the Report object. + + * class.cs (TypeContainer.Indexers): New property to access the list of indexers. + (Populate): Iterate thru the indexers we have and define them too. + (Indexer.GetMethodBuilder, .SetMethodBuilder): New members to hold the method builders + for the get and set accessors. + (Indexer::Define): Implement. + +2001-09-09 Miguel de Icaza + + * expression.cs (Binary::Resolve): Beginning of it. I scratched + my previous implementation, did not work. + + * typemanager.cs: Add a couple of missing types (the longs). + + * literal.cs: Use TypeManager.bool_type instead of getting it. + + * expression.cs (EventExpr): New kind of expressions. + (Expressio::ExprClassFromMemberInfo): finish + +2001-09-08 Miguel de Icaza + + * assign.cs: Emit stores to static fields differently. + +2001-09-08 Ravi Pratap + + * Merge in changes and adjust code to tackle conflicts. Backed out my + code in Assign::Resolve ;-) + +2001-09-08 Ravi Pratap + + * cs-parser.jay (CheckAttributeTarget): Modify call to error to use + instead Report.Error and also pass in the location. + (CSharpParser::Lexer): New readonly property to return the reference + to the Tokenizer object. + (declare_local_variables): Use Report.Error with location instead of plain + old error. + (CheckDef): Ditto. + + * class.cs (Operator::CheckUnaryOperator): Move into cs-parser.jay. + (Operator.CheckBinaryOperator): Ditto. + + * cs-parser.jay (operator_declarator): Update accordingly. + + * cs-parser.jay (CheckUnaryOperator): Modify to use Report.Error + (CheckBinaryOperator): Same here. + + * rootcontext.cs (LookupType): Add an extra lookup which simply does a lookup + on the name without any prefixes of namespace names etc. This is because we + already might have something already fully qualified like + 'System.Console.WriteLine' + + * assign.cs (Resolve): Begin implementation. Stuck ;-) + +2001-09-07 Ravi Pratap + + * cs-tokenizer.cs (location): Return a string which also contains + the file name. + + * expression.cs (ElementAccess): New class for expressions of the + type 'element access.' + (BaseAccess): New class for expressions of the type 'base access.' + (CheckedExpr, UnCheckedExpr): New classes for Checked and Unchecked expressions + respectively. + + * cs-parser.jay (element_access): Implement action. + (base_access): Implement actions. + (checked_expression, unchecked_expression): Implement. + + * cs-parser.jay (local_variable_type): Correct and implement. + (type_suffixes, type_suffix_list, type_suffix): Implement actions. + + * cs-tokenizer.cs (real_type_suffix): Comment out the extra getchar. + + * cs-parser.jay (rank_specifiers): Remove space while concatenating the type's + name and the specifiers. + + * interface.cs (InterfaceAttr): New property to return the corresponding TypeAttributes + + * rootcontext.cs (CreateInterface): Use the InterfaceAttr property instead of + making them all public ;-) + + * cs-parser.jay (error): Remove entirely as we have an implementation in the base + class anyways. + +2001-09-07 Miguel de Icaza + + * expression.cs (ExprClassFromMemberInfo): Return FieldExpr and + PropertyExprs. + (FieldExpr, PropertyExprs): New resolved expressions. + (SimpleName::MemberStaticCheck): Perform static checks for access + to non-static fields on static methods. Maybe this should be + generalized for MemberAccesses. + (SimpleName::ResolveSimpleName): More work on simple name + resolution. + + * cs-parser.jay (primary_expression/qualified_identifier): track + the parameter index. + + * codegen.cs (CodeGen::Save): Catch save exception, report error. + (EmitContext::EmitBoolExpression): Chain to expression generation + instead of temporary hack. + (::EmitStatementExpression): Put generic expression code generation. + + * assign.cs (Assign::Emit): Implement variable assignments to + local variables, parameters and fields. + +2001-09-06 Miguel de Icaza + + * statement.cs (Block::GetVariableInfo): New method, returns the + VariableInfo for a variable name in a block. + (Block::GetVariableType): Implement in terms of GetVariableInfo + + * literal.cs (IntLiteral::Emit, FloatLiteral::Emit, + DoubleLiteral::Emit, CharLiteral::Emit, BoolLiteral::Emit): Implement + +2001-09-06 Ravi Pratap + + * cs-parser.jay (operator_declaration): Continue on my quest : update + to take attributes argument. + (event_declaration): Ditto. + (enum_declaration): Ditto. + (indexer_declaration): Ditto. + + * class.cs (Operator::Operator): Update constructor accordingly. + (Event::Event): Ditto. + + * delegate.cs (Delegate::Delegate): Same here. + + * enum.cs (Enum::Enum): Same here. + +2001-09-05 Ravi Pratap + + * cs-parser.jay (CheckAttributeTarget): Update to use the right error number. + + * ../tests/cs0658.cs : New file to demonstrate error 0658. + + * attribute.cs (Attributes): New class to encapsulate all attributes which were + being passed around as an arraylist. + (Attributes::AddAttribute): Method to add attribute sections. + + * cs-parser.jay (opt_attributes): Modify actions to use the new Attributes class. + (struct_declaration): Update accordingly. + (constant_declaration): Update. + (field_declaration): Update. + (method_header): Update. + (fixed_parameter): Update. + (parameter_array): Ditto. + (property_declaration): Ditto. + (destructor_declaration): Ditto. + + * class.cs (Struct::Struct): Update constructors accordingly. + (Class::Class): Ditto. + (Field::Field): Ditto. + (Method::Method): Ditto. + (Property::Property): Ditto. + (TypeContainer::OptAttribute): update property's return type. + + * interface.cs (Interface.opt_attributes): New member. + (Interface::Interface): Update to take the extra Attributes argument. + + * parameter.cs (Parameter::Parameter): Ditto. + + * constant.cs (Constant::Constant): Ditto. + + * interface.cs (InterfaceMemberBase): New OptAttributes field. + (InterfaceMemberBase::InterfaceMemberBase): Update constructor to take + the attributes as a parameter. + (InterfaceProperty): Update constructor call. + (InterfaceEvent): Ditto. + (InterfaceMethod): Ditto. + (InterfaceIndexer): Ditto. + + * cs-parser.jay (interface_indexer_declaration): Update call to constructor to + pass the attributes too. + (interface_event_declaration): Ditto. + (interface_property_declaration): Ditto. + (interface_method_declaration): Ditto. + (interface_declaration): Ditto. + +2001-09-05 Miguel de Icaza + + * class.cs (Method::Define): Track the "static Main" definition to + create an entry point. + + * rootcontext.cs (RootContext::EntryPoint): MethodInfo that holds the + EntryPoint if we find it. + + * codegen.cs (EmitContext::EmitInvocation): Emit invocations. + (EmitContext::ig): Make this variable public. + + * driver.cs: Make the default output file be the first file name + with the .exe extension. + + Detect empty compilations + + Handle various kinds of output targets. Handle --target and + rename -t to --dumper. + + * expression.cs, literal.cs, assign.cs, constant.cs: All `Resolve' + methods inherited from Expression return now an Expression. This + will is used during the tree rewriting as we resolve them during + semantic analysis. + + (Expression::MemberLookup): Implements the MemberLookup (7.3) from + the spec. Missing entirely is the information about + accessability of elements of it. + + (Expression::ExprClassFromMemberInfo): New constructor for + Expressions that creates a fully initialized Expression based on + a MemberInfo that is one of Eventinfo, FieldINfo, PropertyInfo or + a Type. + + (Invocation::Resolve): Begin implementing resolution of invocations. + + * literal.cs (StringLiteral): Implement Emit. + +2001-09-05 Ravi Pratap + + * cs-parser.jay (error): Add new modifier because we are hiding an inherited + member. + +2001-09-04 Ravi Pratap + + * cs-parser.jay (attribute_arguments): Implement actions. + (attribute): Fix bug in production. Implement action. + (attribute_list): Implement. + (attribute_target): Implement. + (attribute_target_specifier, opt_target_specifier): Implement + (CheckAttributeTarget): New method to check if the attribute target + is valid. + (attribute_section): Implement. + (opt_attributes): Implement. + + * attribute.cs : New file to handle attributes. + (Attribute): Class to hold attribute info. + + * cs-parser.jay (opt_attribute_target_specifier): Remove production + (attribute_section): Modify production to use 2 different rules to + achieve the same thing. 1 s/r conflict down ! + Clean out commented, useless, non-reducing dimension_separator rules. + + * class.cs (TypeContainer.attributes): New member to hold list + of attributes for a type. + (Struct::Struct): Modify to take one more argument, the attribute list. + (Class::Class): Ditto. + (Field::Field): Ditto. + (Method::Method): Ditto. + (Property::Property): Ditto. + + * cs-parser.jay (struct_declaration): Update constructor call to + pass in the attributes too. + (class_declaration): Ditto. + (constant_declaration): Ditto. + (field_declaration): Ditto. + (method_header): Ditto. + (fixed_parameter): Ditto. + (parameter_array): Ditto. + (property_declaration): Ditto. + + * constant.cs (Constant::Constant): Update constructor similarly. + Use System.Collections. + + * parameter.cs (Parameter::Parameter): Update as above. + +2001-09-02 Ravi Pratap + + * class.cs (TypeContainer::AddDelegate): New method to add a delegate. + (TypeContainer.delegates): New member to hold list of delegates. + + * cs-parser.jay (delegate_declaration): Implement the action correctly + this time as I seem to be on crack ;-) + +2001-09-02 Miguel de Icaza + + * rootcontext.cs (RootContext::IsNamespace): new function, used to + tell whether an identifier represents a namespace. + + * expression.cs (NamespaceExpr): A namespace expression, used only + temporarly during expression resolution. + (Expression::ResolveSimpleName, ::ResolvePrimary, ::ResolveName): + utility functions to resolve names on expressions. + +2001-09-01 Miguel de Icaza + + * codegen.cs: Add hook for StatementExpressions. + + * class.cs: Fix inverted test for static flag in methods. + +2001-09-02 Ravi Pratap + + * class.cs (Operator::CheckUnaryOperator): Correct error number used + to make it coincide with MS' number. + (Operator::CheckBinaryOperator): Ditto. + + * ../errors/errors.txt : Remove error numbers added earlier. + + * ../errors/cs1019.cs : Test case for error # 1019 + + * ../errros/cs1020.cs : Test case for error # 1020 + + * cs-parser.jay : Clean out commented cruft. + (dimension_separators, dimension_separator): Comment out. Ostensibly not + used anywhere - non-reducing rule. + (namespace_declarations): Non-reducing rule - comment out. + + * enum.cs (Enum::AddEnum): Rename to AddEnumMember as I was getting confused + with TypeContainer::AddEnum. + + * delegate.cs : New file for delegate handling classes. + (Delegate): Class for declaring delegates. + + * makefile : Update. + + * cs-parser.jay (delegate_declaration): Implement. + +2001-09-01 Ravi Pratap + + * class.cs (Event::Define): Implement. + (Event.EventBuilder): New member. + + * class.cs (TypeContainer::Populate): Update to define all enums and events + we have. + (Events): New property for the events arraylist we hold. Shouldn't we move to using + readonly fields for all these cases ? + +2001-08-31 Ravi Pratap + + * class.cs (Property): Revamp to use the convention of making fields readonly. + Accordingly modify code elsewhere. + + * class.cs : Apply patch from Mr. Mandar for implementing + the Define method of the Property class. + + * class.cs : Clean up applied patch and update references to variables etc. Fix + trivial bug. + (TypeContainer::Populate): Update to define all the properties we have. Also + define all enumerations. + + * enum.cs (Define): Implement. + +2001-08-31 Ravi Pratap + + * cs-parser.jay (overloadable_operator): The semantic value is an + enum of the Operator class. + (operator_declarator): Implement actions. + (operator_declaration): Implement. + + * class.cs (Operator::CheckUnaryOperator): New static method to help in checking + validity of definitions. + (Operator::CheckBinaryOperator): Static method to check for binary operators + (TypeContainer::AddOperator): New method to add an operator to a type. + + * cs-parser.jay (indexer_declaration): Added line to actually call the + AddIndexer method so it gets added ;-) + + * ../errors/errors.txt : Update to include new error numbers. Are these numbers + already taken care of by the MS compiler ? + +2001-08-29 Ravi Pratap + + * class.cs (Operator): New class for operator declarations. + (Operator::OpType): Enum for the various operators. + +2001-08-29 Ravi Pratap + + * class.cs (TypeContainer::AddIndexer): Remove FIXME comment. We + ostensibly handle this in semantic analysis. + + * cs-parser.jay (general_catch_clause): Comment out + (specific_catch_clauses, specific_catch_clause): Ditto. + (opt_general_catch_clause, opt_specific_catch_clauses): Ditto + (catch_args, opt_catch_args): New productions. + (catch_clause): Rewrite to use the new productions above + (catch_clauses): Modify accordingly. + (opt_catch_clauses): New production to use in try_statement + (try_statement): Revamp. Basically, we get rid of one unnecessary rule + and re-write the code in the actions to extract the specific and + general catch clauses by being a little smart ;-) + + * ../tests/try.cs : Fix. It's not 'finalize' my friend, it's 'finally' ! + Hooray, try and catch statements parse fine ! + +2001-08-28 Ravi Pratap + + * statement.cs (Block::GetVariableType): Fix logic to extract the type + string from the hashtable of variables. + + * cs-parser.jay (event_accessor_declarations): Trivial fix. Man, how did + I end up making that mistake ;-) + (catch_clauses): Fixed gross error which made Key and Value of the + DictionaryEntry the same : $1 !! + +2001-08-28 Ravi Pratap + + * cs-tokenizer.cs (initTokens): Add keywords 'add' and 'remove' + + * cs-parser.jay (event_declaration): Correct to remove the semicolon + when the add and remove accessors are specified. + +2001-08-28 Ravi Pratap + + * cs-parser.jay (IndexerDeclaration): New helper class to hold + information about indexer_declarator. + (indexer_declarator): Implement actions. + (parsing_indexer): New local boolean used to keep track of whether + we are parsing indexers or properties. This is necessary because + implicit_parameters come into picture even for the get accessor in the + case of an indexer. + (get_accessor_declaration, set_accessor_declaration): Correspondingly modified. + + * class.cs (Indexer): New class for indexer declarations. + (TypeContainer::AddIndexer): New method to add an indexer to a type. + (TypeContainer::indexers): New member to hold list of indexers for the + type. + +2001-08-27 Ravi Pratap + + * cs-parser.jay (add_accessor_declaration): Implement action. + (remove_accessor_declaration): Implement action. + (event_accessors_declaration): Implement + (variable_declarators): swap statements for first rule - trivial. + + * class.cs (Event): New class to hold information about event + declarations. + (TypeContainer::AddEvent): New method to add an event to a type + (TypeContainer::events): New member to hold list of events. + + * cs-parser.jay (event_declaration): Implement actions. + +2001-08-27 Ravi Pratap + + * cs-parser.jay (dim_separators): Implement. Make it a string + concatenating all the commas together, just as they appear. + (opt_dim_separators): Modify accordingly + (rank_specifiers): Update accordingly. Basically do the same + thing - instead, collect the brackets here. + (opt_rank_sepcifiers): Modify accordingly. + (array_type): Modify to actually return the complete type string + instead of ignoring the rank_specifiers. + (expression_list): Implement to collect the expressions + (variable_initializer): Implement. We make it a list of expressions + essentially so that we can handle the array_initializer case neatly too. + (variable_initializer_list): Implement. + (array_initializer): Make it a list of variable_initializers + (opt_array_initializer): Modify accordingly. + + * expression.cs (New::NType): Add enumeration to help us + keep track of whether we have an object/delegate creation + or an array creation. + (New:NewType, New::Rank, New::Indices, New::Initializers): New + members to hold data about array creation. + (New:New): Modify to update NewType + (New:New): New Overloaded contructor for the array creation + case. + + * cs-parser.jay (array_creation_expression): Implement to call + the overloaded New constructor. + +2001-08-26 Ravi Pratap + + * class.cs (TypeContainer::Constructors): Return member + constructors instead of returning null. + +2001-08-26 Miguel de Icaza + + * typemanager.cs (InitCoreTypes): Initialize the various core + types after we have populated the type manager with the user + defined types (this distinction will be important later while + compiling corlib.dll) + + * expression.cs, literal.cs, assign.cs, constant.cs: Started work + on Expression Classification. Now all expressions have a method + `Resolve' and a method `Emit'. + + * codegen.cs, cs-parser.jay: Fixed the bug that stopped code + generation from working. Also add some temporary debugging + code. + +2001-08-24 Miguel de Icaza + + * codegen.cs: Lots of code generation pieces. This is only the + beginning, will continue tomorrow with more touches of polish. We + handle the fundamentals of if, while, do, for, return. Others are + trickier and I need to start working on invocations soon. + + * gen-treedump.cs: Bug fix, use s.Increment here instead of + s.InitStatement. + + * codegen.cs (EmitContext): New struct, used during code + emission to keep a context. Most of the code generation will be + here. + + * cs-parser.jay: Add embedded blocks to the list of statements of + this block. So code generation proceeds in a top down fashion. + +2001-08-23 Miguel de Icaza + + * statement.cs: Add support for multiple child blocks. + +2001-08-22 Miguel de Icaza + + * codegen.cs (EmitCode): New function, will emit the code for a + Block of code given a TypeContainer and its ILGenerator. + + * statement.cs (Block): Standard public readonly optimization. + (Block::Block constructors): Link children. + (Block::Child): Child Linker. + (Block::EmitVariables): Emits IL variable declarations. + + * class.cs: Drop support for MethodGroups here, delay until + Semantic Analysis. + (Method::): Applied the same simplification that I did before, and + move from Properties to public readonly fields. + (Method::ParameterTypes): Returns the parameter types for the + function, and implements a cache that will be useful later when I + do error checking and the semantic analysis on the methods is + performed. + (Constructor::GetCallingConvention): Renamed from CallingConvetion + and made a method, optional argument tells whether this is a class + or a structure to apply the `has-this' bit. + (Method::GetCallingConvention): Implement, returns the calling + convention. + (Method::Define): Defines the type, a second pass is performed + later to populate the methods. + + (Constructor::ParameterTypes): implement a cache similar to the + one on Method::ParameterTypes, useful later when we do semantic + analysis. + + (TypeContainer::EmitMethod): New method. Emits methods. + + * expression.cs: Removed MethodGroup class from here. + + * parameter.cs (Parameters::GetCallingConvention): new method. + +2001-08-21 Miguel de Icaza + + * class.cs (TypeContainer::Populate): Drop RootContext from the + argument. + + (Constructor::CallingConvention): Returns the calling convention. + (Constructor::ParameterTypes): Returns the constructor parameter + types. + + (TypeContainer::AddConstructor): Keep track of default constructor + and the default static constructor. + + (Constructor::) Another class that starts using `public readonly' + instead of properties. + + (Constructor::IsDefault): Whether this is a default constructor. + + (Field::) use readonly public fields instead of properties also. + + (TypeContainer::TypeAttr, TypeContainer::AddConstructor): Keep + track of static constructors; If none is used, turn on + BeforeFieldInit in the TypeAttributes. + + * cs-parser.jay (opt_argument_list): now the return can be null + for the cases where there are no arguments. + + (constructor_declarator): If there is no implicit `base' or + `this', then invoke the default parent constructor. + + * modifiers.cs (MethodAttr): New static function maps a set of + modifiers flags into a MethodAttributes enum + (FieldAttr): renamed from `Map'. So now we have FieldAttr, + MethodAttr, TypeAttr to represent the various mappings where the + modifiers are used. + (FieldAttr): Map also `readonly' to `FieldAttributes.InitOnly' + +2001-08-19 Miguel de Icaza + + * parameter.cs (GetParameterInfo): Fix bug where there would be no + method arguments. + + * interface.cs (PopulateIndexer): Implemented the code generator + for interface indexers. + +2001-08-17 Miguel de Icaza + + * interface.cs (InterfaceMemberBase): Now we track the new status + here. + + (PopulateProperty): Implement property population. Woohoo! Got + Methods and Properties going today. + + Removed all the properties for interfaces, and replaced them with + `public readonly' fields. + +2001-08-16 Miguel de Icaza + + * interface.cs (AddEvent, AddMethod, AddIndexer, AddProperty): + initialize their hashtables/arraylists only when they are needed + instead of doing this always. + + * parameter.cs: Handle refs and out parameters. + + * cs-parser.jay: Use an ArrayList to construct the arguments + instead of the ParameterCollection, and then cast that to a + Parameter[] array. + + * parameter.cs: Drop the use of ParameterCollection and use + instead arrays of Parameters. + + (GetParameterInfo): Use the Type, not the Name when resolving + types. + +2001-08-13 Miguel de Icaza + + * parameter.cs: Eliminate the properties Name, Type and ModFlags, + and instead use public readonly fields. + + * class.cs: Put back walking code for type containers. + +2001-08-11 Miguel de Icaza + + * class.cs (MakeConstant): Code to define constants. + + * rootcontext.cs (LookupType): New function. Used to locate types + + +2001-08-08 Miguel de Icaza + + * rootcontext.cs: OH MY! My trick works! It is amazing how nice + this System.Reflection code is. Kudos to Microsoft + + * typemanager.cs: Implement a type cache and avoid loading all + types at boot time. Wrap in LookupType the internals. This made + the compiler so much faster. Wow. I rule! + + * driver.cs: Make sure we always load mscorlib first (for + debugging purposes, nothing really important). + + * Renamespaced things that were on `CSC' to `CIR'. Maybe I should + have moved to `CSC' rather than `CIR'. Oh man! The confussion! + + * rootcontext.cs: Lookup types on their namespace; Lookup types + on namespaces that have been imported using the `using' keyword. + + * class.cs (TypeContainer::TypeAttr): Virtualize. + (Class::TypeAttr): Return attributes suitable for this bad boy. + (Struct::TypeAttr): ditto. + Handle nested classes. + (TypeContainer::) Remove all the type visiting code, it is now + replaced with the rootcontext.cs code + + * rootcontext.cs (GetClassBases): Added support for structs. + +2001-08-06 Miguel de Icaza + + * interface.cs, statement.cs, class.cs, parameter.cs, + rootcontext.cs, gen-treedump.cs, enum.cs, cs-parse.jay: + Drop use of TypeRefs, and use strings instead. + +2001-08-04 Miguel de Icaza + + * rootcontext.cs: + + * class.cs (Struct::Struct): set the SEALED flags after + checking the modifiers. + (TypeContainer::TypeAttr): new property, returns the + TypeAttributes for a class. + + * cs-parser.jay (type_list): Oops, list production was creating a + new list of base types. + + * rootcontext.cs (StdLib): New property. + (GetInterfaceTypeByName): returns an interface by type name, and + encapsulates error handling here. + (GetInterfaces): simplified. + (ResolveTree): Encapsulated all the tree resolution here. + (CreateClass, GetClassBases, GetInterfaceOrClass): Create class + types. + + * driver.cs: Add support for --nostdlib, to avoid loading the + default assemblies. + (Main): Do not put tree resolution here. + + * rootcontext.cs: Beginning of the class resolution. + +2001-08-03 Miguel de Icaza + + * rootcontext.cs: Provide better error reporting. + + * cs-parser.jay (interface_base): set our $$ to be interfaces. + + * rootcontext.cs (CreateInterface): Handle the case where there + are no parent interfaces. + + (CloseTypes): Routine to flush types at the end. + (CreateInterface): Track types. + (GetInterfaces): Returns an array of Types from the list of + defined interfaces. + + * typemanager.c (AddUserType): Mechanism to track user types (puts + the type on the global type hash, and allows us to close it at the + end). + +2001-08-02 Miguel de Icaza + + * tree.cs: Removed RecordType, added RecordClass, RecordStruct and + RecordInterface instead. + + * cs-parser.jay: Updated to reflect changes above. + + * decl.cs (Definition): Keep track of the TypeBuilder type that + represents this type here. Not sure we will use it in the long + run, but wont hurt for now. + + * driver.cs: Smaller changes to accomodate the new code. + + Call ResolveInterfaceBases, Call ResolveClassBases, Save assembly + when done. + + * rootcontext.cs (CreateInterface): New method, used to create + the System.TypeBuilder type for interfaces. + (ResolveInterfaces): new entry point to resolve the interface + hierarchy. + (CodeGen): Property, used to keep track of the code generator. + +2001-07-26 Miguel de Icaza + + * cs-parser.jay: Add a second production for delegate_declaration + with `VOID'. + + (enum_body): Put an opt_comma here instead of putting it on + enum_body or enum_member_declarations so we can handle trailing + commas on enumeration members. Gets rid of a shift/reduce. + + (type_list): Need a COMMA in the middle. + + (indexer_declaration): Tell tokenizer to recognize get/set + + * Remove old targets. + + * Re-add the parser target. + +2001-07-13 Simon Cozens + + * cs-parser.jay: Add precendence rules for a number of operators + ot reduce the number of shift/reduce conflicts in the grammar. + +2001-07-17 Miguel de Icaza + + * tree.cs: moved IGenerator interface and renamed it to ITreeDump + and put it here. + + Get rid of old crufty code. + + * rootcontext.cs: Use this to keep track of the parsed + representation and the defined types available to the program. + + * gen-treedump.cs: adjust for new convention. + + * type.cs: Split out the type manager, and the assembly builder + from here. + + * typemanager.cs: the type manager will live here now. + + * cil-codegen.cs: And the code generator here. + +2001-07-14 Sean MacIsaac + + * makefile: Fixed up for easy making. + +2001-07-13 Simon Cozens + + * cs-parser.jay (rank_specifier): Remove a conflict by reordering + the + + (unary_expression): Expand pre_increment_expression and + post_decrement_expression to reduce a shift/reduce. + +2001-07-11 Simon Cozens + + * cs-tokenizer.cs: Hex numbers should begin with a 0. + + Improve allow_keyword_as_indent name. + +2001-06-19 Miguel de Icaza + + * Adjustments for Beta2. + +2001-06-13 Miguel de Icaza + + * decl.cs: Added `Define' abstract method. + (InTransit): new property, used to catch recursive definitions. + + * interface.cs: Implement `Define'. + + * modifiers.cs: Map Modifiers.constants to + System.Reflection.TypeAttribute flags. + + * class.cs: Keep track of types and user-defined types. + (BuilderInit): New method for creating an assembly + (ResolveType): New function to launch the resolution process, only + used by interfaces for now. + + * cs-parser.jay: Keep track of Classes, Structs and Interfaces + that are inserted into the name space. + +2001-06-08 Miguel de Icaza + + * ARGH. I have screwed up my tree so many times due to the use of + rsync rather than using CVS. Going to fix this at once. + + * driver.cs: Objetify driver. Load assemblies, use assemblies to + load types. + +2001-06-07 Miguel de Icaza + + * Experiment successful: Use System.Type rather that our own + version of Type. + +2001-05-25 Miguel de Icaza + + * cs-parser.jay: Removed nsAliases from here. + + Use new namespaces, handle `using XXX;' + + * namespace.cs: Reimplemented namespace handling, use a recursive + definition of the class. Now we can keep track of using clauses + and catch invalid using clauses. + +2001-05-24 Miguel de Icaza + + * gen-treedump.cs: Adapted for all the renaming. + + * expression.cs (Expression): this class now has a Type property + which returns an expression Type. + + (Probe::, New::, TypeOf::, SizeOf::, Constant::): renamed from + `Type', as this has a different meaning now in the base + +2001-05-22 Miguel de Icaza + + * interface.cs, class.cs: Removed from all the sources the + references to signature computation, as we can not do method + signature computation during the parsing time, as we are not + trying to solve at that point distinguishing: + + class X { + void a (Blah x) {} + void a (NS.Blah x) {} + } + + Which depending on the context might be valid or not, as we do not + know if Blah is the same thing as NS.Blah at that point. + + * Redid everything so the code uses TypeRefs now instead of + Types. TypeRefs are just temporary type placeholders, that need + to be resolved. They initially have a pointer to a string and the + current scope in which they are used. This is used later by the + compiler to resolve the reference to an actual Type. + + * DeclSpace is no longer a CIR.Type, and neither are + TypeContainers (Class and Struct) nor Interfaces nor Enums. They + are all DeclSpaces, but no Types. + + * type.cs (TypeRefManager): This implements the TypeRef manager, + which keeps track of all the types that need to be resolved after + the parsing has finished. + +2001-05-13 Miguel de Icaza + + * ARGH. We are going to have to store `foreach' as a class rather + than resolving it, as we need to verify error 1579 after name + resolution. *OR* we could keep a flag that says `This request to + IEnumerator comes from a foreach statement' which we can then use + to generate the error. + +2001-05-10 Miguel de Icaza + + * class.cs (TypeContainer.AddMethod): we now add methods to the + MethodGroup instead of the method hashtable. + + * expression.cs: Add MethodGroup abstraction, which gets us one + step closer to the specification in the way we handle method + declarations. + + * cs-parser.jay (primary_expression): qualified_identifier now + tried to match up an identifier to a local variable reference or + to a parameter reference. + + current_local_parameters is now a parser global variable that + points to the current parameters for the block, used during name + lookup. + + (property_declaration): Now creates an implicit `value' argument to + the set accessor. + +2001-05-09 Miguel de Icaza + + * parameter.cs: Do not use `param' arguments as part of the + signature, per the spec. + +2001-05-08 Miguel de Icaza + + * decl.cs: Base class for classes, structs and interfaces. This + is the "Declaration Space" + + * cs-parser.jay: Use CheckDef for checking declaration errors + instead of having one on each function. + + * class.cs: Factor out some code for handling error handling in + accordance to the "Declarations" section in the "Basic Concepts" + chapter in the ECMA C# spec. + + * interface.cs: Make all interface member classes derive from + InterfaceMemberBase. + +2001-05-07 Miguel de Icaza + + * Many things: all interfaces are parsed and generated in + gen-treedump. Support for member variables, constructors, + destructors, properties, constants is there. + + Beginning of the IL backend, but very little done, just there for + testing purposes. + +2001-04-29 Miguel de Icaza + + * cs-parser.jay: Fix labeled statement. + + * cs-tokenizer.cs (escape): Escape " and ' always. + ref_line, ref_name: keep track of the line/filename as instructed + by #line by the compiler. + Parse #line. + +2001-04-27 Miguel de Icaza + + * System.CodeDOM/CodeBinaryOperatorExpression.cs: Rearrange enum + to match the values in System.CodeDOM. + + Divid renamed to Divide. + + * System.CodeDOM/CodeForLoopStatement.cs: Always have valid + statements. + (Statements.set): remove. + + * System.CodeDOM/CodeCatchClause.cs: always have a valid + statements. + + * System.CodeDOM/CodeIfStatement.cs: trueStatements and + falseStatements always have valid values. + + * cs-parser.jay: Use System.CodeDOM now. + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs new file mode 100644 index 0000000000..a56e94d01e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs @@ -0,0 +1,754 @@ +// +// CryptoConvert.cs - Crypto Convertion Routines +// +// Author: +// Sebastien Pouliot +// +// (C) 2003 Motus Technologies Inc. (http://www.motus.com) +// Copyright (C) 2004-2006 Novell Inc. (http://www.novell.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.Globalization; +using System.Security.Cryptography; +using System.Text; + +namespace Mono.Security.Cryptography { + +#if INSIDE_CORLIB + internal +#else + public +#endif + sealed class CryptoConvert { + + private CryptoConvert () + { + } + + static private int ToInt32LE (byte [] bytes, int offset) + { + return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]; + } + + static private uint ToUInt32LE (byte [] bytes, int offset) + { + return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]); + } + + static private byte [] GetBytesLE (int val) + { + return new byte [] { + (byte) (val & 0xff), + (byte) ((val >> 8) & 0xff), + (byte) ((val >> 16) & 0xff), + (byte) ((val >> 24) & 0xff) + }; + } + + static private byte[] Trim (byte[] array) + { + for (int i=0; i < array.Length; i++) { + if (array [i] != 0x00) { + byte[] result = new byte [array.Length - i]; + Buffer.BlockCopy (array, i, result, 0, result.Length); + return result; + } + } + return null; + } + + // convert the key from PRIVATEKEYBLOB to RSA + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/Security/private_key_blobs.asp + // e.g. SNK files, PVK files + static public RSA FromCapiPrivateKeyBlob (byte[] blob) + { + return FromCapiPrivateKeyBlob (blob, 0); + } + + static public RSA FromCapiPrivateKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + RSAParameters rsap = new RSAParameters (); + try { + if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07) + (blob [offset+1] != 0x02) || // Version (0x02) + (blob [offset+2] != 0x00) || // Reserved (word) + (blob [offset+3] != 0x00) || + (ToUInt32LE (blob, offset+8) != 0x32415352)) // DWORD magic = RSA2 + throw new CryptographicException ("Invalid blob header"); + + // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) + // int algId = ToInt32LE (blob, offset+4); + + // DWORD bitlen + int bitLen = ToInt32LE (blob, offset+12); + + // DWORD public exponent + byte[] exp = new byte [4]; + Buffer.BlockCopy (blob, offset+16, exp, 0, 4); + Array.Reverse (exp); + rsap.Exponent = Trim (exp); + + int pos = offset+20; + // BYTE modulus[rsapubkey.bitlen/8]; + int byteLen = (bitLen >> 3); + rsap.Modulus = new byte [byteLen]; + Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); + Array.Reverse (rsap.Modulus); + pos += byteLen; + + // BYTE prime1[rsapubkey.bitlen/16]; + int byteHalfLen = (byteLen >> 1); + rsap.P = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen); + Array.Reverse (rsap.P); + pos += byteHalfLen; + + // BYTE prime2[rsapubkey.bitlen/16]; + rsap.Q = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen); + Array.Reverse (rsap.Q); + pos += byteHalfLen; + + // BYTE exponent1[rsapubkey.bitlen/16]; + rsap.DP = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen); + Array.Reverse (rsap.DP); + pos += byteHalfLen; + + // BYTE exponent2[rsapubkey.bitlen/16]; + rsap.DQ = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen); + Array.Reverse (rsap.DQ); + pos += byteHalfLen; + + // BYTE coefficient[rsapubkey.bitlen/16]; + rsap.InverseQ = new byte [byteHalfLen]; + Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen); + Array.Reverse (rsap.InverseQ); + pos += byteHalfLen; + + // ok, this is hackish but CryptoAPI support it so... + // note: only works because CRT is used by default + // http://bugzilla.ximian.com/show_bug.cgi?id=57941 + rsap.D = new byte [byteLen]; // must be allocated + if (pos + byteLen + offset <= blob.Length) { + // BYTE privateExponent[rsapubkey.bitlen/8]; + Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen); + Array.Reverse (rsap.D); + } + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + +#if NET_2_1 + RSA rsa = RSA.Create (); + rsa.ImportParameters (rsap); +#else + RSA rsa = null; + try { + rsa = RSA.Create (); + rsa.ImportParameters (rsap); + } + catch (CryptographicException ce) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + try { + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + rsa = new RSACryptoServiceProvider (csp); + rsa.ImportParameters (rsap); + } + catch { + // rethrow original, not the later, exception if this fails + throw ce; + } + } +#endif + return rsa; + } + + static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob) + { + return FromCapiPrivateKeyBlobDSA (blob, 0); + } + + static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + DSAParameters dsap = new DSAParameters (); + try { + if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07) + (blob [offset + 1] != 0x02) || // Version (0x02) + (blob [offset + 2] != 0x00) || // Reserved (word) + (blob [offset + 3] != 0x00) || + (ToUInt32LE (blob, offset + 8) != 0x32535344)) // DWORD magic + throw new CryptographicException ("Invalid blob header"); + + int bitlen = ToInt32LE (blob, offset + 12); + int bytelen = bitlen >> 3; + int pos = offset + 16; + + dsap.P = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen); + Array.Reverse (dsap.P); + pos += bytelen; + + dsap.Q = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20); + Array.Reverse (dsap.Q); + pos += 20; + + dsap.G = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen); + Array.Reverse (dsap.G); + pos += bytelen; + + dsap.X = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.X, 0, 20); + Array.Reverse (dsap.X); + pos += 20; + + dsap.Counter = ToInt32LE (blob, pos); + pos += 4; + + dsap.Seed = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20); + Array.Reverse (dsap.Seed); + pos += 20; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + +#if NET_2_1 + DSA dsa = (DSA)DSA.Create (); + dsa.ImportParameters (dsap); +#else + DSA dsa = null; + try { + dsa = (DSA)DSA.Create (); + dsa.ImportParameters (dsap); + } + catch (CryptographicException ce) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + try { + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + dsa = new DSACryptoServiceProvider (csp); + dsa.ImportParameters (dsap); + } + catch { + // rethrow original, not the later, exception if this fails + throw ce; + } + } +#endif + return dsa; + } + + static public byte[] ToCapiPrivateKeyBlob (RSA rsa) + { + RSAParameters p = rsa.ExportParameters (true); + int keyLength = p.Modulus.Length; // in bytes + byte[] blob = new byte [20 + (keyLength << 2) + (keyLength >> 1)]; + + blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN) + blob [8] = 0x52; // Magic - RSA2 (ASCII in hex) + blob [9] = 0x53; + blob [10] = 0x41; + blob [11] = 0x32; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; // bitlen + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + // public exponent (DWORD) + int pos = 16; + int n = p.Exponent.Length; + while (n > 0) + blob [pos++] = p.Exponent [--n]; + // modulus + pos = 20; + byte[] part = p.Modulus; + int len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + // private key + part = p.P; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.Q; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.DP; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.DQ; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.InverseQ; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + + part = p.D; + len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + + return blob; + } + + static public byte[] ToCapiPrivateKeyBlob (DSA dsa) + { + DSAParameters p = dsa.ExportParameters (true); + int keyLength = p.P.Length; // in bytes + + // header + P + Q + G + X + count + seed + byte[] blob = new byte [16 + keyLength + 20 + keyLength + 20 + 4 + 20]; + + blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x22; // ALGID + blob [8] = 0x44; // Magic + blob [9] = 0x53; + blob [10] = 0x53; + blob [11] = 0x32; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + int pos = 16; + byte[] part = p.P; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.Q; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + pos += 20; + + part = p.G; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.X; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + pos += 20; + + Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4); + pos += 4; + + part = p.Seed; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + + return blob; + } + + static public RSA FromCapiPublicKeyBlob (byte[] blob) + { + return FromCapiPublicKeyBlob (blob, 0); + } + + static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + try { + if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06) + (blob [offset+1] != 0x02) || // Version (0x02) + (blob [offset+2] != 0x00) || // Reserved (word) + (blob [offset+3] != 0x00) || + (ToUInt32LE (blob, offset+8) != 0x31415352)) // DWORD magic = RSA1 + throw new CryptographicException ("Invalid blob header"); + + // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...) + // int algId = ToInt32LE (blob, offset+4); + + // DWORD bitlen + int bitLen = ToInt32LE (blob, offset+12); + + // DWORD public exponent + RSAParameters rsap = new RSAParameters (); + rsap.Exponent = new byte [3]; + rsap.Exponent [0] = blob [offset+18]; + rsap.Exponent [1] = blob [offset+17]; + rsap.Exponent [2] = blob [offset+16]; + + int pos = offset+20; + // BYTE modulus[rsapubkey.bitlen/8]; + int byteLen = (bitLen >> 3); + rsap.Modulus = new byte [byteLen]; + Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen); + Array.Reverse (rsap.Modulus); +#if NET_2_1 + RSA rsa = RSA.Create (); + rsa.ImportParameters (rsap); +#else + RSA rsa = null; + try { + rsa = RSA.Create (); + rsa.ImportParameters (rsap); + } + catch (CryptographicException) { + // this may cause problem when this code is run under + // the SYSTEM identity on Windows (e.g. ASP.NET). See + // http://bugzilla.ximian.com/show_bug.cgi?id=77559 + CspParameters csp = new CspParameters (); + csp.Flags = CspProviderFlags.UseMachineKeyStore; + rsa = new RSACryptoServiceProvider (csp); + rsa.ImportParameters (rsap); + } +#endif + return rsa; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + } + + static public DSA FromCapiPublicKeyBlobDSA (byte[] blob) + { + return FromCapiPublicKeyBlobDSA (blob, 0); + } + + static public DSA FromCapiPublicKeyBlobDSA (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + try { + if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06) + (blob [offset + 1] != 0x02) || // Version (0x02) + (blob [offset + 2] != 0x00) || // Reserved (word) + (blob [offset + 3] != 0x00) || + (ToUInt32LE (blob, offset + 8) != 0x31535344)) // DWORD magic + throw new CryptographicException ("Invalid blob header"); + + int bitlen = ToInt32LE (blob, offset + 12); + DSAParameters dsap = new DSAParameters (); + int bytelen = bitlen >> 3; + int pos = offset + 16; + + dsap.P = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen); + Array.Reverse (dsap.P); + pos += bytelen; + + dsap.Q = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20); + Array.Reverse (dsap.Q); + pos += 20; + + dsap.G = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen); + Array.Reverse (dsap.G); + pos += bytelen; + + dsap.Y = new byte [bytelen]; + Buffer.BlockCopy (blob, pos, dsap.Y, 0, bytelen); + Array.Reverse (dsap.Y); + pos += bytelen; + + dsap.Counter = ToInt32LE (blob, pos); + pos += 4; + + dsap.Seed = new byte [20]; + Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20); + Array.Reverse (dsap.Seed); + pos += 20; + + DSA dsa = (DSA)DSA.Create (); + dsa.ImportParameters (dsap); + return dsa; + } + catch (Exception e) { + throw new CryptographicException ("Invalid blob.", e); + } + } + + static public byte[] ToCapiPublicKeyBlob (RSA rsa) + { + RSAParameters p = rsa.ExportParameters (false); + int keyLength = p.Modulus.Length; // in bytes + byte[] blob = new byte [20 + keyLength]; + + blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN) + blob [8] = 0x52; // Magic - RSA1 (ASCII in hex) + blob [9] = 0x53; + blob [10] = 0x41; + blob [11] = 0x31; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; // bitlen + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + // public exponent (DWORD) + int pos = 16; + int n = p.Exponent.Length; + while (n > 0) + blob [pos++] = p.Exponent [--n]; + // modulus + pos = 20; + byte[] part = p.Modulus; + int len = part.Length; + Array.Reverse (part, 0, len); + Buffer.BlockCopy (part, 0, blob, pos, len); + pos += len; + return blob; + } + + static public byte[] ToCapiPublicKeyBlob (DSA dsa) + { + DSAParameters p = dsa.ExportParameters (false); + int keyLength = p.P.Length; // in bytes + + // header + P + Q + G + Y + count + seed + byte[] blob = new byte [16 + keyLength + 20 + keyLength + keyLength + 4 + 20]; + + blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06) + blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02) + // [2], [3] // RESERVED - Always 0 + blob [5] = 0x22; // ALGID + blob [8] = 0x44; // Magic + blob [9] = 0x53; + blob [10] = 0x53; + blob [11] = 0x31; + + byte[] bitlen = GetBytesLE (keyLength << 3); + blob [12] = bitlen [0]; + blob [13] = bitlen [1]; + blob [14] = bitlen [2]; + blob [15] = bitlen [3]; + + int pos = 16; + byte[] part; + + part = p.P; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.Q; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + pos += 20; + + part = p.G; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + part = p.Y; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, keyLength); + pos += keyLength; + + Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4); + pos += 4; + + part = p.Seed; + Array.Reverse (part); + Buffer.BlockCopy (part, 0, blob, pos, 20); + + return blob; + } + + // PRIVATEKEYBLOB + // PUBLICKEYBLOB + static public RSA FromCapiKeyBlob (byte[] blob) + { + return FromCapiKeyBlob (blob, 0); + } + + static public RSA FromCapiKeyBlob (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + switch (blob [offset]) { + case 0x00: + // this could be a public key inside an header + // like "sn -e" would produce + if (blob [offset + 12] == 0x06) { + return FromCapiPublicKeyBlob (blob, offset + 12); + } + break; + case 0x06: + return FromCapiPublicKeyBlob (blob, offset); + case 0x07: + return FromCapiPrivateKeyBlob (blob, offset); + } + throw new CryptographicException ("Unknown blob format."); + } + + static public DSA FromCapiKeyBlobDSA (byte[] blob) + { + return FromCapiKeyBlobDSA (blob, 0); + } + + static public DSA FromCapiKeyBlobDSA (byte[] blob, int offset) + { + if (blob == null) + throw new ArgumentNullException ("blob"); + if (offset >= blob.Length) + throw new ArgumentException ("blob is too small."); + + switch (blob [offset]) { + case 0x06: + return FromCapiPublicKeyBlobDSA (blob, offset); + case 0x07: + return FromCapiPrivateKeyBlobDSA (blob, offset); + } + throw new CryptographicException ("Unknown blob format."); + } + + static public byte[] ToCapiKeyBlob (AsymmetricAlgorithm keypair, bool includePrivateKey) + { + if (keypair == null) + throw new ArgumentNullException ("keypair"); + + // check between RSA and DSA (and potentially others like DH) + if (keypair is RSA) + return ToCapiKeyBlob ((RSA)keypair, includePrivateKey); + else if (keypair is DSA) + return ToCapiKeyBlob ((DSA)keypair, includePrivateKey); + else + return null; // TODO + } + + static public byte[] ToCapiKeyBlob (RSA rsa, bool includePrivateKey) + { + if (rsa == null) + throw new ArgumentNullException ("rsa"); + + if (includePrivateKey) + return ToCapiPrivateKeyBlob (rsa); + else + return ToCapiPublicKeyBlob (rsa); + } + + static public byte[] ToCapiKeyBlob (DSA dsa, bool includePrivateKey) + { + if (dsa == null) + throw new ArgumentNullException ("dsa"); + + if (includePrivateKey) + return ToCapiPrivateKeyBlob (dsa); + else + return ToCapiPublicKeyBlob (dsa); + } + + static public string ToHex (byte[] input) + { + if (input == null) + return null; + + StringBuilder sb = new StringBuilder (input.Length * 2); + foreach (byte b in input) { + sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture)); + } + return sb.ToString (); + } + + static private byte FromHexChar (char c) + { + if ((c >= 'a') && (c <= 'f')) + return (byte) (c - 'a' + 10); + if ((c >= 'A') && (c <= 'F')) + return (byte) (c - 'A' + 10); + if ((c >= '0') && (c <= '9')) + return (byte) (c - '0'); + throw new ArgumentException ("invalid hex char"); + } + + static public byte[] FromHex (string hex) + { + if (hex == null) + return null; + if ((hex.Length & 0x1) == 0x1) + throw new ArgumentException ("Length must be a multiple of 2"); + + byte[] result = new byte [hex.Length >> 1]; + int n = 0; + int i = 0; + while (n < result.Length) { + result [n] = (byte) (FromHexChar (hex [i++]) << 4); + result [n++] += FromHexChar (hex [i++]); + } + return result; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile new file mode 100644 index 0000000000..43a2780851 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile @@ -0,0 +1,126 @@ +thisdir := mcs +SUBDIRS := +include ../build/rules.make + +EXTRA_DISTFILES = \ + *mcs.csproj \ + compiler.doc \ + *mcs.sln \ + *cs-parser.jay \ + *.sources \ + NOTES \ + TODO \ + *mcs.exe.config + +COMPILER_NAME = gmcs + +ifeq (net_2_0, $(PROFILE)) +INTERNAL_GMCS = $(RUNTIME) $(RUNTIME_FLAGS) $(topdir)/class/lib/$(BOOTSTRAP_PROFILE)/gmcs.exe +endif + +ifeq (moonlight_bootstrap, $(PROFILE)) +INTERNAL_GMCS = $(RUNTIME) $(RUNTIME_FLAGS) $(topdir)/class/lib/$(BOOTSTRAP_PROFILE)/gmcs.exe +endif + +ifeq (2.1, $(FRAMEWORK_VERSION)) +LOCAL_MCS_FLAGS += -d:SMCS_SOURCE +COMPILER_NAME = smcs +endif + +ifeq (4.0, $(FRAMEWORK_VERSION)) +COMPILER_NAME = dmcs +endif + +PROGRAM = $(topdir)/class/lib/$(PROFILE)/$(COMPILER_NAME).exe + +BUILT_SOURCES = cs-parser.cs + +PROGRAM_COMPILE = $(BOOT_COMPILE) + +CLEAN_FILES += y.output + +%-parser.cs: %-parser.jay $(topdir)/jay/skeleton.cs + $(topdir)/jay/jay -cvt < $(topdir)/jay/skeleton.cs $< > jay-tmp.out && mv jay-tmp.out $@ + + +KEEP_OUTPUT_FILE_COPY = yes + +include ../build/executable.make + +csproj-local: + config_file=`basename $(PROGRAM) .exe`-$(PROFILE).input; \ + echo $(thisdir):$$config_file >> $(topdir)/../mono/msvc/scripts/order; \ + (echo $(is_boot); \ + echo $(BOOTSTRAP_MCS); \ + echo $(USE_MCS_FLAGS) $(LIBRARY_FLAGS) $(LIB_MCS_FLAGS); \ + echo $(PROGRAM); \ + echo $(BUILT_SOURCES); \ + echo $(PROGRAM); \ + echo $(response)) > $(topdir)/../mono/msvc/scripts/inputs/$$config_file + +# +# Below this line we have local targets used for testing and development +# + +# Testing targets + +TIME = time + +# This used to be called test, but that conflicts with the global +# recursive target. + +btest: mcs2.exe mcs3.exe + ls -l mcs2.exe mcs3.exe + +mcs2.exe: $(PROGRAM) + $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) $(PROGRAM) $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response) + +mcs3.exe: mcs2.exe + $(TIME) $(RUNTIME) $(RUNTIME_FLAGS) ./mcs2.exe $(USE_MCS_FLAGS) -target:exe -out:$@ $(BUILT_SOURCES) @$(response) + +wc: + wc -l $(BUILT_SOURCES) `cat $(sourcefile)` + +ctest: + rm -f mcs2.exe mcs3.exe + $(MAKE) USE_MCS_FLAGS="-d:NET_1_1 -d:ONLY_1_1" btest + +# we need this because bash tries to use its own crappy timer +FRIENDLY_TIME = $(shell which time) -f'%U seconds' + +do-time : $(PROGRAM) + @ echo -n "Run 1: " + @ rm -f mcs2.exe + @ $(MAKE) TIME="$(FRIENDLY_TIME)" mcs2.exe > /dev/null || (echo FAILED; exit 1) + @ echo -n "Run 2: " + @ rm -f mcs3.exe + @ $(MAKE) TIME="$(FRIENDLY_TIME)" mcs3.exe > /dev/null || (echo FAILED; exit 1) + @ $(MAKE) do-corlib + +do-corlib: + @ echo -n "corlib: " + @ rm -f ../class/lib/mscorlib.dll + @ cd ../class/corlib ; $(MAKE) BOOTSTRAP_MCS='$(FRIENDLY_TIME) mono $$(topdir)/class/lib/$(PROFILE)/mcs.exe' > /dev/null || (echo FAILED; exit 1) + +PROFILER=default + +do-gettext: + xgettext --keyword='Report.Error:3' --keyword='Report.Error:2' --keyword='Report.Warning:3' --keyword='Report.Warning:2' -o mcs.po --language='C#' `cat gmcs.exe.sources | grep -v /` + +profile : $(PROGRAM) + $(RUNTIME) $(RUNTIME_FLAGS) --profile=$(PROFILER) $(PROGRAM) $(USE_MCS_FLAGS) -target:exe -out:mcs2.exe $(BUILT_SOURCES) @$(response) + +# +# quick hack target, to quickly develop the gmcs compiler +# Update manually. + +q: cs-parser.cs qh + echo 'System.Console.WriteLine ("Hello");' | mono csharp.exe + echo -e 'using System;\nConsole.WriteLine ("hello");' | mono csharp.exe + echo -e '"foo" == "bar";' | mono csharp.exe + echo -e 'var a = 1;\na + 2;' | mono csharp.exe + echo -e 'int j;\nj = 1;' | mono csharp.exe + echo -e 'var a = new int[]{1,2,3};\nfrom x in a select x;' | mono csharp.exe + echo -e 'var a = from f in System.IO.Directory.GetFiles ("/tmp") where f == "passwd" select f;' | mono csharp.exe + + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs new file mode 100644 index 0000000000..465f4c7cbe --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs @@ -0,0 +1,723 @@ +// +// Mono.CSharp.Debugger/MonoSymbolFile.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// (C) 2003 Ximian, Inc. http://www.ximian.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.Reflection; +using SRE = System.Reflection.Emit; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.IO; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class MonoSymbolFileException : Exception + { + public MonoSymbolFileException () + : base () + { } + + public MonoSymbolFileException (string message, params object[] args) + : base (String.Format (message, args)) + { } + } + + internal class MyBinaryWriter : BinaryWriter + { + public MyBinaryWriter (Stream stream) + : base (stream) + { } + + public void WriteLeb128 (int value) + { + base.Write7BitEncodedInt (value); + } + } + + internal class MyBinaryReader : BinaryReader + { + public MyBinaryReader (Stream stream) + : base (stream) + { } + + public int ReadLeb128 () + { + return base.Read7BitEncodedInt (); + } + + public string ReadString (int offset) + { + long old_pos = BaseStream.Position; + BaseStream.Position = offset; + + string text = ReadString (); + + BaseStream.Position = old_pos; + return text; + } + } + + public interface ISourceFile + { + SourceFileEntry Entry { + get; + } + } + + public interface ICompileUnit + { + CompileUnitEntry Entry { + get; + } + } + + public interface IMethodDef + { + string Name { + get; + } + + int Token { + get; + } + } + +#if !CECIL + // TODO: Obsolete under .net 4 + internal class MonoDebuggerSupport + { + static GetMethodTokenFunc get_method_token; + static GetGuidFunc get_guid; + + delegate int GetMethodTokenFunc (MethodBase method); + delegate Guid GetGuidFunc (Module module); + + static Delegate create_delegate (Type type, Type delegate_type, string name) + { + MethodInfo mi = type.GetMethod (name, BindingFlags.Static | + BindingFlags.NonPublic); + if (mi == null) + throw new Exception ("Can't find " + name); + + return Delegate.CreateDelegate (delegate_type, mi); + } + + static MonoDebuggerSupport () + { + get_method_token = (GetMethodTokenFunc) create_delegate ( + typeof (Assembly), typeof (GetMethodTokenFunc), + "MonoDebugger_GetMethodToken"); + + get_guid = (GetGuidFunc) create_delegate ( + typeof (Module), typeof (GetGuidFunc), "Mono_GetGuid"); + } + + public static int GetMethodToken (MethodBase method) + { + return get_method_token (method); + } + + public static Guid GetGuid (Module module) + { + return get_guid (module); + } + } +#endif + + public class MonoSymbolFile : IDisposable + { + List methods = new List (); + List sources = new List (); + List comp_units = new List (); + Dictionary type_hash = new Dictionary (); + Dictionary anonymous_scopes; + + OffsetTable ot; + int last_type_index; + int last_method_index; + int last_namespace_index; + + public readonly string FileName = ""; + public readonly int MajorVersion = OffsetTable.MajorVersion; + public readonly int MinorVersion = OffsetTable.MinorVersion; + + public int NumLineNumbers; + + internal MonoSymbolFile () + { + ot = new OffsetTable (); + } + + internal int AddSource (SourceFileEntry source) + { + sources.Add (source); + return sources.Count; + } + + internal int AddCompileUnit (CompileUnitEntry entry) + { + comp_units.Add (entry); + return comp_units.Count; + } + + internal int DefineType (Type type) + { + int index; + if (type_hash.TryGetValue (type, out index)) + return index; + + index = ++last_type_index; + type_hash.Add (type, index); + return index; + } + + internal void AddMethod (MethodEntry entry) + { + methods.Add (entry); + } + + public MethodEntry DefineMethod (CompileUnitEntry comp_unit, int token, + ScopeVariable[] scope_vars, LocalVariableEntry[] locals, + LineNumberEntry[] lines, CodeBlockEntry[] code_blocks, + string real_name, MethodEntry.Flags flags, + int namespace_id) + { + if (reader != null) + throw new InvalidOperationException (); + + MethodEntry method = new MethodEntry ( + this, comp_unit, token, scope_vars, locals, lines, code_blocks, + real_name, flags, namespace_id); + AddMethod (method); + return method; + } + + internal void DefineAnonymousScope (int id) + { + if (reader != null) + throw new InvalidOperationException (); + + if (anonymous_scopes == null) + anonymous_scopes = new Dictionary (); + + anonymous_scopes.Add (id, new AnonymousScopeEntry (id)); + } + + internal void DefineCapturedVariable (int scope_id, string name, string captured_name, + CapturedVariable.CapturedKind kind) + { + if (reader != null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope = anonymous_scopes [scope_id]; + scope.AddCapturedVariable (name, captured_name, kind); + } + + internal void DefineCapturedScope (int scope_id, int id, string captured_name) + { + if (reader != null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope = anonymous_scopes [scope_id]; + scope.AddCapturedScope (id, captured_name); + } + + internal int GetNextTypeIndex () + { + return ++last_type_index; + } + + internal int GetNextMethodIndex () + { + return ++last_method_index; + } + + internal int GetNextNamespaceIndex () + { + return ++last_namespace_index; + } + + void Write (MyBinaryWriter bw, Guid guid) + { + // Magic number and file version. + bw.Write (OffsetTable.Magic); + bw.Write (MajorVersion); + bw.Write (MinorVersion); + + bw.Write (guid.ToByteArray ()); + + // + // Offsets of file sections; we must write this after we're done + // writing the whole file, so we just reserve the space for it here. + // + long offset_table_offset = bw.BaseStream.Position; + ot.Write (bw, MajorVersion, MinorVersion); + + // + // Sort the methods according to their tokens and update their index. + // + methods.Sort (); + for (int i = 0; i < methods.Count; i++) + ((MethodEntry) methods [i]).Index = i + 1; + + // + // Write data sections. + // + ot.DataSectionOffset = (int) bw.BaseStream.Position; + foreach (SourceFileEntry source in sources) + source.WriteData (bw); + foreach (CompileUnitEntry comp_unit in comp_units) + comp_unit.WriteData (bw); + foreach (MethodEntry method in methods) + method.WriteData (this, bw); + ot.DataSectionSize = (int) bw.BaseStream.Position - ot.DataSectionOffset; + + // + // Write the method index table. + // + ot.MethodTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < methods.Count; i++) { + MethodEntry entry = (MethodEntry) methods [i]; + entry.Write (bw); + } + ot.MethodTableSize = (int) bw.BaseStream.Position - ot.MethodTableOffset; + + // + // Write source table. + // + ot.SourceTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < sources.Count; i++) { + SourceFileEntry source = (SourceFileEntry) sources [i]; + source.Write (bw); + } + ot.SourceTableSize = (int) bw.BaseStream.Position - ot.SourceTableOffset; + + // + // Write compilation unit table. + // + ot.CompileUnitTableOffset = (int) bw.BaseStream.Position; + for (int i = 0; i < comp_units.Count; i++) { + CompileUnitEntry unit = (CompileUnitEntry) comp_units [i]; + unit.Write (bw); + } + ot.CompileUnitTableSize = (int) bw.BaseStream.Position - ot.CompileUnitTableOffset; + + // + // Write anonymous scope table. + // + ot.AnonymousScopeCount = anonymous_scopes != null ? anonymous_scopes.Count : 0; + ot.AnonymousScopeTableOffset = (int) bw.BaseStream.Position; + if (anonymous_scopes != null) { + foreach (AnonymousScopeEntry scope in anonymous_scopes.Values) + scope.Write (bw); + } + ot.AnonymousScopeTableSize = (int) bw.BaseStream.Position - ot.AnonymousScopeTableOffset; + + // + // Fixup offset table. + // + ot.TypeCount = last_type_index; + ot.MethodCount = methods.Count; + ot.SourceCount = sources.Count; + ot.CompileUnitCount = comp_units.Count; + + // + // Write offset table. + // + ot.TotalFileSize = (int) bw.BaseStream.Position; + bw.Seek ((int) offset_table_offset, SeekOrigin.Begin); + ot.Write (bw, MajorVersion, MinorVersion); + bw.Seek (0, SeekOrigin.End); + +#if false + Console.WriteLine ("TOTAL: {0} line numbes, {1} bytes, extended {2} bytes, " + + "{3} methods.", NumLineNumbers, LineNumberSize, + ExtendedLineNumberSize, methods.Count); +#endif + } + + public void CreateSymbolFile (Guid guid, FileStream fs) + { + if (reader != null) + throw new InvalidOperationException (); + + Write (new MyBinaryWriter (fs), guid); + } + + MyBinaryReader reader; + Dictionary source_file_hash; + Dictionary compile_unit_hash; + + List method_list; + Dictionary method_token_hash; + Dictionary source_name_hash; + + Guid guid; + + MonoSymbolFile (string filename) + { + this.FileName = filename; + FileStream stream = new FileStream (filename, FileMode.Open, FileAccess.Read); + reader = new MyBinaryReader (stream); + + try { + long magic = reader.ReadInt64 (); + int major_version = reader.ReadInt32 (); + int minor_version = reader.ReadInt32 (); + + if (magic != OffsetTable.Magic) + throw new MonoSymbolFileException ( + "Symbol file `{0}' is not a valid " + + "Mono symbol file", filename); + if (major_version != OffsetTable.MajorVersion) + throw new MonoSymbolFileException ( + "Symbol file `{0}' has version {1}, " + + "but expected {2}", filename, major_version, + OffsetTable.MajorVersion); + if (minor_version != OffsetTable.MinorVersion) + throw new MonoSymbolFileException ( + "Symbol file `{0}' has version {1}.{2}, " + + "but expected {3}.{4}", filename, major_version, + minor_version, OffsetTable.MajorVersion, + OffsetTable.MinorVersion); + + MajorVersion = major_version; + MinorVersion = minor_version; + guid = new Guid (reader.ReadBytes (16)); + + ot = new OffsetTable (reader, major_version, minor_version); + } catch { + throw new MonoSymbolFileException ( + "Cannot read symbol file `{0}'", filename); + } + + source_file_hash = new Dictionary (); + compile_unit_hash = new Dictionary (); + } + + void CheckGuidMatch (Guid other, string filename, string assembly) + { + if (other == guid) + return; + + throw new MonoSymbolFileException ( + "Symbol file `{0}' does not match assembly `{1}'", + filename, assembly); + } + +#if CECIL + protected MonoSymbolFile (string filename, Mono.Cecil.ModuleDefinition module) + : this (filename) + { + CheckGuidMatch (module.Mvid, filename, module.FullyQualifiedName); + } + + public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module) + { + return ReadSymbolFile (module, module.FullyQualifiedName); + } + + public static MonoSymbolFile ReadSymbolFile (Mono.Cecil.ModuleDefinition module, string filename) + { + string name = filename + ".mdb"; + + return new MonoSymbolFile (name, module); + } +#else + protected MonoSymbolFile (string filename, Assembly assembly) : this (filename) + { + // Check that the MDB file matches the assembly, if we have been + // passed an assembly. + if (assembly == null) + return; + + Module[] modules = assembly.GetModules (); + Guid assembly_guid = MonoDebuggerSupport.GetGuid (modules [0]); + + CheckGuidMatch (assembly_guid, filename, assembly.Location); + } + + public static MonoSymbolFile ReadSymbolFile (Assembly assembly) + { + string filename = assembly.Location; + string name = filename + ".mdb"; + + return new MonoSymbolFile (name, assembly); + } +#endif + + public static MonoSymbolFile ReadSymbolFile (string mdbFilename) + { + return new MonoSymbolFile (mdbFilename, null); + } + + public int CompileUnitCount { + get { return ot.CompileUnitCount; } + } + + public int SourceCount { + get { return ot.SourceCount; } + } + + public int MethodCount { + get { return ot.MethodCount; } + } + + public int TypeCount { + get { return ot.TypeCount; } + } + + public int AnonymousScopeCount { + get { return ot.AnonymousScopeCount; } + } + + public int NamespaceCount { + get { return last_namespace_index; } + } + + public Guid Guid { + get { return guid; } + } + + public OffsetTable OffsetTable { + get { return ot; } + } + + internal int LineNumberCount = 0; + internal int LocalCount = 0; + internal int StringSize = 0; + + internal int LineNumberSize = 0; + internal int ExtendedLineNumberSize = 0; + + public SourceFileEntry GetSourceFile (int index) + { + if ((index < 1) || (index > ot.SourceCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + SourceFileEntry source; + if (source_file_hash.TryGetValue (index, out source)) + return source; + + long old_pos = reader.BaseStream.Position; + + reader.BaseStream.Position = ot.SourceTableOffset + + SourceFileEntry.Size * (index - 1); + source = new SourceFileEntry (this, reader); + source_file_hash.Add (index, source); + + reader.BaseStream.Position = old_pos; + return source; + } + } + + public SourceFileEntry[] Sources { + get { + if (reader == null) + throw new InvalidOperationException (); + + SourceFileEntry[] retval = new SourceFileEntry [SourceCount]; + for (int i = 0; i < SourceCount; i++) + retval [i] = GetSourceFile (i + 1); + return retval; + } + } + + public CompileUnitEntry GetCompileUnit (int index) + { + if ((index < 1) || (index > ot.CompileUnitCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + CompileUnitEntry unit; + if (compile_unit_hash.TryGetValue (index, out unit)) + return unit; + + long old_pos = reader.BaseStream.Position; + + reader.BaseStream.Position = ot.CompileUnitTableOffset + + CompileUnitEntry.Size * (index - 1); + unit = new CompileUnitEntry (this, reader); + compile_unit_hash.Add (index, unit); + + reader.BaseStream.Position = old_pos; + return unit; + } + } + + public CompileUnitEntry[] CompileUnits { + get { + if (reader == null) + throw new InvalidOperationException (); + + CompileUnitEntry[] retval = new CompileUnitEntry [CompileUnitCount]; + for (int i = 0; i < CompileUnitCount; i++) + retval [i] = GetCompileUnit (i + 1); + return retval; + } + } + + void read_methods () + { + lock (this) { + if (method_token_hash != null) + return; + + method_token_hash = new Dictionary (); + method_list = new List (); + + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = ot.MethodTableOffset; + + for (int i = 0; i < MethodCount; i++) { + MethodEntry entry = new MethodEntry (this, reader, i + 1); + method_token_hash.Add (entry.Token, entry); + method_list.Add (entry); + } + + reader.BaseStream.Position = old_pos; + } + } + + public MethodEntry GetMethodByToken (int token) + { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + MethodEntry me; + method_token_hash.TryGetValue (token, out me); + return me; + } + } + + public MethodEntry GetMethod (int index) + { + if ((index < 1) || (index > ot.MethodCount)) + throw new ArgumentException (); + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + return (MethodEntry) method_list [index - 1]; + } + } + + public MethodEntry[] Methods { + get { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + read_methods (); + MethodEntry[] retval = new MethodEntry [MethodCount]; + method_list.CopyTo (retval, 0); + return retval; + } + } + } + + public int FindSource (string file_name) + { + if (reader == null) + throw new InvalidOperationException (); + + lock (this) { + if (source_name_hash == null) { + source_name_hash = new Dictionary (); + + for (int i = 0; i < ot.SourceCount; i++) { + SourceFileEntry source = GetSourceFile (i + 1); + source_name_hash.Add (source.FileName, i); + } + } + + int value; + if (!source_name_hash.TryGetValue (file_name, out value)) + return -1; + return value; + } + } + + public AnonymousScopeEntry GetAnonymousScope (int id) + { + if (reader == null) + throw new InvalidOperationException (); + + AnonymousScopeEntry scope; + lock (this) { + if (anonymous_scopes != null) { + anonymous_scopes.TryGetValue (id, out scope); + return scope; + } + + anonymous_scopes = new Dictionary (); + reader.BaseStream.Position = ot.AnonymousScopeTableOffset; + for (int i = 0; i < ot.AnonymousScopeCount; i++) { + scope = new AnonymousScopeEntry (reader); + anonymous_scopes.Add (scope.ID, scope); + } + + return anonymous_scopes [id]; + } + } + + internal MyBinaryReader BinaryReader { + get { + if (reader == null) + throw new InvalidOperationException (); + + return reader; + } + } + + public void Dispose () + { + Dispose (true); + } + + protected virtual void Dispose (bool disposing) + { + if (disposing) { + if (reader != null) { + reader.Close (); + reader = null; + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs new file mode 100644 index 0000000000..5f30818ff6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs @@ -0,0 +1,1376 @@ +// +// Mono.CSharp.Debugger/MonoSymbolTable.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// (C) 2002 Ximian, Inc. http://www.ximian.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.Security.Cryptography; +using System.Collections.Generic; +using System.Text; +using System.IO; + +// +// Parts which are actually written into the symbol file are marked with +// +// #region This is actually written to the symbol file +// #endregion +// +// Please do not modify these regions without previously talking to me. +// +// All changes to the file format must be synchronized in several places: +// +// a) The fields in these regions (and their order) must match the actual +// contents of the symbol file. +// +// This helps people to understand the symbol file format without reading +// too much source code, ie. you look at the appropriate region and then +// you know what's actually in the file. +// +// It is also required to help me enforce b). +// +// b) The regions must be kept in sync with the unmanaged code in +// mono/metadata/debug-mono-symfile.h +// +// When making changes to the file format, you must also increase two version +// numbers: +// +// i) OffsetTable.Version in this file. +// ii) MONO_SYMBOL_FILE_VERSION in mono/metadata/debug-mono-symfile.h +// +// After doing so, recompile everything, including the debugger. Symbol files +// with different versions are incompatible to each other and the debugger and +// the runtime enfore this, so you need to recompile all your assemblies after +// changing the file format. +// + +namespace Mono.CompilerServices.SymbolWriter +{ + public class OffsetTable + { + public const int MajorVersion = 50; + public const int MinorVersion = 0; + public const long Magic = 0x45e82623fd7fa614; + + #region This is actually written to the symbol file + public int TotalFileSize; + public int DataSectionOffset; + public int DataSectionSize; + public int CompileUnitCount; + public int CompileUnitTableOffset; + public int CompileUnitTableSize; + public int SourceCount; + public int SourceTableOffset; + public int SourceTableSize; + public int MethodCount; + public int MethodTableOffset; + public int MethodTableSize; + public int TypeCount; + public int AnonymousScopeCount; + public int AnonymousScopeTableOffset; + public int AnonymousScopeTableSize; + + [Flags] + public enum Flags + { + IsAspxSource = 1, + WindowsFileNames = 2 + } + + public Flags FileFlags; + + public int LineNumberTable_LineBase = LineNumberTable.Default_LineBase; + public int LineNumberTable_LineRange = LineNumberTable.Default_LineRange; + public int LineNumberTable_OpcodeBase = LineNumberTable.Default_OpcodeBase; + #endregion + + internal OffsetTable () + { + int platform = (int) Environment.OSVersion.Platform; + if ((platform != 4) && (platform != 128)) + FileFlags |= Flags.WindowsFileNames; + } + + internal OffsetTable (BinaryReader reader, int major_version, int minor_version) + { + TotalFileSize = reader.ReadInt32 (); + DataSectionOffset = reader.ReadInt32 (); + DataSectionSize = reader.ReadInt32 (); + CompileUnitCount = reader.ReadInt32 (); + CompileUnitTableOffset = reader.ReadInt32 (); + CompileUnitTableSize = reader.ReadInt32 (); + SourceCount = reader.ReadInt32 (); + SourceTableOffset = reader.ReadInt32 (); + SourceTableSize = reader.ReadInt32 (); + MethodCount = reader.ReadInt32 (); + MethodTableOffset = reader.ReadInt32 (); + MethodTableSize = reader.ReadInt32 (); + TypeCount = reader.ReadInt32 (); + + AnonymousScopeCount = reader.ReadInt32 (); + AnonymousScopeTableOffset = reader.ReadInt32 (); + AnonymousScopeTableSize = reader.ReadInt32 (); + + LineNumberTable_LineBase = reader.ReadInt32 (); + LineNumberTable_LineRange = reader.ReadInt32 (); + LineNumberTable_OpcodeBase = reader.ReadInt32 (); + + FileFlags = (Flags) reader.ReadInt32 (); + } + + internal void Write (BinaryWriter bw, int major_version, int minor_version) + { + bw.Write (TotalFileSize); + bw.Write (DataSectionOffset); + bw.Write (DataSectionSize); + bw.Write (CompileUnitCount); + bw.Write (CompileUnitTableOffset); + bw.Write (CompileUnitTableSize); + bw.Write (SourceCount); + bw.Write (SourceTableOffset); + bw.Write (SourceTableSize); + bw.Write (MethodCount); + bw.Write (MethodTableOffset); + bw.Write (MethodTableSize); + bw.Write (TypeCount); + + bw.Write (AnonymousScopeCount); + bw.Write (AnonymousScopeTableOffset); + bw.Write (AnonymousScopeTableSize); + + bw.Write (LineNumberTable_LineBase); + bw.Write (LineNumberTable_LineRange); + bw.Write (LineNumberTable_OpcodeBase); + + bw.Write ((int) FileFlags); + } + + public override string ToString () + { + return String.Format ( + "OffsetTable [{0} - {1}:{2} - {3}:{4}:{5} - {6}:{7}:{8} - {9}]", + TotalFileSize, DataSectionOffset, DataSectionSize, SourceCount, + SourceTableOffset, SourceTableSize, MethodCount, MethodTableOffset, + MethodTableSize, TypeCount); + } + } + + public class LineNumberEntry + { + #region This is actually written to the symbol file + public readonly int Row; + public readonly int File; + public readonly int Offset; + public readonly bool IsHidden; + #endregion + + public LineNumberEntry (int file, int row, int offset) + : this (file, row, offset, false) + { } + + public LineNumberEntry (int file, int row, int offset, bool is_hidden) + { + this.File = file; + this.Row = row; + this.Offset = offset; + this.IsHidden = is_hidden; + } + + public static LineNumberEntry Null = new LineNumberEntry (0, 0, 0); + + private class OffsetComparerClass : IComparer + { + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + if (l1.Offset < l2.Offset) + return -1; + else if (l1.Offset > l2.Offset) + return 1; + else + return 0; + } + } + + private class RowComparerClass : IComparer + { + public int Compare (LineNumberEntry l1, LineNumberEntry l2) + { + if (l1.Row < l2.Row) + return -1; + else if (l1.Row > l2.Row) + return 1; + else + return 0; + } + } + + public static readonly IComparer OffsetComparer = new OffsetComparerClass (); + public static readonly IComparer RowComparer = new RowComparerClass (); + + public override string ToString () + { + return String.Format ("[Line {0}:{1}:{2}]", File, Row, Offset); + } + } + + public class CodeBlockEntry + { + public int Index; + #region This is actually written to the symbol file + public int Parent; + public Type BlockType; + public int StartOffset; + public int EndOffset; + #endregion + + public enum Type { + Lexical = 1, + CompilerGenerated = 2, + IteratorBody = 3, + IteratorDispatcher = 4 + } + + public CodeBlockEntry (int index, int parent, Type type, int start_offset) + { + this.Index = index; + this.Parent = parent; + this.BlockType = type; + this.StartOffset = start_offset; + } + + internal CodeBlockEntry (int index, MyBinaryReader reader) + { + this.Index = index; + int type_flag = reader.ReadLeb128 (); + BlockType = (Type) (type_flag & 0x3f); + this.Parent = reader.ReadLeb128 (); + this.StartOffset = reader.ReadLeb128 (); + this.EndOffset = reader.ReadLeb128 (); + + /* Reserved for future extensions. */ + if ((type_flag & 0x40) != 0) { + int data_size = reader.ReadInt16 (); + reader.BaseStream.Position += data_size; + } + } + + public void Close (int end_offset) + { + this.EndOffset = end_offset; + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 ((int) BlockType); + bw.WriteLeb128 (Parent); + bw.WriteLeb128 (StartOffset); + bw.WriteLeb128 (EndOffset); + } + + public override string ToString () + { + return String.Format ("[CodeBlock {0}:{1}:{2}:{3}:{4}]", + Index, Parent, BlockType, StartOffset, EndOffset); + } + } + + public struct LocalVariableEntry + { + #region This is actually written to the symbol file + public readonly int Index; + public readonly string Name; + public readonly int BlockIndex; + #endregion + + public LocalVariableEntry (int index, string name, int block) + { + this.Index = index; + this.Name = name; + this.BlockIndex = block; + } + + internal LocalVariableEntry (MonoSymbolFile file, MyBinaryReader reader) + { + Index = reader.ReadLeb128 (); + Name = reader.ReadString (); + BlockIndex = reader.ReadLeb128 (); + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + bw.WriteLeb128 (Index); + bw.Write (Name); + bw.WriteLeb128 (BlockIndex); + } + + public override string ToString () + { + return String.Format ("[LocalVariable {0}:{1}:{2}]", + Name, Index, BlockIndex - 1); + } + } + + public struct CapturedVariable + { + #region This is actually written to the symbol file + public readonly string Name; + public readonly string CapturedName; + public readonly CapturedKind Kind; + #endregion + + public enum CapturedKind : byte + { + Local, + Parameter, + This + } + + public CapturedVariable (string name, string captured_name, + CapturedKind kind) + { + this.Name = name; + this.CapturedName = captured_name; + this.Kind = kind; + } + + internal CapturedVariable (MyBinaryReader reader) + { + Name = reader.ReadString (); + CapturedName = reader.ReadString (); + Kind = (CapturedKind) reader.ReadByte (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.Write (Name); + bw.Write (CapturedName); + bw.Write ((byte) Kind); + } + + public override string ToString () + { + return String.Format ("[CapturedVariable {0}:{1}:{2}]", + Name, CapturedName, Kind); + } + } + + public struct CapturedScope + { + #region This is actually written to the symbol file + public readonly int Scope; + public readonly string CapturedName; + #endregion + + public CapturedScope (int scope, string captured_name) + { + this.Scope = scope; + this.CapturedName = captured_name; + } + + internal CapturedScope (MyBinaryReader reader) + { + Scope = reader.ReadLeb128 (); + CapturedName = reader.ReadString (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (Scope); + bw.Write (CapturedName); + } + + public override string ToString () + { + return String.Format ("[CapturedScope {0}:{1}]", + Scope, CapturedName); + } + } + + public struct ScopeVariable + { + #region This is actually written to the symbol file + public readonly int Scope; + public readonly int Index; + #endregion + + public ScopeVariable (int scope, int index) + { + this.Scope = scope; + this.Index = index; + } + + internal ScopeVariable (MyBinaryReader reader) + { + Scope = reader.ReadLeb128 (); + Index = reader.ReadLeb128 (); + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (Scope); + bw.WriteLeb128 (Index); + } + + public override string ToString () + { + return String.Format ("[ScopeVariable {0}:{1}]", Scope, Index); + } + } + + public class AnonymousScopeEntry + { + #region This is actually written to the symbol file + public readonly int ID; + #endregion + + List captured_vars = new List (); + List captured_scopes = new List (); + + public AnonymousScopeEntry (int id) + { + this.ID = id; + } + + internal AnonymousScopeEntry (MyBinaryReader reader) + { + ID = reader.ReadLeb128 (); + + int num_captured_vars = reader.ReadLeb128 (); + for (int i = 0; i < num_captured_vars; i++) + captured_vars.Add (new CapturedVariable (reader)); + + int num_captured_scopes = reader.ReadLeb128 (); + for (int i = 0; i < num_captured_scopes; i++) + captured_scopes.Add (new CapturedScope (reader)); + } + + internal void AddCapturedVariable (string name, string captured_name, + CapturedVariable.CapturedKind kind) + { + captured_vars.Add (new CapturedVariable (name, captured_name, kind)); + } + + public CapturedVariable[] CapturedVariables { + get { + CapturedVariable[] retval = new CapturedVariable [captured_vars.Count]; + captured_vars.CopyTo (retval, 0); + return retval; + } + } + + internal void AddCapturedScope (int scope, string captured_name) + { + captured_scopes.Add (new CapturedScope (scope, captured_name)); + } + + public CapturedScope[] CapturedScopes { + get { + CapturedScope[] retval = new CapturedScope [captured_scopes.Count]; + captured_scopes.CopyTo (retval, 0); + return retval; + } + } + + internal void Write (MyBinaryWriter bw) + { + bw.WriteLeb128 (ID); + + bw.WriteLeb128 (captured_vars.Count); + foreach (CapturedVariable cv in captured_vars) + cv.Write (bw); + + bw.WriteLeb128 (captured_scopes.Count); + foreach (CapturedScope cs in captured_scopes) + cs.Write (bw); + } + + public override string ToString () + { + return String.Format ("[AnonymousScope {0}]", ID); + } + } + + public class CompileUnitEntry : ICompileUnit + { + #region This is actually written to the symbol file + public readonly int Index; + int DataOffset; + #endregion + + MonoSymbolFile file; + SourceFileEntry source; + List include_files; + List namespaces; + + bool creating; + + public static int Size { + get { return 8; } + } + + CompileUnitEntry ICompileUnit.Entry { + get { return this; } + } + + public CompileUnitEntry (MonoSymbolFile file, SourceFileEntry source) + { + this.file = file; + this.source = source; + + this.Index = file.AddCompileUnit (this); + + creating = true; + namespaces = new List (); + } + + public void AddFile (SourceFileEntry file) + { + if (!creating) + throw new InvalidOperationException (); + + if (include_files == null) + include_files = new List (); + + include_files.Add (file); + } + + public SourceFileEntry SourceFile { + get { + if (creating) + return source; + + ReadData (); + return source; + } + } + + public int DefineNamespace (string name, string[] using_clauses, int parent) + { + if (!creating) + throw new InvalidOperationException (); + + int index = file.GetNextNamespaceIndex (); + NamespaceEntry ns = new NamespaceEntry (name, index, using_clauses, parent); + namespaces.Add (ns); + return index; + } + + internal void WriteData (MyBinaryWriter bw) + { + DataOffset = (int) bw.BaseStream.Position; + bw.WriteLeb128 (source.Index); + + int count_includes = include_files != null ? include_files.Count : 0; + bw.WriteLeb128 (count_includes); + if (include_files != null) { + foreach (SourceFileEntry entry in include_files) + bw.WriteLeb128 (entry.Index); + } + + bw.WriteLeb128 (namespaces.Count); + foreach (NamespaceEntry ns in namespaces) + ns.Write (file, bw); + } + + internal void Write (BinaryWriter bw) + { + bw.Write (Index); + bw.Write (DataOffset); + } + + internal CompileUnitEntry (MonoSymbolFile file, MyBinaryReader reader) + { + this.file = file; + + Index = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + } + + void ReadData () + { + if (creating) + throw new InvalidOperationException (); + + lock (file) { + if (namespaces != null) + return; + + MyBinaryReader reader = file.BinaryReader; + int old_pos = (int) reader.BaseStream.Position; + + reader.BaseStream.Position = DataOffset; + + int source_idx = reader.ReadLeb128 (); + source = file.GetSourceFile (source_idx); + + int count_includes = reader.ReadLeb128 (); + if (count_includes > 0) { + include_files = new List (); + for (int i = 0; i < count_includes; i++) + include_files.Add (file.GetSourceFile (reader.ReadLeb128 ())); + } + + int count_ns = reader.ReadLeb128 (); + namespaces = new List (); + for (int i = 0; i < count_ns; i ++) + namespaces.Add (new NamespaceEntry (file, reader)); + + reader.BaseStream.Position = old_pos; + } + } + + public NamespaceEntry[] Namespaces { + get { + ReadData (); + NamespaceEntry[] retval = new NamespaceEntry [namespaces.Count]; + namespaces.CopyTo (retval, 0); + return retval; + } + } + + public SourceFileEntry[] IncludeFiles { + get { + ReadData (); + if (include_files == null) + return new SourceFileEntry [0]; + + SourceFileEntry[] retval = new SourceFileEntry [include_files.Count]; + include_files.CopyTo (retval, 0); + return retval; + } + } + } + + public class SourceFileEntry + { + #region This is actually written to the symbol file + public readonly int Index; + int DataOffset; + #endregion + + MonoSymbolFile file; + string file_name; + byte[] guid; + byte[] hash; + bool creating; + bool auto_generated; + + public static int Size { + get { return 8; } + } + + public SourceFileEntry (MonoSymbolFile file, string file_name) + { + this.file = file; + this.file_name = file_name; + this.Index = file.AddSource (this); + + creating = true; + } + + public SourceFileEntry (MonoSymbolFile file, string file_name, + byte[] guid, byte[] checksum) + : this (file, file_name) + { + this.guid = guid; + this.hash = checksum; + } + + internal void WriteData (MyBinaryWriter bw) + { + DataOffset = (int) bw.BaseStream.Position; + bw.Write (file_name); + + if (guid == null) { + guid = Guid.NewGuid ().ToByteArray (); + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open, FileAccess.Read)) { + MD5 md5 = MD5.Create (); + hash = md5.ComputeHash (fs); + } + } catch { + hash = new byte [16]; + } + } + + bw.Write (guid); + bw.Write (hash); + bw.Write ((byte) (auto_generated ? 1 : 0)); + } + + internal void Write (BinaryWriter bw) + { + bw.Write (Index); + bw.Write (DataOffset); + } + + internal SourceFileEntry (MonoSymbolFile file, MyBinaryReader reader) + { + this.file = file; + + Index = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + + int old_pos = (int) reader.BaseStream.Position; + reader.BaseStream.Position = DataOffset; + + file_name = reader.ReadString (); + guid = reader.ReadBytes (16); + hash = reader.ReadBytes (16); + auto_generated = reader.ReadByte () == 1; + + reader.BaseStream.Position = old_pos; + } + + public string FileName { + get { return file_name; } + } + + public bool AutoGenerated { + get { return auto_generated; } + } + + public void SetAutoGenerated () + { + if (!creating) + throw new InvalidOperationException (); + + auto_generated = true; + file.OffsetTable.FileFlags |= OffsetTable.Flags.IsAspxSource; + } + + public bool CheckChecksum () + { + try { + using (FileStream fs = new FileStream (file_name, FileMode.Open)) { + MD5 md5 = MD5.Create (); + byte[] data = md5.ComputeHash (fs); + for (int i = 0; i < 16; i++) + if (data [i] != hash [i]) + return false; + return true; + } + } catch { + return false; + } + } + + public override string ToString () + { + return String.Format ("SourceFileEntry ({0}:{1})", Index, DataOffset); + } + } + + public class LineNumberTable + { + protected LineNumberEntry[] _line_numbers; + public LineNumberEntry[] LineNumbers { + get { return _line_numbers; } + } + + public readonly int LineBase; + public readonly int LineRange; + public readonly byte OpcodeBase; + public readonly int MaxAddressIncrement; + +#region Configurable constants + public const int Default_LineBase = -1; + public const int Default_LineRange = 8; + public const byte Default_OpcodeBase = 9; + + public const bool SuppressDuplicates = true; +#endregion + + public const byte DW_LNS_copy = 1; + public const byte DW_LNS_advance_pc = 2; + public const byte DW_LNS_advance_line = 3; + public const byte DW_LNS_set_file = 4; + public const byte DW_LNS_const_add_pc = 8; + + public const byte DW_LNE_end_sequence = 1; + + // MONO extensions. + public const byte DW_LNE_MONO_negate_is_hidden = 0x40; + + internal const byte DW_LNE_MONO__extensions_start = 0x40; + internal const byte DW_LNE_MONO__extensions_end = 0x7f; + + protected LineNumberTable (MonoSymbolFile file) + { + this.LineBase = file.OffsetTable.LineNumberTable_LineBase; + this.LineRange = file.OffsetTable.LineNumberTable_LineRange; + this.OpcodeBase = (byte) file.OffsetTable.LineNumberTable_OpcodeBase; + this.MaxAddressIncrement = (255 - OpcodeBase) / LineRange; + } + + internal LineNumberTable (MonoSymbolFile file, LineNumberEntry[] lines) + : this (file) + { + this._line_numbers = lines; + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + int start = (int) bw.BaseStream.Position; + + bool last_is_hidden = false; + int last_line = 1, last_offset = 0, last_file = 1; + for (int i = 0; i < LineNumbers.Length; i++) { + int line_inc = LineNumbers [i].Row - last_line; + int offset_inc = LineNumbers [i].Offset - last_offset; + + if (SuppressDuplicates && (i+1 < LineNumbers.Length)) { + if (LineNumbers [i+1].Equals (LineNumbers [i])) + continue; + } + + if (LineNumbers [i].File != last_file) { + bw.Write (DW_LNS_set_file); + bw.WriteLeb128 (LineNumbers [i].File); + last_file = LineNumbers [i].File; + } + + if (LineNumbers [i].IsHidden != last_is_hidden) { + bw.Write ((byte) 0); + bw.Write ((byte) 1); + bw.Write (DW_LNE_MONO_negate_is_hidden); + last_is_hidden = LineNumbers [i].IsHidden; + } + + if (offset_inc >= MaxAddressIncrement) { + if (offset_inc < 2 * MaxAddressIncrement) { + bw.Write (DW_LNS_const_add_pc); + offset_inc -= MaxAddressIncrement; + } else { + bw.Write (DW_LNS_advance_pc); + bw.WriteLeb128 (offset_inc); + offset_inc = 0; + } + } + + if ((line_inc < LineBase) || (line_inc >= LineBase + LineRange)) { + bw.Write (DW_LNS_advance_line); + bw.WriteLeb128 (line_inc); + if (offset_inc != 0) { + bw.Write (DW_LNS_advance_pc); + bw.WriteLeb128 (offset_inc); + } + bw.Write (DW_LNS_copy); + } else { + byte opcode; + opcode = (byte) (line_inc - LineBase + (LineRange * offset_inc) + + OpcodeBase); + bw.Write (opcode); + } + + last_line = LineNumbers [i].Row; + last_offset = LineNumbers [i].Offset; + } + + bw.Write ((byte) 0); + bw.Write ((byte) 1); + bw.Write (DW_LNE_end_sequence); + + file.ExtendedLineNumberSize += (int) bw.BaseStream.Position - start; + } + + internal static LineNumberTable Read (MonoSymbolFile file, MyBinaryReader br) + { + LineNumberTable lnt = new LineNumberTable (file); + lnt.DoRead (file, br); + return lnt; + } + + void DoRead (MonoSymbolFile file, MyBinaryReader br) + { + var lines = new List (); + + bool is_hidden = false, modified = false; + int stm_line = 1, stm_offset = 0, stm_file = 1; + while (true) { + byte opcode = br.ReadByte (); + + if (opcode == 0) { + byte size = br.ReadByte (); + long end_pos = br.BaseStream.Position + size; + opcode = br.ReadByte (); + + if (opcode == DW_LNE_end_sequence) { + if (modified) + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + break; + } else if (opcode == DW_LNE_MONO_negate_is_hidden) { + is_hidden = !is_hidden; + modified = true; + } else if ((opcode >= DW_LNE_MONO__extensions_start) && + (opcode <= DW_LNE_MONO__extensions_end)) { + ; // reserved for future extensions + } else { + throw new MonoSymbolFileException ( + "Unknown extended opcode {0:x} in LNT ({1})", + opcode, file.FileName); + } + + br.BaseStream.Position = end_pos; + continue; + } else if (opcode < OpcodeBase) { + switch (opcode) { + case DW_LNS_copy: + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + modified = false; + break; + case DW_LNS_advance_pc: + stm_offset += br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_advance_line: + stm_line += br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_set_file: + stm_file = br.ReadLeb128 (); + modified = true; + break; + case DW_LNS_const_add_pc: + stm_offset += MaxAddressIncrement; + modified = true; + break; + default: + throw new MonoSymbolFileException ( + "Unknown standard opcode {0:x} in LNT", + opcode); + } + } else { + opcode -= OpcodeBase; + + stm_offset += opcode / LineRange; + stm_line += LineBase + (opcode % LineRange); + lines.Add (new LineNumberEntry ( + stm_file, stm_line, stm_offset, is_hidden)); + modified = false; + } + } + + _line_numbers = new LineNumberEntry [lines.Count]; + lines.CopyTo (_line_numbers, 0); + } + + public bool GetMethodBounds (out LineNumberEntry start, out LineNumberEntry end) + { + if (_line_numbers.Length > 1) { + start = _line_numbers [0]; + end = _line_numbers [_line_numbers.Length - 1]; + return true; + } + + start = LineNumberEntry.Null; + end = LineNumberEntry.Null; + return false; + } + } + + public class MethodEntry : IComparable + { + #region This is actually written to the symbol file + public readonly int CompileUnitIndex; + public readonly int Token; + public readonly int NamespaceID; + + int DataOffset; + int LocalVariableTableOffset; + int LineNumberTableOffset; + int CodeBlockTableOffset; + int ScopeVariableTableOffset; + int RealNameOffset; + Flags flags; + #endregion + + int index; + + public Flags MethodFlags { + get { return flags; } + } + + public readonly CompileUnitEntry CompileUnit; + + LocalVariableEntry[] locals; + CodeBlockEntry[] code_blocks; + ScopeVariable[] scope_vars; + LineNumberTable lnt; + string real_name; + + public readonly MonoSymbolFile SymbolFile; + + public int Index { + get { return index; } + set { index = value; } + } + + [Flags] + public enum Flags + { + LocalNamesAmbiguous = 1 + } + + public const int Size = 12; + + internal MethodEntry (MonoSymbolFile file, MyBinaryReader reader, int index) + { + this.SymbolFile = file; + this.index = index; + + Token = reader.ReadInt32 (); + DataOffset = reader.ReadInt32 (); + LineNumberTableOffset = reader.ReadInt32 (); + + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = DataOffset; + + CompileUnitIndex = reader.ReadLeb128 (); + LocalVariableTableOffset = reader.ReadLeb128 (); + NamespaceID = reader.ReadLeb128 (); + + CodeBlockTableOffset = reader.ReadLeb128 (); + ScopeVariableTableOffset = reader.ReadLeb128 (); + + RealNameOffset = reader.ReadLeb128 (); + + flags = (Flags) reader.ReadLeb128 (); + + reader.BaseStream.Position = old_pos; + + CompileUnit = file.GetCompileUnit (CompileUnitIndex); + } + + internal MethodEntry (MonoSymbolFile file, CompileUnitEntry comp_unit, + int token, ScopeVariable[] scope_vars, + LocalVariableEntry[] locals, LineNumberEntry[] lines, + CodeBlockEntry[] code_blocks, string real_name, + Flags flags, int namespace_id) + { + this.SymbolFile = file; + this.real_name = real_name; + this.locals = locals; + this.code_blocks = code_blocks; + this.scope_vars = scope_vars; + this.flags = flags; + + index = -1; + + Token = token; + CompileUnitIndex = comp_unit.Index; + CompileUnit = comp_unit; + NamespaceID = namespace_id; + + CheckLineNumberTable (lines); + lnt = new LineNumberTable (file, lines); + file.NumLineNumbers += lines.Length; + + int num_locals = locals != null ? locals.Length : 0; + + if (num_locals <= 32) { + // Most of the time, the O(n^2) factor is actually + // less than the cost of allocating the hash table, + // 32 is a rough number obtained through some testing. + + for (int i = 0; i < num_locals; i ++) { + string nm = locals [i].Name; + + for (int j = i + 1; j < num_locals; j ++) { + if (locals [j].Name == nm) { + flags |= Flags.LocalNamesAmbiguous; + goto locals_check_done; + } + } + } + locals_check_done : + ; + } else { + var local_names = new Dictionary (); + foreach (LocalVariableEntry local in locals) { + if (local_names.ContainsKey (local.Name)) { + flags |= Flags.LocalNamesAmbiguous; + break; + } + local_names.Add (local.Name, local); + } + } + } + + void CheckLineNumberTable (LineNumberEntry[] line_numbers) + { + int last_offset = -1; + int last_row = -1; + + if (line_numbers == null) + return; + + for (int i = 0; i < line_numbers.Length; i++) { + LineNumberEntry line = line_numbers [i]; + + if (line.Equals (LineNumberEntry.Null)) + throw new MonoSymbolFileException (); + + if (line.Offset < last_offset) + throw new MonoSymbolFileException (); + + if (line.Offset > last_offset) { + last_row = line.Row; + last_offset = line.Offset; + } else if (line.Row > last_row) { + last_row = line.Row; + } + } + } + + internal void Write (MyBinaryWriter bw) + { + if ((index <= 0) || (DataOffset == 0)) + throw new InvalidOperationException (); + + bw.Write (Token); + bw.Write (DataOffset); + bw.Write (LineNumberTableOffset); + } + + internal void WriteData (MonoSymbolFile file, MyBinaryWriter bw) + { + if (index <= 0) + throw new InvalidOperationException (); + + LocalVariableTableOffset = (int) bw.BaseStream.Position; + int num_locals = locals != null ? locals.Length : 0; + bw.WriteLeb128 (num_locals); + for (int i = 0; i < num_locals; i++) + locals [i].Write (file, bw); + file.LocalCount += num_locals; + + CodeBlockTableOffset = (int) bw.BaseStream.Position; + int num_code_blocks = code_blocks != null ? code_blocks.Length : 0; + bw.WriteLeb128 (num_code_blocks); + for (int i = 0; i < num_code_blocks; i++) + code_blocks [i].Write (bw); + + ScopeVariableTableOffset = (int) bw.BaseStream.Position; + int num_scope_vars = scope_vars != null ? scope_vars.Length : 0; + bw.WriteLeb128 (num_scope_vars); + for (int i = 0; i < num_scope_vars; i++) + scope_vars [i].Write (bw); + + if (real_name != null) { + RealNameOffset = (int) bw.BaseStream.Position; + bw.Write (real_name); + } + + LineNumberTableOffset = (int) bw.BaseStream.Position; + lnt.Write (file, bw); + + DataOffset = (int) bw.BaseStream.Position; + + bw.WriteLeb128 (CompileUnitIndex); + bw.WriteLeb128 (LocalVariableTableOffset); + bw.WriteLeb128 (NamespaceID); + + bw.WriteLeb128 (CodeBlockTableOffset); + bw.WriteLeb128 (ScopeVariableTableOffset); + + bw.WriteLeb128 (RealNameOffset); + bw.WriteLeb128 ((int) flags); + } + + public LineNumberTable GetLineNumberTable () + { + lock (SymbolFile) { + if (lnt != null) + return lnt; + + if (LineNumberTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = LineNumberTableOffset; + + lnt = LineNumberTable.Read (SymbolFile, reader); + + reader.BaseStream.Position = old_pos; + return lnt; + } + } + + public LocalVariableEntry[] GetLocals () + { + lock (SymbolFile) { + if (locals != null) + return locals; + + if (LocalVariableTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = LocalVariableTableOffset; + + int num_locals = reader.ReadLeb128 (); + locals = new LocalVariableEntry [num_locals]; + + for (int i = 0; i < num_locals; i++) + locals [i] = new LocalVariableEntry (SymbolFile, reader); + + reader.BaseStream.Position = old_pos; + return locals; + } + } + + public CodeBlockEntry[] GetCodeBlocks () + { + lock (SymbolFile) { + if (code_blocks != null) + return code_blocks; + + if (CodeBlockTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = CodeBlockTableOffset; + + int num_code_blocks = reader.ReadLeb128 (); + code_blocks = new CodeBlockEntry [num_code_blocks]; + + for (int i = 0; i < num_code_blocks; i++) + code_blocks [i] = new CodeBlockEntry (i, reader); + + reader.BaseStream.Position = old_pos; + return code_blocks; + } + } + + public ScopeVariable[] GetScopeVariables () + { + lock (SymbolFile) { + if (scope_vars != null) + return scope_vars; + + if (ScopeVariableTableOffset == 0) + return null; + + MyBinaryReader reader = SymbolFile.BinaryReader; + long old_pos = reader.BaseStream.Position; + reader.BaseStream.Position = ScopeVariableTableOffset; + + int num_scope_vars = reader.ReadLeb128 (); + scope_vars = new ScopeVariable [num_scope_vars]; + + for (int i = 0; i < num_scope_vars; i++) + scope_vars [i] = new ScopeVariable (reader); + + reader.BaseStream.Position = old_pos; + return scope_vars; + } + } + + public string GetRealName () + { + lock (SymbolFile) { + if (real_name != null) + return real_name; + + if (RealNameOffset == 0) + return null; + + real_name = SymbolFile.BinaryReader.ReadString (RealNameOffset); + return real_name; + } + } + + public int CompareTo (object obj) + { + MethodEntry method = (MethodEntry) obj; + + if (method.Token < Token) + return 1; + else if (method.Token > Token) + return -1; + else + return 0; + } + + public override string ToString () + { + return String.Format ("[Method {0}:{1:x}:{2}:{3}]", + index, Token, CompileUnitIndex, CompileUnit); + } + } + + public struct NamespaceEntry + { + #region This is actually written to the symbol file + public readonly string Name; + public readonly int Index; + public readonly int Parent; + public readonly string[] UsingClauses; + #endregion + + public NamespaceEntry (string name, int index, string[] using_clauses, int parent) + { + this.Name = name; + this.Index = index; + this.Parent = parent; + this.UsingClauses = using_clauses != null ? using_clauses : new string [0]; + } + + internal NamespaceEntry (MonoSymbolFile file, MyBinaryReader reader) + { + Name = reader.ReadString (); + Index = reader.ReadLeb128 (); + Parent = reader.ReadLeb128 (); + + int count = reader.ReadLeb128 (); + UsingClauses = new string [count]; + for (int i = 0; i < count; i++) + UsingClauses [i] = reader.ReadString (); + } + + internal void Write (MonoSymbolFile file, MyBinaryWriter bw) + { + bw.Write (Name); + bw.WriteLeb128 (Index); + bw.WriteLeb128 (Parent); + bw.WriteLeb128 (UsingClauses.Length); + foreach (string uc in UsingClauses) + bw.Write (uc); + } + + public override string ToString () + { + return String.Format ("[Namespace {0}:{1}:{2}]", Name, Index, Parent); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs new file mode 100644 index 0000000000..4d6d1f3d2d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs @@ -0,0 +1,403 @@ +// +// Mono.CSharp.Debugger/MonoSymbolWriter.cs +// +// Author: +// Martin Baulig (martin@ximian.com) +// +// This is the default implementation of the System.Diagnostics.SymbolStore.ISymbolWriter +// interface. +// +// (C) 2002 Ximian, Inc. http://www.ximian.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.Runtime.CompilerServices; +using System.Collections.Generic; +using System.IO; + +namespace Mono.CompilerServices.SymbolWriter +{ + public class MonoSymbolWriter + { + List methods; + List sources; + List comp_units; + protected readonly MonoSymbolFile file; + string filename; + + private SourceMethodBuilder current_method; +#if NET_2_1 + System.Collections.Stack current_method_stack = new System.Collections.Stack (); +#else + Stack current_method_stack = new Stack (); +#endif + + public MonoSymbolWriter (string filename) + { + this.methods = new List (); + this.sources = new List (); + this.comp_units = new List (); + this.file = new MonoSymbolFile (); + + this.filename = filename + ".mdb"; + } + + public MonoSymbolFile SymbolFile { + get { return file; } + } + + public void CloseNamespace () + { } + + public void DefineLocalVariable (int index, string name) + { + if (current_method == null) + return; + + current_method.AddLocal (index, name); + } + + public void DefineCapturedLocal (int scope_id, string name, string captured_name) + { + file.DefineCapturedVariable (scope_id, name, captured_name, + CapturedVariable.CapturedKind.Local); + } + + public void DefineCapturedParameter (int scope_id, string name, string captured_name) + { + file.DefineCapturedVariable (scope_id, name, captured_name, + CapturedVariable.CapturedKind.Parameter); + } + + public void DefineCapturedThis (int scope_id, string captured_name) + { + file.DefineCapturedVariable (scope_id, "this", captured_name, + CapturedVariable.CapturedKind.This); + } + + public void DefineCapturedScope (int scope_id, int id, string captured_name) + { + file.DefineCapturedScope (scope_id, id, captured_name); + } + + public void DefineScopeVariable (int scope, int index) + { + if (current_method == null) + return; + + current_method.AddScopeVariable (scope, index); + } + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, + bool is_hidden) + { + if (current_method == null) + return; + + current_method.MarkSequencePoint (offset, file, line, column, is_hidden); + } + + public SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, IMethodDef method) + { + SourceMethodBuilder builder = new SourceMethodBuilder (file, ns_id, method); + current_method_stack.Push (current_method); + current_method = builder; + methods.Add (current_method); + return builder; + } + + public void CloseMethod () + { + current_method = (SourceMethodBuilder) current_method_stack.Pop (); + } + + public SourceFileEntry DefineDocument (string url) + { + SourceFileEntry entry = new SourceFileEntry (file, url); + sources.Add (entry); + return entry; + } + + public SourceFileEntry DefineDocument (string url, byte[] guid, byte[] checksum) + { + SourceFileEntry entry = new SourceFileEntry (file, url, guid, checksum); + sources.Add (entry); + return entry; + } + + public CompileUnitEntry DefineCompilationUnit (SourceFileEntry source) + { + CompileUnitEntry entry = new CompileUnitEntry (file, source); + comp_units.Add (entry); + return entry; + } + + public int DefineNamespace (string name, CompileUnitEntry unit, + string[] using_clauses, int parent) + { + if ((unit == null) || (using_clauses == null)) + throw new NullReferenceException (); + + return unit.DefineNamespace (name, using_clauses, parent); + } + + public int OpenScope (int start_offset) + { + if (current_method == null) + return 0; + + current_method.StartBlock (CodeBlockEntry.Type.Lexical, start_offset); + return 0; + } + + public void CloseScope (int end_offset) + { + if (current_method == null) + return; + + current_method.EndBlock (end_offset); + } + + public void OpenCompilerGeneratedBlock (int start_offset) + { + if (current_method == null) + return; + + current_method.StartBlock (CodeBlockEntry.Type.CompilerGenerated, + start_offset); + } + + public void CloseCompilerGeneratedBlock (int end_offset) + { + if (current_method == null) + return; + + current_method.EndBlock (end_offset); + } + + public void StartIteratorBody (int start_offset) + { + current_method.StartBlock (CodeBlockEntry.Type.IteratorBody, + start_offset); + } + + public void EndIteratorBody (int end_offset) + { + current_method.EndBlock (end_offset); + } + + public void StartIteratorDispatcher (int start_offset) + { + current_method.StartBlock (CodeBlockEntry.Type.IteratorDispatcher, + start_offset); + } + + public void EndIteratorDispatcher (int end_offset) + { + current_method.EndBlock (end_offset); + } + + public void DefineAnonymousScope (int id) + { + file.DefineAnonymousScope (id); + } + + public void WriteSymbolFile (Guid guid) + { + foreach (SourceMethodBuilder method in methods) + method.DefineMethod (file); + + try { + // We mmap the file, so unlink the previous version since it may be in use + File.Delete (filename); + } catch { + // We can safely ignore + } + using (FileStream fs = new FileStream (filename, FileMode.Create, FileAccess.Write)) { + file.CreateSymbolFile (guid, fs); + } + } + } + + public class SourceMethodBuilder + { + List _locals; + List _blocks; + List _scope_vars; +#if NET_2_1 + System.Collections.Stack _block_stack; +#else + Stack _block_stack; +#endif + string _real_name; + IMethodDef _method; + ICompileUnit _comp_unit; +// MethodEntry.Flags _method_flags; + int _ns_id; + + public SourceMethodBuilder (ICompileUnit comp_unit, int ns_id, IMethodDef method) + { + this._comp_unit = comp_unit; + this._method = method; + this._ns_id = ns_id; + + method_lines = new LineNumberEntry [32]; + } + + private LineNumberEntry [] method_lines; + private int method_lines_pos = 0; + + public void MarkSequencePoint (int offset, SourceFileEntry file, int line, int column, + bool is_hidden) + { + if (method_lines_pos == method_lines.Length) { + LineNumberEntry [] tmp = method_lines; + method_lines = new LineNumberEntry [method_lines.Length * 2]; + Array.Copy (tmp, method_lines, method_lines_pos); + } + + int file_idx = file != null ? file.Index : 0; + method_lines [method_lines_pos++] = new LineNumberEntry ( + file_idx, line, offset, is_hidden); + } + + public void StartBlock (CodeBlockEntry.Type type, int start_offset) + { + if (_block_stack == null) { +#if NET_2_1 + _block_stack = new System.Collections.Stack (); +#else + _block_stack = new Stack (); +#endif + } + + if (_blocks == null) + _blocks = new List (); + + int parent = CurrentBlock != null ? CurrentBlock.Index : -1; + + CodeBlockEntry block = new CodeBlockEntry ( + _blocks.Count + 1, parent, type, start_offset); + + _block_stack.Push (block); + _blocks.Add (block); + } + + public void EndBlock (int end_offset) + { + CodeBlockEntry block = (CodeBlockEntry) _block_stack.Pop (); + block.Close (end_offset); + } + + public CodeBlockEntry[] Blocks { + get { + if (_blocks == null) + return new CodeBlockEntry [0]; + + CodeBlockEntry[] retval = new CodeBlockEntry [_blocks.Count]; + _blocks.CopyTo (retval, 0); + return retval; + } + } + + public CodeBlockEntry CurrentBlock { + get { + if ((_block_stack != null) && (_block_stack.Count > 0)) + return (CodeBlockEntry) _block_stack.Peek (); + else + return null; + } + } + + public LocalVariableEntry[] Locals { + get { + if (_locals == null) + return new LocalVariableEntry [0]; + else { + LocalVariableEntry[] retval = + new LocalVariableEntry [_locals.Count]; + _locals.CopyTo (retval, 0); + return retval; + } + } + } + + public void AddLocal (int index, string name) + { + if (_locals == null) + _locals = new List (); + int block_idx = CurrentBlock != null ? CurrentBlock.Index : 0; + _locals.Add (new LocalVariableEntry (index, name, block_idx)); + } + + public ScopeVariable[] ScopeVariables { + get { + if (_scope_vars == null) + return new ScopeVariable [0]; + + ScopeVariable[] retval = new ScopeVariable [_scope_vars.Count]; + _scope_vars.CopyTo (retval); + return retval; + } + } + + public void AddScopeVariable (int scope, int index) + { + if (_scope_vars == null) + _scope_vars = new List (); + _scope_vars.Add ( + new ScopeVariable (scope, index)); + } + + public string RealMethodName { + get { return _real_name; } + } + + public void SetRealMethodName (string name) + { + _real_name = name; + } + + public ICompileUnit SourceFile { + get { return _comp_unit; } + } + + public IMethodDef Method { + get { return _method; } + } + + public void DefineMethod (MonoSymbolFile file) + { + LineNumberEntry[] lines = new LineNumberEntry [method_lines_pos]; + Array.Copy (method_lines, lines, method_lines_pos); + + MethodEntry entry = new MethodEntry ( + file, _comp_unit.Entry, _method.Token, ScopeVariables, + Locals, lines, Blocks, RealMethodName, 0, //_method_flags, + _ns_id); + + file.AddMethod (entry); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES new file mode 100644 index 0000000000..ccae274939 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES @@ -0,0 +1,38 @@ +* Notes on improving error handling in MCS + (from Axel Schreiner ) + + +I included the 'recover' example with C# as well. Currently the package +is at . I did change some +names and the embedding that the user does somewhat, i.e., it is not +directly compatible with what you did. + +Here is the important part about error recovery. To make the typical +iterations bullet-proof, code them as follows: + +opt : // null + | opt WORD { yyErrorFlag = 0; } + | opt error + +seq : WORD + | seq WORD { yyErrorFlag = 0; } + | error + | seq error + +list : WORD + | list ',' WORD { yyErrorFlag = 0; } + | error + | list error + | list error WORD { yyErrorFlag = 0; } + | list ',' error + +i.e., throw in 'error' wherever a token can be. 'yyErrorFlag' need not +be set to zero, but if it is done this way, second errors are caught +earlier. This may introduce s/r conflicts, but they tend to be harmless. + +In your case -- the comment concerning error recovery at the beginning +of your compiler jay file -- just adding 'error' to the different +global things won't work. Your example will already have started to +advance in one of the rules and 'error' is then not in the lookahead of +wherever the parse then is. You need to put 'error' into the iteration +above those global things. \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE new file mode 100644 index 0000000000..6fa1e31e94 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE @@ -0,0 +1,26 @@ +This document describes all code optimalizations performed by Mono C# compiler +when optimalizations are enabled via /optimize+ option. + +Optimalizations: + +* Instance field initializer to default value +--------------------------------------------- + +Code to optimize: + +class C +{ + enum E + { + Test + } + + int i = 0; // Field will not be redundantly assigned + int i2 = new int (); // This will be also completely optimized out + + E e = E.Test; // Even this will go out. + +} + + + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO new file mode 100644 index 0000000000..ee2cc56f83 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO @@ -0,0 +1,239 @@ +---- This is a list of old tasks, just here for historical value ---- + +Open question: + Create a toplevel block for anonymous methods? + +Anonymous Methods +----------------- + + Plan: + + * Resolve anonymous methods before. + * Each time a Local matches, if the mode is `InAnonymous', flag + the VariableInfo for `proxying'. + * During Resolve track the depth required for local variables. + * Before Emit, create proxy classes with proper depth. + * Emit. + +Notes on memory allocation +-------------------------- + + Outdated: + + A run of the AllocationProfile shows that the compiler allocates roughly + 30 megabytes of strings. From those, 20 megabytes come from + LookupType. + + See the notes on current_container problems below on memory usage. + +LookupTypeReflection: +--------------------- + + With something like `System.Object', LookupTypeReflection will be called + twice: once to find out that `System' is not a type and once + for System.Object. + + This is required because System.Reflection requires that the type/nested types are + not separated by a dot but by a plus sign. + + A nested class would be My+Class (My being the toplevel, Class the nested one). + + It is interesting to look at the most called lookups when bootstrapping MCS: + + 647 LTR: ArrayList + 713 LTR: System.Globalization + 822 LTR: System.Object+Expression + 904 LTR: Mono.CSharp.ArrayList + 976 LTR: System.Runtime.CompilerServices + 999 LTR: Type + 1118 LTR: System.Runtime + 1208 LTR: Mono.CSharp.Type + 1373 LTR: Mono.Languages + 1599 LTR: System.Diagnostics + 2036 LTR: System.Text + 2302 LTR: System.Reflection.Emit + 2515 LTR: System.Collections + 4527 LTR: System.Reflection + 22273 LTR: Mono.CSharp + 24245 LTR: System + 27005 LTR: Mono + + Analysis: + The top 9 lookups are done for things which are not types. + + Mono.CSharp.Type happens to be a common lookup: the class Type + used heavily in the compiler in the default namespace. + + RED FLAG: + + Then `Type' is looked up alone a lot of the time, this happens + in parameter declarations and am not entirely sure that this is + correct (FindType will pass to LookupInterfaceOrClass a the current_type.FullName, + which for some reason is null!). This seems to be a problem with a lost + piece of context during FindType. + + System.Object is also used a lot as a toplevel class, and we assume it will + have children, we should just shortcut this. + + A cache: + + Adding a cache and adding a catch for `System.Object' to flag that it wont be the + root of a hierarchy reduced the MCS bootstrap time from 10.22 seconds to 8.90 seconds. + + This cache is currently enabled with SIMPLE_SPEEDUP in typemanager.cs. Memory consumption + went down from 74 megs to 65 megs with this change. + +Major tasks: +------------ + + Pinned and volatile require type modifiers that can not be encoded + with Reflection.Emit. + +* Revisit + + Primary-expression, as it has now been split into + non-array-creation-expression and array-creation-expression. + +* Emit `pinned' for pinned local variables. + + Both `modreq' and pinned will require special hacks in the compiler. + +* Make sure that we are pinning the right variable + +* local_variable_declaration + + Not sure that this grammar is correct, we might have to + resolve this during semantic analysis. + +* Optimizations + + In Indexers and Properties, probably support an EmitWithDup + That emits the code to call Get and then leaves a this pointer + in the stack, so that later a Store can be emitted using that + this pointer (consider Property++ or Indexer++) + +* Use of local temporary in UnaryMutator + + We should get rid of the Localtemporary there for some cases + + This turns out to be very complex, at least for the post-version, + because this case: + + a = i++ + + To produce optimal code, it is necessary for UnaryMutator to know + that it is being assigned to a variable (the way the stack is laid + out using dup requires the store to happen inside UnaryMutator). + +* Interface indexers + + I have not figured out why the Microsoft version puts an + `instance' attribute, and I am not generating this `instance' attribute. + + Explanation: The reason for the `instance' attribute on + indexers is that indexers only apply to instances + +* Check for Final when overriding, if the parent is Final, then we cant + allow an override. + + Implement base indexer access. + +current_container/current_namespace and the DeclSpace +----------------------------------------------------- + + We are storing fully qualified names in the DeclSpace instead of the node, + this is because `current_namespace' (Namepsace) is not a DeclSpace like + `current_container'. + + The reason for storing the full names today is this: + + namespace X { + class Y { + } + } + + namespace A { + class Y { + } + } + + The problem is that we only use the namespace stack to track the "prefix" + for typecontainers, but they are not typecontainers themselves, so we have + to use fully qualified names, because both A.X and A.Y would be entered + in the toplevel type container. If we use the short names, there would be + a name clash. + + To fix this problem, we have to make namespaces DeclSpaces. + + The full size, contrasted with the size that could be stored is: + corlib: + Size of strings held: 368901 + Size of strings short: 147863 + + System: + Size of strings held: 212677 + Size of strings short: 97521 + + System.XML: + Size of strings held: 128055 + Size of strings short: 35782 + + System.Data: + Size of strings held: 117896 + Size of strings short: 36153 + + System.Web: + Size of strings held: 194527 + Size of strings short: 58064 + + System.Windows.Forms: + Size of strings held: 220495 + Size of strings short: 64923 + + +The use of DottedName +--------------------- + + We could probably use a different system to represent names, like this: + + class Name { + string simplename; + Name parent; + } + + So `System.ComponentModel' becomes: + + x: (System, null) + y: (ComponentModel, x) + + The problem is that we would still need to construct the name to pass to + GetType. + + This has been now implemented, its called "QualifiedIdentifier" + +TODO: + + 1. Create a "partial" emit context for each TypeContainer.. + + 2. EmitContext should be partially constructed. No IL Generator. + + interface_type review. + + parameter_array, line 952: `note: must be a single dimension array type'. Validate this + +Instance idea +------------- + + It would be nice to have things that can be "instances" to have an + EmitInstance method (this would default to nothing). + + The idea is to be able to use efficiently the instance data on stack + manipulations, as opposed to the current scheme, where we basically have + a few special cases. + + * `yield' is no longer a keyword, it only has special + meaning before a return or break keywords. + + * Study side effects with assign + * Study TemporaryStorage/LocalStorage -> Merge/rename + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN new file mode 100644 index 0000000000..dc8324c3d5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN @@ -0,0 +1,66 @@ +Clean Up +-------- + + Move MapVariable from CodeGen into Block? + +Improve test: + + Necesitamos que a-capture8.cs pruebe si la asignacion funciona o no. + +Audit: + + Al emitir instancias de variables + (EmitCaptureVariableInstance) parece ser que el loop de iteracion: + + while (si.ScopeBlock.ID != li.Block.ID) + + está mas actulizado que el codigo similar para parámetros, es posible + que sea bitrot de parámetros o que en los parámetros usamos otra estrategia + (lo segundo es más razonable). + +Iteradores: + + En algún lugar no pongo el `FieldBuilder' a un valor con los + iteradores, ver expression.cs: 3616, local_info.FieldBuilder es nulo. + +Parameters: + + a-parameter4.cs falla por que no se liga el método anónimo + anidado con el padre. + +Cleanup: + + CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name); + if (cc != this){ + cc.EmitParameter (ec, name); + return; + } + + That should be a static method, and call the instance method + in the right CaptureContext, instead of having the CaptureContext + compute that itself. + +MakePinned is gone: + + Need to audit the code now that use DeclareLocal, and that this uses + a differnent code path than the main mcs. + +Need to fix the order in which types are closed: currently we are not +compatible with the MS requirement that the parent has to be created +before the children are. + +Tests and pending features: + + Switch statement is broken (because it uses ILGenerator during + the Resolve phase, which with the `anonymous' branch is no longer + the case: so we have to delay the creation of labels until they + are needed, during the Emit phase). + +Validation: + + For testing, set ec.IG == null during resolve, restore value + for emit. + + Currently it is commented out: there is a bug in the + statement.cs changes (see the old-statement.cs, the compiler + fails during bootstrap) diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README new file mode 100644 index 0000000000..f7023e675c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/README @@ -0,0 +1,72 @@ +Completion support +================== + + Supported: + + a. to complete members of type `a' + a for types and namespaces + a.W + a for local variables + + Unsupported: + + delegate { FOO. + using statement autocompletion + +These are the sources to the Mono C# compiler +--------------------------------------------- + + Read the mcs/docs/compiler.txt for an overview of the compiler. + +Testing the Compiler +-------------------- + + You might want to use the `make btest' in this directory to + have the compiler bootstrap itself, this is the basic regression + test. + + Before commiting changes to MCS, make sure that all the tests + in `mcs/tests' pass, and all the tests in 'mcs/errors' have the + expected result, type: + + cd mcs # The top-level 'mcs' directory + make compiler-tests + + If you want to test the installed compiler, you can run: + + cd mcs # The top-level 'mcs' directory + make test-installed-compiler + +Full Bootstrap +============== + + To finally ensure the state of the compiler, it is ideal to do + a full bootstrap, to do this, do: + + cd mcs + make clean; + make + make install + + That installs the compiler and assemblies compiled by the new compiler. + + Then, repeat that step again: + + make clean + make + + If things work, the compiler has not added a new regression + while building the mscorlib and the compiler itself. + +Tests +===== + + When bugs are fixed, new tests must be added to the + `mcs/tests' directory to excercise the problem and to guarantee + that we keep the compiler in a good state. + + When an error is reported, it should be added to mcs/errors. + + We try to make the errors numbers be the same as the ones in + Microsoft C#, if this is not possible, allocate a negative error + number, and list it in mcs/errors/errors.txt diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO new file mode 100644 index 0000000000..1abb0382b7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO @@ -0,0 +1,223 @@ +=========================================== + +* Value Parameter + + I believe that `Value Parameter' might have been introduced + after C# 1.0, also notice than in the treatment of Value Parameter + the parameters are defined in four categories: + + Section 9.3 in the latest spec. + + +Large project: +-------------- + +New +--- + + It would be nice to optimize the case of: + + Method (new ValueType ()) + + So that no temporary is created, and we only use a newobj call + that remains on the stack, as opposed to ldloca, initobj, ldloc + call. + +NEW NOTES: +---------- + + ImplicitStandardConversionExists and ImplicitStandardConversion + should always be the same, but there are a few diverging lines that + must be studied: + + if (expr_type == target_type && !(expr is NullLiteral)) + return expr; + + vs: + + if (expr_type == target_type) + return true; + +**************************************************************************************** +* +* The information on the rest of this file is mostly outdated, and its kept here for +* historical reasons +* +**************************************************************************************** + +Error Reporting: +---------------- + + * Make yyerror show a nice syntax error, instead of the current mess. + +Optimization ideas +------------------ + + Currently when we build a type cache, it contains private members, + internal members, and internal protected members; We should trim + these out, as it shows up on the profile. + + We create too many Arraylists; When we know the size, we should create + an array; + + During parsing we use arraylists to accumulate data, like this: + + thing: + + thing_list + : thing { $$ =new ArrayList (); $$.Add ($1); } + | thing_list thing { ArrayList a = $1; a.Add ($2); $$ = a; } + + We probably could start using "Pairs" there: + + thing_list + : thing { $$ = new Pair ($1, null); } + | thing_list thing { Pair p = $1; $$ = new Pair ($2, $1); } + + +EmitContext.ResolveTypeTree +--------------------------- + + We should investigate its usage. The problem is that by default + this will be set when calling FindType, that triggers a more expensive + lookup. + + I believe we should pass the current EmitContext (which has this turned off + by default) to ResolveType/REsolveTypeExpr and then have the routines that + need ResolveType to pass null as the emit context. + +DeclareLocal audit +------------------ + + DeclareLocal is used in various statements. The audit should be done + in two steps: + + * Identify all the declare locals. + + * Identify its uses. + + * Find if we can make wrapper functions for all of them. + + Then we can move DeclareLocal into a helper class. + + This is required to fix foreach in iterators. + +Ideas: +------ + + Instead of the hack that *knows* about System.Object not having any children classes, + we should just make it simple for a probe to know that there is no need for it. + +Dead Code Elimination bugs: +--------------------------- + + I should also resolve all the children expressions in Switch, Fixed, Using. + +Major tasks: +------------ + Properties and 17.6.3: Finish it. + +readonly variables and ref/out + +BUGS +---- + +* Break/Continue statements + + A finally block should reset the InLoop/LoopBegin/LoopEnd, as + they are logically outside the scope of the loop. + +* Break/continue part 2. + + They should transfer control to the finally block if inside a try/catch + block. + +* +> // CSC sets beforefieldinit +> class X { +> // .cctor will be generated by compiler +> public static readonly object O = new System.Object (); +> public static void Main () {} +> } +> + +PENDING TASKS +------------- + +* Merge test 89 and test-34 + +* Code cleanup + + The information when registering a method in InternalParameters + is duplicated, you can always get the types from the InternalParameters + +* Emit modreq for volatiles + + Handle modreq from public apis. + +* Merge tree.cs, rootcontext.cs + +OPTIMIZATIONS +------------- + +* User Defined Conversions is doing way too many calls to do union sets that are not needed + +* Add test case for destructors + +* Places that use `Ldelema' are basically places where I will be + initializing a value type. I could apply an optimization to + disable the implicit local temporary from being created (by using + the method in New). + +* Dropping TypeContainer as an argument to EmitContext + + My theory is that I can get rid of the TypeBuilder completely from + the EmitContext, and have typecasts where it is used (from + DeclSpace to where it matters). + + The only pending problem is that the code that implements Aliases + is on TypeContainer, and probably should go in DeclSpace. + +* Tests + + Write tests for the various reference conversions. We have + test for all the numeric conversions. + +* Optimizations: variable allocation. + + When local variables of a type are required, we should request + the variable and later release it when we are done, so that + the same local variable slot can be reused later on. + +* Add a cache for the various GetArrayMethod operations. + +* MakeUnionSet Callers + + If the types are the same, there is no need to compute the unionset, + we can just use the list from one of the types. + +* Factor the lookup code for class declarations an interfaces + (interface.cs:GetInterfaceByName) + +RECOMMENDATIONS +--------------- + +* Use of lexer.Location in the parser + + Currently we do: + + TOKEN nt TERMINAL nt TERMINAL nt3 { + $$ = new Blah ($2, $4, $6, lexer.Location); + } + + This is bad, because the lexer.Location is for the last item in `nt3' + + We need to change that to use this pattern: + + TOKEN { oob_stack.Push (lexer.Location) } nt TERMINAL nt TERMINAL nt3 { + $$ = new Blah ($3, $5, $7, (Location) oob_stack.Pop ()); + } + + Notice how numbering of the arguments changes as the + { oob_stack.Push (lexer.Location) } takes a "slot" in the productions. + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs new file mode 100644 index 0000000000..5576bcc5f6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs @@ -0,0 +1,2038 @@ +// +// anonymous.cs: Support for anonymous methods and types +// +// Author: +// Miguel de Icaza (miguel@ximain.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + public abstract class CompilerGeneratedClass : Class + { + protected CompilerGeneratedClass (TypeContainer parent, MemberName name, Modifiers mod) + : base (parent.NamespaceEntry, parent, name, mod | Modifiers.COMPILER_GENERATED, null) + { + } + + protected void CheckMembersDefined () + { + if (HasMembersDefined) + throw new InternalErrorException ("Helper class already defined!"); + } + + protected static MemberName MakeMemberName (MemberBase host, string name, int unique_id, TypeParameter[] tparams, Location loc) + { + string host_name = host == null ? null : host.Name; + string tname = MakeName (host_name, "c", name, unique_id); + TypeArguments args = null; + if (tparams != null) { + args = new TypeArguments (); + foreach (TypeParameter tparam in tparams) + args.Add (new TypeParameterName (tparam.Name, null, loc)); + } + + return new MemberName (tname, args, loc); + } + + public static string MakeName (string host, string typePrefix, string name, int id) + { + return "<" + host + ">" + typePrefix + "__" + name + id.ToString ("X"); + } + } + + public class HoistedStoreyClass : CompilerGeneratedClass + { + public sealed class HoistedField : Field + { + public HoistedField (HoistedStoreyClass parent, FullNamedExpression type, Modifiers mod, string name, + Attributes attrs, Location loc) + : base (parent, type, mod, new MemberName (name, loc), attrs) + { + } + + protected override bool ResolveMemberType () + { + if (!base.ResolveMemberType ()) + return false; + + HoistedStoreyClass parent = ((HoistedStoreyClass) Parent).GetGenericStorey (); + if (parent != null && parent.Mutator != null) + member_type = parent.Mutator.Mutate (MemberType); + + return true; + } + } + + protected TypeParameterMutator mutator; + + public HoistedStoreyClass (TypeContainer parent, MemberName name, TypeParameter[] tparams, Modifiers mod) + : base (parent, name, mod | Modifiers.PRIVATE) + { + if (tparams != null) { + type_params = new TypeParameter[tparams.Length]; + var src = new TypeParameterSpec[tparams.Length]; + var dst = new TypeParameterSpec[tparams.Length]; + + for (int i = 0; i < type_params.Length; ++i) { + type_params[i] = tparams[i].CreateHoistedCopy (this, spec); + + src[i] = tparams[i].Type; + dst[i] = type_params[i].Type; + } + + // A copy is not enough, inflate any type parameter constraints + // using a new type parameters + var inflator = new TypeParameterInflator (this, null, src, dst); + for (int i = 0; i < type_params.Length; ++i) { + src[i].InflateConstraints (inflator, dst[i]); + } + + mutator = new TypeParameterMutator (tparams, type_params); + } + } + + #region Properties + + public TypeParameterMutator Mutator { + get { + return mutator; + } + set { + mutator = value; + } + } + + #endregion + + public HoistedStoreyClass GetGenericStorey () + { + DeclSpace storey = this; + while (storey != null && storey.CurrentTypeParameters == null) + storey = storey.Parent; + + return storey as HoistedStoreyClass; + } + } + + + // + // Anonymous method storey is created when an anonymous method uses + // variable or parameter from outer scope. They are then hoisted to + // anonymous method storey (captured) + // + public class AnonymousMethodStorey : HoistedStoreyClass + { + struct StoreyFieldPair + { + public readonly AnonymousMethodStorey Storey; + public readonly Field Field; + + public StoreyFieldPair (AnonymousMethodStorey storey, Field field) + { + this.Storey = storey; + this.Field = field; + } + } + + // + // Needed to delay hoisted _this_ initialization. When an anonymous + // method is used inside ctor and _this_ is hoisted, base ctor has to + // be called first, otherwise _this_ will be initialized with + // uninitialized value. + // + sealed class ThisInitializer : Statement + { + readonly HoistedThis hoisted_this; + + public ThisInitializer (HoistedThis hoisted_this) + { + this.hoisted_this = hoisted_this; + } + + protected override void DoEmit (EmitContext ec) + { + hoisted_this.EmitHoistingAssignment (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing to clone + } + } + + // Unique storey ID + public readonly int ID; + static int unique_id; + + public readonly Block OriginalSourceBlock; + + // A list of StoreyFieldPair with local field keeping parent storey instance + List used_parent_storeys; + List children_references; + + // A list of hoisted parameters + protected List hoisted_params; + protected List hoisted_locals; + + // Hoisted this + protected HoistedThis hoisted_this; + + // Local variable which holds this storey instance + public LocalTemporary Instance; + + public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name) + : base (parent, MakeMemberName (host, name, unique_id, tparams, block.StartLocation), + tparams, Modifiers.SEALED) + { + OriginalSourceBlock = block; + ID = unique_id++; + } + + public void AddCapturedThisField (EmitContext ec) + { + TypeExpr type_expr = new TypeExpression (ec.CurrentType, Location); + Field f = AddCompilerGeneratedField ("<>f__this", type_expr); + f.Define (); + hoisted_this = new HoistedThis (this, f); + + // Inflated type instance has to be updated manually + if (Instance.Type is InflatedTypeSpec) { + var inflator = new TypeParameterInflator (this, Instance.Type, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + Instance.Type.MemberCache.AddMember (f.Spec.InflateMember (inflator)); + + inflator = new TypeParameterInflator (this, f.Parent.CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + f.Parent.CurrentType.MemberCache.AddMember (f.Spec.InflateMember (inflator)); + } + } + + public Field AddCapturedVariable (string name, TypeSpec type) + { + CheckMembersDefined (); + + FullNamedExpression field_type = new TypeExpression (type, Location); + if (!IsGeneric) + return AddCompilerGeneratedField (name, field_type); + + const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + Field f = new HoistedField (this, field_type, mod, name, null, Location); + AddField (f); + return f; + } + + protected Field AddCompilerGeneratedField (string name, FullNamedExpression type) + { + const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + Field f = new Field (this, type, mod, new MemberName (name, Location), null); + AddField (f); + return f; + } + + // + // Creates a link between hoisted variable block and the anonymous method storey + // + // An anonymous method can reference variables from any outer block, but they are + // hoisted in their own ExplicitBlock. When more than one block is referenced we + // need to create another link between those variable storeys + // + public void AddReferenceFromChildrenBlock (ExplicitBlock block) + { + if (children_references == null) + children_references = new List (); + + if (!children_references.Contains (block)) + children_references.Add (block); + } + + public void AddParentStoreyReference (EmitContext ec, AnonymousMethodStorey storey) + { + CheckMembersDefined (); + + if (used_parent_storeys == null) + used_parent_storeys = new List (); + else if (used_parent_storeys.Exists (i => i.Storey == storey)) + return; + + TypeExpr type_expr = storey.CreateStoreyTypeExpression (ec); + Field f = AddCompilerGeneratedField ("<>f__ref$" + storey.ID, type_expr); + used_parent_storeys.Add (new StoreyFieldPair (storey, f)); + } + + public void CaptureLocalVariable (ResolveContext ec, LocalVariable local_info) + { + ec.CurrentBlock.Explicit.HasCapturedVariable = true; + if (ec.CurrentBlock.Explicit != local_info.Block.Explicit) + AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); + + if (local_info.HoistedVariant != null) + return; + + HoistedVariable var = new HoistedLocalVariable (this, local_info, GetVariableMangledName (local_info)); + local_info.HoistedVariant = var; + + if (hoisted_locals == null) + hoisted_locals = new List (); + + hoisted_locals.Add (var); + } + + public void CaptureParameter (ResolveContext ec, ParameterReference param_ref) + { + ec.CurrentBlock.Explicit.HasCapturedVariable = true; + AddReferenceFromChildrenBlock (ec.CurrentBlock.Explicit); + + if (param_ref.GetHoistedVariable (ec) != null) + return; + + if (hoisted_params == null) + hoisted_params = new List (2); + + var expr = new HoistedParameter (this, param_ref); + param_ref.Parameter.HoistedVariant = expr; + hoisted_params.Add (expr); + } + + TypeExpr CreateStoreyTypeExpression (EmitContext ec) + { + // + // Create an instance of storey type + // + TypeExpr storey_type_expr; + if (CurrentTypeParameters != null) { + // + // Use current method type parameter (MVAR) for top level storey only. All + // nested storeys use class type parameter (VAR) + // + TypeParameter[] tparams = ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null ? + ec.CurrentAnonymousMethod.Storey.TypeParameters : + ec.CurrentTypeParameters; + + TypeArguments targs = new TypeArguments (); + + // + // Use type parameter name instead of resolved type parameter + // specification to resolve to correctly nested type parameters + // + for (int i = 0; i < tparams.Length; ++i) + targs.Add (new SimpleName (tparams [i].Name, Location)); // new TypeParameterExpr (tparams[i], Location)); + + storey_type_expr = new GenericTypeExpr (Definition, targs, Location); + } else { + storey_type_expr = new TypeExpression (CurrentType, Location); + } + + return storey_type_expr; + } + + public void SetNestedStoryParent (AnonymousMethodStorey parentStorey) + { + Parent = parentStorey; + type_params = null; + spec.IsGeneric = false; + spec.DeclaringType = parentStorey.CurrentType; + MemberName.TypeArguments = null; + } + + protected override bool DoResolveTypeParameters () + { + // Although any storey can have type parameters they are all clones of method type + // parameters therefore have to mutate MVAR references in any of cloned constraints + if (type_params != null) { + for (int i = 0; i < type_params.Length; ++i) { + var spec = type_params[i].Type; + spec.BaseType = mutator.Mutate (spec.BaseType); + if (spec.InterfacesDefined != null) { + var mutated = new TypeSpec[spec.InterfacesDefined.Length]; + for (int ii = 0; ii < mutated.Length; ++ii) { + mutated[ii] = mutator.Mutate (spec.InterfacesDefined[ii]); + } + + spec.InterfacesDefined = mutated; + } + + if (spec.TypeArguments != null) { + spec.TypeArguments = mutator.Mutate (spec.TypeArguments); + } + } + } + + // + // Update parent cache as we most likely passed the point + // where the cache was constructed + // + Parent.CurrentType.MemberCache.AddMember (this.spec); + + return true; + } + + // + // Initializes all hoisted variables + // + public void EmitStoreyInstantiation (EmitContext ec, ExplicitBlock block) + { + // There can be only one instance variable for each storey type + if (Instance != null) + throw new InternalErrorException (); + + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + // + // Create an instance of a storey + // + var storey_type_expr = CreateStoreyTypeExpression (ec); + + ResolveContext rc = new ResolveContext (ec.MemberContext); + rc.CurrentBlock = block; + Expression e = new New (storey_type_expr, null, Location).Resolve (rc); + e.Emit (ec); + + Instance = new LocalTemporary (storey_type_expr.Type); + Instance.Store (ec); + + EmitHoistedFieldsInitialization (rc, ec); + + SymbolWriter.DefineScopeVariable (ID, Instance.Builder); + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + void EmitHoistedFieldsInitialization (ResolveContext rc, EmitContext ec) + { + // + // Initialize all storey reference fields by using local or hoisted variables + // + if (used_parent_storeys != null) { + foreach (StoreyFieldPair sf in used_parent_storeys) { + // + // Get instance expression of storey field + // + Expression instace_expr = GetStoreyInstanceExpression (ec); + var fs = sf.Field.Spec; + if (TypeManager.IsGenericType (instace_expr.Type)) + fs = MemberCache.GetMember (instace_expr.Type, fs); + + FieldExpr f_set_expr = new FieldExpr (fs, Location); + f_set_expr.InstanceExpression = instace_expr; + + SimpleAssign a = new SimpleAssign (f_set_expr, sf.Storey.GetStoreyInstanceExpression (ec)); + if (a.Resolve (rc) != null) + a.EmitStatement (ec); + } + } + + // + // Define hoisted `this' in top-level storey only + // + if (OriginalSourceBlock.Explicit.HasCapturedThis && !(Parent is AnonymousMethodStorey)) { + AddCapturedThisField (ec); + rc.CurrentBlock.AddScopeStatement (new ThisInitializer (hoisted_this)); + } + + // + // Setting currect anonymous method to null blocks any further variable hoisting + // + AnonymousExpression ae = ec.CurrentAnonymousMethod; + ec.CurrentAnonymousMethod = null; + + if (hoisted_params != null) { + EmitHoistedParameters (ec, hoisted_params); + } + + ec.CurrentAnonymousMethod = ae; + } + + protected virtual void EmitHoistedParameters (EmitContext ec, IList hoisted) + { + foreach (HoistedParameter hp in hoisted) { + hp.EmitHoistingAssignment (ec); + } + } + + public override void EmitType () + { + SymbolWriter.DefineAnonymousScope (ID); + + if (hoisted_this != null) + hoisted_this.EmitSymbolInfo (); + + if (hoisted_locals != null) { + foreach (HoistedVariable local in hoisted_locals) + local.EmitSymbolInfo (); + } + + if (hoisted_params != null) { + foreach (HoistedParameter param in hoisted_params) + param.EmitSymbolInfo (); + } + + if (used_parent_storeys != null) { + foreach (StoreyFieldPair sf in used_parent_storeys) { + SymbolWriter.DefineCapturedScope (ID, sf.Storey.ID, sf.Field.Name); + } + } + + base.EmitType (); + } + + // + // Returns a field which holds referenced storey instance + // + Field GetReferencedStoreyField (AnonymousMethodStorey storey) + { + if (used_parent_storeys == null) + return null; + + foreach (StoreyFieldPair sf in used_parent_storeys) { + if (sf.Storey == storey) + return sf.Field; + } + + return null; + } + + // + // Creates storey instance expression regardless of currect IP + // + public Expression GetStoreyInstanceExpression (EmitContext ec) + { + AnonymousExpression am = ec.CurrentAnonymousMethod; + + // + // Access from original block -> storey + // + if (am == null) + return Instance; + + // + // Access from anonymous method implemented as a static -> storey + // + if (am.Storey == null) + return Instance; + + Field f = am.Storey.GetReferencedStoreyField (this); + if (f == null) { + if (am.Storey == this) { + // + // Access inside of same storey (S -> S) + // + return new CompilerGeneratedThis (CurrentType, Location); + } + // + // External field access + // + return Instance; + } + + // + // Storey was cached to local field + // + FieldExpr f_ind = new FieldExpr (f, Location); + f_ind.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location); + return f_ind; + } + + protected virtual string GetVariableMangledName (LocalVariable local_info) + { + // + // No need to mangle anonymous method hoisted variables cause they + // are hoisted in their own scopes + // + return local_info.Name; + } + + public HoistedThis HoistedThis { + get { return hoisted_this; } + } + + public IList ReferencesFromChildrenBlock { + get { return children_references; } + } + + public static void Reset () + { + unique_id = 0; + } + } + + public abstract class HoistedVariable + { + // + // Hoisted version of variable references used in expression + // tree has to be delayed until we know its location. The variable + // doesn't know its location until all stories are calculated + // + class ExpressionTreeVariableReference : Expression + { + readonly HoistedVariable hv; + + public ExpressionTreeVariableReference (HoistedVariable hv) + { + this.hv = hv; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return hv.CreateExpressionTree (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + type = ec.Module.PredefinedTypes.Expression.Resolve (); + return this; + } + + public override void Emit (EmitContext ec) + { + ResolveContext rc = new ResolveContext (ec.MemberContext); + Expression e = hv.GetFieldExpression (ec).CreateExpressionTree (rc); + // This should never fail + e = e.Resolve (rc); + if (e != null) + e.Emit (ec); + } + } + + protected readonly AnonymousMethodStorey storey; + protected Field field; + Dictionary cached_inner_access; // TODO: Hashtable is too heavyweight + FieldExpr cached_outer_access; + + protected HoistedVariable (AnonymousMethodStorey storey, string name, TypeSpec type) + : this (storey, storey.AddCapturedVariable (name, type)) + { + } + + protected HoistedVariable (AnonymousMethodStorey storey, Field field) + { + this.storey = storey; + this.field = field; + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + GetFieldExpression (ec).AddressOf (ec, mode); + } + + public Expression CreateExpressionTree () + { + return new ExpressionTreeVariableReference (this); + } + + public void Emit (EmitContext ec) + { + GetFieldExpression (ec).Emit (ec); + } + + // + // Creates field access expression for hoisted variable + // + protected virtual FieldExpr GetFieldExpression (EmitContext ec) + { + if (ec.CurrentAnonymousMethod == null || ec.CurrentAnonymousMethod.Storey == null) { + if (cached_outer_access != null) + return cached_outer_access; + + // + // When setting top-level hoisted variable in generic storey + // change storey generic types to method generic types (VAR -> MVAR) + // + if (storey.Instance.Type.IsGenericOrParentIsGeneric) { + var fs = MemberCache.GetMember (storey.Instance.Type, field.Spec); + cached_outer_access = new FieldExpr (fs, field.Location); + } else { + cached_outer_access = new FieldExpr (field, field.Location); + } + + cached_outer_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); + return cached_outer_access; + } + + FieldExpr inner_access; + if (cached_inner_access != null) { + if (!cached_inner_access.TryGetValue (ec.CurrentAnonymousMethod, out inner_access)) + inner_access = null; + } else { + inner_access = null; + cached_inner_access = new Dictionary (4); + } + + if (inner_access == null) { + if (field.Parent.IsGeneric) { + var fs = MemberCache.GetMember (field.Parent.CurrentType, field.Spec); + inner_access = new FieldExpr (fs, field.Location); + } else { + inner_access = new FieldExpr (field, field.Location); + } + + inner_access.InstanceExpression = storey.GetStoreyInstanceExpression (ec); + cached_inner_access.Add (ec.CurrentAnonymousMethod, inner_access); + } + + return inner_access; + } + + public abstract void EmitSymbolInfo (); + + public void Emit (EmitContext ec, bool leave_copy) + { + GetFieldExpression (ec).Emit (ec, leave_copy); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + GetFieldExpression (ec).EmitAssign (ec, source, leave_copy, false); + } + } + + public class HoistedParameter : HoistedVariable + { + sealed class HoistedFieldAssign : Assign + { + public HoistedFieldAssign (Expression target, Expression source) + : base (target, source, source.Location) + { + } + + protected override Expression ResolveConversions (ResolveContext ec) + { + // + // Implicit conversion check fails for hoisted type arguments + // as they are of different types (!!0 x !0) + // + return this; + } + } + + readonly ParameterReference parameter; + + public HoistedParameter (AnonymousMethodStorey scope, ParameterReference par) + : base (scope, par.Name, par.Type) + { + this.parameter = par; + } + + public HoistedParameter (HoistedParameter hp, string name) + : base (hp.storey, name, hp.parameter.Type) + { + this.parameter = hp.parameter; + } + + public void EmitHoistingAssignment (EmitContext ec) + { + // + // Remove hoisted redirection to emit assignment from original parameter + // + HoistedVariable temp = parameter.Parameter.HoistedVariant; + parameter.Parameter.HoistedVariant = null; + + Assign a = new HoistedFieldAssign (GetFieldExpression (ec), parameter); + if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) + a.EmitStatement (ec); + + parameter.Parameter.HoistedVariant = temp; + } + + public override void EmitSymbolInfo () + { + SymbolWriter.DefineCapturedParameter (storey.ID, field.Name, field.Name); + } + + public Field Field { + get { return field; } + } + } + + class HoistedLocalVariable : HoistedVariable + { + readonly string name; + + public HoistedLocalVariable (AnonymousMethodStorey scope, LocalVariable local, string name) + : base (scope, name, local.Type) + { + this.name = local.Name; + } + + public override void EmitSymbolInfo () + { + SymbolWriter.DefineCapturedLocal (storey.ID, name, field.Name); + } + } + + public class HoistedThis : HoistedVariable + { + public HoistedThis (AnonymousMethodStorey storey, Field field) + : base (storey, field) + { + } + + public void EmitHoistingAssignment (EmitContext ec) + { + SimpleAssign a = new SimpleAssign (GetFieldExpression (ec), new CompilerGeneratedThis (ec.CurrentType, field.Location)); + if (a.Resolve (new ResolveContext (ec.MemberContext)) != null) + a.EmitStatement (ec); + } + + public override void EmitSymbolInfo () + { + SymbolWriter.DefineCapturedThis (storey.ID, field.Name); + } + + public Field Field { + get { return field; } + } + } + + // + // Anonymous method expression as created by parser + // + public class AnonymousMethodExpression : Expression + { + // + // Special conversion for nested expression tree lambdas + // + class Quote : ShimExpression + { + public Quote (Expression expr) + : base (expr) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + var args = new Arguments (1); + args.Add (new Argument (expr.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "Quote", args); + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr == null) + return null; + + eclass = expr.eclass; + type = expr.Type; + return this; + } + } + + readonly Dictionary compatibles; + readonly bool is_async; + + public ParametersBlock Block; + + public AnonymousMethodExpression (bool isAsync, Location loc) + { + this.is_async = isAsync; + this.loc = loc; + this.compatibles = new Dictionary (); + } + + #region Properties + + public override string ExprClassName { + get { + return "anonymous method"; + } + } + + public virtual bool HasExplicitParameters { + get { + return Parameters != ParametersCompiled.Undefined; + } + } + + public bool IsAsync { + get { + return is_async; + } + } + + public ParametersCompiled Parameters { + get { + return Block.Parameters; + } + } + + #endregion + + // + // Returns true if the body of lambda expression can be implicitly + // converted to the delegate of type `delegate_type' + // + public bool ImplicitStandardConversionExists (ResolveContext ec, TypeSpec delegate_type) + { + using (ec.With (ResolveContext.Options.InferReturnType, false)) { + using (ec.Set (ResolveContext.Options.ProbingMode)) { + return Compatible (ec, delegate_type) != null; + } + } + } + + TypeSpec CompatibleChecks (ResolveContext ec, TypeSpec delegate_type) + { + if (delegate_type.IsDelegate) + return delegate_type; + + if (delegate_type.IsExpressionTreeType) { + delegate_type = delegate_type.TypeArguments [0]; + if (delegate_type.IsDelegate) + return delegate_type; + + ec.Report.Error (835, loc, "Cannot convert `{0}' to an expression tree of non-delegate type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + return null; + } + + ec.Report.Error (1660, loc, "Cannot convert `{0}' to non-delegate type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + return null; + } + + protected bool VerifyExplicitParameters (ResolveContext ec, TypeSpec delegate_type, AParametersCollection parameters) + { + if (VerifyParameterCompatibility (ec, delegate_type, parameters, ec.IsInProbingMode)) + return true; + + if (!ec.IsInProbingMode) + ec.Report.Error (1661, loc, + "Cannot convert `{0}' to delegate type `{1}' since there is a parameter mismatch", + GetSignatureForError (), TypeManager.CSharpName (delegate_type)); + + return false; + } + + protected bool VerifyParameterCompatibility (ResolveContext ec, TypeSpec delegate_type, AParametersCollection invoke_pd, bool ignore_errors) + { + if (Parameters.Count != invoke_pd.Count) { + if (ignore_errors) + return false; + + ec.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", + TypeManager.CSharpName (delegate_type), Parameters.Count.ToString ()); + return false; + } + + bool has_implicit_parameters = !HasExplicitParameters; + bool error = false; + + for (int i = 0; i < Parameters.Count; ++i) { + Parameter.Modifier p_mod = invoke_pd.FixedParameters [i].ModFlags; + if (Parameters.FixedParameters [i].ModFlags != p_mod && p_mod != Parameter.Modifier.PARAMS) { + if (ignore_errors) + return false; + + if (p_mod == Parameter.Modifier.NONE) + ec.Report.Error (1677, loc, "Parameter `{0}' should not be declared with the `{1}' keyword", + (i + 1).ToString (), Parameter.GetModifierSignature (Parameters.FixedParameters [i].ModFlags)); + else + ec.Report.Error (1676, loc, "Parameter `{0}' must be declared with the `{1}' keyword", + (i+1).ToString (), Parameter.GetModifierSignature (p_mod)); + error = true; + } + + if (has_implicit_parameters) + continue; + + TypeSpec type = invoke_pd.Types [i]; + + // We assume that generic parameters are always inflated + if (TypeManager.IsGenericParameter (type)) + continue; + + if (TypeManager.HasElementType (type) && TypeManager.IsGenericParameter (TypeManager.GetElementType (type))) + continue; + + if (!TypeSpecComparer.IsEqual (invoke_pd.Types [i], Parameters.Types [i])) { + if (ignore_errors) + return false; + + ec.Report.Error (1678, loc, "Parameter `{0}' is declared as type `{1}' but should be `{2}'", + (i+1).ToString (), + TypeManager.CSharpName (Parameters.Types [i]), + TypeManager.CSharpName (invoke_pd.Types [i])); + error = true; + } + } + + return !error; + } + + // + // Infers type arguments based on explicit arguments + // + public bool ExplicitTypeInference (ResolveContext ec, TypeInferenceContext type_inference, TypeSpec delegate_type) + { + if (!HasExplicitParameters) + return false; + + if (!delegate_type.IsDelegate) { + if (!delegate_type.IsExpressionTreeType) + return false; + + delegate_type = TypeManager.GetTypeArguments (delegate_type) [0]; + if (!delegate_type.IsDelegate) + return false; + } + + AParametersCollection d_params = Delegate.GetParameters (delegate_type); + if (d_params.Count != Parameters.Count) + return false; + + for (int i = 0; i < Parameters.Count; ++i) { + TypeSpec itype = d_params.Types [i]; + if (!TypeManager.IsGenericParameter (itype)) { + if (!TypeManager.HasElementType (itype)) + continue; + + if (!TypeManager.IsGenericParameter (TypeManager.GetElementType (itype))) + continue; + } + type_inference.ExactInference (Parameters.Types [i], itype); + } + return true; + } + + public TypeSpec InferReturnType (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) + { + Expression expr; + AnonymousExpression am; + + if (compatibles.TryGetValue (delegate_type, out expr)) { + am = expr as AnonymousExpression; + return am == null ? null : am.ReturnType; + } + + using (ec.Set (ResolveContext.Options.ProbingMode | ResolveContext.Options.InferReturnType)) { + 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) + return null; + +// compatibles.Add (delegate_type, am); + return am.ReturnType; + } + + // + // Returns AnonymousMethod container if this anonymous method + // expression can be implicitly converted to the delegate type `delegate_type' + // + public Expression Compatible (ResolveContext ec, TypeSpec type) + { + Expression am; + if (compatibles.TryGetValue (type, out am)) + return am; + + TypeSpec delegate_type = CompatibleChecks (ec, type); + if (delegate_type == null) + return null; + + // + // At this point its the first time we know the return type that is + // needed for the anonymous method. We create the method here. + // + + var invoke_mb = Delegate.GetInvokeMethod (delegate_type); + TypeSpec return_type = invoke_mb.ReturnType; + + // + // Second: the return type of the delegate must be compatible with + // the anonymous type. Instead of doing a pass to examine the block + // we satisfy the rule by setting the return type on the EmitContext + // to be the delegate type return type. + // + + var body = CompatibleMethodBody (ec, null, return_type, delegate_type); + if (body == null) + return null; + + bool etree_conversion = delegate_type != type; + + try { + if (etree_conversion) { + if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) { + // + // Nested expression tree lambda use same scope as parent + // lambda, this also means no variable capturing between this + // and parent scope + // + am = body.Compatible (ec, ec.CurrentAnonymousMethod, is_async); + + // + // Quote nested expression tree + // + if (am != null) + am = new Quote (am); + } else { + int errors = ec.Report.Errors; + + using (ec.Set (ResolveContext.Options.ExpressionTreeConversion)) { + am = body.Compatible (ec); + } + + // + // Rewrite expressions into expression tree when targeting Expression + // + if (am != null && errors == ec.Report.Errors) + am = CreateExpressionTree (ec, delegate_type); + } + } else { + if (is_async) { + AsyncInitializer.Create (body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc); + } + + am = body.Compatible (ec); + } + } catch (CompletionResult) { + throw; + } catch (Exception e) { + throw new InternalErrorException (e, loc); + } + + if (!ec.IsInProbingMode) { + compatibles.Add (type, am ?? EmptyExpression.Null); + } + + return am; + } + + protected virtual Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) + { + return CreateExpressionTree (ec); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1946, loc, "An anonymous method cannot be converted to an expression tree"); + return null; + } + + protected virtual ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegate_type) + { + var delegate_parameters = Delegate.GetParameters (delegate_type); + + if (Parameters == ParametersCompiled.Undefined) { + // + // We provide a set of inaccessible parameters + // + Parameter[] fixedpars = new Parameter[delegate_parameters.Count]; + + for (int i = 0; i < delegate_parameters.Count; i++) { + Parameter.Modifier i_mod = delegate_parameters.FixedParameters [i].ModFlags; + if (i_mod == Parameter.Modifier.OUT) { + if (!ec.IsInProbingMode) { + ec.Report.Error (1688, loc, + "Cannot convert anonymous method block without a parameter list to delegate type `{0}' because it has one or more `out' parameters", + delegate_type.GetSignatureForError ()); + } + + return null; + } + fixedpars[i] = new Parameter ( + new TypeExpression (delegate_parameters.Types [i], loc), null, + delegate_parameters.FixedParameters [i].ModFlags, null, loc); + } + + return ParametersCompiled.CreateFullyResolved (fixedpars, delegate_parameters.Types); + } + + if (!VerifyExplicitParameters (ec, delegate_type, delegate_parameters)) { + return null; + } + + return Parameters; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (1706, loc, "Anonymous methods and lambda expressions cannot be used in the current context"); + return null; + } + + // + // Set class type, set type + // + + eclass = ExprClass.Value; + + // + // This hack means `The type is not accessible + // anywhere', we depend on special conversion + // rules. + // + type = InternalType.AnonymousMethod; + + if (!DoResolveParameters (ec)) + return null; + + // FIXME: The emitted code isn't very careful about reachability + // so, ensure we have a 'ret' at the end + BlockContext bc = ec as BlockContext; + if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable) + bc.NeedReturnLabel (); + + return this; + } + + protected virtual bool DoResolveParameters (ResolveContext rc) + { + return Parameters.Resolve (rc); + } + + public override void Emit (EmitContext ec) + { + // nothing, as we only exist to not do anything. + } + + public static void Error_AddressOfCapturedVar (ResolveContext ec, IVariableReference var, Location loc) + { + ec.Report.Error (1686, loc, + "Local variable or parameter `{0}' cannot have their address taken and be used inside an anonymous method, lambda expression or query expression", + var.Name); + } + + public override string GetSignatureForError () + { + return ExprClassName; + } + + AnonymousMethodBody CompatibleMethodBody (ResolveContext ec, TypeInferenceContext tic, TypeSpec return_type, TypeSpec delegate_type) + { + ParametersCompiled p = ResolveParameters (ec, tic, delegate_type); + if (p == null) + return null; + + ParametersBlock b = ec.IsInProbingMode ? (ParametersBlock) Block.PerformClone () : Block; + + return CompatibleMethodFactory (return_type, delegate_type, p, b); + } + + protected virtual AnonymousMethodBody CompatibleMethodFactory (TypeSpec return_type, TypeSpec delegate_type, ParametersCompiled p, ParametersBlock b) + { + return new AnonymousMethodBody (p, b, return_type, delegate_type, loc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + AnonymousMethodExpression target = (AnonymousMethodExpression) t; + + target.Block = (ParametersBlock) clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Abstract expression for any block which requires variables hoisting + // + public abstract class AnonymousExpression : ExpressionStatement + { + protected class AnonymousMethodMethod : Method + { + public readonly AnonymousExpression AnonymousMethod; + public readonly AnonymousMethodStorey Storey; + readonly string RealName; + + public AnonymousMethodMethod (DeclSpace parent, AnonymousExpression am, AnonymousMethodStorey storey, + GenericMethod generic, TypeExpr return_type, + Modifiers mod, string real_name, MemberName name, + ParametersCompiled parameters) + : base (parent, generic, return_type, mod | Modifiers.COMPILER_GENERATED, + name, parameters, null) + { + this.AnonymousMethod = am; + this.Storey = storey; + this.RealName = real_name; + + Parent.PartialContainer.AddMethod (this); + Block = new ToplevelBlock (am.block, parameters); + } + + public override EmitContext CreateEmitContext (ILGenerator ig) + { + EmitContext ec = new EmitContext (this, ig, ReturnType); + ec.CurrentAnonymousMethod = AnonymousMethod; + if (AnonymousMethod.return_label != null) { + ec.HasReturnLabel = true; + ec.ReturnLabel = (Label) AnonymousMethod.return_label; + } + + return ec; + } + + protected override void DefineTypeParameters () + { + // Type parameters were cloned + } + + protected override bool ResolveMemberType () + { + if (!base.ResolveMemberType ()) + return false; + + if (Storey != null && Storey.Mutator != null) { + if (!parameters.IsEmpty) { + var mutated = Storey.Mutator.Mutate (parameters.Types); + if (mutated != parameters.Types) + parameters = ParametersCompiled.CreateFullyResolved ((Parameter[]) parameters.FixedParameters, mutated); + } + + member_type = Storey.Mutator.Mutate (member_type); + } + + return true; + } + + public override void Emit () + { + if (MethodBuilder == null) { + Define (); + } + + base.Emit (); + } + + public override void EmitExtraSymbolInfo (SourceMethod source) + { + source.SetRealMethodName (RealName); + } + } + + protected ParametersBlock block; + + public TypeSpec ReturnType; + + object return_label; + + protected AnonymousExpression (ParametersBlock block, TypeSpec return_type, Location loc) + { + this.ReturnType = return_type; + this.block = block; + this.loc = loc; + } + + public abstract string ContainerType { get; } + public abstract bool IsIterator { get; } + public abstract AnonymousMethodStorey Storey { get; } + + public AnonymousExpression Compatible (ResolveContext ec) + { + return Compatible (ec, this, false); + } + + public AnonymousExpression Compatible (ResolveContext ec, AnonymousExpression ae, bool isAsync) + { + if (block.Resolved) + return this; + + // TODO: Implement clone + BlockContext aec = new BlockContext (ec, block, ReturnType); + aec.CurrentAnonymousMethod = ae; + + ResolveContext.Options flags = 0; + + var am = this as AnonymousMethodBody; + + if (ec.HasSet (ResolveContext.Options.InferReturnType) && am != null) { + am.ReturnTypeInference = new TypeInferenceContext (); + } + + if (ec.IsInProbingMode) + flags |= ResolveContext.Options.ProbingMode; + + if (ec.HasSet (ResolveContext.Options.FieldInitializerScope)) + flags |= ResolveContext.Options.FieldInitializerScope; + + if (ec.HasSet (ResolveContext.Options.ExpressionTreeConversion)) + flags |= ResolveContext.Options.ExpressionTreeConversion; + + aec.Set (flags); + + var errors = ec.Report.Errors; + + bool res = Block.Resolve (ec.CurrentBranching, aec, null); + + if (aec.HasReturnLabel) + return_label = aec.ReturnLabel; + + if (am != null && am.ReturnTypeInference != null) { + 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 + // + if (isAsync && ReturnType != null) { + ReturnType = ec.Module.PredefinedTypes.TaskGeneric.TypeSpec.MakeGenericType (ec, new [] { ReturnType }); + } + } + + if (res && errors != ec.Report.Errors) + return null; + + return res ? this : null; + } + + public void SetHasThisAccess () + { + ExplicitBlock b = block; + do { + if (b.HasCapturedThis) + return; + + b.HasCapturedThis = true; + b = b.Parent == null ? null : b.Parent.Explicit; + } while (b != null); + } + + // + // The block that makes up the body for the anonymous method + // + public ParametersBlock Block { + get { + return block; + } + } + + } + + public class AnonymousMethodBody : AnonymousExpression + { + protected readonly ParametersCompiled parameters; + AnonymousMethodStorey storey; + + AnonymousMethodMethod method; + Field am_cache; + string block_name; + TypeInferenceContext return_inference; + + static int unique_id; + + public AnonymousMethodBody (ParametersCompiled parameters, + ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type, + Location loc) + : base (block, return_type, loc) + { + this.type = delegate_type; + this.parameters = parameters; + } + + #region Properties + + public override string ContainerType { + get { return "anonymous method"; } + } + + public override bool IsIterator { + get { + return false; + } + } + + public ParametersCompiled Parameters { + get { + return parameters; + } + } + + public TypeInferenceContext ReturnTypeInference { + get { + return return_inference; + } + set { + return_inference = value; + } + } + + public override AnonymousMethodStorey Storey { + get { return storey; } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1945, loc, "An expression tree cannot contain an anonymous method expression"); + return null; + } + + bool Define (ResolveContext ec) + { + if (!Block.Resolved && Compatible (ec) == null) + return false; + + if (block_name == null) { + MemberCore mc = (MemberCore) ec.MemberContext; + block_name = mc.MemberName.Basename; + } + + return true; + } + + // + // Creates a host for the anonymous method + // + AnonymousMethodMethod DoCreateMethodHost (EmitContext ec) + { + // + // Anonymous method body can be converted to + // + // 1, an instance method in current scope when only `this' is hoisted + // 2, a static method in current scope when neither `this' nor any variable is hoisted + // 3, an instance method in compiler generated storey when any hoisted variable exists + // + + Modifiers modifiers; + if (Block.HasCapturedVariable || Block.HasCapturedThis) { + storey = FindBestMethodStorey (); + modifiers = storey != null ? Modifiers.INTERNAL : Modifiers.PRIVATE; + } else { + if (ec.CurrentAnonymousMethod != null) + storey = ec.CurrentAnonymousMethod.Storey; + + modifiers = Modifiers.STATIC | Modifiers.PRIVATE; + } + + TypeContainer parent = storey != null ? storey : ec.CurrentTypeDefinition.Parent.PartialContainer; + + MemberCore mc = ec.MemberContext as MemberCore; + string name = CompilerGeneratedClass.MakeName (parent != storey ? block_name : null, + "m", null, unique_id++); + + MemberName member_name; + GenericMethod generic_method; + if (storey == null && mc.MemberName.TypeArguments != null) { + member_name = new MemberName (name, mc.MemberName.TypeArguments.Clone (), Location); + + var hoisted_tparams = ec.CurrentTypeParameters; + var type_params = new TypeParameter[hoisted_tparams.Length]; + for (int i = 0; i < type_params.Length; ++i) { + type_params[i] = hoisted_tparams[i].CreateHoistedCopy (parent, null); + } + + generic_method = new GenericMethod (parent.NamespaceEntry, parent, member_name, type_params, + new TypeExpression (ReturnType, Location), parameters); + } else { + member_name = new MemberName (name, Location); + generic_method = null; + } + + string real_name = String.Format ( + "{0}~{1}{2}", mc.GetSignatureForError (), GetSignatureForError (), + parameters.GetSignatureForError ()); + + return new AnonymousMethodMethod (parent, + this, storey, generic_method, new TypeExpression (ReturnType, Location), modifiers, + real_name, member_name, parameters); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (!Define (ec)) + return null; + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + // + // Use same anonymous method implementation for scenarios where same + // code is used from multiple blocks, e.g. field initializers + // + if (method == null) { + // + // Delay an anonymous method definition to avoid emitting unused code + // for unreachable blocks or expression trees + // + method = DoCreateMethodHost (ec); + method.Define (); + } + + bool is_static = (method.ModFlags & Modifiers.STATIC) != 0; + if (is_static && am_cache == null) { + // + // Creates a field cache to store delegate instance if it's not generic + // + if (!method.MemberName.IsGeneric) { + TypeContainer parent = method.Parent.PartialContainer; + int id = parent.Fields == null ? 0 : parent.Fields.Count; + var cache_type = storey != null && storey.Mutator != null ? storey.Mutator.Mutate (type) : type; + + am_cache = new Field (parent, new TypeExpression (cache_type, loc), + Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, + new MemberName (CompilerGeneratedClass.MakeName (null, "f", "am$cache", id), loc), null); + am_cache.Define (); + parent.AddField (am_cache); + } else { + // TODO: Implement caching of generated generic static methods + // + // Idea: + // + // Some extra class is needed to capture variable generic type + // arguments. Maybe we could re-use anonymous types, with a unique + // anonymous method id, but they are quite heavy. + // + // Consider : "() => typeof(T);" + // + // We need something like + // static class Wrap { + // public static DelegateType cache; + // } + // + // We then specialize local variable to capture all generic parameters + // and delegate type, e.g. "Wrap cache;" + // + } + } + + Label l_initialized = ec.DefineLabel (); + + if (am_cache != null) { + ec.Emit (OpCodes.Ldsfld, am_cache.Spec); + ec.Emit (OpCodes.Brtrue_S, l_initialized); + } + + // + // Load method delegate implementation + // + + if (is_static) { + ec.Emit (OpCodes.Ldnull); + } else if (storey != null) { + Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); + if (e != null) + e.Emit (ec); + } else { + ec.Emit (OpCodes.Ldarg_0); + } + + var delegate_method = method.Spec; + if (storey != null && storey.MemberName.IsGeneric) { + TypeSpec t = storey.Instance.Type; + + // + // Mutate anonymous method instance type if we are in nested + // hoisted generic anonymous method storey + // + if (ec.CurrentAnonymousMethod != null && + ec.CurrentAnonymousMethod.Storey != null && + ec.CurrentAnonymousMethod.Storey.Mutator != null) { + t = storey.Mutator.Mutate (t); + } + + ec.Emit (OpCodes.Ldftn, TypeBuilder.GetMethod (t.GetMetaInfo (), (MethodInfo) delegate_method.GetMetaInfo ())); + } else { + if (delegate_method.IsGeneric) + delegate_method = delegate_method.MakeGenericMethod (ec.MemberContext, method.TypeParameters); + + ec.Emit (OpCodes.Ldftn, delegate_method); + } + + var constructor_method = Delegate.GetConstructor (type); + ec.Emit (OpCodes.Newobj, constructor_method); + + if (am_cache != null) { + ec.Emit (OpCodes.Stsfld, am_cache.Spec); + ec.MarkLabel (l_initialized); + ec.Emit (OpCodes.Ldsfld, am_cache.Spec); + } + } + + public override void EmitStatement (EmitContext ec) + { + throw new NotImplementedException (); + } + + // + // Look for the best storey for this anonymous method + // + AnonymousMethodStorey FindBestMethodStorey () + { + // + // Use the nearest parent block which has a storey + // + for (Block b = Block.Parent; b != null; b = b.Parent) { + AnonymousMethodStorey s = b.Explicit.AnonymousMethodStorey; + if (s != null) + return s; + } + + return null; + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpName (type); + } + + public static void Reset () + { + unique_id = 0; + } + } + + // + // Anonymous type container + // + public class AnonymousTypeClass : CompilerGeneratedClass + { + static int types_counter; + public const string ClassNamePrefix = "<>__AnonType"; + public const string SignatureForError = "anonymous type"; + + readonly IList parameters; + + private AnonymousTypeClass (TypeContainer parent, MemberName name, IList parameters, Location loc) + : base (parent, name, (parent.Module.Evaluator != null ? Modifiers.PUBLIC : 0) | Modifiers.SEALED) + { + this.parameters = parameters; + } + + public static AnonymousTypeClass Create (TypeContainer parent, IList parameters, Location loc) + { + string name = ClassNamePrefix + types_counter++; + + ParametersCompiled all_parameters; + TypeParameterName[] t_params; + SimpleName[] t_args; + + if (parameters.Count == 0) { + all_parameters = ParametersCompiled.EmptyReadOnlyParameters; + t_params = new TypeParameterName[0]; + t_args = null; + } else { + t_args = new SimpleName[parameters.Count]; + t_params = new TypeParameterName[parameters.Count]; + Parameter[] ctor_params = new Parameter[parameters.Count]; + for (int i = 0; i < parameters.Count; ++i) { + AnonymousTypeParameter p = parameters[i]; + for (int ii = 0; ii < i; ++ii) { + if (parameters[ii].Name == p.Name) { + parent.Compiler.Report.Error (833, parameters[ii].Location, + "`{0}': An anonymous type cannot have multiple properties with the same name", + p.Name); + + p = new AnonymousTypeParameter (null, "$" + i.ToString (), p.Location); + parameters[i] = p; + break; + } + } + + t_args[i] = new SimpleName ("<" + p.Name + ">__T", p.Location); + t_params[i] = new TypeParameterName (t_args[i].Name, null, p.Location); + ctor_params[i] = new Parameter (t_args[i], p.Name, Parameter.Modifier.NONE, null, p.Location); + } + + all_parameters = new ParametersCompiled (ctor_params); + } + + // + // Create generic anonymous type host with generic arguments + // named upon properties names + // + AnonymousTypeClass a_type = new AnonymousTypeClass (parent.NamespaceEntry.SlaveDeclSpace, + new MemberName (name, new TypeArguments (t_params), loc), parameters, loc); + + if (parameters.Count > 0) + a_type.SetParameterInfo (null); + + Constructor c = new Constructor (a_type, name, Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, + null, all_parameters, null, loc); + c.Block = new ToplevelBlock (parent.Module.Compiler, c.ParameterInfo, loc); + + // + // Create fields and contructor body with field initialization + // + bool error = false; + for (int i = 0; i < parameters.Count; ++i) { + AnonymousTypeParameter p = parameters [i]; + + Field f = new Field (a_type, t_args [i], Modifiers.PRIVATE | Modifiers.READONLY, + new MemberName ("<" + p.Name + ">", p.Location), null); + + if (!a_type.AddField (f)) { + error = true; + continue; + } + + c.Block.AddStatement (new StatementExpression ( + new SimpleAssign (new MemberAccess (new This (p.Location), f.Name), + c.Block.GetParameterReference (i, p.Location)))); + + ToplevelBlock get_block = new ToplevelBlock (parent.Module.Compiler, p.Location); + get_block.AddStatement (new Return ( + new MemberAccess (new This (p.Location), f.Name), p.Location)); + + Property prop = new Property (a_type, t_args [i], Modifiers.PUBLIC, + new MemberName (p.Name, p.Location), null); + prop.Get = new Property.GetMethod (prop, 0, null, p.Location); + prop.Get.Block = get_block; + a_type.AddProperty (prop); + } + + if (error) + return null; + + a_type.AddConstructor (c); + return a_type; + } + + public static void Reset () + { + types_counter = 0; + } + + protected override bool AddToContainer (MemberCore symbol, string name) + { + MemberCore mc = GetDefinition (name); + + if (mc == null) { + defined_names.Add (name, symbol); + return true; + } + + // A conflict between anonymous type members will be reported + if (symbol is TypeParameter) { + Report.SymbolRelatedToPreviousError (symbol); + return false; + } + + // Ignore other conflicts + return true; + } + + protected override bool DoDefineMembers () + { + if (!base.DoDefineMembers ()) + return false; + + Location loc = Location; + + var equals_parameters = ParametersCompiled.CreateFullyResolved ( + new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc), Compiler.BuiltinTypes.Object); + + Method equals = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.Bool, loc), + Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("Equals", loc), + equals_parameters, null); + + equals_parameters[0].Resolve (equals, 0); + + Method tostring = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.String, loc), + Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, new MemberName ("ToString", loc), + Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + + ToplevelBlock equals_block = new ToplevelBlock (Compiler, equals.ParameterInfo, loc); + + TypeExpr current_type; + if (type_params != null) { + var targs = new TypeArguments (); + foreach (var type_param in type_params) + targs.Add (new TypeParameterExpr (type_param, type_param.Location)); + + current_type = new GenericTypeExpr (Definition, targs, loc); + } else { + current_type = new TypeExpression (Definition, loc); + } + + var li_other = LocalVariable.CreateCompilerGenerated (CurrentType, equals_block, loc); + equals_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_other.Type, loc), li_other)); + var other_variable = new LocalVariableReference (li_other, loc); + + MemberAccess system_collections_generic = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember ("global", "System", loc), "Collections", loc), "Generic", loc); + + Expression rs_equals = null; + Expression string_concat = new StringConstant (Compiler.BuiltinTypes, "{", loc); + Expression rs_hashcode = new IntConstant (Compiler.BuiltinTypes, -2128831035, loc); + for (int i = 0; i < parameters.Count; ++i) { + var p = parameters [i]; + var f = Fields [i]; + + MemberAccess equality_comparer = new MemberAccess (new MemberAccess ( + system_collections_generic, "EqualityComparer", + new TypeArguments (new SimpleName (CurrentTypeParameters [i].Name, loc)), loc), + "Default", loc); + + Arguments arguments_equal = new Arguments (2); + arguments_equal.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); + arguments_equal.Add (new Argument (new MemberAccess (other_variable, f.Name))); + + Expression field_equal = new Invocation (new MemberAccess (equality_comparer, + "Equals", loc), arguments_equal); + + Arguments arguments_hashcode = new Arguments (1); + arguments_hashcode.Add (new Argument (new MemberAccess (new This (f.Location), f.Name))); + Expression field_hashcode = new Invocation (new MemberAccess (equality_comparer, + "GetHashCode", loc), arguments_hashcode); + + IntConstant FNV_prime = new IntConstant (Compiler.BuiltinTypes, 16777619, loc); + rs_hashcode = new Binary (Binary.Operator.Multiply, + new Binary (Binary.Operator.ExclusiveOr, rs_hashcode, field_hashcode, loc), + FNV_prime, loc); + + Expression field_to_string = new Conditional (new BooleanExpression (new Binary (Binary.Operator.Inequality, + new MemberAccess (new This (f.Location), f.Name), new NullLiteral (loc), loc)), + new Invocation (new MemberAccess ( + new MemberAccess (new This (f.Location), f.Name), "ToString"), null), + new StringConstant (Compiler.BuiltinTypes, string.Empty, loc), loc); + + if (rs_equals == null) { + rs_equals = field_equal; + string_concat = new Binary (Binary.Operator.Addition, + string_concat, + new Binary (Binary.Operator.Addition, + new StringConstant (Compiler.BuiltinTypes, " " + p.Name + " = ", loc), + field_to_string, + loc), + loc); + continue; + } + + // + // Implementation of ToString () body using string concatenation + // + string_concat = new Binary (Binary.Operator.Addition, + new Binary (Binary.Operator.Addition, + string_concat, + new StringConstant (Compiler.BuiltinTypes, ", " + p.Name + " = ", loc), + loc), + field_to_string, + loc); + + rs_equals = new Binary (Binary.Operator.LogicalAnd, rs_equals, field_equal, loc); + } + + string_concat = new Binary (Binary.Operator.Addition, + string_concat, + new StringConstant (Compiler.BuiltinTypes, " }", loc), + loc); + + // + // Equals (object obj) override + // + var other_variable_assign = new TemporaryVariableReference (li_other, loc); + equals_block.AddStatement (new StatementExpression ( + new SimpleAssign (other_variable_assign, + new As (equals_block.GetParameterReference (0, loc), + current_type, loc), loc))); + + Expression equals_test = new Binary (Binary.Operator.Inequality, other_variable, new NullLiteral (loc), loc); + if (rs_equals != null) + equals_test = new Binary (Binary.Operator.LogicalAnd, equals_test, rs_equals, loc); + equals_block.AddStatement (new Return (equals_test, loc)); + + equals.Block = equals_block; + equals.Define (); + AddMethod (equals); + + // + // GetHashCode () override + // + Method hashcode = new Method (this, null, new TypeExpression (Compiler.BuiltinTypes.Int, loc), + Modifiers.PUBLIC | Modifiers.OVERRIDE | Modifiers.DEBUGGER_HIDDEN, + new MemberName ("GetHashCode", loc), + Mono.CSharp.ParametersCompiled.EmptyReadOnlyParameters, null); + + // + // Modified FNV with good avalanche behavior and uniform + // distribution with larger hash sizes. + // + // const int FNV_prime = 16777619; + // int hash = (int) 2166136261; + // foreach (int d in data) + // hash = (hash ^ d) * FNV_prime; + // hash += hash << 13; + // hash ^= hash >> 7; + // hash += hash << 3; + // hash ^= hash >> 17; + // hash += hash << 5; + + ToplevelBlock hashcode_top = new ToplevelBlock (Compiler, loc); + Block hashcode_block = new Block (hashcode_top, loc, loc); + hashcode_top.AddStatement (new Unchecked (hashcode_block, loc)); + + var li_hash = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Int, hashcode_top, loc); + hashcode_block.AddStatement (new BlockVariableDeclaration (new TypeExpression (li_hash.Type, loc), li_hash)); + LocalVariableReference hash_variable_assign = new LocalVariableReference (li_hash, loc); + hashcode_block.AddStatement (new StatementExpression ( + new SimpleAssign (hash_variable_assign, rs_hashcode))); + + var hash_variable = new LocalVariableReference (li_hash, loc); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.Addition, hash_variable, + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 13, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, + new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 7, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.Addition, hash_variable, + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 3, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.ExclusiveOr, hash_variable, + new Binary (Binary.Operator.RightShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 17, loc), loc), loc))); + hashcode_block.AddStatement (new StatementExpression ( + new CompoundAssign (Binary.Operator.Addition, hash_variable, + new Binary (Binary.Operator.LeftShift, hash_variable, new IntConstant (Compiler.BuiltinTypes, 5, loc), loc), loc))); + + hashcode_block.AddStatement (new Return (hash_variable, loc)); + hashcode.Block = hashcode_top; + hashcode.Define (); + AddMethod (hashcode); + + // + // ToString () override + // + + ToplevelBlock tostring_block = new ToplevelBlock (Compiler, loc); + tostring_block.AddStatement (new Return (string_concat, loc)); + tostring.Block = tostring_block; + tostring.Define (); + AddMethod (tostring); + + return true; + } + + public override string GetSignatureForError () + { + return SignatureForError; + } + + public IList Parameters { + get { + return parameters; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs new file mode 100644 index 0000000000..a246066896 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs @@ -0,0 +1,551 @@ +// +// argument.cs: Argument expressions +// +// Author: +// Miguel de Icaza (miguel@ximain.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // + // Argument expression used for invocation + // + public class Argument + { + public enum AType : byte + { + None = 0, + Ref = 1, // ref modifier used + Out = 2, // out modifier used + Default = 3, // argument created from default parameter value + DynamicTypeName = 4, // System.Type argument for dynamic binding + ExtensionType = 5, // Instance expression inserted as the first argument + } + + public readonly AType ArgType; + public Expression Expr; + + public Argument (Expression expr, AType type) + { + this.Expr = expr; + this.ArgType = type; + } + + public Argument (Expression expr) + { + if (expr == null) + throw new ArgumentNullException (); + + this.Expr = expr; + } + + #region Properties + + public bool IsByRef { + get { return ArgType == AType.Ref || ArgType == AType.Out; } + } + + public bool IsDefaultArgument { + get { return ArgType == AType.Default; } + } + + public Parameter.Modifier Modifier { + get { + switch (ArgType) { + case AType.Out: + return Parameter.Modifier.OUT; + + case AType.Ref: + return Parameter.Modifier.REF; + + default: + return Parameter.Modifier.NONE; + } + } + } + + public TypeSpec Type { + get { return Expr.Type; } + } + + #endregion + + public Argument Clone (Expression expr) + { + Argument a = (Argument) MemberwiseClone (); + a.Expr = expr; + return a; + } + + public Argument Clone (CloneContext clonectx) + { + return Clone (Expr.Clone (clonectx)); + } + + public virtual Expression CreateExpressionTree (ResolveContext ec) + { + if (ArgType == AType.Default) + ec.Report.Error (854, Expr.Location, "An expression tree cannot contain an invocation which uses optional parameter"); + + return Expr.CreateExpressionTree (ec); + } + + public string GetSignatureForError () + { + if (Expr.eclass == ExprClass.MethodGroup) + return Expr.ExprClassName; + + return TypeManager.CSharpName (Expr.Type); + } + + public bool ResolveMethodGroup (ResolveContext ec) + { + SimpleName sn = Expr as SimpleName; + if (sn != null) + Expr = sn.GetMethodGroup (); + + // FIXME: csc doesn't report any error if you try to use `ref' or + // `out' in a delegate creation expression. + Expr = Expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + if (Expr == null) + return false; + + return true; + } + + public void Resolve (ResolveContext ec) + { +// using (ec.With (ResolveContext.Options.DoFlowAnalysis, true)) { + // Verify that the argument is readable + if (ArgType != AType.Out) + Expr = Expr.Resolve (ec); + + // Verify that the argument is writeable + if (Expr != null && IsByRef) + Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess); + + if (Expr == null) + Expr = ErrorExpression.Instance; +// } + } + + public virtual void Emit (EmitContext ec) + { + if (!IsByRef) { + Expr.Emit (ec); + return; + } + + AddressOp mode = AddressOp.Store; + if (ArgType == AType.Ref) + mode |= AddressOp.Load; + + IMemoryLocation ml = (IMemoryLocation) Expr; + ml.AddressOf (ec, mode); + } + } + + public class MovableArgument : Argument + { + LocalTemporary variable; + + public MovableArgument (Argument arg) + : this (arg.Expr, arg.ArgType) + { + } + + protected MovableArgument (Expression expr, AType modifier) + : base (expr, modifier) + { + } + + public override void Emit (EmitContext ec) + { + // TODO: Should guard against multiple emits + base.Emit (ec); + + // Release temporary variable when used + if (variable != null) + variable.Release (ec); + } + + public void EmitAssign (EmitContext ec) + { + var type = Expr.Type; + if (IsByRef) { + var ml = (IMemoryLocation) Expr; + ml.AddressOf (ec, AddressOp.Load); + type = ReferenceContainer.MakeType (ec.Module, type); + } else { + Expr.Emit (ec); + } + + variable = new LocalTemporary (type); + variable.Store (ec); + + Expr = variable; + } + } + + public class NamedArgument : MovableArgument + { + public readonly string Name; + readonly Location loc; + + public NamedArgument (string name, Location loc, Expression expr) + : this (name, loc, expr, AType.None) + { + } + + public NamedArgument (string name, Location loc, Expression expr, AType modifier) + : base (expr, modifier) + { + this.Name = name; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (853, loc, "An expression tree cannot contain named argument"); + return base.CreateExpressionTree (ec); + } + + public Location Location { + get { return loc; } + } + } + + public class Arguments + { + sealed class ArgumentsOrdered : Arguments + { + readonly List ordered; + + public ArgumentsOrdered (Arguments args) + : base (args.Count) + { + AddRange (args); + ordered = new List (); + } + + public void AddOrdered (MovableArgument arg) + { + ordered.Add (arg); + } + + public override Expression[] Emit (EmitContext ec, bool dup_args) + { + foreach (var a in ordered) { + a.EmitAssign (ec); + } + + return base.Emit (ec, dup_args); + } + } + + // Try not to add any more instances to this class, it's allocated a lot + List args; + + public Arguments (int capacity) + { + args = new List (capacity); + } + + public void Add (Argument arg) + { + args.Add (arg); + } + + public void AddRange (Arguments args) + { + this.args.AddRange (args.args); + } + + public ArrayInitializer CreateDynamicBinderArguments (ResolveContext rc) + { + Location loc = Location.Null; + var all = new ArrayInitializer (args.Count, loc); + + MemberAccess binder = DynamicExpressionStatement.GetBinderNamespace (loc); + + foreach (Argument a in args) { + Arguments dargs = new Arguments (2); + + // CSharpArgumentInfoFlags.None = 0 + const string info_flags_enum = "CSharpArgumentInfoFlags"; + Expression info_flags = new IntLiteral (rc.BuiltinTypes, 0, loc); + + if (a.Expr is Constant) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "Constant", loc), loc); + } else if (a.ArgType == Argument.AType.Ref) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsRef", loc), loc); + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); + } else if (a.ArgType == Argument.AType.Out) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsOut", loc), loc); + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); + } else if (a.ArgType == Argument.AType.DynamicTypeName) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "IsStaticType", loc), loc); + } + + var arg_type = a.Expr.Type; + + if (arg_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && arg_type != InternalType.NullLiteral) { + MethodGroupExpr mg = a.Expr as MethodGroupExpr; + if (mg != null) { + rc.Report.Error (1976, a.Expr.Location, + "The method group `{0}' cannot be used as an argument of dynamic operation. Consider using parentheses to invoke the method", + mg.Name); + } else if (arg_type == InternalType.AnonymousMethod) { + rc.Report.Error (1977, a.Expr.Location, + "An anonymous method or lambda expression cannot be used as an argument of dynamic operation. Consider using a cast"); + } else if (arg_type.Kind == MemberKind.Void || arg_type == InternalType.Arglist || arg_type.IsPointer) { + rc.Report.Error (1978, a.Expr.Location, + "An expression of type `{0}' cannot be used as an argument of dynamic operation", + TypeManager.CSharpName (arg_type)); + } + + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "UseCompileTimeType", loc), loc); + } + + string named_value; + NamedArgument na = a as NamedArgument; + if (na != null) { + info_flags = new Binary (Binary.Operator.BitwiseOr, info_flags, + new MemberAccess (new MemberAccess (binder, info_flags_enum, loc), "NamedArgument", loc), loc); + + named_value = na.Name; + } else { + named_value = null; + } + + dargs.Add (new Argument (info_flags)); + dargs.Add (new Argument (new StringLiteral (rc.BuiltinTypes, named_value, loc))); + all.Add (new Invocation (new MemberAccess (new MemberAccess (binder, "CSharpArgumentInfo", loc), "Create", loc), dargs)); + } + + return all; + } + + public static Arguments CreateForExpressionTree (ResolveContext ec, Arguments args, params Expression[] e) + { + Arguments all = new Arguments ((args == null ? 0 : args.Count) + e.Length); + for (int i = 0; i < e.Length; ++i) { + if (e [i] != null) + all.Add (new Argument (e[i])); + } + + if (args != null) { + foreach (Argument a in args.args) { + Expression tree_arg = a.CreateExpressionTree (ec); + if (tree_arg != null) + all.Add (new Argument (tree_arg)); + } + } + + return all; + } + + public void CheckArrayAsAttribute (CompilerContext ctx) + { + foreach (Argument arg in args) { + // Type is undefined (was error 246) + if (arg.Type == null) + continue; + + if (arg.Type.IsArray) + ctx.Report.Warning (3016, 1, arg.Expr.Location, "Arrays as attribute arguments are not CLS-compliant"); + } + } + + public Arguments Clone (CloneContext ctx) + { + Arguments cloned = new Arguments (args.Count); + foreach (Argument a in args) + cloned.Add (a.Clone (ctx)); + + return cloned; + } + + public int Count { + get { return args.Count; } + } + + // + // Emits a list of resolved Arguments + // + public void Emit (EmitContext ec) + { + Emit (ec, false); + } + + // + // if `dup_args' is true, a copy of the arguments will be left + // on the stack and return value will contain an array of access + // expressions + // NOTE: It's caller responsibility is to release temporary variables + // + public virtual Expression[] Emit (EmitContext ec, bool dup_args) + { + Expression[] temps; + + if (dup_args && Count != 0) + temps = new Expression [Count]; + else + temps = null; + + int i = 0; + LocalTemporary lt; + foreach (Argument a in args) { + a.Emit (ec); + if (!dup_args) + continue; + + if (a.Expr is Constant || a.Expr is This) { + // + // No need to create a temporary variable for constants + // + temps[i] = a.Expr; + } else { + ec.Emit (OpCodes.Dup); + temps[i] = lt = new LocalTemporary (a.Type); + lt.Store (ec); + } + + ++i; + } + + return temps; + } + + public List.Enumerator GetEnumerator () + { + return args.GetEnumerator (); + } + + // + // At least one argument is of dynamic type + // + public bool HasDynamic { + get { + foreach (Argument a in args) { + if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef) + return true; + } + + return false; + } + } + + // + // At least one argument is named argument + // + public bool HasNamed { + get { + foreach (Argument a in args) { + if (a is NamedArgument) + return true; + } + + return false; + } + } + + + public void Insert (int index, Argument arg) + { + args.Insert (index, arg); + } + + public static System.Linq.Expressions.Expression[] MakeExpression (Arguments args, BuilderContext ctx) + { + if (args == null || args.Count == 0) + return null; + + var exprs = new System.Linq.Expressions.Expression [args.Count]; + for (int i = 0; i < exprs.Length; ++i) { + Argument a = args.args [i]; + exprs[i] = a.Expr.MakeExpression (ctx); + } + + return exprs; + } + + // + // For named arguments when the order of execution is different + // to order of invocation + // + public Arguments MarkOrderedArgument (NamedArgument a) + { + // + // Constant expression have no effect on left-to-right execution + // + if (a.Expr is Constant) + return this; + + ArgumentsOrdered ra = this as ArgumentsOrdered; + if (ra == null) { + ra = new ArgumentsOrdered (this); + + for (int i = 0; i < args.Count; ++i) { + var la = args [i]; + if (la == a) + break; + + var ma = la as MovableArgument; + if (ma == null) { + ma = new MovableArgument (la); + ra.args[i] = ma; + } + + ra.AddOrdered (ma); + } + } + + ra.AddOrdered (a); + return ra; + } + + // + // Returns dynamic when at least one argument is of dynamic type + // + public void Resolve (ResolveContext ec, out bool dynamic) + { + dynamic = false; + foreach (Argument a in args) { + a.Resolve (ec); + if (a.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && !a.IsByRef) + dynamic = true; + } + } + + public void RemoveAt (int index) + { + args.RemoveAt (index); + } + + public Argument this [int index] { + get { return args [index]; } + set { args [index] = value; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs new file mode 100644 index 0000000000..afae0c57af --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs @@ -0,0 +1,1183 @@ +// +// assembly.cs: Assembly declaration and specifications +// +// Authors: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004 Novell, Inc. +// + + +using System; +using System.IO; +using System.Collections.Generic; +using System.Globalization; +using System.Security; +using System.Security.Cryptography; +using System.Security.Permissions; +using Mono.Security.Cryptography; +using Mono.CompilerServices.SymbolWriter; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +using SecurityType = System.Collections.Generic.List; +#else +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public interface IAssemblyDefinition + { + string FullName { get; } + bool HasExtensionMethod { get; } + bool IsCLSCompliant { get; } + bool IsMissing { get; } + string Name { get; } + + byte[] GetPublicKeyToken (); + bool IsFriendAssemblyTo (IAssemblyDefinition assembly); + } + + public abstract class AssemblyDefinition : IAssemblyDefinition + { + // TODO: make it private and move all builder based methods here + public AssemblyBuilder Builder; + protected AssemblyBuilderExtension builder_extra; + MonoSymbolWriter symbol_writer; + + bool is_cls_compliant; + bool wrap_non_exception_throws; + bool wrap_non_exception_throws_custom; + + protected ModuleContainer module; + readonly string name; + protected readonly string file_name; + + byte[] public_key, public_key_token; + bool delay_sign; + + // Holds private/public key pair when private key + // was available + StrongNameKeyPair private_key; + + Attribute cls_attribute; + Method entry_point; + + protected List added_modules; + SecurityType declarative_security; + Dictionary emitted_forwarders; + AssemblyAttributesPlaceholder module_target_attrs; + + protected AssemblyDefinition (ModuleContainer module, string name) + { + this.module = module; + this.name = Path.GetFileNameWithoutExtension (name); + + wrap_non_exception_throws = true; + + delay_sign = Compiler.Settings.StrongNameDelaySign; + + // + // Load strong name key early enough for assembly importer to be able to + // use the keys for InternalsVisibleTo + // This should go somewhere close to ReferencesLoading but don't have the place yet + // + if (Compiler.Settings.HasKeyFileOrContainer) { + LoadPublicKey (Compiler.Settings.StrongNameKeyFile, Compiler.Settings.StrongNameKeyContainer); + } + } + + protected AssemblyDefinition (ModuleContainer module, string name, string fileName) + : this (module, name) + { + this.file_name = fileName; + } + + #region Properties + + public Attribute CLSCompliantAttribute { + get { + return cls_attribute; + } + } + + public CompilerContext Compiler { + get { + return module.Compiler; + } + } + + // + // Assembly entry point, aka Main method + // + public Method EntryPoint { + get { + return entry_point; + } + set { + entry_point = value; + } + } + + public string FullName { + get { + return Builder.FullName; + } + } + + public bool HasExtensionMethod { + get { + return module.HasExtensionMethod; + } + } + + public bool HasCLSCompliantAttribute { + get { + return cls_attribute != null; + } + } + + // TODO: This should not exist here but will require more changes + public MetadataImporter Importer { + get; set; + } + + public bool IsCLSCompliant { + get { + return is_cls_compliant; + } + } + + bool IAssemblyDefinition.IsMissing { + get { + return false; + } + } + + public string Name { + get { + return name; + } + } + + public bool WrapNonExceptionThrows { + get { + return wrap_non_exception_throws; + } + } + + protected Report Report { + get { + return Compiler.Report; + } + } + + #endregion + + public void AddModule (ImportedModuleDefinition module) + { + if (added_modules == null) { + added_modules = new List (); + added_modules.Add (module); + } + } + + public void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Type == pa.AssemblyCulture) { + string value = a.GetString (); + if (value == null || value.Length == 0) + return; + + if (Compiler.Settings.Target == Target.Exe) { + a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty"); + return; + } + + if (value == "neutral") + value = ""; + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetCulture (value, a.Location); + } + + return; + } + + if (a.Type == pa.AssemblyVersion) { + string value = a.GetString (); + if (value == null || value.Length == 0) + return; + + var vinfo = IsValidAssemblyVersion (value, true); + if (vinfo == null) { + a.Error_AttributeEmitError (string.Format ("Specified version `{0}' is not valid", value)); + return; + } + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetVersion (vinfo, a.Location); + } + + return; + } + + if (a.Type == pa.AssemblyAlgorithmId) { + const int pos = 2; // skip CA header + uint alg = (uint) cdata [pos]; + alg |= ((uint) cdata [pos + 1]) << 8; + alg |= ((uint) cdata [pos + 2]) << 16; + alg |= ((uint) cdata [pos + 3]) << 24; + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetAlgorithmId (alg, a.Location); + } + + return; + } + + if (a.Type == pa.AssemblyFlags) { + const int pos = 2; // skip CA header + uint flags = (uint) cdata[pos]; + flags |= ((uint) cdata [pos + 1]) << 8; + flags |= ((uint) cdata [pos + 2]) << 16; + flags |= ((uint) cdata [pos + 3]) << 24; + + // Ignore set PublicKey flag if assembly is not strongnamed + if ((flags & (uint) AssemblyNameFlags.PublicKey) != 0 && public_key == null) + flags &= ~(uint) AssemblyNameFlags.PublicKey; + + if (Compiler.Settings.Target == Target.Module) { + SetCustomAttribute (ctor, cdata); + } else { + builder_extra.SetFlags (flags, a.Location); + } + + return; + } + + if (a.Type == pa.TypeForwarder) { + TypeSpec t = a.GetArgumentType (); + if (t == null || TypeManager.HasElementType (t)) { + Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute"); + return; + } + + if (emitted_forwarders == null) { + emitted_forwarders = new Dictionary (); + } else if (emitted_forwarders.ContainsKey (t.MemberDefinition)) { + Report.SymbolRelatedToPreviousError (emitted_forwarders[t.MemberDefinition].Location, null); + Report.Error (739, a.Location, "A duplicate type forward of type `{0}'", + TypeManager.CSharpName (t)); + return; + } + + emitted_forwarders.Add (t.MemberDefinition, a); + + if (t.MemberDefinition.DeclaringAssembly == this) { + Report.SymbolRelatedToPreviousError (t); + Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly", + TypeManager.CSharpName (t)); + return; + } + + if (t.IsNested) { + Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type", + TypeManager.CSharpName (t)); + return; + } + + builder_extra.AddTypeForwarder (t.GetDefinition (), a.Location); + return; + } + + if (a.Type == pa.Extension) { + a.Error_MisusedExtensionAttribute (); + return; + } + + if (a.Type == pa.InternalsVisibleTo) { + string assembly_name = a.GetString (); + if (assembly_name.Length == 0) + return; + + AssemblyName aname = null; + try { + aname = new AssemblyName (assembly_name); + } catch (Exception) { + Report.Warning (1700, 3, a.Location, "Assembly reference `{0}' is invalid and cannot be resolved", + assembly_name); + return; + } + + if (aname.Version != null || aname.CultureInfo != null || aname.ProcessorArchitecture != ProcessorArchitecture.None) { + Report.Error (1725, a.Location, + "Friend assembly reference `{0}' is invalid. InternalsVisibleTo declarations cannot have a version, culture or processor architecture specified", + assembly_name); + + return; + } + + // TODO: GetPublicKey () does not work on .NET when AssemblyName is constructed from a string + if (public_key != null && aname.GetPublicKey () == null) { + Report.Error (1726, a.Location, + "Friend assembly reference `{0}' is invalid. Strong named assemblies must specify a public key in their InternalsVisibleTo declarations", + assembly_name); + return; + } + } else if (a.Type == pa.RuntimeCompatibility) { + wrap_non_exception_throws_custom = true; + } else if (a.Type == pa.AssemblyFileVersion) { + string value = a.GetString (); + if (string.IsNullOrEmpty (value) || IsValidAssemblyVersion (value, false) == null) { + Report.Warning (1607, 1, a.Location, "The version number `{0}' specified for `{1}' is invalid", + value, a.Name); + return; + } + } + + + SetCustomAttribute (ctor, cdata); + } + + // + // When using assembly public key attributes InternalsVisibleTo key + // was not checked, we have to do it later when we actually know what + // our public key token is + // + void CheckReferencesPublicToken () + { + // TODO: It should check only references assemblies but there is + // no working SRE API + foreach (var entry in Importer.Assemblies) { + var a = entry as ImportedAssemblyDefinition; + if (a == null) + continue; + + if (public_key != null && !a.HasStrongName) { + Report.Error (1577, "Referenced assembly `{0}' does not have a strong name", + a.FullName); + } + + var ci = a.Assembly.GetName ().CultureInfo; + if (!ci.Equals (System.Globalization.CultureInfo.InvariantCulture)) { + Report.Warning (1607, 1, "Referenced assembly `{0}' has different culture setting of `{1}'", + a.Name, ci.Name); + } + + if (!a.IsFriendAssemblyTo (this)) + continue; + + var attr = a.GetAssemblyVisibleToName (this); + var atoken = attr.GetPublicKeyToken (); + + if (ArrayComparer.IsEqual (GetPublicKeyToken (), atoken)) + continue; + + Report.SymbolRelatedToPreviousError (a.Location); + Report.Error (281, + "Friend access was granted to `{0}', but the output assembly is named `{1}'. Try adding a reference to `{0}' or change the output assembly name to match it", + attr.FullName, FullName); + } + } + + protected AssemblyName CreateAssemblyName () + { + var an = new AssemblyName (name); + + if (public_key != null && Compiler.Settings.Target != Target.Module) { + if (delay_sign) { + an.SetPublicKey (public_key); + } else { + if (public_key.Length == 16) { + Report.Error (1606, "Could not sign the assembly. ECMA key can only be used to delay-sign assemblies"); + } else if (private_key == null) { + Error_AssemblySigning ("The specified key file does not have a private key"); + } else { + an.KeyPair = private_key; + } + } + } + + return an; + } + + public virtual ModuleBuilder CreateModuleBuilder () + { + if (file_name == null) + throw new NotSupportedException ("transient module in static assembly"); + + var module_name = Path.GetFileName (file_name); + + // Always initialize module without symbolInfo. We could be framework dependent + // but returned ISymbolWriter does not have all what we need therefore some + // adaptor will be needed for now we alwayas emit MDB format when generating + // debug info + return Builder.DefineDynamicModule (module_name, module_name, false); + } + + public virtual void Emit () + { + if (Compiler.Settings.Target == Target.Module) { + module_target_attrs = new AssemblyAttributesPlaceholder (module, name); + module_target_attrs.CreateType (); + module_target_attrs.DefineType (); + module_target_attrs.Define (); + module.AddCompilerGeneratedClass (module_target_attrs); + } else if (added_modules != null) { + ReadModulesAssemblyAttributes (); + } + + if (Compiler.Settings.GenerateDebugInfo) { + symbol_writer = new MonoSymbolWriter (file_name); + + // Register all source files with symbol writer + foreach (var source in Compiler.SourceFiles) { + source.DefineSymbolInfo (symbol_writer); + } + + // TODO: global variables + SymbolWriter.symwriter = symbol_writer; + } + + module.Emit (); + + if (module.HasExtensionMethod) { + var pa = module.PredefinedAttributes.Extension; + if (pa.IsDefined) { + SetCustomAttribute (pa.Constructor, AttributeEncoder.Empty); + } + } + + if (!wrap_non_exception_throws_custom) { + PredefinedAttribute pa = module.PredefinedAttributes.RuntimeCompatibility; + if (pa.IsDefined && pa.ResolveBuilder ()) { + var prop = module.PredefinedMembers.RuntimeCompatibilityWrapNonExceptionThrows.Get (); + if (prop != null) { + AttributeEncoder encoder = new AttributeEncoder (); + encoder.EncodeNamedPropertyArgument (prop, new BoolLiteral (Compiler.BuiltinTypes, true, Location.Null)); + SetCustomAttribute (pa.Constructor, encoder.ToArray ()); + } + } + } + + if (declarative_security != null) { +#if STATIC + foreach (var entry in declarative_security) { + Builder.__AddDeclarativeSecurity (entry); + } +#else + var args = new PermissionSet[3]; + declarative_security.TryGetValue (SecurityAction.RequestMinimum, out args[0]); + declarative_security.TryGetValue (SecurityAction.RequestOptional, out args[1]); + declarative_security.TryGetValue (SecurityAction.RequestRefuse, out args[2]); + builder_extra.AddPermissionRequests (args); +#endif + } + + CheckReferencesPublicToken (); + + SetEntryPoint (); + } + + public byte[] GetPublicKeyToken () + { + if (public_key == null || public_key_token != null) + return public_key_token; + + HashAlgorithm ha = SHA1.Create (); + byte[] hash = ha.ComputeHash (public_key); + // we need the last 8 bytes in reverse order + public_key_token = new byte[8]; + Buffer.BlockCopy (hash, hash.Length - 8, public_key_token, 0, 8); + Array.Reverse (public_key_token, 0, 8); + return public_key_token; + } + + // + // Either keyFile or keyContainer has to be non-null + // + void LoadPublicKey (string keyFile, string keyContainer) + { + if (keyContainer != null) { + try { + private_key = new StrongNameKeyPair (keyContainer); + public_key = private_key.PublicKey; + } catch { + Error_AssemblySigning ("The specified key container `" + keyContainer + "' does not exist"); + } + + return; + } + + bool key_file_exists = File.Exists (keyFile); + + // + // For attribute based KeyFile do additional lookup + // in output assembly path + // + if (!key_file_exists && Compiler.Settings.StrongNameKeyFile == null) { + // + // The key file can be relative to output assembly + // + string test_path = Path.Combine (Path.GetDirectoryName (file_name), keyFile); + key_file_exists = File.Exists (test_path); + if (key_file_exists) + keyFile = test_path; + } + + if (!key_file_exists) { + Error_AssemblySigning ("The specified key file `" + keyFile + "' does not exist"); + return; + } + + using (FileStream fs = new FileStream (keyFile, FileMode.Open, FileAccess.Read)) { + byte[] snkeypair = new byte[fs.Length]; + fs.Read (snkeypair, 0, snkeypair.Length); + + // check for ECMA key + if (snkeypair.Length == 16) { + public_key = snkeypair; + return; + } + + try { + // take it, with or without, a private key + RSA rsa = CryptoConvert.FromCapiKeyBlob (snkeypair); + // and make sure we only feed the public part to Sys.Ref + byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa); + + // AssemblyName.SetPublicKey requires an additional header + byte[] publicKeyHeader = new byte[8] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00 }; + + // Encode public key + public_key = new byte[12 + publickey.Length]; + Buffer.BlockCopy (publicKeyHeader, 0, public_key, 0, publicKeyHeader.Length); + + // Length of Public Key (in bytes) + int lastPart = public_key.Length - 12; + public_key[8] = (byte) (lastPart & 0xFF); + public_key[9] = (byte) ((lastPart >> 8) & 0xFF); + public_key[10] = (byte) ((lastPart >> 16) & 0xFF); + public_key[11] = (byte) ((lastPart >> 24) & 0xFF); + + Buffer.BlockCopy (publickey, 0, public_key, 12, publickey.Length); + } catch { + Error_AssemblySigning ("The specified key file `" + keyFile + "' has incorrect format"); + return; + } + + if (delay_sign) + return; + + try { + // TODO: Is there better way to test for a private key presence ? + CryptoConvert.FromCapiPrivateKeyBlob (snkeypair); + private_key = new StrongNameKeyPair (snkeypair); + } catch { } + } + } + + void ReadModulesAssemblyAttributes () + { + foreach (var m in added_modules) { + var cattrs = m.ReadAssemblyAttributes (); + if (cattrs == null) + continue; + + module.OptAttributes.AddAttributes (cattrs); + } + } + + public void Resolve () + { + if (Compiler.Settings.Unsafe && module.PredefinedTypes.SecurityAction.Define ()) { + // + // Emits [assembly: SecurityPermissionAttribute (SecurityAction.RequestMinimum, SkipVerification = true)] + // when -unsafe option was specified + // + Location loc = Location.Null; + + MemberAccess system_security_permissions = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Security", loc), "Permissions", loc); + + var req_min = module.PredefinedMembers.SecurityActionRequestMinimum.Resolve (loc); + + Arguments pos = new Arguments (1); + pos.Add (new Argument (req_min.GetConstant (null))); + + Arguments named = new Arguments (1); + named.Add (new NamedArgument ("SkipVerification", loc, new BoolLiteral (Compiler.BuiltinTypes, true, loc))); + + Attribute g = new Attribute ("assembly", + new MemberAccess (system_security_permissions, "SecurityPermissionAttribute"), + new Arguments[] { pos, named }, loc, false); + g.AttachTo (module, module); + var ctor = g.Resolve (); + if (ctor != null) { + g.ExtractSecurityPermissionSet (ctor, ref declarative_security); + } + } + + if (module.OptAttributes == null) + return; + + // Ensure that we only have GlobalAttributes, since the Search isn't safe with other types. + if (!module.OptAttributes.CheckTargets()) + return; + + cls_attribute = module.ResolveAssemblyAttribute (module.PredefinedAttributes.CLSCompliant); + + if (cls_attribute != null) { + is_cls_compliant = cls_attribute.GetClsCompliantAttributeValue (); + } + + if (added_modules != null && Compiler.Settings.VerifyClsCompliance && is_cls_compliant) { + foreach (var m in added_modules) { + if (!m.IsCLSCompliant) { + Report.Error (3013, + "Added modules must be marked with the CLSCompliant attribute to match the assembly", + m.Name); + } + } + } + + Attribute a = module.ResolveAssemblyAttribute (module.PredefinedAttributes.RuntimeCompatibility); + if (a != null) { + var val = a.GetNamedValue ("WrapNonExceptionThrows") as BoolConstant; + if (val != null) + wrap_non_exception_throws = val.Value; + } + } + + protected void ResolveAssemblySecurityAttributes () + { + string key_file = null; + string key_container = null; + + if (module.OptAttributes != null) { + foreach (Attribute a in module.OptAttributes.Attrs) { + // cannot rely on any resolve-based members before you call Resolve + if (a.ExplicitTarget != "assembly") + continue; + + // TODO: This code is buggy: comparing Attribute name without resolving is wrong. + // However, this is invoked by CodeGen.Init, when none of the namespaces + // are loaded yet. + // TODO: Does not handle quoted attributes properly + switch (a.Name) { + case "AssemblyKeyFile": + case "AssemblyKeyFileAttribute": + case "System.Reflection.AssemblyKeyFileAttribute": + if (Compiler.Settings.StrongNameKeyFile != null) { + Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ()); + Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", + "keyfile", "System.Reflection.AssemblyKeyFileAttribute"); + } else { + string value = a.GetString (); + if (!string.IsNullOrEmpty (value)) { + Error_ObsoleteSecurityAttribute (a, "keyfile"); + key_file = value; + } + } + break; + case "AssemblyKeyName": + case "AssemblyKeyNameAttribute": + case "System.Reflection.AssemblyKeyNameAttribute": + if (Compiler.Settings.StrongNameKeyContainer != null) { + Report.SymbolRelatedToPreviousError (a.Location, a.GetSignatureForError ()); + Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module", + "keycontainer", "System.Reflection.AssemblyKeyNameAttribute"); + } else { + string value = a.GetString (); + if (!string.IsNullOrEmpty (value)) { + Error_ObsoleteSecurityAttribute (a, "keycontainer"); + key_container = value; + } + } + break; + case "AssemblyDelaySign": + case "AssemblyDelaySignAttribute": + case "System.Reflection.AssemblyDelaySignAttribute": + bool b = a.GetBoolean (); + if (b) { + Error_ObsoleteSecurityAttribute (a, "delaysign"); + } + + delay_sign = b; + break; + } + } + } + + // We came here only to report assembly attributes warnings + if (public_key != null) + return; + + // + // Load the strong key file found in attributes when no + // command line key was given + // + if (key_file != null || key_container != null) { + LoadPublicKey (key_file, key_container); + } else if (delay_sign) { + Report.Warning (1607, 1, "Delay signing was requested but no key file was given"); + } + } + + public void EmbedResources () + { + // + // Add Win32 resources + // + if (Compiler.Settings.Win32ResourceFile != null) { + Builder.DefineUnmanagedResource (Compiler.Settings.Win32ResourceFile); + } else { + Builder.DefineVersionInfoResource (); + } + + if (Compiler.Settings.Win32IconFile != null) { + builder_extra.DefineWin32IconResource (Compiler.Settings.Win32IconFile); + } + + if (Compiler.Settings.Resources != null) { + if (Compiler.Settings.Target == Target.Module) { + Report.Error (1507, "Cannot link resource file when building a module"); + } else { + int counter = 0; + foreach (var res in Compiler.Settings.Resources) { + if (!File.Exists (res.FileName)) { + Report.Error (1566, "Error reading resource file `{0}'", res.FileName); + continue; + } + + if (res.IsEmbeded) { + Stream stream; + if (counter++ < 10) { + stream = File.OpenRead (res.FileName); + } else { + // TODO: SRE API requires resource stream to be available during AssemblyBuilder::Save + // we workaround it by reading everything into memory to compile projects with + // many embedded resource (over 3500) references + stream = new MemoryStream (File.ReadAllBytes (res.FileName)); + } + + module.Builder.DefineManifestResource (res.Name, stream, res.Attributes); + } else { + Builder.AddResourceFile (res.Name, Path.GetFileName (res.FileName), res.Attributes); + } + } + } + } + } + + public void Save () + { + PortableExecutableKinds pekind; + ImageFileMachine machine; + + switch (Compiler.Settings.Platform) { + case Platform.X86: + pekind = PortableExecutableKinds.Required32Bit | PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.I386; + break; + case Platform.X64: + pekind = PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.AMD64; + break; + case Platform.IA64: + pekind = PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.IA64; + break; + case Platform.AnyCPU: + default: + pekind = PortableExecutableKinds.ILOnly; + machine = ImageFileMachine.I386; + break; + } + + Compiler.TimeReporter.Start (TimeReporter.TimerType.OutputSave); + try { + if (Compiler.Settings.Target == Target.Module) { + SaveModule (pekind, machine); + } else { + Builder.Save (module.Builder.ScopeName, pekind, machine); + } + } catch (Exception e) { + Report.Error (16, "Could not write to file `" + name + "', cause: " + e.Message); + } + Compiler.TimeReporter.Stop (TimeReporter.TimerType.OutputSave); + + // Save debug symbols file + if (symbol_writer != null) { + // TODO: it should run in parallel + Compiler.TimeReporter.Start (TimeReporter.TimerType.DebugSave); + symbol_writer.WriteSymbolFile (SymbolWriter.GetGuid (module.Builder)); + Compiler.TimeReporter.Stop (TimeReporter.TimerType.DebugSave); + } + } + + protected virtual void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine) + { + Report.RuntimeMissingSupport (Location.Null, "-target:module"); + } + + void SetCustomAttribute (MethodSpec ctor, byte[] data) + { + if (module_target_attrs != null) + module_target_attrs.AddAssemblyAttribute (ctor, data); + else + Builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data); + } + + void SetEntryPoint () + { + if (!Compiler.Settings.NeedsEntryPoint) { + if (Compiler.Settings.MainClass != null) + Report.Error (2017, "Cannot specify -main if building a module or library"); + + return; + } + + PEFileKinds file_kind; + + switch (Compiler.Settings.Target) { + case Target.Library: + case Target.Module: + file_kind = PEFileKinds.Dll; + break; + case Target.WinExe: + file_kind = PEFileKinds.WindowApplication; + break; + default: + file_kind = PEFileKinds.ConsoleApplication; + break; + } + + if (entry_point == null) { + string main_class = Compiler.Settings.MainClass; + if (main_class != null) { + // TODO: Handle dotted names + var texpr = module.GlobalRootNamespace.LookupType (module, main_class, 0, LookupMode.Probing, Location.Null); + if (texpr == null) { + Report.Error (1555, "Could not find `{0}' specified for Main method", main_class); + return; + } + + var mtype = texpr.Type.MemberDefinition as ClassOrStruct; + if (mtype == null) { + Report.Error (1556, "`{0}' specified for Main method must be a valid class or struct", main_class); + return; + } + + Report.Error (1558, mtype.Location, "`{0}' does not have a suitable static Main method", mtype.GetSignatureForError ()); + } else { + string pname = file_name == null ? name : Path.GetFileName (file_name); + Report.Error (5001, "Program `{0}' does not contain a static `Main' method suitable for an entry point", + pname); + } + + return; + } + + Builder.SetEntryPoint (entry_point.MethodBuilder, file_kind); + } + + void Error_ObsoleteSecurityAttribute (Attribute a, string option) + { + Report.Warning (1699, 1, a.Location, + "Use compiler option `{0}' or appropriate project settings instead of `{1}' attribute", + option, a.Name); + } + + void Error_AssemblySigning (string text) + { + Report.Error (1548, "Error during assembly signing. " + text); + } + + public bool IsFriendAssemblyTo (IAssemblyDefinition assembly) + { + return false; + } + + static Version IsValidAssemblyVersion (string version, bool allowGenerated) + { + string[] parts = version.Split ('.'); + if (parts.Length < 1 || parts.Length > 4) + return null; + + var values = new int[4]; + for (int i = 0; i < parts.Length; ++i) { + if (!int.TryParse (parts[i], out values[i])) { + if (parts[i].Length == 1 && parts[i][0] == '*' && allowGenerated) { + if (i == 2) { + // Nothing can follow * + if (parts.Length > 3) + return null; + + // Generate Build value based on days since 1/1/2000 + TimeSpan days = DateTime.Today - new DateTime (2000, 1, 1); + values[i] = System.Math.Max (days.Days, 0); + i = 3; + } + + if (i == 3) { + // Generate Revision value based on every other second today + var seconds = DateTime.Now - DateTime.Today; + values[i] = (int) seconds.TotalSeconds / 2; + continue; + } + } + + return null; + } + + if (values[i] > ushort.MaxValue) + return null; + } + + return new Version (values[0], values[1], values[2], values[3]); + } + } + + public class AssemblyResource : IEquatable + { + public AssemblyResource (string fileName, string name) + : this (fileName, name, false) + { + } + + public AssemblyResource (string fileName, string name, bool isPrivate) + { + FileName = fileName; + Name = name; + Attributes = isPrivate ? ResourceAttributes.Private : ResourceAttributes.Public; + } + + public ResourceAttributes Attributes { get; private set; } + public string Name { get; private set; } + public string FileName { get; private set; } + public bool IsEmbeded { get; set; } + + #region IEquatable Members + + public bool Equals (AssemblyResource other) + { + return Name == other.Name; + } + + #endregion + } + + // + // A placeholder class for assembly attributes when emitting module + // + class AssemblyAttributesPlaceholder : CompilerGeneratedClass + { + static readonly string TypeNamePrefix = "<$AssemblyAttributes${0}>"; + public static readonly string AssemblyFieldName = "attributes"; + + Field assembly; + + public AssemblyAttributesPlaceholder (ModuleContainer parent, string outputName) + : base (parent, new MemberName (GetGeneratedName (outputName)), Modifiers.STATIC) + { + assembly = new Field (this, new TypeExpression (parent.Compiler.BuiltinTypes.Object, Location), Modifiers.PUBLIC | Modifiers.STATIC, + new MemberName (AssemblyFieldName), null); + + AddField (assembly); + } + + public void AddAssemblyAttribute (MethodSpec ctor, byte[] data) + { + assembly.SetCustomAttribute (ctor, data); + } + + public static string GetGeneratedName (string outputName) + { + return string.Format (TypeNamePrefix, outputName); + } + } + + // + // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible + // compiler. This is a default implementation for framework System.Reflection.Emit + // which does not implement any of the methods + // + public class AssemblyBuilderExtension + { + readonly CompilerContext ctx; + + public AssemblyBuilderExtension (CompilerContext ctx) + { + this.ctx = ctx; + } + + public virtual System.Reflection.Module AddModule (string module) + { + ctx.Report.RuntimeMissingSupport (Location.Null, "-addmodule"); + return null; + } + + public virtual void AddPermissionRequests (PermissionSet[] permissions) + { + ctx.Report.RuntimeMissingSupport (Location.Null, "assembly declarative security"); + } + + public virtual void AddTypeForwarder (TypeSpec type, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "TypeForwardedToAttribute"); + } + + public virtual void DefineWin32IconResource (string fileName) + { + ctx.Report.RuntimeMissingSupport (Location.Null, "-win32icon"); + } + + public virtual void SetAlgorithmId (uint value, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyAlgorithmIdAttribute"); + } + + public virtual void SetCulture (string culture, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyCultureAttribute"); + } + + public virtual void SetFlags (uint flags, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyFlagsAttribute"); + } + + public virtual void SetVersion (Version version, Location loc) + { + ctx.Report.RuntimeMissingSupport (loc, "AssemblyVersionAttribute"); + } + } + + abstract class AssemblyReferencesLoader + { + protected readonly CompilerContext compiler; + + protected readonly List paths; + + public AssemblyReferencesLoader (CompilerContext compiler) + { + this.compiler = compiler; + + paths = new List (); + paths.AddRange (compiler.Settings.ReferencesLookupPaths); + paths.Add (Directory.GetCurrentDirectory ()); + } + + public abstract bool HasObjectType (T assembly); + protected abstract string[] GetDefaultReferences (); + public abstract T LoadAssemblyFile (string fileName); + public abstract T LoadAssemblyDefault (string assembly); + public abstract void LoadReferences (ModuleContainer module); + + protected void Error_FileNotFound (string fileName) + { + compiler.Report.Error (6, "Metadata file `{0}' could not be found", fileName); + } + + protected void Error_FileCorrupted (string fileName) + { + compiler.Report.Error (9, "Metadata file `{0}' does not contain valid metadata", fileName); + } + + protected void Error_AssemblyIsModule (string fileName) + { + compiler.Report.Error (1509, + "Referenced assembly file `{0}' is a module. Consider using `-addmodule' option to add the module", + fileName); + } + + protected void Error_ModuleIsAssembly (string fileName) + { + compiler.Report.Error (1542, + "Added module file `{0}' is an assembly. Consider using `-r' option to reference the file", + fileName); + } + + protected void LoadReferencesCore (ModuleContainer module, out T corlib_assembly, out List> loaded) + { + compiler.TimeReporter.Start (TimeReporter.TimerType.ReferencesLoading); + + loaded = new List> (); + + // + // Load mscorlib.dll as the first + // + if (module.Compiler.Settings.StdLib) { + corlib_assembly = LoadAssemblyDefault ("mscorlib.dll"); + } else { + corlib_assembly = default (T); + } + + T a; + foreach (string r in module.Compiler.Settings.AssemblyReferences) { + a = LoadAssemblyFile (r); + if (a == null || EqualityComparer.Default.Equals (a, corlib_assembly)) + continue; + + var key = Tuple.Create (module.GlobalRootNamespace, a); + if (loaded.Contains (key)) + continue; + + // A corlib assembly is the first assembly which contains System.Object + if (corlib_assembly == null && HasObjectType (a)) { + corlib_assembly = a; + continue; + } + + loaded.Add (key); + } + + foreach (var entry in module.Compiler.Settings.AssemblyReferencesAliases) { + a = LoadAssemblyFile (entry.Item2); + if (a == null) + continue; + + var key = Tuple.Create (module.CreateRootNamespace (entry.Item1), a); + if (loaded.Contains (key)) + continue; + + loaded.Add (key); + } + + if (compiler.Settings.LoadDefaultReferences) { + foreach (string r in GetDefaultReferences ()) { + a = LoadAssemblyDefault (r); + if (a == null) + continue; + + var key = Tuple.Create (module.GlobalRootNamespace, a); + if (loaded.Contains (key)) + continue; + + loaded.Add (key); + } + } + + compiler.TimeReporter.Stop (TimeReporter.TimerType.ReferencesLoading); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs new file mode 100644 index 0000000000..6fd2a7a03a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs @@ -0,0 +1,786 @@ +// +// assign.cs: Assignments. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004-2008 Novell, Inc +// +using System; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// This interface is implemented by expressions that can be assigned to. + /// + /// + /// This interface is implemented by Expressions whose values can not + /// store the result on the top of the stack. + /// + /// Expressions implementing this (Properties, Indexers and Arrays) would + /// perform an assignment of the Expression "source" into its final + /// location. + /// + /// No values on the top of the stack are expected to be left by + /// invoking this method. + /// + public interface IAssignMethod { + // + // This is an extra version of Emit. If leave_copy is `true' + // A copy of the expression will be left on the stack at the + // end of the code generated for EmitAssign + // + void Emit (EmitContext ec, bool leave_copy); + + // + // This method does the assignment + // `source' will be stored into the location specified by `this' + // if `leave_copy' is true, a copy of `source' will be left on the stack + // if `prepare_for_load' is true, when `source' is emitted, there will + // be data on the stack that it can use to compuatate its value. This is + // for expressions like a [f ()] ++, where you can't call `f ()' twice. + // + void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); + + /* + For simple assignments, this interface is very simple, EmitAssign is called with source + as the source expression and leave_copy and prepare_for_load false. + + For compound assignments it gets complicated. + + EmitAssign will be called as before, however, prepare_for_load will be + true. The @source expression will contain an expression + which calls Emit. So, the calls look like: + + this.EmitAssign (ec, source, false, true) -> + source.Emit (ec); -> + [...] -> + this.Emit (ec, false); -> + end this.Emit (ec, false); -> + end [...] + end source.Emit (ec); + end this.EmitAssign (ec, source, false, true) + + + When prepare_for_load is true, EmitAssign emits a `token' on the stack that + Emit will use for its state. + + Let's take FieldExpr as an example. assume we are emitting f ().y += 1; + + Here is the call tree again. This time, each call is annotated with the IL + it produces: + + this.EmitAssign (ec, source, false, true) + call f + dup + + Binary.Emit () + this.Emit (ec, false); + ldfld y + end this.Emit (ec, false); + + IntConstant.Emit () + ldc.i4.1 + end IntConstant.Emit + + add + end Binary.Emit () + + stfld + end this.EmitAssign (ec, source, false, true) + + Observe two things: + 1) EmitAssign left a token on the stack. It was the result of f (). + 2) This token was used by Emit + + leave_copy (in both EmitAssign and Emit) tells the compiler to leave a copy + of the expression at that point in evaluation. This is used for pre/post inc/dec + and for a = x += y. Let's do the above example with leave_copy true in EmitAssign + + this.EmitAssign (ec, source, true, true) + call f + dup + + Binary.Emit () + this.Emit (ec, false); + ldfld y + end this.Emit (ec, false); + + IntConstant.Emit () + ldc.i4.1 + end IntConstant.Emit + + add + end Binary.Emit () + + dup + stloc temp + stfld + ldloc temp + end this.EmitAssign (ec, source, true, true) + + And with it true in Emit + + this.EmitAssign (ec, source, false, true) + call f + dup + + Binary.Emit () + this.Emit (ec, true); + ldfld y + dup + stloc temp + end this.Emit (ec, true); + + IntConstant.Emit () + ldc.i4.1 + end IntConstant.Emit + + add + end Binary.Emit () + + stfld + ldloc temp + end this.EmitAssign (ec, source, false, true) + + Note that these two examples are what happens for ++x and x++, respectively. + */ + } + + /// + /// An Expression to hold a temporary value. + /// + /// + /// The LocalTemporary class is used to hold temporary values of a given + /// type to "simulate" the expression semantics. The local variable is + /// never captured. + /// + /// The local temporary is used to alter the normal flow of code generation + /// basically it creates a local variable, and its emit instruction generates + /// code to access this value, return its address or save its value. + /// + /// If `is_address' is true, then the value that we store is the address to the + /// real value, and not the value itself. + /// + /// This is needed for a value type, because otherwise you just end up making a + /// copy of the value on the stack and modifying it. You really need a pointer + /// to the origional value so that you can modify it in that location. This + /// Does not happen with a class because a class is a pointer -- so you always + /// get the indirection. + /// + /// + public class LocalTemporary : Expression, IMemoryLocation, IAssignMethod { + LocalBuilder builder; + + public LocalTemporary (TypeSpec t) + { + type = t; + eclass = ExprClass.Value; + } + + public LocalTemporary (LocalBuilder b, TypeSpec t) + : this (t) + { + builder = b; + } + + public void Release (EmitContext ec) + { + ec.FreeTemporaryLocal (builder, type); + builder = null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return this; + } + + public override void Emit (EmitContext ec) + { + if (builder == null) + throw new InternalErrorException ("Emit without Store, or after Release"); + + ec.Emit (OpCodes.Ldloc, builder); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + Emit (ec); + + if (leave_copy) + Emit (ec); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + if (prepare_for_load) + throw new NotImplementedException (); + + source.Emit (ec); + + Store (ec); + + if (leave_copy) + Emit (ec); + } + + #endregion + + public LocalBuilder Builder { + get { return builder; } + } + + public void Store (EmitContext ec) + { + if (builder == null) + builder = ec.GetTemporaryLocal (type); + + ec.Emit (OpCodes.Stloc, builder); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + if (builder == null) + builder = ec.GetTemporaryLocal (type); + + if (builder.LocalType.IsByRef) { + // + // if is_address, than this is just the address anyways, + // so we just return this. + // + ec.Emit (OpCodes.Ldloc, builder); + } else { + ec.Emit (OpCodes.Ldloca, builder); + } + } + } + + /// + /// The Assign node takes care of assigning the value of source into + /// the expression represented by target. + /// + public abstract class Assign : ExpressionStatement { + protected Expression target, source; + + protected Assign (Expression target, Expression source, Location loc) + { + this.target = target; + this.source = source; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator"); + return null; + } + + public Expression Target { + get { return target; } + } + + public Expression Source { + get { + return source; + } + } + + protected override Expression DoResolve (ResolveContext ec) + { + bool ok = true; + source = source.Resolve (ec); + + if (source == null) { + ok = false; + source = EmptyExpression.Null; + } + + target = target.ResolveLValue (ec, source); + + if (target == null || !ok) + return null; + + TypeSpec target_type = target.Type; + TypeSpec source_type = source.Type; + + eclass = ExprClass.Value; + type = target_type; + + if (!(target is IAssignMethod)) { + Error_ValueAssignment (ec, loc); + return null; + } + + if (target_type != source_type) { + Expression resolved = ResolveConversions (ec); + + if (resolved != this) + return resolved; + } + + return this; + } + +#if NET_4_0 + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + var tassign = target as IDynamicAssign; + if (tassign == null) + throw new InternalErrorException (target.GetType () + " does not support dynamic assignment"); + + var target_object = tassign.MakeAssignExpression (ctx, source); + + // + // Some hacking is needed as DLR does not support void type and requires + // always have object convertible return type to support caching and chaining + // + // We do this by introducing an explicit block which returns RHS value when + // available or null + // + if (target_object.NodeType == System.Linq.Expressions.ExpressionType.Block) + return target_object; + + System.Linq.Expressions.UnaryExpression source_object; + if (ctx.HasSet (BuilderContext.Options.CheckedScope)) { + source_object = System.Linq.Expressions.Expression.ConvertChecked (source.MakeExpression (ctx), target_object.Type); + } else { + source_object = System.Linq.Expressions.Expression.Convert (source.MakeExpression (ctx), target_object.Type); + } + + return System.Linq.Expressions.Expression.Assign (target_object, source_object); + } +#endif + protected virtual Expression ResolveConversions (ResolveContext ec) + { + source = Convert.ImplicitConversionRequired (ec, source, target.Type, source.Location); + if (source == null) + return null; + + return this; + } + + void Emit (EmitContext ec, bool is_statement) + { + IAssignMethod t = (IAssignMethod) target; + t.EmitAssign (ec, source, !is_statement, this is CompoundAssign); + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec, true); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Assign _target = (Assign) t; + + _target.target = target.Clone (clonectx); + _target.source = source.Clone (clonectx); + } + } + + public class SimpleAssign : Assign + { + public SimpleAssign (Expression target, Expression source) + : this (target, source, target.Location) + { + } + + public SimpleAssign (Expression target, Expression source, Location loc) + : base (target, source, loc) + { + } + + bool CheckEqualAssign (Expression t) + { + if (source is Assign) { + Assign a = (Assign) source; + if (t.Equals (a.Target)) + return true; + return a is SimpleAssign && ((SimpleAssign) a).CheckEqualAssign (t); + } + return t.Equals (source); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = base.DoResolve (ec); + if (e == null || e != this) + return e; + + if (CheckEqualAssign (target)) + ec.Report.Warning (1717, 3, loc, "Assignment made to same variable; did you mean to assign something else?"); + + return this; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class RuntimeExplicitAssign : Assign + { + public RuntimeExplicitAssign (Expression target, Expression source) + : base (target, source, target.Location) + { + } + + protected override Expression ResolveConversions (ResolveContext ec) + { + source = EmptyCast.Create (source, target.Type); + return this; + } + } + + // + // Compiler generated assign + // + class CompilerAssign : Assign + { + public CompilerAssign (Expression target, Expression source, Location loc) + : base (target, source, loc) + { + } + + public void UpdateSource (Expression source) + { + base.source = source; + } + } + + // + // Implements fields and events class initializers + // + public class FieldInitializer : Assign + { + // + // Field initializers are tricky for partial classes. They have to + // share same constructor (block) for expression trees resolve but + // they have they own resolve scope + // + sealed class FieldInitializerContext : ResolveContext + { + ExplicitBlock ctor_block; + + public FieldInitializerContext (IMemberContext mc, ResolveContext constructorContext) + : base (mc, Options.FieldInitializerScope | Options.ConstructorScope) + { + this.ctor_block = constructorContext.CurrentBlock.Explicit; + } + + public override ExplicitBlock ConstructorBlock { + get { + return ctor_block; + } + } + } + + // + // Keep resolved value because field initializers have their own rules + // + ExpressionStatement resolved; + IMemberContext mc; + + public FieldInitializer (FieldSpec spec, Expression expression, IMemberContext mc) + : base (new FieldExpr (spec, expression.Location), expression, expression.Location) + { + this.mc = mc; + if (!spec.IsStatic) + ((FieldExpr)target).InstanceExpression = new CompilerGeneratedThis (mc.CurrentType, expression.Location); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // Field initializer can be resolved (fail) many times + if (source == null) + return null; + + if (resolved == null) { + var ctx = new FieldInitializerContext (mc, ec); + resolved = base.DoResolve (ctx) as ExpressionStatement; + } + + return resolved; + } + + public override void EmitStatement (EmitContext ec) + { + if (resolved == null) + return; + + if (resolved != this) + resolved.EmitStatement (ec); + else + base.EmitStatement (ec); + } + + public bool IsComplexInitializer { + get { return !(source is Constant); } + } + + public bool IsDefaultInitializer { + get { + Constant c = source as Constant; + if (c == null) + return false; + + FieldExpr fe = (FieldExpr)target; + return c.IsDefaultInitializer (fe.Type); + } + } + } + + // + // This class is used for compound assignments. + // + public class CompoundAssign : Assign + { + // This is just a hack implemented for arrays only + public sealed class TargetExpression : Expression + { + Expression child; + public TargetExpression (Expression child) + { + this.child = child; + this.loc = child.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = child.Type; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + } + } + + // Used for underlying binary operator + readonly Binary.Operator op; + Expression right; + Expression left; + + public Binary.Operator Op { + get { + return op; + } + } + + public CompoundAssign (Binary.Operator op, Expression target, Expression source, Location loc) + : base (target, source, loc) + { + right = source; + this.op = op; + } + + public CompoundAssign (Binary.Operator op, Expression target, Expression source, Expression left, Location loc) + : this (op, target, source, loc) + { + this.left = left; + } + + protected override Expression DoResolve (ResolveContext ec) + { + right = right.Resolve (ec); + if (right == null) + return null; + + MemberAccess ma = target as MemberAccess; + using (ec.Set (ResolveContext.Options.CompoundAssignmentScope)) { + target = target.Resolve (ec); + } + + if (target == null) + return null; + + if (target is MethodGroupExpr){ + ec.Report.Error (1656, loc, + "Cannot assign to `{0}' because it is a `{1}'", + ((MethodGroupExpr)target).Name, target.ExprClassName); + return null; + } + + var event_expr = target as EventExpr; + if (event_expr != null) { + source = Convert.ImplicitConversionRequired (ec, right, target.Type, loc); + if (source == null) + return null; + + Expression rside; + if (op == Binary.Operator.Addition) + rside = EmptyExpression.EventAddition; + else if (op == Binary.Operator.Subtraction) + rside = EmptyExpression.EventSubtraction; + else + rside = null; + + target = target.ResolveLValue (ec, rside); + if (target == null) + return null; + + eclass = ExprClass.Value; + type = event_expr.Operator.ReturnType; + return this; + } + + // + // Only now we can decouple the original source/target + // into a tree, to guarantee that we do not have side + // effects. + // + if (left == null) + left = new TargetExpression (target); + + source = new Binary (op, left, right, true, loc); + + if (target is DynamicMemberAssignable) { + Arguments targs = ((DynamicMemberAssignable) target).Arguments; + source = source.Resolve (ec); + + Arguments args = new Arguments (targs.Count + 1); + args.AddRange (targs); + args.Add (new Argument (source)); + + var binder_flags = CSharpBinderFlags.ValueFromCompoundAssignment; + + // + // Compound assignment does target conversion using additional method + // call, set checked context as the binary operation can overflow + // + if (ec.HasSet (ResolveContext.Options.CheckedScope)) + binder_flags |= CSharpBinderFlags.CheckedContext; + + if (target is DynamicMemberBinder) { + source = new DynamicMemberBinder (ma.Name, binder_flags, args, loc).Resolve (ec); + + // Handles possible event addition/subtraction + if (op == Binary.Operator.Addition || op == Binary.Operator.Subtraction) { + args = new Arguments (targs.Count + 1); + args.AddRange (targs); + args.Add (new Argument (right)); + string method_prefix = op == Binary.Operator.Addition ? + Event.AEventAccessor.AddPrefix : Event.AEventAccessor.RemovePrefix; + + var invoke = DynamicInvocation.CreateSpecialNameInvoke ( + new MemberAccess (right, method_prefix + ma.Name, loc), args, loc).Resolve (ec); + + args = new Arguments (targs.Count); + args.AddRange (targs); + source = new DynamicEventCompoundAssign (ma.Name, args, + (ExpressionStatement) source, (ExpressionStatement) invoke, loc).Resolve (ec); + } + } else { + source = new DynamicIndexBinder (binder_flags, args, loc).Resolve (ec); + } + + return source; + } + + return base.DoResolve (ec); + } + + protected override Expression ResolveConversions (ResolveContext ec) + { + // + // LAMESPEC: Under dynamic context no target conversion is happening + // This allows more natual dynamic behaviour but breaks compatibility + // with static binding + // + if (target is RuntimeValueExpression) + return this; + + TypeSpec target_type = target.Type; + + // + // 1. the return type is implicitly convertible to the type of target + // + if (Convert.ImplicitConversionExists (ec, source, target_type)) { + source = Convert.ImplicitConversion (ec, source, target_type, loc); + return this; + } + + // + // Otherwise, if the selected operator is a predefined operator + // + Binary b = source as Binary; + if (b == null && source is ReducedExpression) + b = ((ReducedExpression) source).OriginalExpression as Binary; + + if (b != null) { + // + // 2a. the operator is a shift operator + // + // 2b. the return type is explicitly convertible to the type of x, and + // y is implicitly convertible to the type of x + // + if ((b.Oper & Binary.Operator.ShiftMask) != 0 || + Convert.ImplicitConversionExists (ec, right, target_type)) { + source = Convert.ExplicitConversion (ec, source, target_type, loc); + return this; + } + } + + if (source.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments arg = new Arguments (1); + arg.Add (new Argument (source)); + return new SimpleAssign (target, new DynamicConversion (target_type, CSharpBinderFlags.ConvertExplicit, arg, loc), loc).Resolve (ec); + } + + right.Error_ValueCannotBeConverted (ec, loc, target_type, false); + return null; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CompoundAssign ctarget = (CompoundAssign) t; + + ctarget.right = ctarget.source = source.Clone (clonectx); + ctarget.target = target.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs new file mode 100644 index 0000000000..1a1345013f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs @@ -0,0 +1,614 @@ +// +// async.cs: Asynchronous functions +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2011 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Linq; +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + class Await : ExpressionStatement + { + Expression expr; + AwaitStatement stmt; + + public Await (Expression expr, Location loc) + { + this.expr = expr; + 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"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + if (rc.HasSet (ResolveContext.Options.FinallyScope)) { + rc.Report.Error (1984, loc, + "The `await' operator cannot be used in the body of a finally clause"); + } + + if (rc.HasSet (ResolveContext.Options.CatchScope)) { + rc.Report.Error (1985, loc, + "The `await' operator cannot be used in the body of a catch clause"); + } + + if (rc.HasSet (ResolveContext.Options.LockScope)) { + rc.Report.Error (1996, loc, + "The `await' operator cannot be used in the body of a lock statement"); + } + + if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) { + rc.Report.Error (1989, loc, "An expression tree cannot contain an await operator"); + return null; + } + + if (rc.IsUnsafe) { + // TODO: New error code + rc.Report.Error (-1900, 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; + + type = stmt.ResultType; + eclass = ExprClass.Variable; + return this; + } + + 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); + } + + public override void EmitStatement (EmitContext ec) + { + stmt.EmitStatement (ec); + } + } + + class AwaitStatement : YieldStatement + { + sealed class AwaitableMemberAccess : MemberAccess + { + public AwaitableMemberAccess (Expression expr) + : base (expr, "GetAwaiter") + { + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext rc, TypeSpec type, string name) + { + Error_WrongGetAwaiter (rc, loc, type); + } + + protected override void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) + { + rc.Report.Error (1991, loc, "Cannot await `{0}' expression", type.GetSignatureForError ()); + } + } + + Field awaiter; + PropertyExpr is_completed; + MethodSpec on_completed; + MethodSpec get_result; + TypeSpec type; + + public AwaitStatement (Expression expr, Location loc) + : base (expr, loc) + { + } + + #region Properties + + public TypeSpec Type { + get { + return type; + } + } + + public TypeSpec ResultType { + get { + return get_result.ReturnType; + } + } + + #endregion + + protected override void DoEmit (EmitContext ec) + { + 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 (); + // + fe_awaiter.EmitAssign (ec, expr, false, false); + + is_completed.InstanceExpression = fe_awaiter; + is_completed.EmitBranchable (ec, resume_point, true); + + var mg_completed = MethodGroupExpr.CreatePredefined (on_completed, fe_awaiter.Type, loc); + mg_completed.InstanceExpression = fe_awaiter; + + 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); + + args.Add (new Argument (fe_cont)); + + // + // awaiter.OnCompleted (continuation); + // + mg_completed.EmitCall (ec, args); + + base.DoEmit (ec); + } + + public void EmitStatement (EmitContext ec) + { + EmitPrologue (ec); + Emit (ec); + + if (ResultType.Kind != MemberKind.Void) { + var storey = (AsyncTaskStorey) machine_initializer.Storey; + + if (storey.HoistedReturn != null) + storey.HoistedReturn.EmitAssign (ec); + else + ec.Emit (OpCodes.Pop); + } + } + + 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", + awaiter.GetSignatureForError ()); + } + + public override bool Resolve (BlockContext bc) + { + if (!base.Resolve (bc)) + return false; + + type = expr.Type; + + // + // The task result is of dynamic type + // + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + throw new NotImplementedException ("dynamic await"); + + // + // Check whether the expression is awaitable + // + Expression ama = new AwaitableMemberAccess (expr).Resolve (bc); + if (ama == null) + return false; + + Arguments args = new Arguments (0); + + var errors_printer = new SessionReportPrinter (); + var old = bc.Report.SetPrinter (errors_printer); + ama = new Invocation (ama, args).Resolve (bc); + + if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) { + bc.Report.SetPrinter (old); + Error_WrongGetAwaiter (bc, loc, expr.Type); + return false; + } + + var awaiter_type = ama.Type; + awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (awaiter_type, loc); + expr = ama; + + // + // Predefined: bool IsCompleted { get; } + // + var is_completed_ma = new MemberAccess (expr, "IsCompleted").Resolve (bc); + if (is_completed_ma != null) { + is_completed = is_completed_ma as PropertyExpr; + if (is_completed != null && is_completed.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && is_completed.IsInstance && is_completed.Getter != null) { + // valid + } else { + bc.Report.SetPrinter (old); + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + } + + bc.Report.SetPrinter (old); + + if (errors_printer.ErrorsCount > 0) { + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + + // + // Predefined: OnCompleted (Action) + // + if (bc.Module.PredefinedTypes.Action.Define ()) { + on_completed = MemberCache.FindMember (awaiter_type, MemberFilter.Method ("OnCompleted", 0, + ParametersCompiled.CreateFullyResolved (bc.Module.PredefinedTypes.Action.TypeSpec), bc.Module.Compiler.BuiltinTypes.Void), + BindingRestriction.InstanceOnly) as MethodSpec; + + if (on_completed == null) { + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + } + + // + // Predefined: GetResult () + // + // The method return type is also result type of await expression + // + get_result = MemberCache.FindMember (awaiter_type, MemberFilter.Method ("GetResult", 0, + ParametersCompiled.EmptyReadOnlyParameters, null), + BindingRestriction.InstanceOnly) as MethodSpec; + + if (get_result == null) { + Error_WrongAwaiterPattern (bc, awaiter_type); + return false; + } + + return true; + } + } + + 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"; + } + } + + public override bool IsIterator { + get { + return false; + } + } + + 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 != 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"); + } + + for (int i = 0; i < parameters.Count; i++) { + Parameter p = parameters[i]; + Parameter.Modifier mod = p.ModFlags; + if ((mod & Parameter.Modifier.ISBYREF) != 0) { + host.Compiler.Report.Error (1988, p.Location, + "Async methods cannot have ref or out parameters"); + return; + } + + // TODO: + if (p is ArglistParameter) { + host.Compiler.Report.Error (1636, p.Location, + "__arglist is not allowed in parameter list of iterators"); + return; + } + + // TODO: + if (parameters.Types[i].IsPointer) { + host.Compiler.Report.Error (1637, p.Location, + "Iterators cannot have unsafe parameters or yield types"); + return; + } + } + + // TODO: Warning + //if (!block.HasAwait) { + //} + + 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); + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + + protected override void EmitMoveNextEpilogue (EmitContext ec) + { + var storey = (AsyncTaskStorey) Storey; + storey.EmitSetResult (ec); + } + + public override void EmitStatement (EmitContext ec) + { + var storey = (AsyncTaskStorey) Storey; + storey.Instance.Emit (ec); + ec.Emit (OpCodes.Call, storey.StateMachineMethod.Spec); + + if (storey.Task != null) { + // + // async.$builder.Task; + // + var pe_task = new PropertyExpr (storey.Task, loc) { + InstanceExpression = new FieldExpr (storey.Builder, loc) { + InstanceExpression = storey.Instance + }, + Getter = storey.Task.Get + }; + + pe_task.Emit (ec); + } + + ec.Emit (OpCodes.Ret); + } + + public override void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) + { + base.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + } + } + + class AsyncTaskStorey : StateMachine + { + int awaiters; + Field builder, continuation; + readonly TypeSpec return_type; + MethodSpec set_result; + PropertySpec task; + LocalVariable hoisted_return; + + public AsyncTaskStorey (AsyncInitializer initializer, TypeSpec type) + : base (initializer.OriginalBlock, initializer.Host, null, null, "async") + { + return_type = type; + } + + public Field AddAwaiter (TypeSpec type, Location loc) + { + return AddCompilerGeneratedField ("$awaiter" + awaiters++.ToString ("X"), new TypeExpression (type, loc)); + } + + #region Properties + + public Field Builder { + get { + return builder; + } + } + + public Field Continuation { + get { + return continuation; + } + } + + public LocalVariable HoistedReturn { + get { + return hoisted_return; + } + } + + public TypeSpec ReturnType { + get { + return return_type; + } + } + + public PropertySpec Task { + get { + return task; + } + } + + #endregion + + protected override bool DoDefineMembers () + { + var action = Module.PredefinedTypes.Action.Resolve (); + if (action != null) { + continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location)); + continuation.ModFlags |= Modifiers.READONLY; + } + + PredefinedType builder_type; + PredefinedMember bf; + PredefinedMember sr; + bool has_task_return_type = false; + var pred_members = Module.PredefinedMembers; + + if (return_type.Kind == MemberKind.Void) { + builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; + bf = pred_members.AsyncVoidMethodBuilderCreate; + sr = pred_members.AsyncVoidMethodBuilderSetResult; + } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { + builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; + bf = pred_members.AsyncTaskMethodBuilderCreate; + sr = pred_members.AsyncTaskMethodBuilderSetResult; + task = pred_members.AsyncTaskMethodBuilderTask.Resolve (Location); + } else { + builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; + bf = pred_members.AsyncTaskMethodBuilderGenericCreate; + sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; + task = pred_members.AsyncTaskMethodBuilderGenericTask.Resolve (Location); + has_task_return_type = true; + } + + set_result = sr.Resolve (Location); + var builder_factory = bf.Resolve (Location); + var bt = builder_type.Resolve (); + if (bt == null || set_result == null || builder_factory == null) + return false; + + // + // Inflate generic Task types + // + if (has_task_return_type) { + bt = bt.MakeGenericType (Module, return_type.TypeArguments); + builder_factory = MemberCache.GetMember (bt, builder_factory); + set_result = MemberCache.GetMember (bt, set_result); + + if (task != null) + task = MemberCache.GetMember (bt, task); + } + + 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); + block.AddStatement ( + new StatementExpression (new SimpleAssign ( + new FieldExpr (builder, Location), + new Invocation (mg, new Arguments (0)), + Location))); + + if (has_task_return_type) { + hoisted_return = LocalVariable.CreateCompilerGenerated (bt.TypeArguments[0], block, Location); + } + + return true; + } + + public void EmitSetResult (EmitContext ec) + { + // + // $builder.SetResult (); + // $builder.SetResult (value); + // + var mg = MethodGroupExpr.CreatePredefined (set_result, set_result.DeclaringType, Location); + mg.InstanceExpression = new FieldExpr (Builder, Location) { + InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location) + }; + + Arguments args; + if (hoisted_return == null) { + args = new Arguments (0); + } else { + args = new Arguments (1); + args.Add (new Argument (new LocalVariableReference (hoisted_return, Location))); + } + + mg.EmitCall (ec, args); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs new file mode 100644 index 0000000000..b58a81351f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs @@ -0,0 +1,2008 @@ +// +// attribute.cs: Attribute Handler +// +// Author: Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// 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. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Security; +using System.Security.Permissions; +using System.Text; +using System.IO; + +#if STATIC +using SecurityType = System.Collections.Generic.List; +using BadImageFormat = IKVM.Reflection.BadImageFormatException; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using SecurityType = System.Collections.Generic.Dictionary; +using BadImageFormat = System.BadImageFormatException; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// Base class for objects that can have Attributes applied to them. + /// + public abstract class Attributable { + // + // Holds all attributes attached to this element + // + protected Attributes attributes; + + public void AddAttributes (Attributes attrs, IMemberContext context) + { + if (attrs == null) + return; + + if (attributes == null) + attributes = attrs; + else + attributes.AddAttributes (attrs.Attrs); + attrs.AttachTo (this, context); + } + + public Attributes OptAttributes { + get { + return attributes; + } + set { + attributes = value; + } + } + + /// + /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder + /// + public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa); + + /// + /// Returns one AttributeTarget for this element. + /// + public abstract AttributeTargets AttributeTargets { get; } + + public abstract bool IsClsComplianceRequired (); + + /// + /// Gets list of valid attribute targets for explicit target declaration. + /// The first array item is default target. Don't break this rule. + /// + public abstract string[] ValidAttributeTargets { get; } + }; + + public class Attribute : Expression + { + public readonly string ExplicitTarget; + public AttributeTargets Target; + readonly ATypeNameExpression expression; + + public Arguments PosArguments; + public Arguments NamedArguments; + + bool resolve_error; + bool arg_resolved; + readonly bool nameEscaped; + + // + // An attribute can be attached to multiple targets (e.g. multiple fields) + // + Attributable[] targets; + + // + // A member context for the attribute, it's much easier to hold it here + // than trying to pull it during resolve + // + IMemberContext context; + + public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All); + public static readonly object[] EmptyObject = new object [0]; + + List> named_values; + + public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped) + { + this.expression = expr; + if (args != null) { + PosArguments = args[0]; + NamedArguments = args[1]; + } + this.loc = loc; + ExplicitTarget = target; + this.nameEscaped = nameEscaped; + } + + void AddModuleCharSet (ResolveContext rc) + { + const string dll_import_char_set = "CharSet"; + + // + // Only when not customized by user + // + if (HasField (dll_import_char_set)) + return; + + if (!rc.Module.PredefinedTypes.CharSet.Define ()) { + return; + } + + if (NamedArguments == null) + NamedArguments = new Arguments (1); + + var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location); + NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value)); + } + + public Attribute Clone () + { + Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped); + a.PosArguments = PosArguments; + a.NamedArguments = NamedArguments; + return a; + } + + // + // When the same attribute is attached to multiple fiels + // we use @target field as a list of targets. The attribute + // has to be resolved only once but emitted for each target. + // + public void AttachTo (Attributable target, IMemberContext context) + { + if (this.targets == null) { + this.targets = new Attributable[] { target }; + this.context = context; + return; + } + + // When re-attaching global attributes + if (context is NamespaceContainer) { + this.targets[0] = target; + this.context = context; + return; + } + + // Resize target array + Attributable[] new_array = new Attributable [this.targets.Length + 1]; + targets.CopyTo (new_array, 0); + new_array [targets.Length] = target; + this.targets = new_array; + + // No need to update context, different targets cannot have + // different contexts, it's enough to remove same attributes + // from secondary members. + + target.OptAttributes = null; + } + + public ResolveContext CreateResolveContext () + { + return new ResolveContext (context, ResolveContext.Options.ConstantScope); + } + + static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name) + { + rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " + + "must be fields which are not readonly, static, const or read-write properties which are " + + "public and not static", + name.Name); + } + + static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name) + { + rc.Report.Error (655, name.Location, + "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type", + name.Name); + } + + public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc) + { + context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression"); + } + + public void Error_MissingGuidAttribute () + { + Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute"); + } + + public void Error_MisusedExtensionAttribute () + { + Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ()); + } + + public void Error_MisusedDynamicAttribute () + { + Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ()); + } + + /// + /// This is rather hack. We report many emit attribute error with same error to be compatible with + /// csc. But because csc has to report them this way because error came from ilasm we needn't. + /// + public void Error_AttributeEmitError (string inner) + { + Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'", + TypeManager.CSharpName (Type), inner); + } + + public void Error_InvalidSecurityParent () + { + Error_AttributeEmitError ("it is attached to invalid parent"); + } + + Attributable Owner { + get { + return targets [0]; + } + } + + /// + /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true. + /// + void ResolveAttributeType () + { + SessionReportPrinter resolve_printer = new SessionReportPrinter (); + ReportPrinter prev_recorder = context.Module.Compiler.Report.SetPrinter (resolve_printer); + + bool t1_is_attr = false; + bool t2_is_attr = false; + TypeSpec t1, t2; + ATypeNameExpression expanded = null; + + // TODO: Additional warnings such as CS0436 are swallowed because we don't + // print on success + + try { + t1 = expression.ResolveAsType (context); + if (t1 != null) + t1_is_attr = t1.IsAttribute; + + resolve_printer.EndSession (); + + if (nameEscaped) { + t2 = null; + } else { + expanded = (ATypeNameExpression) expression.Clone (null); + expanded.Name += "Attribute"; + + t2 = expanded.ResolveAsType (context); + if (t2 != null) + t2_is_attr = t2.IsAttribute; + } + } finally { + context.Module.Compiler.Report.SetPrinter (prev_recorder); + } + + if (t1_is_attr && t2_is_attr && t1 != t2) { + Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'", + GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ()); + resolve_error = true; + return; + } + + if (t1_is_attr) { + Type = t1; + return; + } + + if (t2_is_attr) { + Type = t2; + return; + } + + resolve_error = true; + + if (t1 != null) { + resolve_printer.Merge (prev_recorder); + + Report.SymbolRelatedToPreviousError (t1); + Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ()); + return; + } + + if (t2 != null) { + Report.SymbolRelatedToPreviousError (t2); + Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ()); + return; + } + + resolve_printer.Merge (prev_recorder); + } + + public TypeSpec ResolveType () + { + if (Type == null && !resolve_error) + ResolveAttributeType (); + return Type; + } + + public override string GetSignatureForError () + { + if (Type != null) + return TypeManager.CSharpName (Type); + + return expression.GetSignatureForError (); + } + + public bool HasSecurityAttribute { + get { + PredefinedAttribute pa = context.Module.PredefinedAttributes.Security; + return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false); + } + } + + public bool IsValidSecurityAttribute () + { + return HasSecurityAttribute && IsSecurityActionValid (); + } + + static bool IsValidArgumentType (TypeSpec t) + { + if (t.IsArray) { + var ac = (ArrayContainer) t; + if (ac.Rank > 1) + return false; + + t = ac.Element; + } + + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + case BuiltinTypeSpec.Type.Type: + return true; + } + + return t.IsEnum; + } + + // TODO: Don't use this ambiguous value + public string Name { + get { return expression.Name; } + } + + public ATypeNameExpression TypeNameExpression { + get { + return expression; + } + } + + public Report Report { + get { return context.Module.Compiler.Report; } + } + + public MethodSpec Resolve () + { + if (resolve_error) + return null; + + resolve_error = true; + arg_resolved = true; + + if (Type == null) { + ResolveAttributeType (); + if (Type == null) + return null; + } + + if (Type.IsAbstract) { + Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ()); + return null; + } + + ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete (); + if (obsolete_attr != null) { + AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report); + } + + ResolveContext rc = null; + + MethodSpec ctor; + // Try if the attribute is simple and has been resolved before + if (PosArguments != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) { + rc = CreateResolveContext (); + ctor = ResolveConstructor (rc); + if (ctor == null) { + return null; + } + + if (PosArguments == null && ctor.Parameters.IsEmpty) + context.Module.AttributeConstructorCache.Add (Type, ctor); + } + + // + // Add [module: DefaultCharSet] to all DllImport import attributes + // + var module = context.Module; + if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) { + if (rc == null) + rc = CreateResolveContext (); + + AddModuleCharSet (rc); + } + + if (NamedArguments != null) { + if (rc == null) + rc = CreateResolveContext (); + + if (!ResolveNamedArguments (rc)) + return null; + } + + resolve_error = false; + return ctor; + } + + MethodSpec ResolveConstructor (ResolveContext ec) + { + if (PosArguments != null) { + bool dynamic; + PosArguments.Resolve (ec, out dynamic); + if (dynamic) { + Error_AttributeArgumentIsDynamic (ec.MemberContext, loc); + return null; + } + } + + return ConstructorLookup (ec, Type, ref PosArguments, loc); + } + + bool ResolveNamedArguments (ResolveContext ec) + { + int named_arg_count = NamedArguments.Count; + var seen_names = new List (named_arg_count); + + named_values = new List> (named_arg_count); + + foreach (NamedArgument a in NamedArguments) { + string name = a.Name; + if (seen_names.Contains (name)) { + ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name); + continue; + } + + seen_names.Add (name); + + a.Resolve (ec); + + Expression member = Expression.MemberLookup (ec, false, Type, name, 0, MemberLookupRestrictions.ExactArity, loc); + + if (member == null) { + member = Expression.MemberLookup (ec, true, Type, name, 0, MemberLookupRestrictions.ExactArity, loc); + + if (member != null) { + // TODO: ec.Report.SymbolRelatedToPreviousError (member); + Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc); + return false; + } + } + + if (member == null){ + Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name); + return false; + } + + if (!(member is PropertyExpr || member is FieldExpr)) { + Error_InvalidNamedArgument (ec, a); + return false; + } + + ObsoleteAttribute obsolete_attr; + + if (member is PropertyExpr) { + var pi = ((PropertyExpr) member).PropertyInfo; + + if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) { + ec.Report.SymbolRelatedToPreviousError (pi); + Error_InvalidNamedArgument (ec, a); + return false; + } + + if (!IsValidArgumentType (member.Type)) { + ec.Report.SymbolRelatedToPreviousError (pi); + Error_InvalidNamedArgumentType (ec, a); + return false; + } + + obsolete_attr = pi.GetAttributeObsolete (); + pi.MemberDefinition.SetIsAssigned (); + } else { + var fi = ((FieldExpr) member).Spec; + + if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) { + Error_InvalidNamedArgument (ec, a); + return false; + } + + if (!IsValidArgumentType (member.Type)) { + ec.Report.SymbolRelatedToPreviousError (fi); + Error_InvalidNamedArgumentType (ec, a); + return false; + } + + obsolete_attr = fi.GetAttributeObsolete (); + fi.MemberDefinition.SetIsAssigned (); + } + + if (obsolete_attr != null && !context.IsObsolete) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report); + + if (a.Type != member.Type) { + a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location); + } + + if (a.Expr != null) + named_values.Add (new KeyValuePair ((MemberExpr) member, a)); + } + + return true; + } + + /// + /// Get a string containing a list of valid targets for the attribute 'attr' + /// + public string GetValidTargets () + { + StringBuilder sb = new StringBuilder (); + AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn; + + if ((targets & AttributeTargets.Assembly) != 0) + sb.Append ("assembly, "); + + if ((targets & AttributeTargets.Module) != 0) + sb.Append ("module, "); + + if ((targets & AttributeTargets.Class) != 0) + sb.Append ("class, "); + + if ((targets & AttributeTargets.Struct) != 0) + sb.Append ("struct, "); + + if ((targets & AttributeTargets.Enum) != 0) + sb.Append ("enum, "); + + if ((targets & AttributeTargets.Constructor) != 0) + sb.Append ("constructor, "); + + if ((targets & AttributeTargets.Method) != 0) + sb.Append ("method, "); + + if ((targets & AttributeTargets.Property) != 0) + sb.Append ("property, indexer, "); + + if ((targets & AttributeTargets.Field) != 0) + sb.Append ("field, "); + + if ((targets & AttributeTargets.Event) != 0) + sb.Append ("event, "); + + if ((targets & AttributeTargets.Interface) != 0) + sb.Append ("interface, "); + + if ((targets & AttributeTargets.Parameter) != 0) + sb.Append ("parameter, "); + + if ((targets & AttributeTargets.Delegate) != 0) + sb.Append ("delegate, "); + + if ((targets & AttributeTargets.ReturnValue) != 0) + sb.Append ("return, "); + + if ((targets & AttributeTargets.GenericParameter) != 0) + sb.Append ("type parameter, "); + + return sb.Remove (sb.Length - 2, 2).ToString (); + } + + public AttributeUsageAttribute GetAttributeUsageAttribute () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error) + return DefaultUsageAttribute; + + AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ()); + + var field = GetNamedValue ("AllowMultiple") as BoolConstant; + if (field != null) + usage_attribute.AllowMultiple = field.Value; + + field = GetNamedValue ("Inherited") as BoolConstant; + if (field != null) + usage_attribute.Inherited = field.Value; + + return usage_attribute; + } + + /// + /// Returns custom name of indexer + /// + public string GetIndexerAttributeValue () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error || PosArguments.Count != 1 || !(PosArguments [0].Expr is Constant)) + return null; + + return ((Constant) PosArguments [0].Expr).GetValue () as string; + } + + /// + /// Returns condition of ConditionalAttribute + /// + public string GetConditionalAttributeValue () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error) + return null; + + return ((Constant) PosArguments[0].Expr).GetValue () as string; + } + + /// + /// Creates the instance of ObsoleteAttribute from this attribute instance + /// + public ObsoleteAttribute GetObsoleteAttribute () + { + if (!arg_resolved) { + // corlib only case when obsolete is used before is resolved + var c = type.MemberDefinition as Class; + if (c != null && !c.HasMembersDefined) + c.Define (); + + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + } + + if (resolve_error) + return null; + + if (PosArguments == null) + return new ObsoleteAttribute (); + + string msg = ((Constant) PosArguments[0].Expr).GetValue () as string; + if (PosArguments.Count == 1) + return new ObsoleteAttribute (msg); + + return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value); + } + + /// + /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called + /// before ApplyAttribute. We need to resolve the arguments. + /// This situation occurs when class deps is differs from Emit order. + /// + public bool GetClsCompliantAttributeValue () + { + if (!arg_resolved) + // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args. + // But because a lot of attribute class code must be rewritten will be better to wait... + Resolve (); + + if (resolve_error) + return false; + + return ((BoolConstant) PosArguments[0].Expr).Value; + } + + public TypeSpec GetCoClassAttributeValue () + { + if (!arg_resolved) + Resolve (); + + if (resolve_error) + return null; + + return GetArgumentType (); + } + + public bool CheckTarget () + { + string[] valid_targets = Owner.ValidAttributeTargets; + if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) { + Target = Owner.AttributeTargets; + return true; + } + + // TODO: we can skip the first item + if (Array.Exists (valid_targets, i => i == ExplicitTarget)) { + switch (ExplicitTarget) { + case "return": Target = AttributeTargets.ReturnValue; return true; + case "param": Target = AttributeTargets.Parameter; return true; + case "field": Target = AttributeTargets.Field; return true; + case "method": Target = AttributeTargets.Method; return true; + case "property": Target = AttributeTargets.Property; return true; + case "module": Target = AttributeTargets.Module; return true; + } + throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget); + } + + StringBuilder sb = new StringBuilder (); + foreach (string s in valid_targets) { + sb.Append (s); + sb.Append (", "); + } + sb.Remove (sb.Length - 2, 2); + Report.Warning (657, 1, Location, + "`{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are `{1}'. All attributes in this section will be ignored", + ExplicitTarget, sb.ToString ()); + return false; + } + + /// + /// Tests permitted SecurityAction for assembly or other types + /// + bool IsSecurityActionValid () + { + SecurityAction action = GetSecurityActionValue (); + bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module; + + switch (action) { +#pragma warning disable 618 + case SecurityAction.Demand: + case SecurityAction.Assert: + case SecurityAction.Deny: + case SecurityAction.PermitOnly: + case SecurityAction.LinkDemand: + case SecurityAction.InheritanceDemand: + if (!for_assembly) + return true; + break; + + case SecurityAction.RequestMinimum: + case SecurityAction.RequestOptional: + case SecurityAction.RequestRefuse: + if (for_assembly) + return true; + break; +#pragma warning restore 618 + + default: + Error_AttributeEmitError ("SecurityAction is out of range"); + return false; + } + + Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration")); + return false; + } + + System.Security.Permissions.SecurityAction GetSecurityActionValue () + { + return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue (); + } + + /// + /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table. + /// + /// + public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions) + { +#if STATIC + object[] values = new object [PosArguments.Count]; + for (int i = 0; i < values.Length; ++i) + values [i] = ((Constant) PosArguments [i].Expr).GetValue (); + + PropertyInfo[] prop; + object[] prop_values; + if (named_values == null) { + prop = null; + prop_values = null; + } else { + prop = new PropertyInfo[named_values.Count]; + prop_values = new object [named_values.Count]; + for (int i = 0; i < prop.Length; ++i) { + prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo; + prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue (); + } + } + + if (permissions == null) + permissions = new SecurityType (); + + var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values); + permissions.Add (cab); +#else + throw new NotSupportedException (); +#endif + } + + public Constant GetNamedValue (string name) + { + if (named_values == null) + return null; + + for (int i = 0; i < named_values.Count; ++i) { + if (named_values [i].Value.Name == name) + return named_values [i].Value.Expr as Constant; + } + + return null; + } + + public CharSet GetCharSetValue () + { + return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ()); + } + + public bool HasField (string fieldName) + { + if (named_values == null) + return false; + + foreach (var na in named_values) { + if (na.Value.Name == fieldName) + return true; + } + + return false; + } + + // + // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value + // + public bool IsInternalCall () + { + MethodImplOptions options = 0; + if (PosArguments.Count == 1) { + options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ()); + } else if (HasField ("Value")) { + var named = GetNamedValue ("Value"); + options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ()); + } + + return (options & MethodImplOptions.InternalCall) != 0; + } + + // + // Returns true for StructLayoutAttribute with LayoutKind.Explicit value + // + public bool IsExplicitLayoutKind () + { + if (PosArguments == null || PosArguments.Count != 1) + return false; + + var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ()); + return value == LayoutKind.Explicit; + } + + public Expression GetParameterDefaultValue () + { + if (PosArguments == null) + return null; + + return PosArguments[0].Expr; + } + + public override bool Equals (object obj) + { + Attribute a = obj as Attribute; + if (a == null) + return false; + + return Type == a.Type && Target == a.Target; + } + + public override int GetHashCode () + { + return type.GetHashCode () ^ Target.GetHashCode (); + } + + /// + /// Emit attribute for Attributable symbol + /// + public void Emit (Dictionary> allEmitted) + { + var ctor = Resolve (); + if (ctor == null) + return; + + var predefined = context.Module.PredefinedAttributes; + + AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage); + if ((usage_attr.ValidOn & Target) == 0) { + Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " + + "It is valid on `{1}' declarations only", + GetSignatureForError (), GetValidTargets ()); + return; + } + + byte[] cdata; + if (PosArguments == null && named_values == null) { + cdata = AttributeEncoder.Empty; + } else { + AttributeEncoder encoder = new AttributeEncoder (); + + if (PosArguments != null) { + var param_types = ctor.Parameters.Types; + for (int j = 0; j < PosArguments.Count; ++j) { + var pt = param_types[j]; + var arg_expr = PosArguments[j].Expr; + 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)) { + context.Module.Compiler.Report.Error (633, arg_expr.Location, + "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ()); + return; + } + } else if (Type == predefined.Guid) { + try { + string v = ((StringConstant) arg_expr).Value; + new Guid (v); + } catch (Exception e) { + Error_AttributeEmitError (e.Message); + return; + } + } else if (Type == predefined.AttributeUsage) { + int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value; + if (v == 0) { + context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute", + "System.AttributeUsage"); + } + } else if (Type == predefined.MarshalAs) { + if (PosArguments.Count == 1) { + var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) PosArguments[0].Expr).GetValue ().ToString ()); + if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) { + Error_AttributeEmitError ("Specified unmanaged type is only valid on fields"); + } + } + } else if (Type == predefined.DllImport) { + if (PosArguments.Count == 1 && PosArguments[0].Expr is Constant) { + var value = ((Constant) PosArguments[0].Expr).GetValue () as string; + if (string.IsNullOrEmpty (value)) + Error_AttributeEmitError ("DllName cannot be empty"); + } + } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short && + !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) { + Error_AttributeEmitError ("Incorrect argument value."); + return; + } + } + + arg_expr.EncodeAttributeValue (context, encoder, pt); + } + } + + if (named_values != null) { + encoder.Encode ((ushort) named_values.Count); + foreach (var na in named_values) { + if (na.Key is FieldExpr) + encoder.Encode ((byte) 0x53); + else + encoder.Encode ((byte) 0x54); + + encoder.Encode (na.Key.Type); + encoder.Encode (na.Value.Name); + na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type); + } + } else { + encoder.EncodeEmptyNamedArguments (); + } + + cdata = encoder.ToArray (); + } + + try { + foreach (Attributable target in targets) + target.ApplyAttributeBuilder (this, ctor, cdata, predefined); + } catch (Exception e) { + if (e is BadImageFormat && Report.Errors > 0) + return; + + Error_AttributeEmitError (e.Message); + return; + } + + if (!usage_attr.AllowMultiple && allEmitted != null) { + if (allEmitted.ContainsKey (this)) { + var a = allEmitted [this]; + if (a == null) { + a = new List (2); + allEmitted [this] = a; + } + a.Add (this); + } else { + allEmitted.Add (this, null); + } + } + + if (!context.Module.Compiler.Settings.VerifyClsCompliance) + return; + + // Here we are testing attribute arguments for array usage (error 3016) + if (Owner.IsClsComplianceRequired ()) { + if (PosArguments != null) + PosArguments.CheckArrayAsAttribute (context.Module.Compiler); + + if (NamedArguments == null) + return; + + NamedArguments.CheckArrayAsAttribute (context.Module.Compiler); + } + } + + private Expression GetValue () + { + if (PosArguments == null || PosArguments.Count < 1) + return null; + + return PosArguments [0].Expr; + } + + public string GetString () + { + Expression e = GetValue (); + if (e is StringConstant) + return ((StringConstant)e).Value; + return null; + } + + public bool GetBoolean () + { + Expression e = GetValue (); + if (e is BoolConstant) + return ((BoolConstant)e).Value; + return false; + } + + public TypeSpec GetArgumentType () + { + TypeOf e = GetValue () as TypeOf; + if (e == null) + return null; + return e.TypeArgument; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + throw new NotImplementedException (); + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + } + + public class Attributes + { + public readonly List Attrs; +#if FULL_AST + public readonly List> Sections = new List> (); +#endif + + public Attributes (Attribute a) + { + Attrs = new List (); + Attrs.Add (a); + +#if FULL_AST + Sections.Add (Attrs); +#endif + } + + public Attributes (List attrs) + { + Attrs = attrs; +#if FULL_AST + Sections.Add (attrs); +#endif + } + + public void AddAttribute (Attribute attr) + { + Attrs.Add (attr); + } + + public void AddAttributes (List attrs) + { +#if FULL_AST + Sections.Add (attrs); +#else + Attrs.AddRange (attrs); +#endif + } + + public void AttachTo (Attributable attributable, IMemberContext context) + { + foreach (Attribute a in Attrs) + a.AttachTo (attributable, context); + } + + public Attributes Clone () + { + var al = new List (Attrs.Count); + foreach (Attribute a in Attrs) + al.Add (a.Clone ()); + + return new Attributes (al); + } + + /// + /// Checks whether attribute target is valid for the current element + /// + public bool CheckTargets () + { + for (int i = 0; i < Attrs.Count; ++i) { + if (!Attrs [i].CheckTarget ()) + Attrs.RemoveAt (i--); + } + + return true; + } + + public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal) + { + var member_explicit_targets = member.ValidAttributeTargets; + for (int i = 0; i < Attrs.Count; ++i) { + var attr = Attrs[0]; + if (attr.ExplicitTarget == null) + continue; + + int ii; + for (ii = 0; ii < member_explicit_targets.Length; ++ii) { + if (attr.ExplicitTarget == member_explicit_targets[ii]) { + ii = -1; + break; + } + } + + if (ii < 0 || !isGlobal) + continue; + + member.Module.AddAttribute (attr, currentNamespace); + Attrs.RemoveAt (i); + --i; + } + } + + public Attribute Search (PredefinedAttribute t) + { + return Search (null, t); + } + + public Attribute Search (string explicitTarget, PredefinedAttribute t) + { + foreach (Attribute a in Attrs) { + if (explicitTarget != null && a.ExplicitTarget != explicitTarget) + continue; + + if (a.ResolveType () == t) + return a; + } + return null; + } + + /// + /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true + /// + public Attribute[] SearchMulti (PredefinedAttribute t) + { + List ar = null; + + foreach (Attribute a in Attrs) { + if (a.ResolveType () == t) { + if (ar == null) + ar = new List (Attrs.Count); + ar.Add (a); + } + } + + return ar == null ? null : ar.ToArray (); + } + + public void Emit () + { + CheckTargets (); + + Dictionary> ld = Attrs.Count > 1 ? new Dictionary> () : null; + + foreach (Attribute a in Attrs) + a.Emit (ld); + + if (ld == null || ld.Count == 0) + return; + + foreach (var d in ld) { + if (d.Value == null) + continue; + + Attribute a = d.Key; + + foreach (Attribute collision in d.Value) + a.Report.SymbolRelatedToPreviousError (collision.Location, ""); + + a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times", + a.GetSignatureForError ()); + } + } + + public bool Contains (PredefinedAttribute t) + { + return Search (t) != null; + } + } + + public sealed class AttributeEncoder + { + [Flags] + public enum EncodedTypeProperties + { + None = 0, + DynamicType = 1, + TypeParameter = 1 << 1 + } + + public static readonly byte[] Empty; + + byte[] buffer; + int pos; + const ushort Version = 1; + + static AttributeEncoder () + { + Empty = new byte[4]; + Empty[0] = (byte) Version; + } + + public AttributeEncoder () + { + buffer = new byte[32]; + Encode (Version); + } + + public void Encode (bool value) + { + Encode (value ? (byte) 1 : (byte) 0); + } + + public void Encode (byte value) + { + if (pos == buffer.Length) + Grow (1); + + buffer [pos++] = value; + } + + public void Encode (sbyte value) + { + Encode ((byte) value); + } + + public void Encode (short value) + { + if (pos + 2 > buffer.Length) + Grow (2); + + buffer[pos++] = (byte) value; + buffer[pos++] = (byte) (value >> 8); + } + + public void Encode (ushort value) + { + Encode ((short) value); + } + + public void Encode (int value) + { + if (pos + 4 > buffer.Length) + Grow (4); + + buffer[pos++] = (byte) value; + buffer[pos++] = (byte) (value >> 8); + buffer[pos++] = (byte) (value >> 16); + buffer[pos++] = (byte) (value >> 24); + } + + public void Encode (uint value) + { + Encode ((int) value); + } + + public void Encode (long value) + { + if (pos + 8 > buffer.Length) + Grow (8); + + buffer[pos++] = (byte) value; + buffer[pos++] = (byte) (value >> 8); + buffer[pos++] = (byte) (value >> 16); + buffer[pos++] = (byte) (value >> 24); + buffer[pos++] = (byte) (value >> 32); + buffer[pos++] = (byte) (value >> 40); + buffer[pos++] = (byte) (value >> 48); + buffer[pos++] = (byte) (value >> 56); + } + + public void Encode (ulong value) + { + Encode ((long) value); + } + + public void Encode (float value) + { + Encode (SingleConverter.SingleToInt32Bits (value)); + } + + public void Encode (double value) + { + Encode (BitConverter.DoubleToInt64Bits (value)); + } + + public void Encode (string value) + { + if (value == null) { + Encode ((byte) 0xFF); + return; + } + + var buf = Encoding.UTF8.GetBytes(value); + WriteCompressedValue (buf.Length); + + if (pos + buf.Length > buffer.Length) + Grow (buf.Length); + + Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length); + pos += buf.Length; + } + + public EncodedTypeProperties Encode (TypeSpec type) + { + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + Encode ((byte) 0x02); + break; + case BuiltinTypeSpec.Type.Char: + Encode ((byte) 0x03); + break; + case BuiltinTypeSpec.Type.SByte: + Encode ((byte) 0x04); + break; + case BuiltinTypeSpec.Type.Byte: + Encode ((byte) 0x05); + break; + case BuiltinTypeSpec.Type.Short: + Encode ((byte) 0x06); + break; + case BuiltinTypeSpec.Type.UShort: + Encode ((byte) 0x07); + break; + case BuiltinTypeSpec.Type.Int: + Encode ((byte) 0x08); + break; + case BuiltinTypeSpec.Type.UInt: + Encode ((byte) 0x09); + break; + case BuiltinTypeSpec.Type.Long: + Encode ((byte) 0x0A); + break; + case BuiltinTypeSpec.Type.ULong: + Encode ((byte) 0x0B); + break; + case BuiltinTypeSpec.Type.Float: + Encode ((byte) 0x0C); + break; + case BuiltinTypeSpec.Type.Double: + Encode ((byte) 0x0D); + break; + case BuiltinTypeSpec.Type.String: + Encode ((byte) 0x0E); + break; + case BuiltinTypeSpec.Type.Type: + Encode ((byte) 0x50); + break; + case BuiltinTypeSpec.Type.Object: + Encode ((byte) 0x51); + break; + case BuiltinTypeSpec.Type.Dynamic: + Encode ((byte) 0x51); + return EncodedTypeProperties.DynamicType; + default: + if (type.IsArray) { + Encode ((byte) 0x1D); + return Encode (TypeManager.GetElementType (type)); + } + + if (type.Kind == MemberKind.Enum) { + Encode ((byte) 0x55); + EncodeTypeName (type); + } + + break; + } + + return EncodedTypeProperties.None; + } + + public void EncodeTypeName (TypeSpec type) + { + var old_type = type.GetMetaInfo (); + Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName); + } + + // + // Encodes single property named argument per call + // + public void EncodeNamedPropertyArgument (PropertySpec property, Constant value) + { + Encode ((ushort) 1); // length + Encode ((byte) 0x54); // property + Encode (property.MemberType); + Encode (property.Name); + value.EncodeAttributeValue (null, this, property.MemberType); + } + + // + // Encodes single field named argument per call + // + public void EncodeNamedFieldArgument (FieldSpec field, Constant value) + { + Encode ((ushort) 1); // length + Encode ((byte) 0x53); // field + Encode (field.MemberType); + Encode (field.Name); + value.EncodeAttributeValue (null, this, field.MemberType); + } + + public void EncodeNamedArguments (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec + { + Encode ((ushort) members.Length); + + for (int i = 0; i < members.Length; ++i) + { + var member = members[i]; + + if (member.Kind == MemberKind.Field) + Encode ((byte) 0x53); + else if (member.Kind == MemberKind.Property) + Encode ((byte) 0x54); + else + throw new NotImplementedException (member.Kind.ToString ()); + + Encode (member.MemberType); + Encode (member.Name); + values [i].EncodeAttributeValue (null, this, member.MemberType); + } + } + + public void EncodeEmptyNamedArguments () + { + Encode ((ushort) 0); + } + + void Grow (int inc) + { + int size = System.Math.Max (pos * 4, pos + inc + 2); + Array.Resize (ref buffer, size); + } + + void WriteCompressedValue (int value) + { + if (value < 0x80) { + Encode ((byte) value); + return; + } + + if (value < 0x4000) { + Encode ((byte) (0x80 | (value >> 8))); + Encode ((byte) value); + return; + } + + Encode (value); + } + + public byte[] ToArray () + { + byte[] buf = new byte[pos]; + Array.Copy (buffer, buf, pos); + return buf; + } + } + + + /// + /// Helper class for attribute verification routine. + /// + static class AttributeTester + { + public enum Result { + Ok, + RefOutArrayError, + ArrayArrayError + } + + /// + /// Returns true if parameters of two compared methods are CLS-Compliant. + /// It tests differing only in ref or out, or in array rank. + /// + public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb) + { + TypeSpec [] types_a = pa.Types; + TypeSpec [] types_b = pb.Types; + if (types_a == null || types_b == null) + return Result.Ok; + + if (types_a.Length != types_b.Length) + return Result.Ok; + + Result result = Result.Ok; + for (int i = 0; i < types_b.Length; ++i) { + TypeSpec aType = types_a [i]; + TypeSpec bType = types_b [i]; + + var ac_a = aType as ArrayContainer; + var ac_b = aType as ArrayContainer; + + if (ac_a != null && ac_b != null) { + if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) { + result = Result.RefOutArrayError; + continue; + } + + if (ac_a.Element.IsArray || ac_b.Element.IsArray) { + result = Result.ArrayArrayError; + continue; + } + } + + if (aType != bType) + return Result.Ok; + + const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK); + if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod)) + result = Result.RefOutArrayError; + } + return result; + } + + /// + /// Common method for Obsolete error/warning reporting. + /// + public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report) + { + if (oa.IsError) { + Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message); + return; + } + + if (oa.Message == null || oa.Message.Length == 0) { + Report.Warning (612, 1, loc, "`{0}' is obsolete", member); + return; + } + Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message); + } + } + + // + // Predefined attribute types + // + public class PredefinedAttributes + { + // Build-in attributes + public readonly PredefinedAttribute ParamArray; + public readonly PredefinedAttribute Out; + + // Optional attributes + public readonly PredefinedAttribute Obsolete; + public readonly PredefinedAttribute DllImport; + public readonly PredefinedAttribute MethodImpl; + public readonly PredefinedAttribute MarshalAs; + public readonly PredefinedAttribute In; + public readonly PredefinedAttribute IndexerName; + public readonly PredefinedAttribute Conditional; + public readonly PredefinedAttribute CLSCompliant; + public readonly PredefinedAttribute Security; + public readonly PredefinedAttribute Required; + public readonly PredefinedAttribute Guid; + public readonly PredefinedAttribute AssemblyCulture; + public readonly PredefinedAttribute AssemblyVersion; + public readonly PredefinedAttribute AssemblyAlgorithmId; + public readonly PredefinedAttribute AssemblyFlags; + public readonly PredefinedAttribute AssemblyFileVersion; + public readonly PredefinedAttribute ComImport; + public readonly PredefinedAttribute CoClass; + public readonly PredefinedAttribute AttributeUsage; + public readonly PredefinedAttribute DefaultParameterValue; + public readonly PredefinedAttribute OptionalParameter; + public readonly PredefinedAttribute UnverifiableCode; + public readonly PredefinedAttribute DefaultCharset; + public readonly PredefinedAttribute TypeForwarder; + public readonly PredefinedAttribute FixedBuffer; + public readonly PredefinedAttribute CompilerGenerated; + public readonly PredefinedAttribute InternalsVisibleTo; + public readonly PredefinedAttribute RuntimeCompatibility; + public readonly PredefinedAttribute DebuggerHidden; + public readonly PredefinedAttribute UnsafeValueType; + public readonly PredefinedAttribute UnmanagedFunctionPointer; + + // New in .NET 3.5 + public readonly PredefinedAttribute Extension; + + // New in .NET 4.0 + public readonly PredefinedDynamicAttribute Dynamic; + + // + // Optional types which are used as types and for member lookup + // + public readonly PredefinedAttribute DefaultMember; + public readonly PredefinedDecimalAttribute DecimalConstant; + public readonly PredefinedAttribute StructLayout; + public readonly PredefinedAttribute FieldOffset; + + public PredefinedAttributes (ModuleContainer module) + { + ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute"); + Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute"); + ParamArray.Resolve (); + Out.Resolve (); + + Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute"); + DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute"); + MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute"); + MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute"); + In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute"); + IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute"); + Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute"); + CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute"); + Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute"); + Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute"); + Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute"); + AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute"); + AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute"); + AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute"); + AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute"); + AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute"); + ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute"); + CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute"); + AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute"); + DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute"); + OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute"); + UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute"); + + DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute"); + TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute"); + FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute"); + CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute"); + InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute"); + RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute"); + DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute"); + UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute"); + UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); + + Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute"); + + Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute"); + + DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute"); + DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute"); + StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute"); + FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute"); + + // TODO: Should define only attributes which are used for comparison + const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public | + System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly; + + foreach (var fi in GetType ().GetFields (all_fields)) { + ((PredefinedAttribute) fi.GetValue (this)).Define (); + } + } + } + + public class PredefinedAttribute : PredefinedType + { + protected MethodSpec ctor; + + public PredefinedAttribute (ModuleContainer module, string ns, string name) + : base (module, MemberKind.Class, ns, name) + { + } + + #region Properties + + public MethodSpec Constructor { + get { + return ctor; + } + } + + #endregion + + public static bool operator == (TypeSpec type, PredefinedAttribute pa) + { + return type == pa.type && pa.type != null; + } + + public static bool operator != (TypeSpec type, PredefinedAttribute pa) + { + return type != pa.type; + } + + public override int GetHashCode () + { + return base.GetHashCode (); + } + + public override bool Equals (object obj) + { + throw new NotSupportedException (); + } + + public void EmitAttribute (ConstructorBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (MethodBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (PropertyBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (FieldBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded) + { + builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ()); + } + + public void EmitAttribute (TypeBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded) + { + builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ()); + } + + public void EmitAttribute (AssemblyBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (ModuleBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (ParameterBuilder builder) + { + if (ResolveBuilder ()) + builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty); + } + + public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded) + { + builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ()); + } + + ConstructorInfo GetCtorMetaInfo () + { + return (ConstructorInfo) ctor.GetMetaInfo (); + } + + public bool ResolveBuilder () + { + if (ctor != null) + return true; + + // + // Handle all parameter-less attributes as optional + // + if (!IsDefined) + return false; + + ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly); + return ctor != null; + } + } + + public class PredefinedDecimalAttribute : PredefinedAttribute + { + public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name) + : base (module, ns, name) + { + } + + public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc) + { + var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc); + if (ctor == null) + return; + + int[] bits = decimal.GetBits (value); + AttributeEncoder encoder = new AttributeEncoder (); + encoder.Encode ((byte) (bits[3] >> 16)); + encoder.Encode ((byte) (bits[3] >> 31)); + encoder.Encode ((uint) bits[2]); + encoder.Encode ((uint) bits[1]); + encoder.Encode ((uint) bits[0]); + encoder.EncodeEmptyNamedArguments (); + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + + public void EmitAttribute (FieldBuilder builder, decimal value, Location loc) + { + var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc); + if (ctor == null) + return; + + int[] bits = decimal.GetBits (value); + AttributeEncoder encoder = new AttributeEncoder (); + encoder.Encode ((byte) (bits[3] >> 16)); + encoder.Encode ((byte) (bits[3] >> 31)); + encoder.Encode ((uint) bits[2]); + encoder.Encode ((uint) bits[1]); + encoder.Encode ((uint) bits[0]); + encoder.EncodeEmptyNamedArguments (); + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + } + + public class PredefinedDynamicAttribute : PredefinedAttribute + { + MethodSpec tctor; + + public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name) + : base (module, ns, name) + { + } + + public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc) + { + if (ResolveTransformationCtor (loc)) { + var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) }); + builder.SetCustomAttribute (cab); + } + } + + // + // When any element of the type is a dynamic type + // + // This method builds a transformation array for dynamic types + // used in places where DynamicAttribute cannot be applied to. + // It uses bool flag when type is of dynamic type and each + // section always starts with "false" for some reason. + // + // LAMESPEC: This should be part of C# specification + // + // Example: Func + // Transformation: { false, true, false, false, true } + // + static bool[] GetTransformationFlags (TypeSpec t) + { + bool[] element; + var ac = t as ArrayContainer; + if (ac != null) { + element = GetTransformationFlags (ac.Element); + if (element == null) + return null; + + bool[] res = new bool[element.Length + 1]; + res[0] = false; + Array.Copy (element, 0, res, 1, element.Length); + return res; + } + + if (t == null) + return null; + + if (t.IsGeneric) { + List transform = null; + var targs = t.TypeArguments; + for (int i = 0; i < targs.Length; ++i) { + element = GetTransformationFlags (targs[i]); + if (element != null) { + if (transform == null) { + transform = new List (); + for (int ii = 0; ii <= i; ++ii) + transform.Add (false); + } + + transform.AddRange (element); + } else if (transform != null) { + transform.Add (false); + } + } + + if (transform != null) + return transform.ToArray (); + } + + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return new bool[] { true }; + + return null; + } + + bool ResolveTransformationCtor (Location loc) + { + if (tctor != null) + return true; + + tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc); + return tctor != null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs new file mode 100644 index 0000000000..1659dfe3a6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs @@ -0,0 +1,1173 @@ +// +// cfold.cs: Constant Folding +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2002, 2003 Ximian, Inc. +// Copyright 2003-2008, Novell, Inc. +// +using System; + +namespace Mono.CSharp { + + public static class ConstantFold + { + public static TypeSpec[] CreateBinaryPromotionsTypes (BuiltinTypes types) + { + return new TypeSpec[] { + types.Decimal, types.Double, types.Float, + types.ULong, types.Long, types.UInt + }; + } + + // + // Performs the numeric promotions on the left and right expresions + // and deposits the results on `lc' and `rc'. + // + // On success, the types of `lc' and `rc' on output will always match, + // and the pair will be one of: + // + // TODO: BinaryFold should be called as an optimization step only, + // error checking here is weak + // + static bool DoBinaryNumericPromotions (ResolveContext rc, ref Constant left, ref Constant right) + { + TypeSpec ltype = left.Type; + TypeSpec rtype = right.Type; + + foreach (TypeSpec t in rc.BuiltinTypes.BinaryPromotionsTypes) { + if (t == ltype) + return t == rtype || ConvertPromotion (rc, ref right, ref left, t); + + if (t == rtype) + return t == ltype || ConvertPromotion (rc, ref left, ref right, t); + } + + left = left.ConvertImplicitly (rc.BuiltinTypes.Int); + right = right.ConvertImplicitly (rc.BuiltinTypes.Int); + return left != null && right != null; + } + + static bool ConvertPromotion (ResolveContext rc, ref Constant prim, ref Constant second, TypeSpec type) + { + Constant c = prim.ConvertImplicitly (type); + if (c != null) { + prim = c; + return true; + } + + if (type.BuiltinType == BuiltinTypeSpec.Type.UInt) { + type = rc.BuiltinTypes.Long; + prim = prim.ConvertImplicitly (type); + second = second.ConvertImplicitly (type); + return prim != null && second != null; + } + + return false; + } + + internal static void Error_CompileTimeOverflow (ResolveContext rc, Location loc) + { + rc.Report.Error (220, loc, "The operation overflows at compile time in checked mode"); + } + + /// + /// Constant expression folder for binary operations. + /// + /// Returns null if the expression can not be folded. + /// + static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper, + Constant left, Constant right, Location loc) + { + Constant result = null; + + if (left is EmptyConstantCast) + return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc); + + if (left is SideEffectConstant) { + result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc); + if (result == null) + return null; + return new SideEffectConstant (result, left, loc); + } + + if (right is EmptyConstantCast) + return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc); + + if (right is SideEffectConstant) { + result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc); + if (result == null) + return null; + return new SideEffectConstant (result, right, loc); + } + + TypeSpec lt = left.Type; + TypeSpec rt = right.Type; + bool bool_res; + + if (lt.BuiltinType == BuiltinTypeSpec.Type.Bool && lt == rt) { + bool lv = (bool) left.GetValue (); + bool rv = (bool) right.GetValue (); + switch (oper) { + case Binary.Operator.BitwiseAnd: + case Binary.Operator.LogicalAnd: + return new BoolConstant (ec.BuiltinTypes, lv && rv, left.Location); + case Binary.Operator.BitwiseOr: + case Binary.Operator.LogicalOr: + return new BoolConstant (ec.BuiltinTypes, lv || rv, left.Location); + case Binary.Operator.ExclusiveOr: + return new BoolConstant (ec.BuiltinTypes, lv ^ rv, left.Location); + case Binary.Operator.Equality: + return new BoolConstant (ec.BuiltinTypes, lv == rv, left.Location); + case Binary.Operator.Inequality: + return new BoolConstant (ec.BuiltinTypes, lv != rv, left.Location); + } + return null; + } + + // + // During an enum evaluation, none of the rules are valid + // Not sure whether it is bug in csc or in documentation + // + if (ec.HasSet (ResolveContext.Options.EnumScope)){ + if (left is EnumConstant) + left = ((EnumConstant) left).Child; + + if (right is EnumConstant) + right = ((EnumConstant) right).Child; + } else if (left is EnumConstant && rt == lt) { + switch (oper){ + /// + /// E operator |(E x, E y); + /// E operator &(E x, E y); + /// E operator ^(E x, E y); + /// + case Binary.Operator.BitwiseOr: + case Binary.Operator.BitwiseAnd: + case Binary.Operator.ExclusiveOr: + result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); + if (result != null) + result = result.TryReduce (ec, lt, loc); + return result; + + /// + /// U operator -(E x, E y); + /// + case Binary.Operator.Subtraction: + result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); + if (result != null) + result = result.TryReduce (ec, EnumSpec.GetUnderlyingType (lt), loc); + return result; + + /// + /// bool operator ==(E x, E y); + /// bool operator !=(E x, E y); + /// bool operator <(E x, E y); + /// bool operator >(E x, E y); + /// bool operator <=(E x, E y); + /// bool operator >=(E x, E y); + /// + case Binary.Operator.Equality: + case Binary.Operator.Inequality: + case Binary.Operator.LessThan: + case Binary.Operator.GreaterThan: + case Binary.Operator.LessThanOrEqual: + case Binary.Operator.GreaterThanOrEqual: + return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc); + } + return null; + } + + switch (oper){ + case Binary.Operator.BitwiseOr: + // + // bool? operator &(bool? x, bool? y); + // + if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || + (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { + var b = new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + // false | null => null + // null | false => null + if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue)) + return Nullable.LiftedNull.CreateFromExpression (ec, b); + + // true | null => true + // null | true => true + return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, true, loc), b); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + if (left is IntConstant){ + int res = ((IntConstant) left).Value | ((IntConstant) right).Value; + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is UIntConstant){ + uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value; + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is LongConstant){ + long res = ((LongConstant)left).Value | ((LongConstant)right).Value; + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is ULongConstant){ + ulong res = ((ULongConstant)left).Value | + ((ULongConstant)right).Value; + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } + break; + + case Binary.Operator.BitwiseAnd: + // + // bool? operator &(bool? x, bool? y); + // + if ((lt.BuiltinType == BuiltinTypeSpec.Type.Bool && right is NullLiteral) || + (rt.BuiltinType == BuiltinTypeSpec.Type.Bool && left is NullLiteral)) { + var b = new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + // false & null => false + // null & false => false + if ((right is NullLiteral && left.IsDefaultValue) || (left is NullLiteral && right.IsDefaultValue)) + return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, false, loc), b); + + // true & null => null + // null & true => null + return Nullable.LiftedNull.CreateFromExpression (ec, b); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + /// + /// int operator &(int x, int y); + /// uint operator &(uint x, uint y); + /// long operator &(long x, long y); + /// ulong operator &(ulong x, ulong y); + /// + if (left is IntConstant){ + int res = ((IntConstant) left).Value & ((IntConstant) right).Value; + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is UIntConstant){ + uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value; + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is LongConstant){ + long res = ((LongConstant)left).Value & ((LongConstant)right).Value; + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is ULongConstant){ + ulong res = ((ULongConstant)left).Value & + ((ULongConstant)right).Value; + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } + break; + + case Binary.Operator.ExclusiveOr: + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + if (left is IntConstant){ + int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value; + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is UIntConstant){ + uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value; + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is LongConstant){ + long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value; + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is ULongConstant){ + ulong res = ((ULongConstant)left).Value ^ + ((ULongConstant)right).Value; + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } + break; + + case Binary.Operator.Addition: + if (lt == InternalType.NullLiteral) + return right; + + if (rt == InternalType.NullLiteral) + return left; + + // + // If both sides are strings, then concatenate, if + // one is a string, and the other is not, then defer + // to runtime concatenation + // + if (lt.BuiltinType == BuiltinTypeSpec.Type.String || rt.BuiltinType == BuiltinTypeSpec.Type.String){ + if (lt == rt) + return new StringConstant (ec.BuiltinTypes, (string)left.GetValue () + (string)right.GetValue (), + left.Location); + + return null; + } + + // + // handle "E operator + (E x, U y)" + // handle "E operator + (Y y, E x)" + // + EnumConstant lc = left as EnumConstant; + EnumConstant rc = right as EnumConstant; + if (lc != null || rc != null){ + if (lc == null) { + lc = rc; + lt = lc.Type; + right = left; + } + + // U has to be implicitly convetible to E.base + right = right.ConvertImplicitly (lc.Child.Type); + if (right == null) + return null; + + result = BinaryFold (ec, oper, lc.Child, right, loc); + if (result == null) + return null; + + result = result.TryReduce (ec, lt, loc); + if (result == null) + return null; + + return new EnumConstant (result, lt); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value + + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value + + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } + if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value + + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value + + ((FloatConstant) right).Value); + + result = new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value + + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value + + ((ULongConstant) right).Value); + + result = new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value + + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value + + ((LongConstant) right).Value); + + result = new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value + + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value + + ((UIntConstant) right).Value); + + result = new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value + + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value + + ((IntConstant) right).Value); + + result = new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value + + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value + + ((DecimalConstant) right).Value); + + result = new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + + return result; + + case Binary.Operator.Subtraction: + // + // handle "E operator - (E x, U y)" + // handle "E operator - (Y y, E x)" + // + lc = left as EnumConstant; + rc = right as EnumConstant; + if (lc != null || rc != null){ + if (lc == null) { + lc = rc; + lt = lc.Type; + right = left; + } + + // U has to be implicitly convetible to E.base + right = right.ConvertImplicitly (lc.Child.Type); + if (right == null) + return null; + + result = BinaryFold (ec, oper, lc.Child, right, loc); + if (result == null) + return null; + + result = result.TryReduce (ec, lt, loc); + if (result == null) + return null; + + return new EnumConstant (result, lt); + } + + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value - + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value - + ((DoubleConstant) right).Value); + + result = new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value - + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value - + ((FloatConstant) right).Value); + + result = new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value - + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value - + ((ULongConstant) right).Value); + + result = new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value - + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value - + ((LongConstant) right).Value); + + result = new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value - + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value - + ((UIntConstant) right).Value); + + result = new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value - + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value - + ((IntConstant) right).Value); + + result = new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value - + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value - + ((DecimalConstant) right).Value); + + return new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected subtraction input: " + left); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + + return result; + + case Binary.Operator.Multiply: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value * + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value * + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value * + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value * + ((FloatConstant) right).Value); + + return new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value * + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value * + ((ULongConstant) right).Value); + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value * + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value * + ((LongConstant) right).Value); + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value * + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value * + ((UIntConstant) right).Value); + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value * + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value * + ((IntConstant) right).Value); + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value * + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value * + ((DecimalConstant) right).Value); + + return new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected multiply input: " + left); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + break; + + case Binary.Operator.Division: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value / + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value / + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value / + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value / + ((FloatConstant) right).Value); + + return new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value / + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value / + ((ULongConstant) right).Value); + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value / + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value / + ((LongConstant) right).Value); + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value / + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value / + ((UIntConstant) right).Value); + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value / + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value / + ((IntConstant) right).Value); + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is DecimalConstant) { + decimal res; + + if (ec.ConstantCheckState) + res = checked (((DecimalConstant) left).Value / + ((DecimalConstant) right).Value); + else + res = unchecked (((DecimalConstant) left).Value / + ((DecimalConstant) right).Value); + + return new DecimalConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected division input: " + left); + } + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + + } catch (DivideByZeroException) { + ec.Report.Error (20, loc, "Division by constant zero"); + } + + break; + + case Binary.Operator.Modulus: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + try { + if (left is DoubleConstant){ + double res; + + if (ec.ConstantCheckState) + res = checked (((DoubleConstant) left).Value % + ((DoubleConstant) right).Value); + else + res = unchecked (((DoubleConstant) left).Value % + ((DoubleConstant) right).Value); + + return new DoubleConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is FloatConstant){ + float res; + + if (ec.ConstantCheckState) + res = checked (((FloatConstant) left).Value % + ((FloatConstant) right).Value); + else + res = unchecked (((FloatConstant) left).Value % + ((FloatConstant) right).Value); + + return new FloatConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is ULongConstant){ + ulong res; + + if (ec.ConstantCheckState) + res = checked (((ULongConstant) left).Value % + ((ULongConstant) right).Value); + else + res = unchecked (((ULongConstant) left).Value % + ((ULongConstant) right).Value); + + return new ULongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is LongConstant){ + long res; + + if (ec.ConstantCheckState) + res = checked (((LongConstant) left).Value % + ((LongConstant) right).Value); + else + res = unchecked (((LongConstant) left).Value % + ((LongConstant) right).Value); + + return new LongConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is UIntConstant){ + uint res; + + if (ec.ConstantCheckState) + res = checked (((UIntConstant) left).Value % + ((UIntConstant) right).Value); + else + res = unchecked (((UIntConstant) left).Value % + ((UIntConstant) right).Value); + + return new UIntConstant (ec.BuiltinTypes, res, left.Location); + } else if (left is IntConstant){ + int res; + + if (ec.ConstantCheckState) + res = checked (((IntConstant) left).Value % + ((IntConstant) right).Value); + else + res = unchecked (((IntConstant) left).Value % + ((IntConstant) right).Value); + + return new IntConstant (ec.BuiltinTypes, res, left.Location); + } else { + throw new Exception ( "Unexepected modulus input: " + left); + } + } catch (DivideByZeroException){ + ec.Report.Error (20, loc, "Division by constant zero"); + } catch (OverflowException){ + Error_CompileTimeOverflow (ec, loc); + } + break; + + // + // There is no overflow checking on left shift + // + case Binary.Operator.LeftShift: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + IntConstant ic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; + if (ic == null){ + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); + return null; + } + + int lshift_val = ic.Value; + switch (left.Type.BuiltinType) { + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value << lshift_val, left.Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value << lshift_val, left.Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value << lshift_val, left.Location); + } + + // null << value => null + if (left is NullLiteral) + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + left = left.ConvertImplicitly (ec.BuiltinTypes.Int); + if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) + return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value << lshift_val, left.Location); + + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); + break; + + // + // There is no overflow checking on right shift + // + case Binary.Operator.RightShift: + if (left is NullLiteral && right is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + IntConstant sic = right.ConvertImplicitly (ec.BuiltinTypes.Int) as IntConstant; + if (sic == null){ + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ; + return null; + } + int rshift_val = sic.Value; + switch (left.Type.BuiltinType) { + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (ec.BuiltinTypes, ((ULongConstant) left).Value >> rshift_val, left.Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (ec.BuiltinTypes, ((LongConstant) left).Value >> rshift_val, left.Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (ec.BuiltinTypes, ((UIntConstant) left).Value >> rshift_val, left.Location); + } + + // null >> value => null + if (left is NullLiteral) + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + + left = left.ConvertImplicitly (ec.BuiltinTypes.Int); + if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Int) + return new IntConstant (ec.BuiltinTypes, ((IntConstant) left).Value >> rshift_val, left.Location); + + Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); + break; + + case Binary.Operator.Equality: + if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || + (left is Nullable.LiftedNull && right.IsNull) || + (right is Nullable.LiftedNull && left.IsNull)) { + if (left.IsNull || right.IsNull) { + return ReducedExpression.Create ( + new BoolConstant (ec.BuiltinTypes, left.IsNull == right.IsNull, left.Location), + new Binary (oper, left, right, loc)); + } + + if (left is StringConstant && right is StringConstant) + return new BoolConstant (ec.BuiltinTypes, + ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location); + + return null; + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value == + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value == + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value == + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value == + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value == + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value == + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.Inequality: + if (TypeSpec.IsReferenceType (lt) && TypeSpec.IsReferenceType (rt) || + (left is Nullable.LiftedNull && right.IsNull) || + (right is Nullable.LiftedNull && left.IsNull)) { + if (left.IsNull || right.IsNull) { + return ReducedExpression.Create ( + new BoolConstant (ec.BuiltinTypes, left.IsNull != right.IsNull, left.Location), + new Binary (oper, left, right, loc)); + } + + if (left is StringConstant && right is StringConstant) + return new BoolConstant (ec.BuiltinTypes, + ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location); + + return null; + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value != + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value != + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value != + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value != + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value != + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value != + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.LessThan: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value < + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value < + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value < + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value < + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value < + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value < + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.GreaterThan: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value > + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value > + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value > + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value > + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value > + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value > + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.GreaterThanOrEqual: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value >= + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value >= + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value >= + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value >= + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value >= + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value >= + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + + case Binary.Operator.LessThanOrEqual: + if (right is NullLiteral) { + if (left is NullLiteral) { + var lifted_int = new Nullable.NullableType (ec.BuiltinTypes.Int, loc); + lifted_int.ResolveAsType (ec); + return (Constant) new Nullable.LiftedBinaryOperator (oper, lifted_int, right, loc).Resolve (ec); + } + + if (left is Nullable.LiftedNull) { + return (Constant) new Nullable.LiftedBinaryOperator (oper, left, right, loc).Resolve (ec); + } + } + + if (!DoBinaryNumericPromotions (ec, ref left, ref right)) + return null; + + bool_res = false; + if (left is DoubleConstant) + bool_res = ((DoubleConstant) left).Value <= + ((DoubleConstant) right).Value; + else if (left is FloatConstant) + bool_res = ((FloatConstant) left).Value <= + ((FloatConstant) right).Value; + else if (left is ULongConstant) + bool_res = ((ULongConstant) left).Value <= + ((ULongConstant) right).Value; + else if (left is LongConstant) + bool_res = ((LongConstant) left).Value <= + ((LongConstant) right).Value; + else if (left is UIntConstant) + bool_res = ((UIntConstant) left).Value <= + ((UIntConstant) right).Value; + else if (left is IntConstant) + bool_res = ((IntConstant) left).Value <= + ((IntConstant) right).Value; + else + return null; + + return new BoolConstant (ec.BuiltinTypes, bool_res, left.Location); + } + + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs new file mode 100644 index 0000000000..83fbea0b38 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs @@ -0,0 +1,3622 @@ +// +// class.cs: Class and Struct handlers +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// 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 +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security; +using System.Security.Permissions; +using System.Linq; + +#if NET_2_1 +using XmlElement = System.Object; +#endif + +#if STATIC +using SecurityType = System.Collections.Generic.List; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + + public interface ITypesContainer + { + Location Location { get; } + MemberName MemberName { get; } + } + + /// + /// This is the base class for structs and classes. + /// + public abstract class TypeContainer : DeclSpace, ITypeDefinition, ITypesContainer + { + // + // Different context is needed when resolving type container base + // types. Type names come from the parent scope but type parameter + // names from the container scope. + // + public struct BaseContext : IMemberContext + { + TypeContainer tc; + + public BaseContext (TypeContainer tc) + { + this.tc = tc; + } + + #region IMemberContext Members + + public CompilerContext Compiler { + get { return tc.Compiler; } + } + + public TypeSpec CurrentType { + get { return tc.Parent.CurrentType; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return tc.PartialContainer.CurrentTypeParameters; } + } + + public MemberCore CurrentMemberDefinition { + get { return tc; } + } + + public bool IsObsolete { + get { return tc.IsObsolete; } + } + + public bool IsUnsafe { + get { return tc.IsUnsafe; } + } + + public bool IsStatic { + get { return tc.IsStatic; } + } + + public ModuleContainer Module { + get { return tc.Module; } + } + + public string GetSignatureForError () + { + return tc.GetSignatureForError (); + } + + public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return null; + } + + public FullNamedExpression LookupNamespaceAlias (string name) + { + return tc.Parent.LookupNamespaceAlias (name); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + if (arity == 0) { + TypeParameter[] tp = CurrentTypeParameters; + if (tp != null) { + TypeParameter t = TypeParameter.FindTypeParameter (tp, name); + if (t != null) + return new TypeParameterExpr (t, loc); + } + } + + return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc); + } + + #endregion + } + + [Flags] + enum CachedMethods + { + Equals = 1, + GetHashCode = 1 << 1, + HasStaticFieldInitializer = 1 << 2 + } + + + // Whether this is a struct, class or interface + public readonly MemberKind Kind; + + // Holds a list of classes and structures + protected List types; + + List ordered_explicit_member_list; + List ordered_member_list; + + // Holds the list of properties + List properties; + + // Holds the list of constructors + protected List instance_constructors; + + // Holds the list of fields + protected List fields; + + // Holds a list of fields that have initializers + protected List initialized_fields; + + // Holds a list of static fields that have initializers + protected List initialized_static_fields; + + // Holds the list of constants + protected List constants; + + // Holds the methods. + List methods; + + // Holds the events + protected List events; + + // Holds the indexers + List indexers; + + // Holds the operators + List operators; + + // Holds the compiler generated classes + protected List compiler_generated; + + Dictionary hoisted_base_call_proxies; + + Dictionary Cache = new Dictionary (); + + // + // Pointers to the default constructor and the default static constructor + // + protected Constructor default_constructor; + protected Constructor default_static_constructor; + + // + // Points to the first non-static field added to the container. + // + // This is an arbitrary choice. We are interested in looking at _some_ non-static field, + // and the first one's as good as any. + // + FieldBase first_nonstatic_field; + + // + // This one is computed after we can distinguish interfaces + // from classes from the arraylist `type_bases' + // + protected TypeSpec base_type; + protected FullNamedExpression base_type_expr; // TODO: It's temporary variable + protected TypeSpec[] iface_exprs; + + protected List type_bases; + + bool members_defined; + bool members_defined_ok; + bool type_defined; + + TypeContainer InTransit; + + GenericTypeParameterBuilder[] all_tp_builders; + + public const string DefaultIndexerName = "Item"; + + private bool seen_normal_indexers = false; + private string indexer_name = DefaultIndexerName; + protected bool requires_delayed_unmanagedtype_check; + bool error; + + private CachedMethods cached_method; + + protected TypeSpec spec; + TypeSpec current_type; + + List partial_parts; + + public int DynamicSitesCounter; + + /// + /// The pending methods that need to be implemented + // (interfaces or abstract methods) + /// + PendingImplementation pending; + + public TypeContainer (NamespaceContainer ns, DeclSpace parent, MemberName name, + Attributes attrs, MemberKind kind) + : base (ns, parent, name, attrs) + { + if (parent != null && parent.NamespaceEntry != ns) + throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class"); + + this.Kind = kind; + this.PartialContainer = this; + } + + List orderedAllMembers = new List (); + public List OrderedAllMembers { + get { + return this.orderedAllMembers; + } + } + + #region Properties + + public override TypeSpec CurrentType { + get { + if (current_type == null) { + if (IsGeneric) { + // + // Switch to inflated version as it's used by all expressions + // + var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Select (l => l.Type).ToArray (); + current_type = spec.MakeGenericType (this, targs); + } else { + current_type = spec; + } + } + + return current_type; + } + } + + public override TypeParameter[] CurrentTypeParameters { + get { + return PartialContainer.type_params; + } + } + + int CurrentTypeParametersStartIndex { + get { + int total = all_tp_builders.Length; + if (CurrentTypeParameters != null) { + return total - CurrentTypeParameters.Length; + } + return total; + } + } + + public virtual AssemblyDefinition DeclaringAssembly { + get { + return Module.DeclaringAssembly; + } + } + + IAssemblyDefinition ITypeDefinition.DeclaringAssembly { + get { + return Module.DeclaringAssembly; + } + } + + public TypeSpec Definition { + get { + return spec; + } + } + + public bool HasMembersDefined { + get { + return members_defined; + } + } + + public List TypeBaseExpressions { + get { + return type_bases; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public bool AddMember (MemberCore symbol) + { + return AddToContainer (symbol, symbol.MemberName.Basename); + } + + public bool AddMember (MemberCore symbol, string name) + { + return AddToContainer (symbol, name); + } + + protected virtual bool AddMemberType (TypeContainer ds) + { + return AddToContainer (ds, ds.Basename); + } + + protected virtual void RemoveMemberType (TypeContainer ds) + { + RemoveFromContainer (ds.Basename); + } + + public void AddConstant (Const constant) + { + orderedAllMembers.Add (constant); + if (!AddMember (constant)) + return; + + if (constants == null) + constants = new List (); + constants.Add (constant); + } + + public TypeContainer AddTypeContainer (TypeContainer tc) + { + orderedAllMembers.Add (tc); + if (!AddMemberType (tc)) + return tc; + + if (types == null) + types = new List (); + + types.Add (tc); + return tc; + } + + public virtual TypeContainer AddPartial (TypeContainer next_part) + { + return AddPartial (next_part, next_part.Basename); + } + + protected TypeContainer AddPartial (TypeContainer next_part, string name) + { + next_part.ModFlags |= Modifiers.PARTIAL; + TypeContainer tc = GetDefinition (name) as TypeContainer; + if (tc == null) + return AddTypeContainer (next_part); + + if ((tc.ModFlags & Modifiers.PARTIAL) == 0) { + Report.SymbolRelatedToPreviousError (next_part); + Error_MissingPartialModifier (tc); + } + + if (tc.Kind != next_part.Kind) { + Report.SymbolRelatedToPreviousError (tc); + Report.Error (261, next_part.Location, + "Partial declarations of `{0}' must be all classes, all structs or all interfaces", + next_part.GetSignatureForError ()); + } + + if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) && + ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 && + (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) { + Report.SymbolRelatedToPreviousError (tc); + Report.Error (262, next_part.Location, + "Partial declarations of `{0}' have conflicting accessibility modifiers", + next_part.GetSignatureForError ()); + } + + if (tc.partial_parts == null) + tc.partial_parts = new List (1); + + if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) { + tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask); + } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) { + tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask); + tc.ModFlags |= next_part.ModFlags; + } else { + tc.ModFlags |= next_part.ModFlags; + } + + tc.spec.Modifiers = tc.ModFlags; + + if (next_part.attributes != null) { + if (tc.attributes == null) + tc.attributes = next_part.attributes; + else + tc.attributes.AddAttributes (next_part.attributes.Attrs); + } + + next_part.PartialContainer = tc; + tc.partial_parts.Add (next_part); + return tc; + } + + public virtual void RemoveTypeContainer (TypeContainer next_part) + { + if (types != null) + types.Remove (next_part); + + Cache.Remove (next_part.Basename); + RemoveMemberType (next_part); + } + + public void AddDelegate (Delegate d) + { + AddTypeContainer (d); + } + + private void AddMemberToList (MemberCore mc, List alist, bool isexplicit) + { + if (ordered_explicit_member_list == null) { + ordered_explicit_member_list = new List (); + ordered_member_list = new List (); + } + + if (isexplicit) { + if (Kind == MemberKind.Interface) { + Report.Error (541, mc.Location, + "`{0}': explicit interface declaration can only be declared in a class or struct", + mc.GetSignatureForError ()); + } + + ordered_explicit_member_list.Add (mc); + alist.Insert (0, mc); + } else { + ordered_member_list.Add (mc); + alist.Add (mc); + } + + } + + public void AddMethod (MethodOrOperator method) + { + orderedAllMembers.Add (method); + if (!AddToContainer (method, method.MemberName.Basename)) + return; + + if (methods == null) + methods = new List (); + + if (method.MemberName.Left != null) + AddMemberToList (method, methods, true); + else + AddMemberToList (method, methods, false); + } + + public void AddConstructor (Constructor c) + { + orderedAllMembers.Add (c); + bool is_static = (c.ModFlags & Modifiers.STATIC) != 0; + if (!AddToContainer (c, is_static ? Constructor.ConstructorName : Constructor.TypeConstructorName)) + return; + + if (is_static && c.ParameterInfo.IsEmpty){ + if (default_static_constructor != null) { + Report.SymbolRelatedToPreviousError (default_static_constructor); + Report.Error (111, c.Location, + "A member `{0}' is already defined. Rename this member or use different parameter types", + c.GetSignatureForError ()); + return; + } + + default_static_constructor = c; + } else { + if (c.ParameterInfo.IsEmpty) + default_constructor = c; + if (instance_constructors == null) + instance_constructors = new List (); + + instance_constructors.Add (c); + } + } + + public bool AddField (FieldBase field) + { + orderedAllMembers.Add (field); + if (!AddMember (field)) + return false; + if (fields == null) + fields = new List (); + + fields.Add (field); + + if ((field.ModFlags & Modifiers.STATIC) != 0) + return true; + + if (first_nonstatic_field == null) { + first_nonstatic_field = field; + return true; + } + + if (Kind == MemberKind.Struct && first_nonstatic_field.Parent != field.Parent) { + Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent); + Report.Warning (282, 3, field.Location, + "struct instance field `{0}' found in different declaration from instance field `{1}'", + field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ()); + } + return true; + } + + public void AddProperty (Property prop) + { + orderedAllMembers.Add (prop); + if (!AddMember (prop)) + return; + if (properties == null) + properties = new List (); + + if (prop.MemberName.Left != null) + AddMemberToList (prop, properties, true); + else + AddMemberToList (prop, properties, false); + } + + public void AddEvent (Event e) + { + orderedAllMembers.Add (e); + if (!AddMember (e)) + return; + if (events == null) + events = new List (); + + events.Add (e); + } + + /// + /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute + /// + public void AddIndexer (Indexer i) + { + orderedAllMembers.Add (i); + if (indexers == null) + indexers = new List (); + if (i.IsExplicitImpl) + AddMemberToList (i, indexers, true); + else + AddMemberToList (i, indexers, false); + } + + public void AddOperator (Operator op) + { + orderedAllMembers.Add (op); + if (!AddMember (op)) + return; + if (operators == null) + operators = new List (); + + operators.Add (op); + } + + public void AddCompilerGeneratedClass (CompilerGeneratedClass c) + { + if (compiler_generated == null) + compiler_generated = new List (); + + compiler_generated.Add (c); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.DefaultMember) { + if (Indexers != null) { + Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer"); + return; + } + } + + if (a.Type == pa.Required) { + Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types"); + return; + } + + TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public override AttributeTargets AttributeTargets { + get { + throw new NotSupportedException (); + } + } + + public IList Types { + get { + return types; + } + } + + public IList Methods { + get { + return methods; + } + } + + public IList Constants { + get { + return constants; + } + } + + public TypeSpec BaseType { + get { + return spec.BaseType; + } + } + + public IList Fields { + get { + return fields; + } + } + + public IList InstanceConstructors { + get { + return instance_constructors; + } + } + + public IList Properties { + get { + return properties; + } + } + + public IList Events { + get { + return events; + } + } + + public IList Indexers { + get { + return indexers; + } + } + + public IList Operators { + get { + return operators; + } + } + + protected override TypeAttributes TypeAttr { + get { + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel); + } + } + + public int TypeParametersCount { + get { + return MemberName.Arity; + } + } + + TypeParameterSpec[] ITypeDefinition.TypeParameters { + get { + // TODO MemberCache: this is going to hurt + return PartialContainer.type_params.Select (l => l.Type).ToArray (); + } + } + + public string GetAttributeDefaultMember () + { + return indexers == null ? DefaultIndexerName : indexer_name; + } + + public bool IsComImport { + get { + if (OptAttributes == null) + return false; + + return OptAttributes.Contains (Module.PredefinedAttributes.ComImport); + } + } + + string ITypeDefinition.Namespace { + get { + return NamespaceEntry.NS.MemberName.GetSignatureForError (); + } + } + + public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) + { + if ((field.ModFlags & Modifiers.STATIC) != 0){ + if (initialized_static_fields == null) { + PartialContainer.HasStaticFieldInitializer = true; + initialized_static_fields = new List (4); + } + + initialized_static_fields.Add (expression); + } else { + if (initialized_fields == null) + initialized_fields = new List (4); + + initialized_fields.Add (expression); + } + } + + public void ResolveFieldInitializers (BlockContext ec) + { + if (partial_parts != null) { + foreach (TypeContainer part in partial_parts) { + part.DoResolveFieldInitializers (ec); + } + } + DoResolveFieldInitializers (ec); + } + + void DoResolveFieldInitializers (BlockContext ec) + { + if (ec.IsStatic) { + if (initialized_static_fields == null) + return; + + bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize; + int i; + ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count]; + for (i = 0; i < initialized_static_fields.Count; ++i) { + FieldInitializer fi = initialized_static_fields [i]; + ExpressionStatement s = fi.ResolveStatement (ec); + if (s == null) { + s = EmptyExpressionStatement.Instance; + } else if (fi.IsComplexInitializer) { + has_complex_initializer |= true; + } + + init [i] = s; + } + + for (i = 0; i < initialized_static_fields.Count; ++i) { + FieldInitializer fi = initialized_static_fields [i]; + // + // Need special check to not optimize code like this + // static int a = b = 5; + // static int b = 0; + // + if (!has_complex_initializer && fi.IsDefaultInitializer) + continue; + + ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i])); + } + + return; + } + + if (initialized_fields == null) + return; + + for (int i = 0; i < initialized_fields.Count; ++i) { + FieldInitializer fi = initialized_fields [i]; + ExpressionStatement s = fi.ResolveStatement (ec); + if (s == null) + continue; + + // + // Field is re-initialized to its default value => removed + // + if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize) + continue; + + ec.CurrentBlock.AddScopeStatement (new StatementExpression (s)); + } + } + + public override string DocComment { + get { + return comment; + } + set { + if (value == null) + return; + + comment += value; + } + } + + public PendingImplementation PendingImplementations { + get { return pending; } + } + + internal override void GenerateDocComment (DocumentationBuilder builder) + { + base.GenerateDocComment (builder); + + if (DefaultStaticConstructor != null) + DefaultStaticConstructor.GenerateDocComment (builder); + + if (InstanceConstructors != null) + foreach (Constructor c in InstanceConstructors) + c.GenerateDocComment (builder); + + if (Types != null) + foreach (TypeContainer tc in Types) + tc.GenerateDocComment (builder); + + if (Constants != null) + foreach (Const c in Constants) + c.GenerateDocComment (builder); + + if (Fields != null) + foreach (FieldBase f in Fields) + f.GenerateDocComment (builder); + + if (Events != null) + foreach (Event e in Events) + e.GenerateDocComment (builder); + + if (Indexers != null) + foreach (Indexer ix in Indexers) + ix.GenerateDocComment (builder); + + if (Properties != null) + foreach (Property p in Properties) + p.GenerateDocComment (builder); + + if (Methods != null) + foreach (MethodOrOperator m in Methods) + m.GenerateDocComment (builder); + + if (Operators != null) + foreach (Operator o in Operators) + o.GenerateDocComment (builder); + } + + public TypeSpec GetAttributeCoClass () + { + if (OptAttributes == null) + return null; + + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass); + if (a == null) + return null; + + return a.GetCoClassAttributeValue (); + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + Attribute a = null; + if (OptAttributes != null) { + a = OptAttributes.Search (pa); + } + + if (a == null) + return null; + + return a.GetAttributeUsageAttribute (); + } + + public virtual void AddBasesForPart (DeclSpace part, List bases) + { + // FIXME: get rid of partial_parts and store lists of bases of each part here + // assumed, not verified: 'part' is in 'partial_parts' + ((TypeContainer) part).type_bases = bases; + } + + /// + /// This function computes the Base class and also the + /// list of interfaces that the class or struct @c implements. + /// + /// The return value is an array (might be null) of + /// interfaces implemented (as Types). + /// + /// The @base_class argument is set to the base object or null + /// if this is `System.Object'. + /// + protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + base_class = null; + if (type_bases == null) + return null; + + int count = type_bases.Count; + TypeSpec[] ifaces = null; + var base_context = new BaseContext (this); + for (int i = 0, j = 0; i < count; i++){ + FullNamedExpression fne = type_bases [i]; + + var fne_resolved = fne.ResolveAsType (base_context); + if (fne_resolved == null) + continue; + + if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) { + if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type", + GetSignatureForError ()); + + continue; + } + + base_type = fne_resolved; + base_class = fne; + continue; + } + + if (ifaces == null) + ifaces = new TypeSpec [count - i]; + + if (fne_resolved.IsInterface) { + for (int ii = 0; ii < j; ++ii) { + if (fne_resolved == ifaces [ii]) { + Report.Error (528, Location, "`{0}' is already listed in interface list", + fne_resolved.GetSignatureForError ()); + break; + } + } + + if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) { + Report.Error (61, fne.Location, + "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'", + fne_resolved.GetSignatureForError (), GetSignatureForError ()); + } + } else { + Report.SymbolRelatedToPreviousError (fne_resolved); + if (Kind != MemberKind.Class) { + Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ()); + } else if (base_class != null) + Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')", + GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ()); + else { + Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first", + GetSignatureForError (), fne_resolved.GetSignatureForError ()); + } + } + + ifaces [j++] = fne_resolved; + } + + return ifaces; + } + + TypeSpec[] GetNormalPartialBases () + { + var ifaces = new List (0); + if (iface_exprs != null) + ifaces.AddRange (iface_exprs); + + foreach (TypeContainer part in partial_parts) { + FullNamedExpression new_base_class; + var new_ifaces = part.ResolveBaseTypes (out new_base_class); + if (new_base_class != null) { + if (base_type_expr != null && part.base_type != base_type) { + Report.SymbolRelatedToPreviousError (new_base_class.Location, ""); + Report.Error (263, part.Location, + "Partial declarations of `{0}' must not specify different base classes", + part.GetSignatureForError ()); + } else { + base_type_expr = new_base_class; + base_type = part.base_type; + } + } + + if (new_ifaces == null) + continue; + + foreach (var iface in new_ifaces) { + if (ifaces.Contains (iface)) + continue; + + ifaces.Add (iface); + } + } + + if (ifaces.Count == 0) + return null; + + return ifaces.ToArray (); + } + + // + // Checks that some operators come in pairs: + // == and != + // > and < + // >= and <= + // true and false + // + // They are matched based on the return type and the argument types + // + void CheckPairedOperators () + { + bool has_equality_or_inequality = false; + var operators = this.operators.ToArray (); + bool[] has_pair = new bool[operators.Length]; + + for (int i = 0; i < operators.Length; ++i) { + if (operators[i] == null) + continue; + + Operator o_a = (Operator) operators[i]; + Operator.OpType o_type = o_a.OperatorType; + if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality) + has_equality_or_inequality = true; + + Operator.OpType matching_type = o_a.GetMatchingOperator (); + if (matching_type == Operator.OpType.TOP) { + operators[i] = null; + continue; + } + + for (int ii = 0; ii < operators.Length; ++ii) { + Operator o_b = (Operator) operators[ii]; + if (o_b == null || o_b.OperatorType != matching_type) + continue; + + if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType)) + continue; + + if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes)) + continue; + + operators[i] = null; + + // + // Used to ignore duplicate user conversions + // + has_pair[ii] = true; + } + } + + for (int i = 0; i < operators.Length; ++i) { + if (operators[i] == null || has_pair[i]) + continue; + + Operator o = (Operator) operators [i]; + Report.Error (216, o.Location, + "The operator `{0}' requires a matching operator `{1}' to also be defined", + o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ())); + } + + if (has_equality_or_inequality) { + if (Methods == null || !HasEquals) + Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", + GetSignatureForError ()); + + if (Methods == null || !HasGetHashCode) + Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", + GetSignatureForError ()); + } + } + + bool CreateTypeBuilder () + { + // + // Sets .size to 1 for structs with no instance fields + // + int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0; + + if (IsTopLevel) { + TypeBuilder = Module.CreateBuilder (Name, TypeAttr, type_size); + } else { + TypeBuilder = Parent.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size); + } + + if (DeclaringAssembly.Importer != null) + DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec); + + spec.SetMetaInfo (TypeBuilder); + spec.MemberCache = new MemberCache (this); + spec.DeclaringType = Parent.CurrentType; + + if (!IsTopLevel) + Parent.MemberCache.AddMember (spec); + + if (IsGeneric) { + string[] param_names = new string[TypeParameters.Length]; + for (int i = 0; i < TypeParameters.Length; i++) + param_names [i] = TypeParameters[i].Name; + + all_tp_builders = TypeBuilder.DefineGenericParameters (param_names); + + int offset = CurrentTypeParametersStartIndex; + for (int i = offset; i < all_tp_builders.Length; i++) { + CurrentTypeParameters [i - offset].Define (all_tp_builders [i], spec); + } + } + + return true; + } + + // + // Creates a proxy base method call inside this container for hoisted base member calls + // + public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method) + { + Method proxy_method; + + // + // One proxy per base method is enough + // + if (hoisted_base_call_proxies == null) { + hoisted_base_call_proxies = new Dictionary (); + proxy_method = null; + } else { + hoisted_base_call_proxies.TryGetValue (method, out proxy_method); + } + + if (proxy_method == null) { + string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count); + var base_parameters = new Parameter[method.Parameters.Count]; + for (int i = 0; i < base_parameters.Length; ++i) { + var base_param = method.Parameters.FixedParameters[i]; + base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location), + base_param.Name, base_param.ModFlags, null, Location); + base_parameters[i].Resolve (this, i); + } + + var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types); + if (method.Parameters.HasArglist) { + cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location); + cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (); + } + + GenericMethod generic_method; + MemberName member_name; + TypeArguments targs = null; + if (method.IsGeneric) { + // + // Copy all base generic method type parameters info + // + var hoisted_tparams = method.GenericDefinition.TypeParameters; + var type_params = new TypeParameter[hoisted_tparams.Length]; + targs = new TypeArguments (); + targs.Arguments = new TypeSpec[type_params.Length]; + for (int i = 0; i < type_params.Length; ++i) { + var tp = hoisted_tparams[i]; + targs.Add (new TypeParameterName (tp.Name, null, Location)); + targs.Arguments[i] = tp; + type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null); + } + + member_name = new MemberName (name, targs, Location); + generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params, + new TypeExpression (method.ReturnType, Location), cloned_params); + } else { + member_name = new MemberName (name); + generic_method = null; + } + + // Compiler generated proxy + proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location), + Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN, + member_name, cloned_params, null); + + var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location); + + var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location); + mg.InstanceExpression = new BaseThis (method.DeclaringType, Location); + if (targs != null) + mg.SetTypeArguments (rc, targs); + + // Get all the method parameters and pass them as arguments + var real_base_call = new Invocation (mg, block.GetAllParametersArguments ()); + Statement statement; + if (method.ReturnType.Kind == MemberKind.Void) + statement = new StatementExpression (real_base_call); + else + statement = new Return (real_base_call, Location); + + block.AddStatement (statement); + proxy_method.Block = block; + + methods.Add (proxy_method); + proxy_method.Define (); + + hoisted_base_call_proxies.Add (method, proxy_method); + } + + return proxy_method.Spec; + } + + bool DefineBaseTypes () + { + iface_exprs = ResolveBaseTypes (out base_type_expr); + if (partial_parts != null) { + iface_exprs = GetNormalPartialBases (); + } + + var cycle = CheckRecursiveDefinition (this); + if (cycle != null) { + Report.SymbolRelatedToPreviousError (cycle); + if (this is Interface) { + Report.Error (529, Location, + "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'", + GetSignatureForError (), cycle.GetSignatureForError ()); + + iface_exprs = null; + } else { + Report.Error (146, Location, + "Circular base class dependency involving `{0}' and `{1}'", + GetSignatureForError (), cycle.GetSignatureForError ()); + + base_type = null; + } + } + + if (iface_exprs != null) { + foreach (var iface_type in iface_exprs) { + // Prevents a crash, the interface might not have been resolved: 442144 + if (iface_type == null) + continue; + + if (!spec.AddInterface (iface_type)) + continue; + + TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ()); + + // Ensure the base is always setup + var compiled_iface = iface_type.MemberDefinition as Interface; + if (compiled_iface != null) { + // TODO: Need DefineBaseType only + compiled_iface.DefineType (); + } + + if (iface_type.Interfaces != null) { + var base_ifaces = new List (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)) { + TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ()); + + if (ii_iface_type.Interfaces != null) + base_ifaces.AddRange (ii_iface_type.Interfaces); + } + } + } + } + } + + if (Kind == MemberKind.Interface) { + spec.BaseType = Compiler.BuiltinTypes.Object; + return true; + } + + if (base_type != null) { + spec.BaseType = base_type; + + // Set base type after type creation + TypeBuilder.SetParent (base_type.GetMetaInfo ()); + } else { + TypeBuilder.SetParent (null); + } + + return true; + } + + public virtual void DefineConstants () + { + if (constants != null) { + foreach (Const c in constants) { + c.DefineValue (); + } + } + + if (instance_constructors != null) { + foreach (MethodCore m in instance_constructors) { + var p = m.ParameterInfo; + if (!p.IsEmpty) { + p.ResolveDefaultValues (m); + } + } + } + + if (methods != null) { + foreach (MethodCore m in methods) { + var p = m.ParameterInfo; + if (!p.IsEmpty) { + p.ResolveDefaultValues (m); + } + } + } + + if (indexers != null) { + foreach (Indexer i in indexers) { + i.ParameterInfo.ResolveDefaultValues (i); + } + } + + if (types != null) { + foreach (var t in types) + t.DefineConstants (); + } + } + + // + // Defines the type in the appropriate ModuleBuilder or TypeBuilder. + // + public bool CreateType () + { + if (TypeBuilder != null) + return !error; + + if (error) + return false; + + if (!CreateTypeBuilder ()) { + error = true; + return false; + } + + if (partial_parts != null) { + foreach (TypeContainer part in partial_parts) { + part.spec = spec; + part.current_type = current_type; + part.TypeBuilder = TypeBuilder; + } + } + + if (Types != null) { + foreach (TypeContainer tc in Types) { + tc.CreateType (); + } + } + + return true; + } + + public override void DefineType () + { + if (error) + return; + if (type_defined) + return; + + type_defined = true; + + // TODO: Driver resolves only first level of namespace, do the rest here for now + if (IsTopLevel && (ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + NamespaceEntry.Resolve (); + } + + if (!DefineBaseTypes ()) { + error = true; + return; + } + + if (!DefineNestedTypes ()) { + error = true; + return; + } + } + + public override void SetParameterInfo (List constraints_list) + { + base.SetParameterInfo (constraints_list); + + if (PartialContainer.CurrentTypeParameters == null || PartialContainer == this) + return; + + TypeParameter[] tc_names = PartialContainer.CurrentTypeParameters; + for (int i = 0; i < tc_names.Length; ++i) { + if (tc_names [i].Name != type_params [i].Name) { + Report.SymbolRelatedToPreviousError (PartialContainer.Location, ""); + Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order", + GetSignatureForError ()); + break; + } + + if (tc_names [i].Variance != type_params [i].Variance) { + Report.SymbolRelatedToPreviousError (PartialContainer.Location, ""); + Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers", + GetSignatureForError ()); + break; + } + } + } + + // + // Replaces normal spec with predefined one when compiling corlib + // and this type container defines predefined type + // + public void SetPredefinedSpec (BuiltinTypeSpec spec) + { + // When compiling build-in types we start with two + // version of same type. One is of BuiltinTypeSpec and + // second one is ordinary TypeSpec. The unification + // happens at later stage when we know which type + // really matches the builtin type signature. However + // that means TypeSpec create during CreateType of this + // type has to be replaced with builtin one + // + spec.SetMetaInfo (TypeBuilder); + spec.MemberCache = this.spec.MemberCache; + spec.DeclaringType = this.spec.DeclaringType; + + this.spec = spec; + current_type = null; + } + + void UpdateTypeParameterConstraints (TypeContainer part) + { + TypeParameter[] current_params = type_params; + for (int i = 0; i < current_params.Length; i++) { + if (current_params [i].AddPartialConstraints (part, part.type_params [i])) + continue; + + Report.SymbolRelatedToPreviousError (Location, ""); + Report.Error (265, part.Location, + "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'", + GetSignatureForError (), current_params [i].GetSignatureForError ()); + } + } + + public bool ResolveTypeParameters () + { + if (!DoResolveTypeParameters ()) + return false; + + if (types != null) { + foreach (var type in types) + if (!type.ResolveTypeParameters ()) + return false; + } + + if (compiler_generated != null) { + foreach (CompilerGeneratedClass c in compiler_generated) + if (!c.ResolveTypeParameters ()) + return false; + } + + return true; + } + + protected virtual bool DoResolveTypeParameters () + { + if (CurrentTypeParameters == null) + return true; + + if (PartialContainer != this) + throw new InternalErrorException (); + + var base_context = new BaseContext (this); + foreach (TypeParameter type_param in CurrentTypeParameters) { + if (!type_param.ResolveConstraints (base_context)) { + error = true; + return false; + } + } + + if (partial_parts != null) { + foreach (TypeContainer part in partial_parts) + UpdateTypeParameterConstraints (part); + } + + return true; + } + + protected virtual bool DefineNestedTypes () + { + if (Types != null) { + foreach (TypeContainer tc in Types) + tc.DefineType (); + } + + return true; + } + + TypeSpec CheckRecursiveDefinition (TypeContainer tc) + { + if (InTransit != null) + return spec; + + InTransit = tc; + + if (base_type != null) { + var ptc = base_type.MemberDefinition as TypeContainer; + if (ptc != null && ptc.CheckRecursiveDefinition (this) != null) + return base_type; + } + + if (iface_exprs != null) { + foreach (var iface in iface_exprs) { + // the interface might not have been resolved, prevents a crash, see #442144 + if (iface == null) + continue; + var ptc = iface.MemberDefinition as Interface; + if (ptc != null && ptc.CheckRecursiveDefinition (this) != null) + return iface; + } + } + + if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null) + return spec; + + InTransit = null; + return null; + } + + /// + /// Populates our TypeBuilder with fields and methods + /// + public sealed override bool Define () + { + if (members_defined) + return members_defined_ok; + + members_defined_ok = DoDefineMembers (); + members_defined = true; + + if (types != null) { + foreach (var nested in types) + nested.Define (); + } + + return members_defined_ok; + } + + protected virtual bool DoDefineMembers () + { + if (iface_exprs != null) { + foreach (var iface_type in iface_exprs) { + if (iface_type == null) + continue; + + // Ensure the base is always setup + var compiled_iface = iface_type.MemberDefinition as Interface; + if (compiled_iface != null) + compiled_iface.Define (); + + if (Kind == MemberKind.Interface) + MemberCache.AddInterface (iface_type); + + ObsoleteAttribute oa = iface_type.GetAttributeObsolete (); + if (oa != null && !IsObsolete) + AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report); + + if (iface_type.Arity > 0) { + // TODO: passing `this' is wrong, should be base type iface instead + TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this); + + if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) { + Report.Error (1966, Location, + "`{0}': cannot implement a dynamic interface `{1}'", + GetSignatureForError (), iface_type.GetSignatureForError ()); + return false; + } + + if (spec.Interfaces != null) { + foreach (var prev_iface in iface_exprs) { + if (prev_iface == iface_type) + break; + + if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface)) + continue; + + Report.Error (695, Location, + "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions", + GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ()); + } + } + } + } + } + + if (base_type != null) { + // + // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType) + // + if (base_type_expr != null) { + ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete (); + if (obsolete_attr != null && !IsObsolete) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report); + + if (IsGeneric && base_type.IsAttribute) { + Report.Error (698, base_type_expr.Location, + "A generic type cannot derive from `{0}' because it is an attribute class", + base_type.GetSignatureForError ()); + } + } + + if (base_type.Interfaces != null) { + foreach (var iface in base_type.Interfaces) + spec.AddInterface (iface); + } + + var baseContainer = base_type.MemberDefinition as ClassOrStruct; + if (baseContainer != null) { + baseContainer.Define (); + + // + // It can trigger define of this type (for generic types only) + // + if (HasMembersDefined) + return true; + } + } + + DefineContainerMembers (constants); + DefineContainerMembers (fields); + + if (Kind == MemberKind.Struct || Kind == MemberKind.Class) { + pending = PendingImplementation.GetPendingImplementations (this); + + if (requires_delayed_unmanagedtype_check) { + requires_delayed_unmanagedtype_check = false; + foreach (FieldBase f in fields) { + if (f.MemberType != null && f.MemberType.IsPointer) + TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location); + } + } + } + + // + // Constructors are not in the defined_names array + // + DefineContainerMembers (instance_constructors); + + DefineContainerMembers (events); + DefineContainerMembers (ordered_explicit_member_list); + DefineContainerMembers (ordered_member_list); + + if (operators != null) { + DefineContainerMembers (operators); + CheckPairedOperators (); + } + + ComputeIndexerName(); + CheckEqualsAndGetHashCode(); + + if (Kind == MemberKind.Interface && iface_exprs != null) { + MemberCache.RemoveHiddenMembers (spec); + } + + return true; + } + + protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList + { + if (mcal != null) { + for (int i = 0; i < mcal.Count; ++i) { + MemberCore mc = (MemberCore) mcal[i]; + try { + mc.Define (); + } catch (Exception e) { + throw new InternalErrorException (mc, e); + } + } + } + } + + protected virtual void ComputeIndexerName () + { + if (indexers == null) + return; + + string class_indexer_name = null; + + // + // If there's both an explicit and an implicit interface implementation, the + // explicit one actually implements the interface while the other one is just + // a normal indexer. See bug #37714. + // + + // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers + foreach (Indexer i in indexers) { + if (i.InterfaceType != null) { + if (seen_normal_indexers) + throw new Exception ("Internal Error: 'Indexers' array not sorted properly."); + continue; + } + + seen_normal_indexers = true; + + if (class_indexer_name == null) { + class_indexer_name = i.ShortName; + continue; + } + + if (i.ShortName != class_indexer_name) + Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type"); + } + + if (class_indexer_name != null) + indexer_name = class_indexer_name; + } + + void EmitIndexerName () + { + if (!seen_normal_indexers) + return; + + var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get (); + if (ctor == null) + return; + + var encoder = new AttributeEncoder (); + encoder.Encode (GetAttributeDefaultMember ()); + encoder.EncodeEmptyNamedArguments (); + + TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + + protected virtual void CheckEqualsAndGetHashCode () + { + if (methods == null) + return; + + if (HasEquals && !HasGetHashCode) { + Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ()); + } + } + + // Indicated whether container has StructLayout attribute set Explicit + public bool HasExplicitLayout { + get { return (caching_flags & Flags.HasExplicitLayout) != 0; } + set { caching_flags |= Flags.HasExplicitLayout; } + } + + public bool HasStructLayout { + get { return (caching_flags & Flags.HasStructLayout) != 0; } + set { caching_flags |= Flags.HasStructLayout; } + } + + public MemberCache MemberCache { + get { + return spec.MemberCache; + } + } + + void CheckMemberUsage (List al, string member_type) + { + if (al == null) + return; + + foreach (MemberCore mc in al) { + if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) + continue; + + if ((mc.ModFlags & Modifiers.PARTIAL) != 0) + continue; + + if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) { + Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ()); + } + } + } + + public virtual void VerifyMembers () + { + // + // Check for internal or private fields that were never assigned + // + if (Report.WarningLevel >= 3) { + if (Compiler.Settings.EnhancedWarnings) { + CheckMemberUsage (properties, "property"); + CheckMemberUsage (methods, "method"); + CheckMemberUsage (constants, "constant"); + } + + if (fields != null){ + bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly (); + foreach (FieldBase f in fields) { + if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) { + if (is_type_exposed) + continue; + + f.SetIsUsed (); + } + + if (!f.IsUsed){ + if ((f.caching_flags & Flags.IsAssigned) == 0) + Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ()); + else { + Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used", + f.GetSignatureForError ()); + } + continue; + } + + if ((f.caching_flags & Flags.IsAssigned) != 0) + continue; + + // + // Only report 649 on level 4 + // + if (Report.WarningLevel < 4) + continue; + + // + // Don't be pendatic over serializable attributes + // + if (f.OptAttributes != null || PartialContainer.HasStructLayout) + continue; + + Constant c = New.Constantify (f.MemberType, f.Location); + string value; + if (c != null) { + value = c.GetValueAsLiteral (); + } else if (TypeSpec.IsReferenceType (f.MemberType)) { + value = "null"; + } else { + // Ignore this warning for struct value fields (they are always initialized) + if (f.MemberType.IsStruct) + continue; + + value = null; + } + + if (value != null) + value = " `" + value + "'"; + + Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}", + f.GetSignatureForError (), value); + } + } + } + } + + public override void Emit () + { + if (!IsTopLevel) { + MemberSpec candidate; + bool overrides = false; + var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides); + if (conflict_symbol == null && candidate == null) { + if ((ModFlags & Modifiers.NEW) != 0) + Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", + GetSignatureForError ()); + } else { + if ((ModFlags & Modifiers.NEW) == 0) { + if (candidate == null) + candidate = conflict_symbol; + + Report.SymbolRelatedToPreviousError (candidate); + Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", + GetSignatureForError (), candidate.GetSignatureForError ()); + } + } + } + + // Run constraints check on all possible generic types + if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + if (base_type != null && base_type_expr != null) { + ConstraintChecker.Check (this, base_type, base_type_expr.Location); + } + + if (iface_exprs != null) { + foreach (var iface_type in iface_exprs) { + if (iface_type == null) + continue; + + ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong + } + } + } + + if (all_tp_builders != null) { + int current_starts_index = CurrentTypeParametersStartIndex; + for (int i = 0; i < all_tp_builders.Length; i++) { + if (i < current_starts_index) { + TypeParameters[i].EmitConstraints (all_tp_builders [i]); + } else { + var tp = CurrentTypeParameters [i - current_starts_index]; + tp.CheckGenericConstraints (!IsObsolete); + tp.Emit (); + } + } + } + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder); + +#if STATIC + if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet) + TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType); +#endif + + base.Emit (); + } + + // TODO: move to ClassOrStruct + void EmitConstructors () + { + if (instance_constructors == null) + return; + + if (spec.IsAttribute && IsExposedFromAssembly () && Compiler.Settings.VerifyClsCompliance && IsClsComplianceRequired ()) { + bool has_compliant_args = false; + + foreach (Constructor c in instance_constructors) { + try { + c.Emit (); + } + catch (Exception e) { + throw new InternalErrorException (c, e); + } + + if (has_compliant_args) + continue; + + has_compliant_args = c.HasCompliantArgs; + } + if (!has_compliant_args) + Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ()); + } else { + foreach (Constructor c in instance_constructors) { + try { + c.Emit (); + } + catch (Exception e) { + throw new InternalErrorException (c, e); + } + } + } + } + + /// + /// Emits the code, this step is performed after all + /// the types, enumerations, constructors + /// + public virtual void EmitType () + { + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + + if (OptAttributes != null) + OptAttributes.Emit (); + + Emit (); + + EmitConstructors (); + + if (constants != null) + foreach (Const con in constants) + con.Emit (); + + if (default_static_constructor != null) + default_static_constructor.Emit (); + + if (operators != null) + foreach (Operator o in operators) + o.Emit (); + + if (properties != null) + foreach (Property p in properties) + p.Emit (); + + if (indexers != null) { + foreach (Indexer indx in indexers) + indx.Emit (); + EmitIndexerName (); + } + + if (events != null){ + foreach (Event e in Events) + e.Emit (); + } + + if (methods != null) { + for (int i = 0; i < methods.Count; ++i) + ((MethodOrOperator) methods [i]).Emit (); + } + + if (fields != null) + foreach (FieldBase f in fields) + f.Emit (); + + if (types != null) { + foreach (TypeContainer t in types) + t.EmitType (); + } + + if (pending != null) + pending.VerifyPendingMethods (); + + if (Report.Errors > 0) + return; + + if (compiler_generated != null) { + for (int i = 0; i < compiler_generated.Count; ++i) + compiler_generated [i].EmitType (); + } + } + + public virtual void CloseType () + { + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + + // Close base type container first to avoid TypeLoadException + if (spec.BaseType != null) { + var btype = spec.BaseType.MemberDefinition as TypeContainer; + if (btype != null) { + btype.CloseType (); + + if ((caching_flags & Flags.CloseTypeCreated) != 0) + return; + } + } + + try { + caching_flags |= Flags.CloseTypeCreated; + TypeBuilder.CreateType (); + } catch (TypeLoadException){ + // + // This is fine, the code still created the type + // +// Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name); +// Console.WriteLine (e.Message); + } catch (Exception e) { + throw new InternalErrorException (this, e); + } + + if (Types != null){ + foreach (TypeContainer tc in Types) + tc.CloseType (); + } + + if (compiler_generated != null) + foreach (CompilerGeneratedClass c in compiler_generated) + c.CloseType (); + + types = null; + initialized_fields = null; + initialized_static_fields = null; + constants = null; + ordered_explicit_member_list = null; + ordered_member_list = null; + methods = null; + events = null; + indexers = null; + operators = null; + compiler_generated = null; + default_constructor = null; + default_static_constructor = null; + type_bases = null; + OptAttributes = null; + } + + // + // Performs the validation on a Method's modifiers (properties have + // the same properties). + // + // TODO: Why is it not done at parse stage, move to Modifiers::Check + // + public bool MethodModifiersValid (MemberCore mc) + { + const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE); + const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL); + bool ok = true; + var flags = mc.ModFlags; + + // + // At most one of static, virtual or override + // + if ((flags & Modifiers.STATIC) != 0){ + if ((flags & vao) != 0){ + Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract", + mc.GetSignatureForError ()); + ok = false; + } + } + + if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){ + Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual", + mc.GetSignatureForError ()); + ok = false; + } + + // + // If the declaration includes the abstract modifier, then the + // declaration does not include static, virtual or extern + // + if ((flags & Modifiers.ABSTRACT) != 0){ + if ((flags & Modifiers.EXTERN) != 0){ + Report.Error ( + 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ()); + ok = false; + } + + if ((flags & Modifiers.SEALED) != 0) { + Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ()); + ok = false; + } + + if ((flags & Modifiers.VIRTUAL) != 0){ + Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ()); + ok = false; + } + + if ((ModFlags & Modifiers.ABSTRACT) == 0){ + Report.SymbolRelatedToPreviousError (this); + Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'", + mc.GetSignatureForError (), GetSignatureForError ()); + ok = false; + } + } + + if ((flags & Modifiers.PRIVATE) != 0){ + if ((flags & vao) != 0){ + Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ()); + ok = false; + } + } + + if ((flags & Modifiers.SEALED) != 0){ + if ((flags & Modifiers.OVERRIDE) == 0){ + Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ()); + ok = false; + } + } + + return ok; + } + + public Constructor DefaultStaticConstructor { + get { return default_static_constructor; } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + // Check this name against other containers + NamespaceEntry.NS.VerifyClsCompliance (); + + // Check all container names for user classes + if (Kind != MemberKind.Delegate) + MemberCache.VerifyClsCompliance (Definition, Report); + + if (BaseType != null && !BaseType.IsCLSCompliant ()) { + Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", + GetSignatureForError (), BaseType.GetSignatureForError ()); + } + return true; + } + + /// + /// Performs checks for an explicit interface implementation. First it + /// checks whether the `interface_type' is a base inteface implementation. + /// Then it checks whether `name' exists in the interface type. + /// + public bool VerifyImplements (InterfaceMemberBase mb) + { + var ifaces = spec.Interfaces; + if (ifaces != null) { + foreach (TypeSpec t in ifaces){ + if (t == mb.InterfaceType) + return true; + } + } + + Report.SymbolRelatedToPreviousError (mb.InterfaceType); + Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'", + mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType)); + return false; + } + + // + // Used for visiblity checks to tests whether this definition shares + // base type baseType, it does member-definition search + // + public bool IsBaseTypeDefinition (TypeSpec baseType) + { + // RootContext check + if (TypeBuilder == null) + return false; + + var type = spec; + do { + if (type.MemberDefinition == baseType.MemberDefinition) + return true; + + type = type.BaseType; + } while (type != null); + + return false; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + return Module.DeclaringAssembly == assembly; + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ()); + } + + // + // Public function used to locate types. + // + // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors. + // + // Returns: Type or null if they type can not be found. + // + public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + FullNamedExpression e; + if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility) + return e; + + e = null; + + if (arity == 0) { + TypeParameter[] tp = CurrentTypeParameters; + if (tp != null) { + TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name); + if (tparam != null) + e = new TypeParameterExpr (tparam, Location.Null); + } + } + + if (e == null) { + TypeSpec t = LookupNestedTypeInHierarchy (name, arity); + + if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility)) + e = new TypeExpression (t, Location.Null); + else if (Parent != null) { + e = Parent.LookupNamespaceOrType (name, arity, mode, loc); + } else { + int errors = Report.Errors; + + e = NamespaceEntry.LookupNamespaceOrType (name, arity, mode, loc); + + if (errors != Report.Errors) + return e; + } + } + + // TODO MemberCache: How to cache arity stuff ? + if (arity == 0 && mode == LookupMode.Normal) + Cache[name] = e; + + return e; + } + + TypeSpec LookupNestedTypeInHierarchy (string name, int arity) + { + // TODO: GenericMethod only + if (PartialContainer == null) + return null; + + // Has any nested type + // Does not work, because base type can have + //if (PartialContainer.Types == null) + // return null; + + var container = PartialContainer.CurrentType; + + // Is not Root container + if (container == null) + return null; + + return MemberCache.FindNestedType (container, name, arity); + } + + public void Mark_HasEquals () + { + cached_method |= CachedMethods.Equals; + } + + public void Mark_HasGetHashCode () + { + cached_method |= CachedMethods.GetHashCode; + } + + /// + /// Method container contains Equals method + /// + public bool HasEquals { + get { + return (cached_method & CachedMethods.Equals) != 0; + } + } + + /// + /// Method container contains GetHashCode method + /// + public bool HasGetHashCode { + get { + return (cached_method & CachedMethods.GetHashCode) != 0; + } + } + + public bool HasStaticFieldInitializer { + get { + return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0; + } + set { + if (value) + cached_method |= CachedMethods.HasStaticFieldInitializer; + else + cached_method &= ~CachedMethods.HasStaticFieldInitializer; + } + } + + public override string DocCommentHeader { + get { return "T:"; } + } + } + + public abstract class ClassOrStruct : TypeContainer + { + SecurityType declarative_security; + + public ClassOrStruct (NamespaceContainer ns, DeclSpace parent, + MemberName name, Attributes attrs, MemberKind kind) + : base (ns, parent, name, attrs, kind) + { + } + + protected override bool AddToContainer (MemberCore symbol, string name) + { + if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) { + if (symbol is TypeParameter) { + Report.Error (694, symbol.Location, + "Type parameter `{0}' has same name as containing type, or method", + symbol.GetSignatureForError ()); + return false; + } + + InterfaceMemberBase imb = symbol as InterfaceMemberBase; + if (imb == null || !imb.IsExplicitImpl) { + Report.SymbolRelatedToPreviousError (this); + Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type", + symbol.GetSignatureForError ()); + return false; + } + } + + return base.AddToContainer (symbol, name); + } + + public override void VerifyMembers () + { + base.VerifyMembers (); + + if ((events != null) && Report.WarningLevel >= 3) { + foreach (Event e in events){ + // Note: The event can be assigned from same class only, so we can report + // this warning for all accessibility modes + if ((e.caching_flags & Flags.IsUsed) == 0) + Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ()); + } + } + + if (types != null) { + foreach (var t in types) + t.VerifyMembers (); + } + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Type == pa.StructLayout) { + PartialContainer.HasStructLayout = true; + if (a.IsExplicitLayoutKind ()) + PartialContainer.HasExplicitLayout = true; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + /// + /// Defines the default constructors + /// + protected void DefineDefaultConstructor (bool is_static) + { + // The default instance constructor is public + // If the class is abstract, the default constructor is protected + // The default static constructor is private + + Modifiers mods; + if (is_static) { + mods = Modifiers.STATIC | Modifiers.PRIVATE; + } else { + mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC; + } + + Constructor c = new Constructor (this, MemberName.Name, mods, + null, ParametersCompiled.EmptyReadOnlyParameters, + new GeneratedBaseInitializer (Location), + Location); + + AddConstructor (c); + c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location); + } + + protected override bool DoDefineMembers () + { + CheckProtectedModifier (); + + base.DoDefineMembers (); + + if (default_static_constructor != null) + default_static_constructor.Define (); + + return true; + } + + public override void Emit () + { + if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) { + DefineDefaultConstructor (true); + default_static_constructor.Define (); + } + + base.Emit (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + TypeBuilder.__AddDeclarativeSecurity (de); +#else + TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + } + + public override IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + DeclSpace top_level = Parent; + if (top_level != null) { + var candidates = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity); + if (candidates != null) { + scope = NamespaceEntry; + return candidates; + } + } + + return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + protected override TypeAttributes TypeAttr { + get { + if (default_static_constructor == null) + return base.TypeAttr | TypeAttributes.BeforeFieldInit; + + return base.TypeAttr; + } + } + } + + + // TODO: should be sealed + public class Class : ClassOrStruct { + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.ABSTRACT | + Modifiers.SEALED | + Modifiers.STATIC | + Modifiers.UNSAFE; + + public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed; + + public Class (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod, + Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Class) + { + var accmods = (Parent == null || Parent.Parent == null) ? Modifiers.INTERNAL : Modifiers.PRIVATE; + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report); + spec = new TypeSpec (Kind, null, this, null, ModFlags); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void AddBasesForPart (DeclSpace part, List bases) + { + if (part.Name == "System.Object") + Report.Error (537, part.Location, + "The class System.Object cannot have a base class or implement an interface."); + base.AddBasesForPart (part, bases); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.AttributeUsage) { + if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) { + Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ()); + } + } + + if (a.Type == pa.Conditional && !BaseType.IsAttribute) { + Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes"); + return; + } + + if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) { + a.Error_MissingGuidAttribute (); + return; + } + + if (a.Type == pa.Extension) { + a.Error_MisusedExtensionAttribute (); + return; + } + + if (a.Type.IsConditionallyExcluded (Compiler, Location)) + return; + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Class; + } + } + + protected override void DefineContainerMembers (System.Collections.IList list) + { + if (list == null) + return; + + if (!IsStatic) { + base.DefineContainerMembers (list); + return; + } + + foreach (MemberCore m in list) { + if (m is Operator) { + Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ()); + continue; + } + + if (m is Destructor) { + Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ()); + continue; + } + + if (m is Indexer) { + Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ()); + continue; + } + + if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate) + continue; + + if (m is Constructor) { + Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ()); + 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 ()); + } + + base.DefineContainerMembers (list); + } + + protected override bool DoDefineMembers () + { + if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) { + Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ()); + } + + if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) { + Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ()); + } + + if (InstanceConstructors == null && !IsStatic) + DefineDefaultConstructor (false); + + return base.DoDefineMembers (); + } + + public override void Emit () + { + base.Emit (); + + if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0) + Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder); + + if (base_type != null && base_type.HasDynamicElement) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location); + } + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + var ifaces = base.ResolveBaseTypes (out base_class); + + if (base_class == null) { + if (spec.BuiltinType != BuiltinTypeSpec.Type.Object) + base_type = Compiler.BuiltinTypes.Object; + } else { + if (base_type.IsGenericParameter){ + Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + } else if (base_type.IsStatic) { + Report.SymbolRelatedToPreviousError (base_type); + Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + } else if (base_type.IsSealed) { + Report.SymbolRelatedToPreviousError (base_type); + Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) { + Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object", + GetSignatureForError (), base_type.GetSignatureForError ()); + } + + switch (base_type.BuiltinType) { + case BuiltinTypeSpec.Type.Enum: + case BuiltinTypeSpec.Type.ValueType: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.Array: + if (!(spec is BuiltinTypeSpec)) { + Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'", + GetSignatureForError (), base_type.GetSignatureForError ()); + + base_type = Compiler.BuiltinTypes.Object; + } + break; + } + + if (!IsAccessibleAs (base_type)) { + Report.SymbolRelatedToPreviousError (base_type); + Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'", + base_type.GetSignatureForError (), GetSignatureForError ()); + } + } + + if (PartialContainer.IsStatic && ifaces != null) { + foreach (var t in ifaces) + Report.SymbolRelatedToPreviousError (t); + Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ()); + } + + return ifaces; + } + + /// Search for at least one defined condition in ConditionalAttribute of attribute class + /// Valid only for attribute classes. + public override string[] ConditionalConditions () + { + if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0) + return null; + + caching_flags &= ~Flags.Excluded_Undetected; + + if (OptAttributes == null) + return null; + + Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional); + if (attrs == null) + return null; + + string[] conditions = new string[attrs.Length]; + for (int i = 0; i < conditions.Length; ++i) + conditions[i] = attrs[i].GetConditionalAttributeValue (); + + caching_flags |= Flags.Excluded; + return conditions; + } + + // + // FIXME: How do we deal with the user specifying a different + // layout? + // + protected override TypeAttributes TypeAttr { + get { + TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class; + if (IsStatic) + ta |= StaticClassAttribute; + return ta; + } + } + } + + public sealed class Struct : ClassOrStruct { + + bool is_unmanaged, has_unmanaged_check_done; + bool InTransit; + + // + // Modifiers allowed in a struct declaration + // + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Struct (NamespaceContainer ns, DeclSpace parent, MemberName name, + Modifiers mod, Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Struct) + { + var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE; + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ; + spec = new TypeSpec (Kind, null, this, null, ModFlags); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Struct; + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + + // + // When struct constains fixed fixed and struct layout has explicitly + // set CharSet, its value has to be propagated to compiler generated + // fixed types + // + if (a.Type == pa.StructLayout && Fields != null) { + var value = a.GetNamedValue ("CharSet"); + if (value == null) + return; + + for (int i = 0; i < Fields.Count; ++i) { + FixedField ff = Fields [i] as FixedField; + if (ff == null) + continue; + + ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ()); + } + } + } + + bool CheckStructCycles (Struct s) + { + if (s.Fields == null) + return true; + + if (s.InTransit) + return false; + + s.InTransit = true; + foreach (FieldBase field in s.Fields) { + TypeSpec ftype = field.Spec.MemberType; + if (!ftype.IsStruct) + continue; + + if (ftype is BuiltinTypeSpec) + continue; + + foreach (var targ in ftype.TypeArguments) { + if (!CheckFieldTypeCycle (targ)) { + Report.Error (523, field.Location, + "Struct member `{0}' of type `{1}' causes a cycle in the struct layout", + field.GetSignatureForError (), ftype.GetSignatureForError ()); + break; + } + } + + if ((field.IsStatic && (!ftype.IsGeneric || ftype == CurrentType))) + continue; + + if (!CheckFieldTypeCycle (ftype)) { + Report.Error (523, field.Location, + "Struct member `{0}' of type `{1}' causes a cycle in the struct layout", + field.GetSignatureForError (), ftype.GetSignatureForError ()); + break; + } + } + + s.InTransit = false; + return true; + } + + bool CheckFieldTypeCycle (TypeSpec ts) + { + var fts = ts.MemberDefinition as Struct; + if (fts == null) + return true; + + return CheckStructCycles (fts); + } + + public override void Emit () + { + CheckStructCycles (this); + + base.Emit (); + } + + 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; + + 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.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; + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + var ifaces = base.ResolveBaseTypes (out base_class); + base_type = Compiler.BuiltinTypes.ValueType; + return ifaces; + } + + protected override TypeAttributes TypeAttr { + get { + const + TypeAttributes DefaultTypeAttributes = + TypeAttributes.SequentialLayout | + TypeAttributes.Sealed ; + + return base.TypeAttr | DefaultTypeAttributes; + } + } + + public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression) + { + if ((field.ModFlags & Modifiers.STATIC) == 0) { + Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers", + field.GetSignatureForError ()); + return; + } + base.RegisterFieldForInitialization (field, expression); + } + + } + + /// + /// Interfaces + /// + public sealed class Interface : TypeContainer { + + /// + /// Modifiers allowed in a class declaration + /// + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Interface (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod, + Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Interface) + { + var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE; + + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report); + spec = new TypeSpec (Kind, null, this, null, ModFlags); + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Interface; + } + } + + protected override TypeAttributes TypeAttr { + get { + const TypeAttributes DefaultTypeAttributes = + TypeAttributes.AutoLayout | + TypeAttributes.Abstract | + TypeAttributes.Interface; + + return base.TypeAttr | DefaultTypeAttributes; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) { + a.Error_MissingGuidAttribute (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (iface_exprs != null) { + foreach (var iface in iface_exprs) { + if (iface.IsCLSCompliant ()) + continue; + + Report.SymbolRelatedToPreviousError (iface); + Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant", + GetSignatureForError (), TypeManager.CSharpName (iface)); + } + } + + return true; + } + } + + public abstract class InterfaceMemberBase : MemberBase + { + // + // Common modifiers allowed in a class declaration + // + protected const Modifiers AllowedModifiersClass = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.VIRTUAL | + Modifiers.SEALED | + Modifiers.OVERRIDE | + Modifiers.ABSTRACT | + Modifiers.UNSAFE | + Modifiers.EXTERN; + + // + // Common modifiers allowed in a struct declaration + // + protected const Modifiers AllowedModifiersStruct = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.OVERRIDE | + Modifiers.UNSAFE | + Modifiers.EXTERN; + + // + // Common modifiers allowed in a interface declaration + // + protected const Modifiers AllowedModifiersInterface = + Modifiers.NEW | + Modifiers.UNSAFE; + + // + // Whether this is an interface member. + // + public bool IsInterface; + + // + // If true, this is an explicit interface implementation + // + public bool IsExplicitImpl; + + protected bool is_external_implementation; + + // + // The interface type we are explicitly implementing + // + public TypeSpec InterfaceType; + + // + // The method we're overriding if this is an override method. + // + protected MethodSpec base_method; + + readonly Modifiers explicit_mod_flags; + public MethodAttributes flags; + + public InterfaceMemberBase (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, + MemberName name, Attributes attrs) + : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE, + name, attrs) + { + IsInterface = parent.PartialContainer.Kind == MemberKind.Interface; + IsExplicitImpl = (MemberName.Left != null); + explicit_mod_flags = mod; + } + + public abstract Variance ExpectedMemberTypeVariance { get; } + + protected override bool CheckBase () + { + if (!base.CheckBase ()) + return false; + + if ((caching_flags & Flags.MethodOverloadsExist) != 0) + CheckForDuplications (); + + if (IsExplicitImpl) + return true; + + // For System.Object only + if (Parent.BaseType == null) + return true; + + MemberSpec candidate; + bool overrides = false; + var base_member = FindBaseMember (out candidate, ref overrides); + + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + if (base_member == null) { + if (candidate == null) { + if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) { + Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead", + "object.Finalize()"); + } else { + Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override", + GetSignatureForError (), SimpleName.GetMemberType (this)); + } + } else { + Report.SymbolRelatedToPreviousError (candidate); + if (this is Event) + Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", + GetSignatureForError (), TypeManager.GetFullNameSignature (candidate)); + else if (this is PropertyBase) + Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", + GetSignatureForError (), TypeManager.GetFullNameSignature (candidate)); + else + Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", + GetSignatureForError (), TypeManager.GetFullNameSignature (candidate)); + } + + return false; + } + + // + // Handles ambiguous overrides + // + if (candidate != null) { + Report.SymbolRelatedToPreviousError (candidate); + Report.SymbolRelatedToPreviousError (base_member); + + // Get member definition for error reporting + var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member); + var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate); + + Report.Error (462, Location, + "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'", + GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ()); + } + + if (!CheckOverrideAgainstBase (base_member)) + return false; + + ObsoleteAttribute oa = base_member.GetAttributeObsolete (); + if (oa != null) { + 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)); + } + } 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)); + } + } + + base_method = base_member as MethodSpec; + return true; + } + + if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember))) + base_member = candidate; + + if (base_member == null) { + if ((ModFlags & Modifiers.NEW) != 0) { + if (base_member == null) { + Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", + GetSignatureForError ()); + } + } + } else { + if ((ModFlags & Modifiers.NEW) == 0) { + ModFlags |= Modifiers.NEW; + if (!IsCompilerGenerated) { + Report.SymbolRelatedToPreviousError (base_member); + if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) { + Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", + GetSignatureForError (), base_member.GetSignatureForError ()); + } else { + Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", + GetSignatureForError (), base_member.GetSignatureForError ()); + } + } + } + + if (!IsInterface && base_member.IsAbstract && !overrides) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'", + GetSignatureForError (), base_member.GetSignatureForError ()); + } + } + + return true; + } + + protected virtual bool CheckForDuplications () + { + return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters); + } + + // + // Performs various checks on the MethodInfo `mb' regarding the modifier flags + // that have been defined. + // + protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member) + { + bool ok = true; + + if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (506, Location, + "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override", + GetSignatureForError (), TypeManager.CSharpSignature (base_member)); + ok = false; + } + + // Now we check that the overriden method is not final + if ((base_member.Modifiers & Modifiers.SEALED) != 0) { + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed", + GetSignatureForError (), TypeManager.CSharpSignature (base_member)); + ok = false; + } + + var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType; + if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) { + Report.SymbolRelatedToPreviousError (base_member); + if (this is PropertyBasedMember) { + Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'", + GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member)); + } else { + Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'", + GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member)); + } + ok = false; + } + + return ok; + } + + protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member) + { + var thisp = this_member.ModFlags & Modifiers.AccessibilityMask; + var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask; + + if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) { + // + // It must be at least "protected" + // + if ((thisp & Modifiers.PROTECTED) == 0) { + return false; + } + + // + // when overriding protected internal, the method can be declared + // protected internal only within the same assembly or assembly + // which has InternalsVisibleTo + // + if ((thisp & Modifiers.INTERNAL) != 0) { + return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly); + } + + // + // protected overriding protected internal inside same assembly + // requires internal modifier as well + // + if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) { + return false; + } + + return true; + } + + return thisp == base_classp; + } + + public override bool Define () + { + if (IsInterface) { + ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT | + Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW)); + + flags = MethodAttributes.Public | + MethodAttributes.Abstract | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.Virtual; + } else { + Parent.PartialContainer.MethodModifiersValid (this); + + flags = ModifiersExtensions.MethodAttr (ModFlags); + } + + if (IsExplicitImpl) { + InterfaceType = MemberName.Left.GetTypeExpression ().ResolveAsType (Parent); + if (InterfaceType == null) + return false; + + if ((ModFlags & Modifiers.PARTIAL) != 0) { + Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface", + GetSignatureForError ()); + } + + if (!InterfaceType.IsInterface) { + Report.SymbolRelatedToPreviousError (InterfaceType); + Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface", + TypeManager.CSharpName (InterfaceType)); + } else { + Parent.PartialContainer.VerifyImplements (this); + } + + ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report); + } + + return base.Define (); + } + + protected bool DefineParameters (ParametersCompiled parameters) + { + if (!parameters.Resolve (this)) + return false; + + bool error = false; + for (int i = 0; i < parameters.Count; ++i) { + Parameter p = parameters [i]; + + if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1))) + p.Warning_UselessOptionalParameter (Report); + + if (p.CheckAccessibility (this)) + continue; + + TypeSpec t = parameters.Types [i]; + Report.SymbolRelatedToPreviousError (t); + if (this is Indexer) + Report.Error (55, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'", + TypeManager.CSharpName (t), GetSignatureForError ()); + else if (this is Operator) + Report.Error (57, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'", + TypeManager.CSharpName (t), GetSignatureForError ()); + else + Report.Error (51, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'", + TypeManager.CSharpName (t), GetSignatureForError ()); + error = true; + } + return !error; + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this); + } + + public override void Emit() + { + // for extern static method must be specified either DllImport attribute or MethodImplAttribute. + // We are more strict than csc and report this as an error because SRE does not allow emit that + if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) { + if (this is Constructor) { + Report.Warning (824, 1, Location, + "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ()); + } else { + Report.Warning (626, 1, Location, + "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation", + GetSignatureForError ()); + } + } + + base.Emit (); + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + // + // Two members can differ in their explicit interface + // type parameter only + // + InterfaceMemberBase imb = overload as InterfaceMemberBase; + if (imb != null && imb.IsExplicitImpl) { + if (IsExplicitImpl) { + caching_flags |= Flags.MethodOverloadsExist; + } + return true; + } + + return IsExplicitImpl; + } + + protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member) + { + var base_modifiers = base_member.Modifiers; + + // Remove internal modifier from types which are not internally accessible + if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) && + !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly)) + base_modifiers = Modifiers.PROTECTED; + + Report.SymbolRelatedToPreviousError (base_member); + Report.Error (507, member.Location, + "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'", + member.GetSignatureForError (), + ModifiersExtensions.AccessibilityName (base_modifiers), + base_member.GetSignatureForError ()); + } + + protected void Error_StaticReturnType () + { + Report.Error (722, Location, + "`{0}': static types cannot be used as return types", + MemberType.GetSignatureForError ()); + } + + /// + /// Gets base method and its return type + /// + protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) + { + return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides); + } + + // + // The "short" name of this property / indexer / event. This is the + // name without the explicit interface. + // + public string ShortName { + get { return MemberName.Name; } + set { SetMemberName (new MemberName (MemberName.Left, value, Location)); } + } + + // + // Returns full metadata method name + // + public string GetFullName (MemberName name) + { + return GetFullName (name.Name); + } + + public string GetFullName (string name) + { + if (!IsExplicitImpl) + return name; + + // + // When dealing with explicit members a full interface type + // name is added to member name to avoid possible name conflicts + // + // We use CSharpName which gets us full name with benefit of + // replacing predefined names which saves some space and name + // is still unique + // + return TypeManager.CSharpName (InterfaceType) + "." + name; + } + + public override string GetSignatureForDocumentation () + { + if (IsExplicitImpl) + return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName; + + return Parent.GetSignatureForDocumentation () + "." + ShortName; + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) { + return false; + } + + if (GenericMethod != null) + GenericMethod.VerifyClsCompliance (); + + return true; + } + + public override bool IsUsed + { + get { return IsExplicitImpl || base.IsUsed; } + } + + } + + public abstract class MemberBase : MemberCore + { + protected FullNamedExpression type_expr; + protected TypeSpec member_type; + + public readonly DeclSpace ds; + public readonly GenericMethod GenericMethod; + + public FullNamedExpression TypeName { + get { + return type_expr; + } + } + + protected MemberBase (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, + MemberName name, Attributes attrs) + : base (parent, name, attrs) + { + this.ds = generic != null ? generic : (DeclSpace) parent; + this.type_expr = type; + ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report); + GenericMethod = generic; + if (GenericMethod != null) + GenericMethod.ModFlags = ModFlags; + } + + #region Properties + + public TypeSpec MemberType { + get { + return member_type; + } + } + + public FullNamedExpression TypeExpression { + get { + return type_expr; + } + } + + #endregion + + // + // Main member define entry + // + public override bool Define () + { + DoMemberTypeIndependentChecks (); + + // + // Returns false only when type resolution failed + // + if (!ResolveMemberType ()) + return false; + + DoMemberTypeDependentChecks (); + return true; + } + + // + // Any type_name independent checks + // + protected virtual void DoMemberTypeIndependentChecks () + { + if ((Parent.ModFlags & Modifiers.SEALED) != 0 && + (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) { + Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'", + GetSignatureForError (), Parent.GetSignatureForError ()); + } + } + + // + // Any type_name dependent checks + // + protected virtual void DoMemberTypeDependentChecks () + { + // verify accessibility + if (!IsAccessibleAs (MemberType)) { + Report.SymbolRelatedToPreviousError (MemberType); + if (this is Property) + Report.Error (53, Location, + "Inconsistent accessibility: property type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than property `" + GetSignatureForError () + "'"); + else if (this is Indexer) + Report.Error (54, Location, + "Inconsistent accessibility: indexer return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than indexer `" + GetSignatureForError () + "'"); + else if (this is MethodCore) { + if (this is Operator) + Report.Error (56, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than operator `" + GetSignatureForError () + "'"); + else + Report.Error (50, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than method `" + GetSignatureForError () + "'"); + } else { + Report.Error (52, Location, + "Inconsistent accessibility: field type `" + + TypeManager.CSharpName (MemberType) + "' is less " + + "accessible than field `" + GetSignatureForError () + "'"); + } + } + } + + protected bool IsTypePermitted () + { + if (MemberType.IsSpecialRuntimeType) { + Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType)); + return false; + } + return true; + } + + protected virtual bool CheckBase () + { + CheckProtectedModifier (); + + return true; + } + + public override string GetSignatureForDocumentation () + { + return Parent.Name + "." + Name; + } + + protected virtual bool ResolveMemberType () + { + if (member_type != null) + throw new InternalErrorException ("Multi-resolve"); + + member_type = type_expr.ResolveAsType (this); + return member_type != null; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs new file mode 100644 index 0000000000..abd114d2f9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs @@ -0,0 +1,728 @@ +// +// codegen.cs: The code generator +// +// Authors: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + /// + /// An Emit Context is created for each body of code (from methods, + /// properties bodies, indexer bodies or constructor bodies) + /// + public class EmitContext : BuilderContext + { + // TODO: Has to be private + public readonly ILGenerator ig; + + /// + /// The value that is allowed to be returned or NULL if there is no + /// return type. + /// + readonly TypeSpec return_type; + + /// + /// Keeps track of the Type to LocalBuilder temporary storage created + /// to store structures (used to compute the address of the structure + /// value on structure method invocations) + /// + Dictionary temporary_storage; + + /// + /// The location where we store the return value. + /// + public LocalBuilder return_value; + + /// + /// The location where return has to jump to return the + /// value + /// + public Label ReturnLabel; + + /// + /// If we already defined the ReturnLabel + /// + public bool HasReturnLabel; + + /// + /// Current loop begin and end labels. + /// + public Label LoopBegin, LoopEnd; + + /// + /// Default target in a switch statement. Only valid if + /// InSwitch is true + /// + public Label DefaultTarget; + + /// + /// If this is non-null, points to the current switch statement + /// + public Switch Switch; + + /// + /// Whether we are inside an anonymous method. + /// + public AnonymousExpression CurrentAnonymousMethod; + + readonly IMemberContext member_context; + + DynamicSiteClass dynamic_site_container; + + public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type) + { + this.member_context = rc; + this.ig = ig; + + this.return_type = return_type; + +#if STATIC + ig.__CleverExceptionBlockAssistance (); +#endif + } + + #region Properties + + public BuiltinTypes BuiltinTypes { + get { + return MemberContext.Module.Compiler.BuiltinTypes; + } + } + + public TypeSpec CurrentType { + get { return member_context.CurrentType; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return member_context.CurrentTypeParameters; } + } + + public MemberCore CurrentTypeDefinition { + get { return member_context.CurrentMemberDefinition; } + } + + public bool IsStatic { + get { return member_context.IsStatic; } + } + + public bool IsAnonymousStoreyMutateRequired { + get { + return CurrentAnonymousMethod != null && + CurrentAnonymousMethod.Storey != null && + CurrentAnonymousMethod.Storey.Mutator != null; + } + } + + public IMemberContext MemberContext { + get { + return member_context; + } + } + + public ModuleContainer Module { + get { + return member_context.Module; + } + } + + // Has to be used for specific emitter errors only any + // possible resolver errors have to be reported during Resolve + public Report Report { + get { + return member_context.Module.Compiler.Report; + } + } + + public TypeSpec ReturnType { + get { + return return_type; + } + } + #endregion + + /// + /// This is called immediately before emitting an IL opcode to tell the symbol + /// writer to which source line this opcode belongs. + /// + public void Mark (Location loc) + { + if (!SymbolWriter.HasSymbolWriter || HasSet (Options.OmitDebugInfo) || loc.IsNull) + return; + + SymbolWriter.MarkSequencePoint (ig, loc); + } + + public void DefineLocalVariable (string name, LocalBuilder builder) + { + SymbolWriter.DefineLocalVariable (name, builder); + } + + public void BeginCatchBlock (TypeSpec type) + { + ig.BeginCatchBlock (type.GetMetaInfo ()); + } + + public void BeginExceptionBlock () + { + ig.BeginExceptionBlock (); + } + + public void BeginFinallyBlock () + { + ig.BeginFinallyBlock (); + } + + public void BeginScope () + { + SymbolWriter.OpenScope(ig); + } + + public void EndExceptionBlock () + { + ig.EndExceptionBlock (); + } + + public void EndScope () + { + SymbolWriter.CloseScope(ig); + } + + // + // Creates a nested container in this context for all dynamic compiler generated stuff + // + internal DynamicSiteClass CreateDynamicSite () + { + if (dynamic_site_container == null) { + var mc = member_context.CurrentMemberDefinition as MemberBase; + dynamic_site_container = new DynamicSiteClass (CurrentTypeDefinition.Parent.PartialContainer, mc, CurrentTypeParameters); + + CurrentTypeDefinition.Module.AddCompilerGeneratedClass (dynamic_site_container); + dynamic_site_container.CreateType (); + dynamic_site_container.DefineType (); + dynamic_site_container.ResolveTypeParameters (); + dynamic_site_container.Define (); + + var inflator = new TypeParameterInflator (Module, CurrentType, TypeParameterSpec.EmptyTypes, TypeSpec.EmptyTypes); + var inflated = dynamic_site_container.CurrentType.InflateMember (inflator); + CurrentType.MemberCache.AddMember (inflated); + } + + return dynamic_site_container; + } + + public LocalBuilder DeclareLocal (TypeSpec type, bool pinned) + { + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + return ig.DeclareLocal (type.GetMetaInfo (), pinned); + } + + public Label DefineLabel () + { + return ig.DefineLabel (); + } + + public void MarkLabel (Label label) + { + ig.MarkLabel (label); + } + + public void Emit (OpCode opcode) + { + ig.Emit (opcode); + } + + public void Emit (OpCode opcode, LocalBuilder local) + { + ig.Emit (opcode, local); + } + + public void Emit (OpCode opcode, string arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, double arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, float arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, int arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, byte arg) + { + ig.Emit (opcode, arg); + } + + public void Emit (OpCode opcode, Label label) + { + ig.Emit (opcode, label); + } + + public void Emit (OpCode opcode, Label[] labels) + { + ig.Emit (opcode, labels); + } + + public void Emit (OpCode opcode, TypeSpec type) + { + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + ig.Emit (opcode, type.GetMetaInfo ()); + } + + public void Emit (OpCode opcode, FieldSpec field) + { + if (IsAnonymousStoreyMutateRequired) + field = field.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (opcode, field.GetMetaInfo ()); + } + + public void Emit (OpCode opcode, MethodSpec method) + { + if (IsAnonymousStoreyMutateRequired) + method = method.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + if (method.IsConstructor) + ig.Emit (opcode, (ConstructorInfo) method.GetMetaInfo ()); + else + ig.Emit (opcode, (MethodInfo) method.GetMetaInfo ()); + } + + // TODO: REMOVE breaks mutator + public void Emit (OpCode opcode, MethodInfo method) + { + ig.Emit (opcode, method); + } + + public void Emit (OpCode opcode, MethodSpec method, MetaType[] vargs) + { + // TODO MemberCache: This should mutate too + ig.EmitCall (opcode, (MethodInfo) method.GetMetaInfo (), vargs); + } + + public void EmitArrayNew (ArrayContainer ac) + { + if (ac.Rank == 1) { + Emit (OpCodes.Newarr, ac.Element); + } else { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Newobj, ac.GetConstructor ()); + } + } + + public void EmitArrayAddress (ArrayContainer ac) + { + if (ac.Rank > 1) { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Call, ac.GetAddressMethod ()); + } else { + Emit (OpCodes.Ldelema, ac.Element); + } + } + + // + // Emits the right opcode to load from an array + // + public void EmitArrayLoad (ArrayContainer ac) + { + if (ac.Rank > 1) { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Call, ac.GetGetMethod ()); + return; + } + + var type = ac.Element; + if (type.Kind == MemberKind.Enum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Bool: + Emit (OpCodes.Ldelem_U1); + return; + case BuiltinTypeSpec.Type.SByte: + Emit (OpCodes.Ldelem_I1); + return; + case BuiltinTypeSpec.Type.Short: + Emit (OpCodes.Ldelem_I2); + return; + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + Emit (OpCodes.Ldelem_U2); + return; + case BuiltinTypeSpec.Type.Int: + Emit (OpCodes.Ldelem_I4); + return; + case BuiltinTypeSpec.Type.UInt: + Emit (OpCodes.Ldelem_U4); + return; + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Long: + Emit (OpCodes.Ldelem_I8); + return; + case BuiltinTypeSpec.Type.Float: + Emit (OpCodes.Ldelem_R4); + return; + case BuiltinTypeSpec.Type.Double: + Emit (OpCodes.Ldelem_R8); + return; + case BuiltinTypeSpec.Type.IntPtr: + Emit (OpCodes.Ldelem_I); + return; + } + + switch (type.Kind) { + case MemberKind.Struct: + Emit (OpCodes.Ldelema, type); + Emit (OpCodes.Ldobj, type); + break; + case MemberKind.TypeParameter: + Emit (OpCodes.Ldelem, type); + break; + case MemberKind.PointerType: + Emit (OpCodes.Ldelem_I); + break; + default: + Emit (OpCodes.Ldelem_Ref); + break; + } + } + + // + // Emits the right opcode to store to an array + // + public void EmitArrayStore (ArrayContainer ac) + { + if (ac.Rank > 1) { + if (IsAnonymousStoreyMutateRequired) + ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); + + ig.Emit (OpCodes.Call, ac.GetSetMethod ()); + return; + } + + var type = ac.Element; + + if (type.Kind == MemberKind.Enum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + Emit (OpCodes.Stelem_I1); + return; + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + Emit (OpCodes.Stelem_I2); + return; + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + Emit (OpCodes.Stelem_I4); + return; + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + Emit (OpCodes.Stelem_I8); + return; + case BuiltinTypeSpec.Type.Float: + Emit (OpCodes.Stelem_R4); + return; + case BuiltinTypeSpec.Type.Double: + Emit (OpCodes.Stelem_R8); + return; + } + + switch (type.Kind) { + case MemberKind.Struct: + Emit (OpCodes.Stobj, type); + break; + case MemberKind.TypeParameter: + Emit (OpCodes.Stelem, type); + break; + case MemberKind.PointerType: + Emit (OpCodes.Stelem_I); + break; + default: + Emit (OpCodes.Stelem_Ref); + break; + } + } + + public void EmitInt (int i) + { + switch (i) { + case -1: + ig.Emit (OpCodes.Ldc_I4_M1); + break; + + case 0: + ig.Emit (OpCodes.Ldc_I4_0); + break; + + case 1: + ig.Emit (OpCodes.Ldc_I4_1); + break; + + case 2: + ig.Emit (OpCodes.Ldc_I4_2); + break; + + case 3: + ig.Emit (OpCodes.Ldc_I4_3); + break; + + case 4: + ig.Emit (OpCodes.Ldc_I4_4); + break; + + case 5: + ig.Emit (OpCodes.Ldc_I4_5); + break; + + case 6: + ig.Emit (OpCodes.Ldc_I4_6); + break; + + case 7: + ig.Emit (OpCodes.Ldc_I4_7); + break; + + case 8: + ig.Emit (OpCodes.Ldc_I4_8); + break; + + default: + if (i >= -128 && i <= 127) { + ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i); + } else + ig.Emit (OpCodes.Ldc_I4, i); + break; + } + } + + public void EmitLong (long l) + { + if (l >= int.MinValue && l <= int.MaxValue) { + EmitInt (unchecked ((int) l)); + ig.Emit (OpCodes.Conv_I8); + return; + } + + if (l >= 0 && l <= uint.MaxValue) { + EmitInt (unchecked ((int) l)); + ig.Emit (OpCodes.Conv_U8); + return; + } + + ig.Emit (OpCodes.Ldc_I8, l); + } + + // + // Load the object from the pointer. + // + public void EmitLoadFromPtr (TypeSpec type) + { + if (type.Kind == MemberKind.Enum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + ig.Emit (OpCodes.Ldind_I4); + return; + case BuiltinTypeSpec.Type.UInt: + ig.Emit (OpCodes.Ldind_U4); + return; + case BuiltinTypeSpec.Type.Short: + ig.Emit (OpCodes.Ldind_I2); + return; + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + ig.Emit (OpCodes.Ldind_U2); + return; + case BuiltinTypeSpec.Type.Byte: + ig.Emit (OpCodes.Ldind_U1); + return; + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + ig.Emit (OpCodes.Ldind_I1); + return; + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Long: + ig.Emit (OpCodes.Ldind_I8); + return; + case BuiltinTypeSpec.Type.Float: + ig.Emit (OpCodes.Ldind_R4); + return; + case BuiltinTypeSpec.Type.Double: + ig.Emit (OpCodes.Ldind_R8); + return; + case BuiltinTypeSpec.Type.IntPtr: + ig.Emit (OpCodes.Ldind_I); + return; + } + + switch (type.Kind) { + case MemberKind.Struct: + case MemberKind.TypeParameter: + Emit (OpCodes.Ldobj, type); + break; + case MemberKind.PointerType: + ig.Emit (OpCodes.Ldind_I); + break; + default: + ig.Emit (OpCodes.Ldind_Ref); + break; + } + } + + // + // The stack contains the pointer and the value of type `type' + // + public void EmitStoreFromPtr (TypeSpec type) + { + if (type.IsEnum) + type = EnumSpec.GetUnderlyingType (type); + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + ig.Emit (OpCodes.Stind_I4); + return; + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + ig.Emit (OpCodes.Stind_I8); + return; + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + ig.Emit (OpCodes.Stind_I2); + return; + case BuiltinTypeSpec.Type.Float: + ig.Emit (OpCodes.Stind_R4); + return; + case BuiltinTypeSpec.Type.Double: + ig.Emit (OpCodes.Stind_R8); + return; + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + ig.Emit (OpCodes.Stind_I1); + return; + case BuiltinTypeSpec.Type.IntPtr: + ig.Emit (OpCodes.Stind_I); + return; + } + + if (type.IsStruct || TypeManager.IsGenericParameter (type)) + Emit (OpCodes.Stobj, type); + else + ig.Emit (OpCodes.Stind_Ref); + } + + /// + /// Returns a temporary storage for a variable of type t as + /// a local variable in the current body. + /// + public LocalBuilder GetTemporaryLocal (TypeSpec t) + { + if (temporary_storage != null) { + object o; + if (temporary_storage.TryGetValue (t, out o)) { + if (o is Stack) { + var s = (Stack) o; + o = s.Count == 0 ? null : s.Pop (); + } else { + temporary_storage.Remove (t); + } + } + if (o != null) + return (LocalBuilder) o; + } + return DeclareLocal (t, false); + } + + public void FreeTemporaryLocal (LocalBuilder b, TypeSpec t) + { + if (temporary_storage == null) { + temporary_storage = new Dictionary (ReferenceEquality.Default); + temporary_storage.Add (t, b); + return; + } + object o; + + if (!temporary_storage.TryGetValue (t, out o)) { + temporary_storage.Add (t, b); + return; + } + var s = o as Stack; + if (s == null) { + s = new Stack (); + s.Push ((LocalBuilder)o); + temporary_storage [t] = s; + } + s.Push (b); + } + + /// + /// ReturnValue creates on demand the LocalBuilder for the + /// return value from the function. By default this is not + /// used. This is only required when returns are found inside + /// Try or Catch statements. + /// + /// This method is typically invoked from the Emit phase, so + /// we allow the creation of a return label if it was not + /// requested during the resolution phase. Could be cleaned + /// up, but it would replicate a lot of logic in the Emit phase + /// of the code that uses it. + /// + public LocalBuilder TemporaryReturn () + { + if (return_value == null){ + return_value = DeclareLocal (return_type, false); + if (!HasReturnLabel){ + ReturnLabel = DefineLabel (); + HasReturnLabel = true; + } + } + + return return_value; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc new file mode 100644 index 0000000000..952437601c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc @@ -0,0 +1,116 @@ +Compiler operation + +The compiler has a number of phases: + +* Parsing. + + Initially the compiler parses all the source files and keeps a + parsed representation in memory. Very syntax error checking + is performed at this point. + + The compiler stores the information in classes whose names + represent the language construct, for example, the "if" + construct is stored in an `If' class. A class is stored in a + `Class'. + +* The TypeManager + + The TypeManager loads all the assemblies that were referenced + by the programmer. The CLR type system is used as our + repository for types defined as well. + + So the same interface that is used to query the types, + properties and flags about system types is the same interface + that we use for our types. + + As we work our way through the code generation and semantic + analysis, new types are entered into the Type system through + the use of System.Reflection.Emit. The TypeManager will + lookup types on both the user defined types and on the system + defined ones. + + So special care has to be used. The order in which we + proceeed from here is important. + +* Base class resolution and type definition. + + Once the parsing has happened, the compiler resolves the + inheritance tree for interfaces. This is done recursively + and we catch recursive interface definitions here. + + After this is done, we continue on with classes. Classes have + can have an optional "parent" inherit from or the implicit + System.Object class (for normal builds, builds with /nostdlib + will allow you to compile class System.Object with no parent). + + At this point we do some error checking and verify that the + inherits/implements section of a class is correct (since we + have previously built the interface inheritance). + + By the time we are done, all classes, structs and interfaces + have been created using System.Reflection.Emit and registered + with the Type Manager. + + This allows us to define fields and resolve argument names for + methods, properties, indexers and events. + +* Field generation + + Fields are generated next, we go through all the type + containers (classes and structs) and enter the fields into + their types. + +* Method, Properties, Indexers and events definitions + + Now all the methods, constructors, properties, indexers and + events are entered. They are only `defined' using + System.Reflection.Emit. No code generation will happen until + everything has been entered into System.Reflection.Emit. + + This is important because to actually generate code we need to + know everything about the environment in which the code is + being generated. + +* Code Generation + + At this point all the definitions have been entered into the + type manager through System.Reflection.Emit. We can now use + System.Reflection to query all the information about the + types. + + Your normal semantic analysis and code generation phase lives + here. + +* Statements + + Most of the statements are handled in the codegen.cs file. + +* Expressions + +* Error reporting + + Always use `Report::Error' or `Report::Warning' methods of Report + class. The actual Report instance is available via local context. + An expression error reporting has to be done during Resolve phase, + except when it's Emit specific (very rare). + + Error reporting should try to use the same codes that the + Microsoft compiler uses (if only so we can track which errors + we handle and which ones we dont). + + If there is an error which is specific to MSC, use negative + numbers, and register the number in mcs/errors/errors.txt + + Try to write a test case for any error that you run into the + code of the compiler if there is none already. + + Put your test case in a file called csNNNN.cs in the + mcs/errors directory, and have the first two lines be: + + // csNNNN.cs: This is the error message + // Line: XXX + // Compiler options: an optional compiler options + + Where `XXX' is the line where the error ocurrs. We will later + use this as a regression test suite for catching errors in the + compiler. diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs new file mode 100644 index 0000000000..965416e79b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs @@ -0,0 +1,200 @@ +// +// complete.cs: Expression that are used for completion suggestions. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2009 Novell, Inc. +// +// Completion* classes derive from ExpressionStatement as this allows +// them to pass through the parser in many conditions that require +// statements even when the expression is incomplete (for example +// completing inside a lambda +// +using System.Collections.Generic; +using System.Linq; + +namespace Mono.CSharp { + + // + // A common base class for Completing expressions, it + // is just a very simple ExpressionStatement + // + public abstract class CompletingExpression : ExpressionStatement + { + public static void AppendResults (List results, string prefix, IEnumerable names) + { + foreach (string name in names) { + if (name == null) + continue; + + if (prefix != null && !name.StartsWith (prefix)) + continue; + + if (results.Contains (name)) + continue; + + if (prefix != null) + results.Add (name.Substring (prefix.Length)); + else + results.Add (name); + } + } + + public override void EmitStatement (EmitContext ec) + { + // Do nothing + } + + public override void Emit (EmitContext ec) + { + // Do nothing + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return null; + } + } + + public class CompletionSimpleName : CompletingExpression { + public string Prefix; + + public CompletionSimpleName (string prefix, Location l) + { + this.loc = l; + this.Prefix = prefix; + } + + protected override Expression DoResolve (ResolveContext ec) + { + var results = new List (); + + AppendResults (results, Prefix, ec.Module.Evaluator.GetVarNames ()); + AppendResults (results, Prefix, ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (Prefix)); + AppendResults (results, Prefix, ec.Module.Evaluator.GetUsingList ()); + + throw new CompletionResult (Prefix, results.ToArray ()); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + } + + public class CompletionMemberAccess : CompletingExpression { + Expression expr; + string partial_name; + TypeArguments targs; + + public CompletionMemberAccess (Expression e, string partial_name, Location l) + { + this.expr = e; + this.loc = l; + this.partial_name = partial_name; + } + + public CompletionMemberAccess (Expression e, string partial_name, TypeArguments targs, Location l) + { + this.expr = e; + this.loc = l; + this.partial_name = partial_name; + this.targs = targs; + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression expr_resolved = expr.Resolve (ec, + ResolveFlags.VariableOrValue | ResolveFlags.Type); + + if (expr_resolved == null) + return null; + + 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); + return null; + } + + if (targs != null) { + if (!targs.Resolve (ec)) + return null; + } + + var results = new List (); + if (expr_resolved is Namespace){ + Namespace nexpr = expr_resolved as Namespace; + string namespaced_partial; + + if (partial_name == null) + namespaced_partial = nexpr.Name; + else + namespaced_partial = nexpr.Name + "." + partial_name; + +#if false + Console.WriteLine ("Workign with: namespaced partial {0}", namespaced_partial); + foreach (var x in ec.TypeContainer.NamespaceEntry.CompletionGetTypesStartingWith (ec.TypeContainer, namespaced_partial)){ + Console.WriteLine (" {0}", x); + } +#endif + + CompletionSimpleName.AppendResults ( + results, + partial_name, + ec.CurrentMemberDefinition.Parent.NamespaceEntry.CompletionGetTypesStartingWith (namespaced_partial)); + } else { + var r = MemberCache.GetCompletitionMembers (ec, expr_type, partial_name).Select (l => l.Name); + AppendResults (results, partial_name, r); + } + + throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ()); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CompletionMemberAccess target = (CompletionMemberAccess) t; + + if (targs != null) + target.targs = targs.Clone (); + + target.expr = expr.Clone (clonectx); + } + } + + public class CompletionElementInitializer : CompletingExpression { + string partial_name; + + public CompletionElementInitializer (string partial_name, Location l) + { + this.partial_name = partial_name; + this.loc = l; + } + + protected override Expression DoResolve (ResolveContext ec) + { + var members = MemberCache.GetCompletitionMembers (ec, ec.CurrentInitializerVariable.Type, partial_name); + +// TODO: Does this mean exact match only ? +// if (partial_name != null && results.Count > 0 && result [0] == "") +// throw new CompletionResult ("", new string [] { "=" }); + + var results = members.Where (l => (l.Kind & (MemberKind.Field | MemberKind.Property)) != 0).Select (l => l.Name).ToList (); + if (partial_name != null) { + var temp = new List (); + AppendResults (temp, partial_name, results); + results = temp; + } + + throw new CompletionResult (partial_name == null ? "" : partial_name, results.Distinct ().ToArray ()); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + } + +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs new file mode 100644 index 0000000000..0ff7bf81f8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs @@ -0,0 +1,237 @@ +// +// const.cs: Constant declarations. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001-2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +#if STATIC +using IKVM.Reflection; +#else +using System.Reflection; +#endif + +namespace Mono.CSharp { + + public class Const : FieldBase + { + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; + + public Const (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, type, mod_flags, AllowedModifiers, name, attrs) + { + ModFlags |= Modifiers.STATIC; + } + + /// + /// Defines the constant in the @parent + /// + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!member_type.IsConstantCompatible) { + Error_InvalidConstantType (member_type, Location, Report); + } + + FieldAttributes field_attr = FieldAttributes.Static | ModifiersExtensions.FieldAttr (ModFlags); + // Decimals cannot be emitted into the constant blob. So, convert to 'readonly'. + if (member_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + field_attr |= FieldAttributes.InitOnly; + } else { + field_attr |= FieldAttributes.Literal; + } + + FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), field_attr); + spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer); + + Parent.MemberCache.AddMember (spec); + + if ((field_attr & FieldAttributes.InitOnly) != 0) + Parent.PartialContainer.RegisterFieldForInitialization (this, + new FieldInitializer (spec, initializer, this)); + + if (declarators != null) { + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Constants.IndexOf (this); + foreach (var d in declarators) { + var c = new Const (Parent, t, ModFlags & ~Modifiers.STATIC, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + c.initializer = d.Initializer; + ((ConstInitializer) c.initializer).Name = d.Name.Value; + Parent.PartialContainer.Constants.Insert (++index, c); + } + } + + return true; + } + + public void DefineValue () + { + var rc = new ResolveContext (this); + ((ConstSpec) spec).GetConstant (rc); + } + + /// + /// Emits the field value by evaluating the expression + /// + public override void Emit () + { + var c = ((ConstSpec) spec).Value as Constant; + if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + Module.PredefinedAttributes.DecimalConstant.EmitAttribute (FieldBuilder, (decimal) c.GetValue (), c.Location); + } else { + FieldBuilder.SetConstant (c.GetValue ()); + } + + base.Emit (); + } + + public static void Error_InvalidConstantType (TypeSpec t, Location loc, Report Report) + { + if (t.IsGenericParameter) { + Report.Error (1959, loc, + "Type parameter `{0}' cannot be declared const", TypeManager.CSharpName (t)); + } else { + Report.Error (283, loc, + "The type `{0}' cannot be declared const", TypeManager.CSharpName (t)); + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class ConstSpec : FieldSpec + { + Expression value; + + public ConstSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo fi, Modifiers mod, Expression value) + : base (declaringType, definition, memberType, fi, mod) + { + this.value = value; + } + + // + // This expresion is guarantee to be a constant at emit phase only + // + public Expression Value { + get { + return value; + } + } + + // + // For compiled constants we have to resolve the value as there could be constant dependecies. This + // is needed for imported constants too to get the right context type + // + public Constant GetConstant (ResolveContext rc) + { + if (value.eclass != ExprClass.Value) + value = value.Resolve (rc); + + return (Constant) value; + } + } + + public class ConstInitializer : ShimExpression + { + bool in_transit; + readonly FieldBase field; + + public ConstInitializer (FieldBase field, Expression value, Location loc) + : base (value) + { + this.loc = loc; + this.field = field; + } + + public string Name { get; set; } + + protected override Expression DoResolve (ResolveContext unused) + { + if (type != null) + return expr; + + var opt = ResolveContext.Options.ConstantScope; + if (field is EnumMember) + opt |= ResolveContext.Options.EnumScope; + + // + // Use a context in which the constant was declared and + // not the one in which is referenced + // + var rc = new ResolveContext (field, opt); + expr = DoResolveInitializer (rc); + type = expr.Type; + + return expr; + } + + protected virtual Expression DoResolveInitializer (ResolveContext rc) + { + if (in_transit) { + field.Compiler.Report.Error (110, expr.Location, + "The evaluation of the constant value for `{0}' involves a circular definition", + GetSignatureForError ()); + + expr = null; + } else { + in_transit = true; + expr = expr.Resolve (rc); + } + + in_transit = false; + + if (expr != null) { + Constant c = expr as Constant; + if (c != null) + c = field.ConvertInitializer (rc, c); + + if (c == null) { + if (TypeSpec.IsReferenceType (field.MemberType)) + Error_ConstantCanBeInitializedWithNullOnly (rc, field.MemberType, expr.Location, GetSignatureForError ()); + else if (!(expr is Constant)) + Error_ExpressionMustBeConstant (rc, expr.Location, GetSignatureForError ()); + else + expr.Error_ValueCannotBeConverted (rc, expr.Location, field.MemberType, false); + } + + expr = c; + } + + if (expr == null) { + expr = New.Constantify (field.MemberType, Location); + if (expr == null) + expr = Constant.CreateConstantFromValue (field.MemberType, null, Location); + expr = expr.Resolve (rc); + } + + return expr; + } + + public override string GetSignatureForError () + { + if (Name == null) + return field.GetSignatureForError (); + + return field.Parent.GetSignatureForError () + "." + Name; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs new file mode 100644 index 0000000000..2848e46a7e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs @@ -0,0 +1,2232 @@ +// +// constant.cs: Constants. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001-2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Globalization; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// Base class for constants and literals. + /// + public abstract class Constant : Expression + { + static readonly NumberFormatInfo nfi = CultureInfo.InvariantCulture.NumberFormat; + + protected Constant (Location loc) + { + this.loc = loc; + } + + override public string ToString () + { + return this.GetType ().Name + " (" + GetValueAsLiteral () + ")"; + } + + /// + /// This is used to obtain the actual value of the literal + /// cast into an object. + /// + public abstract object GetValue (); + + public abstract long GetValueAsLong (); + + public abstract string GetValueAsLiteral (); + +#if !STATIC + // + // Returns an object value which is typed to contant type + // + public virtual object GetTypedValue () + { + return GetValue (); + } +#endif + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + if (!expl && IsLiteral && + BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) && + BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) { + ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", + GetValueAsLiteral (), TypeManager.CSharpName (target)); + } else { + base.Error_ValueCannotBeConverted (ec, loc, target, expl); + } + } + + public Constant ImplicitConversionRequired (ResolveContext ec, TypeSpec type, Location loc) + { + Constant c = ConvertImplicitly (type); + if (c == null) + Error_ValueCannotBeConverted (ec, loc, type, false); + + return c; + } + + public virtual Constant ConvertImplicitly (TypeSpec type) + { + if (this.type == type) + return this; + + if (Convert.ImplicitNumericConversion (this, type) == null) + return null; + + bool fail; + object constant_value = ChangeType (GetValue (), type, out fail); + if (fail){ + // + // We should always catch the error before this is ever + // reached, by calling Convert.ImplicitStandardConversionExists + // + throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'", + TypeManager.CSharpName (Type), TypeManager.CSharpName (type)); + } + + return CreateConstant (type, constant_value, loc); + } + + // + // Returns a constant instance based on Type + // + public static Constant CreateConstant (TypeSpec t, object v, Location loc) + { + return CreateConstantFromValue (t, v, loc); + } + + public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return new IntConstant (t, (int) v, loc); + case BuiltinTypeSpec.Type.String: + return new StringConstant (t, (string) v, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (t, (uint) v, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (t, (long) v, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (t, (ulong) v, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (t, (float) v, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (t, (double) v, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (t, (short) v, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (t, (ushort) v, loc); + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (t, (sbyte) v, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (t, (byte) v, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (t, (char) v, loc); + case BuiltinTypeSpec.Type.Bool: + return new BoolConstant (t, (bool) v, loc); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (t, (decimal) v, loc); + } + + if (t.IsEnum) { + var real_type = EnumSpec.GetUnderlyingType (t); + return new EnumConstant (CreateConstantFromValue (real_type, v, loc), t); + } + + if (v == null) { + if (t.IsNullableType) + return Nullable.LiftedNull.Create (t, loc); + + if (TypeSpec.IsReferenceType (t)) + return new NullConstant (t, loc); + } + + throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", + v, TypeManager.CSharpName (t)); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (type, loc))); + + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + /// + /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type. + /// It throws OverflowException + /// + // DON'T CALL THIS METHOD DIRECTLY AS IT DOES NOT HANDLE ENUMS + public abstract Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type); + + // This is a custom version of Convert.ChangeType() which works + // with the TypeBuilder defined types when compiling corlib. + static object ChangeType (object value, TypeSpec targetType, out bool error) + { + IConvertible convert_value = value as IConvertible; + + if (convert_value == null) { + error = true; + return null; + } + + // + // We cannot rely on build-in type conversions as they are + // more limited than what C# supports. + // See char -> float/decimal/double conversion + // + error = false; + try { + switch (targetType.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + return convert_value.ToBoolean (nfi); + case BuiltinTypeSpec.Type.Byte: + return convert_value.ToByte (nfi); + case BuiltinTypeSpec.Type.Char: + return convert_value.ToChar (nfi); + case BuiltinTypeSpec.Type.Short: + return convert_value.ToInt16 (nfi); + case BuiltinTypeSpec.Type.Int: + return convert_value.ToInt32 (nfi); + case BuiltinTypeSpec.Type.Long: + return convert_value.ToInt64 (nfi); + case BuiltinTypeSpec.Type.SByte: + return convert_value.ToSByte (nfi); + case BuiltinTypeSpec.Type.Decimal: + if (convert_value.GetType () == typeof (char)) + return (decimal) convert_value.ToInt32 (nfi); + return convert_value.ToDecimal (nfi); + case BuiltinTypeSpec.Type.Double: + if (convert_value.GetType () == typeof (char)) + return (double) convert_value.ToInt32 (nfi); + return convert_value.ToDouble (nfi); + case BuiltinTypeSpec.Type.Float: + if (convert_value.GetType () == typeof (char)) + return (float) convert_value.ToInt32 (nfi); + return convert_value.ToSingle (nfi); + case BuiltinTypeSpec.Type.String: + return convert_value.ToString (nfi); + case BuiltinTypeSpec.Type.UShort: + return convert_value.ToUInt16 (nfi); + case BuiltinTypeSpec.Type.UInt: + return convert_value.ToUInt32 (nfi); + case BuiltinTypeSpec.Type.ULong: + return convert_value.ToUInt64 (nfi); + case BuiltinTypeSpec.Type.Object: + return value; + } + } catch { + } + + error = true; + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + return this; + } + + /// + /// Attempts to do a compile-time folding of a constant cast. + /// + public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc) + { + try { + return TryReduce (ec, target_type); + } + catch (OverflowException) { + if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { + ec.Report.Error (221, loc, + "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", + GetValueAsLiteral (), target_type.GetSignatureForError ()); + } else { + Error_ValueCannotBeConverted (ec, loc, target_type, false); + } + + return New.Constantify (target_type, loc); + } + } + + Constant TryReduce (ResolveContext ec, TypeSpec target_type) + { + if (Type == target_type) + return this; + + Constant c; + if (TypeManager.IsEnumType (target_type)) { + c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type)); + if (c == null) + return null; + + return new EnumConstant (c, target_type); + } + + return ConvertExplicitly (ec.ConstantCheckState, target_type); + } + + /// + /// Need to pass type as the constant can require a boxing + /// and in such case no optimization is possible + /// + public bool IsDefaultInitializer (TypeSpec type) + { + if (type == Type) + return IsDefaultValue; + + return this is NullLiteral; + } + + public abstract bool IsDefaultValue { + get; + } + + public abstract bool IsNegative { + get; + } + + // + // When constant is declared as literal + // + public virtual bool IsLiteral { + get { return false; } + } + + public virtual bool IsOneInteger { + get { return false; } + } + + // + // Returns true iff 1) the stack type of this is one of Object, + // int32, int64 and 2) this == 0 or this == null. + // + public virtual bool IsZeroInteger { + get { return false; } + } + + public override void EmitSideEffect (EmitContext ec) + { + // do nothing + } + + public sealed override Expression Clone (CloneContext clonectx) + { + // No cloning is not needed for constants + return this; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + throw new NotSupportedException ("should not be reached"); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return System.Linq.Expressions.Expression.Constant (GetTypedValue (), type.GetMetaInfo ()); +#endif + } + + public new bool Resolve (ResolveContext rc) + { + // It exists only as hint not to call Resolve on constants + return true; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + public abstract class IntegralConstant : Constant + { + protected IntegralConstant (TypeSpec type, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + try { + ConvertExplicitly (true, target); + base.Error_ValueCannotBeConverted (ec, loc, target, expl); + } + catch + { + ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'", + GetValue ().ToString (), TypeManager.CSharpName (target)); + } + } + + public override string GetValueAsLiteral () + { + return GetValue ().ToString (); + } + + public abstract Constant Increment (); + } + + public class BoolConstant : Constant { + public readonly bool Value; + + public BoolConstant (BuiltinTypes types, bool val, Location loc) + : this (types.Bool, val, loc) + { + } + + public BoolConstant (TypeSpec type, bool val, Location loc) + : base (loc) + { + eclass = ExprClass.Value; + this.type = type; + + Value = val; + } + + public override object GetValue () + { + return (object) Value; + } + + public override string GetValueAsLiteral () + { + return Value ? "true" : "false"; + } + + public override long GetValueAsLong () + { + return Value ? 1 : 0; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + if (Value) + ec.Emit (OpCodes.Ldc_I4_1); + else + ec.Emit (OpCodes.Ldc_I4_0); + } + + public override bool IsDefaultValue { + get { + return !Value; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsZeroInteger { + get { return Value == false; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + return null; + } + + } + + public class ByteConstant : IntegralConstant + { + public readonly byte Value; + + public ByteConstant (BuiltinTypes types, byte v, Location loc) + : this (types.Byte, v, loc) + { + } + + public ByteConstant (TypeSpec type, byte v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new ByteConstant (type, checked ((byte)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context){ + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class CharConstant : Constant { + public readonly char Value; + + public CharConstant (BuiltinTypes types, char v, Location loc) + : this (types.Char, v, loc) + { + } + + public CharConstant (TypeSpec type, char v, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode ((ushort) Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + static string descape (char c) + { + switch (c){ + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\n': + return "\\n"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + case '\r': + return "\\r"; + case '\\': + return "\\\\"; + case '\f': + return "\\f"; + case '\0': + return "\\0"; + case '"': + return "\\\""; + case '\'': + return "\\\'"; + } + return c.ToString (); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return "\"" + descape (Value) + "\""; + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsZeroInteger { + get { return Value == '\0'; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class SByteConstant : IntegralConstant + { + public readonly sbyte Value; + + public SByteConstant (BuiltinTypes types, sbyte v, Location loc) + : this (types.SByte, v, loc) + { + } + + public SByteConstant (TypeSpec type, sbyte v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new SByteConstant (type, checked((sbyte)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class ShortConstant : IntegralConstant { + public readonly short Value; + + public ShortConstant (BuiltinTypes types, short v, Location loc) + : this (types.Short, v, loc) + { + } + + public ShortConstant (TypeSpec type, short v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new ShortConstant (type, checked((short)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context && Value < 0) + throw new OverflowException (); + + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class UShortConstant : IntegralConstant + { + public readonly ushort Value; + + public UShortConstant (BuiltinTypes types, ushort v, Location loc) + : this (types.UShort, v, loc) + { + } + + public UShortConstant (TypeSpec type, ushort v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new UShortConstant (type, checked((ushort)(Value + 1)), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + } + + public class IntConstant : IntegralConstant + { + public readonly int Value; + + public IntConstant (BuiltinTypes types, int v, Location loc) + : this (types.Int, v, loc) + { + } + + public IntConstant (TypeSpec type, int v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new IntConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < Int16.MinValue || Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < UInt16.MinValue || Value > UInt16.MaxValue) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < UInt32.MinValue) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue || Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (this.type == type) + return this; + + Constant c = TryImplicitIntConversion (type); + if (c != null) + return c; //.Resolve (rc); + + return base.ConvertImplicitly (type); + } + + /// + /// Attempts to perform an implicit constant conversion of the IntConstant + /// into a different data type using casts (See Implicit Constant + /// Expression Conversions) + /// + Constant TryImplicitIntConversion (TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + if (Value >= SByte.MinValue && Value <= SByte.MaxValue) + return new SByteConstant (target_type, (sbyte) Value, loc); + break; + case BuiltinTypeSpec.Type.Byte: + if (Value >= Byte.MinValue && Value <= Byte.MaxValue) + return new ByteConstant (target_type, (byte) Value, loc); + break; + case BuiltinTypeSpec.Type.Short: + if (Value >= Int16.MinValue && Value <= Int16.MaxValue) + return new ShortConstant (target_type, (short) Value, loc); + break; + case BuiltinTypeSpec.Type.UShort: + if (Value >= UInt16.MinValue && Value <= UInt16.MaxValue) + return new UShortConstant (target_type, (ushort) Value, loc); + break; + case BuiltinTypeSpec.Type.UInt: + if (Value >= 0) + return new UIntConstant (target_type, (uint) Value, loc); + break; + case BuiltinTypeSpec.Type.ULong: + // + // we can optimize this case: a positive int32 + // always fits on a uint64. But we need an opcode + // to do it. + // + if (Value >= 0) + return new ULongConstant (target_type, (ulong) Value, loc); + break; + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + } + + return null; + } + } + + public class UIntConstant : IntegralConstant { + public readonly uint Value; + + public UIntConstant (BuiltinTypes types, uint v, Location loc) + : this (types.UInt, v, loc) + { + } + + public UIntConstant (TypeSpec type, uint v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitInt (unchecked ((int) Value)); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new UIntConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < 0 || Value > byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < UInt16.MinValue || Value > UInt16.MaxValue) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value > Int32.MaxValue) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue || Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class LongConstant : IntegralConstant { + public readonly long Value; + + public LongConstant (BuiltinTypes types, long v, Location loc) + : this (types.Long, v, loc) + { + } + + public LongConstant (TypeSpec type, long v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitLong (Value); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return Value; + } + + public override Constant Increment () + { + return new LongConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < Int16.MinValue || Value > Int16.MaxValue) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < UInt16.MinValue || Value > UInt16.MaxValue) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < Int32.MinValue || Value > Int32.MaxValue) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < UInt32.MinValue || Value > UInt32.MaxValue) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context && Value < 0) + throw new OverflowException (); + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < Char.MinValue || Value > Char.MaxValue) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (Value >= 0 && type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + return new ULongConstant (type, (ulong) Value, loc); + } + + return base.ConvertImplicitly (type); + } + } + + public class ULongConstant : IntegralConstant { + public readonly ulong Value; + + public ULongConstant (BuiltinTypes types, ulong v, Location loc) + : this (types.ULong, v, loc) + { + } + + public ULongConstant (TypeSpec type, ulong v, Location loc) + : base (type, loc) + { + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.EmitLong (unchecked ((long) Value)); + } + + public override object GetValue () + { + return Value; + } + + public override long GetValueAsLong () + { + return (long) Value; + } + + public override Constant Increment () + { + return new ULongConstant (type, checked(Value + 1), loc); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsOneInteger { + get { + return Value == 1; + } + } + + public override bool IsZeroInteger { + get { return Value == 0; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context && Value > Byte.MaxValue) + throw new OverflowException (); + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context && Value > ((ulong) SByte.MaxValue)) + throw new OverflowException (); + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context && Value > ((ulong) Int16.MaxValue)) + throw new OverflowException (); + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context && Value > UInt16.MaxValue) + throw new OverflowException (); + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context && Value > UInt32.MaxValue) + throw new OverflowException (); + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context && Value > UInt32.MaxValue) + throw new OverflowException (); + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + if (in_checked_context && Value > Int64.MaxValue) + throw new OverflowException (); + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context && Value > Char.MaxValue) + throw new OverflowException (); + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class FloatConstant : Constant { + public readonly float Value; + + public FloatConstant (BuiltinTypes types, float v, Location loc) + : this (types.Float, v, loc) + { + } + + public FloatConstant (TypeSpec type, float v, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldc_R4, Value); + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < byte.MinValue || Value > byte.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < sbyte.MinValue || Value > sbyte.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < short.MinValue || Value > short.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < ushort.MinValue || Value > ushort.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < int.MinValue || Value > int.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < uint.MinValue || Value > uint.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + if (in_checked_context) { + if (Value < long.MinValue || Value > long.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context) { + if (Value < ulong.MinValue || Value > ulong.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < (float) char.MinValue || Value > (float) char.MaxValue || float.IsNaN (Value)) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class DoubleConstant : Constant + { + public readonly double Value; + + public DoubleConstant (BuiltinTypes types, double v, Location loc) + : this (types.Double, v, loc) + { + } + + public DoubleConstant (TypeSpec type, double v, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = v; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + enc.Encode (Value); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldc_R8, Value); + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + if (in_checked_context) { + if (Value < Byte.MinValue || Value > Byte.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new ByteConstant (target_type, (byte) Value, Location); + case BuiltinTypeSpec.Type.SByte: + if (in_checked_context) { + if (Value < SByte.MinValue || Value > SByte.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new SByteConstant (target_type, (sbyte) Value, Location); + case BuiltinTypeSpec.Type.Short: + if (in_checked_context) { + if (Value < short.MinValue || Value > short.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new ShortConstant (target_type, (short) Value, Location); + case BuiltinTypeSpec.Type.UShort: + if (in_checked_context) { + if (Value < ushort.MinValue || Value > ushort.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new UShortConstant (target_type, (ushort) Value, Location); + case BuiltinTypeSpec.Type.Int: + if (in_checked_context) { + if (Value < int.MinValue || Value > int.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new IntConstant (target_type, (int) Value, Location); + case BuiltinTypeSpec.Type.UInt: + if (in_checked_context) { + if (Value < uint.MinValue || Value > uint.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new UIntConstant (target_type, (uint) Value, Location); + case BuiltinTypeSpec.Type.Long: + if (in_checked_context) { + if (Value < long.MinValue || Value > long.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new LongConstant (target_type, (long) Value, Location); + case BuiltinTypeSpec.Type.ULong: + if (in_checked_context) { + if (Value < ulong.MinValue || Value > ulong.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new ULongConstant (target_type, (ulong) Value, Location); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, Location); + case BuiltinTypeSpec.Type.Char: + if (in_checked_context) { + if (Value < (double) char.MinValue || Value > (double) char.MaxValue || double.IsNaN (Value)) + throw new OverflowException (); + } + return new CharConstant (target_type, (char) Value, Location); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (target_type, (decimal) Value, Location); + } + + return null; + } + + } + + public class DecimalConstant : Constant { + public readonly decimal Value; + + public DecimalConstant (BuiltinTypes types, decimal d, Location loc) + : this (types.Decimal, d, loc) + { + } + + public DecimalConstant (TypeSpec type, decimal d, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = d; + } + + public override void Emit (EmitContext ec) + { + MethodSpec m; + + int [] words = decimal.GetBits (Value); + int power = (words [3] >> 16) & 0xff; + + if (power == 0) { + if (Value <= int.MaxValue && Value >= int.MinValue) { + m = ec.Module.PredefinedMembers.DecimalCtorInt.Resolve (loc); + if (m == null) { + return; + } + + ec.EmitInt ((int) Value); + ec.Emit (OpCodes.Newobj, m); + return; + } + + if (Value <= long.MaxValue && Value >= long.MinValue) { + m = ec.Module.PredefinedMembers.DecimalCtorLong.Resolve (loc); + if (m == null) { + return; + } + + ec.EmitLong ((long) Value); + ec.Emit (OpCodes.Newobj, m); + return; + } + } + + ec.EmitInt (words [0]); + ec.EmitInt (words [1]); + ec.EmitInt (words [2]); + + // sign + ec.EmitInt (words [3] >> 31); + + // power + ec.EmitInt (power); + + m = ec.Module.PredefinedMembers.DecimalCtor.Resolve (loc); + if (m != null) { + ec.Emit (OpCodes.Newobj, m); + } + } + + public override bool IsDefaultValue { + get { + return Value == 0; + } + } + + public override bool IsNegative { + get { + return Value < 0; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (target_type, (sbyte) Value, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (target_type, (byte) Value, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (target_type, (short) Value, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (target_type, (ushort) Value, loc); + case BuiltinTypeSpec.Type.Int: + return new IntConstant (target_type, (int) Value, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (target_type, (uint) Value, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (target_type, (long) Value, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (target_type, (ulong) Value, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (target_type, (char) Value, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (target_type, (float) Value, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (target_type, (double) Value, loc); + } + + return null; + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + return Value.ToString () + "M"; + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + } + + public class StringConstant : Constant { + public readonly string Value; + + public StringConstant (BuiltinTypes types, string s, Location loc) + : this (types.String, s, loc) + { + } + + public StringConstant (TypeSpec type, string s, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Value; + + Value = s; + } + + public override object GetValue () + { + return Value; + } + + public override string GetValueAsLiteral () + { + // FIXME: Escape the string. + return "\"" + Value + "\""; + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override void Emit (EmitContext ec) + { + if (Value == null) { + ec.Emit (OpCodes.Ldnull); + return; + } + + // + // Use string.Empty for both literals and constants even if + // it's not allowed at language level + // + if (Value.Length == 0 && ec.Module.Compiler.Settings.Optimize) { + var string_type = ec.BuiltinTypes.String; + if (ec.CurrentType != string_type) { + var m = ec.Module.PredefinedMembers.StringEmpty.Get (); + if (m != null) { + ec.Emit (OpCodes.Ldsfld, m); + return; + } + } + } + + ec.Emit (OpCodes.Ldstr, Value); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // cast to object + if (type != targetType) + enc.Encode (type); + + enc.Encode (Value); + } + + public override bool IsDefaultValue { + get { + return Value == null; + } + } + + public override bool IsNegative { + get { + return false; + } + } + + public override bool IsNull { + get { + return IsDefaultValue; + } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + return null; + } + } + + // + // Null constant can have its own type, think of `default (Foo)' + // + public class NullConstant : Constant + { + public NullConstant (TypeSpec type, Location loc) + : base (loc) + { + eclass = ExprClass.Value; + this.type = type; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (type == InternalType.NullLiteral || type.BuiltinType == BuiltinTypeSpec.Type.Object) { + // Optimized version, also avoids referencing literal internal type + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + return base.CreateExpressionTree (ec); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + switch (targetType.BuiltinType) { + case BuiltinTypeSpec.Type.Object: + // Type it as string cast + enc.Encode (rc.Module.Compiler.BuiltinTypes.String); + goto case BuiltinTypeSpec.Type.String; + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Type: + enc.Encode (byte.MaxValue); + return; + default: + var ac = targetType as ArrayContainer; + if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) { + enc.Encode (uint.MaxValue); + return; + } + + break; + } + + base.EncodeAttributeValue (rc, enc, targetType); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldnull); + + // Only to make verifier happy + if (type.IsGenericParameter) + ec.Emit (OpCodes.Unbox_Any, type); + } + + public override string ExprClassName { + get { + return GetSignatureForError (); + } + } + + public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType) + { + if (targetType.IsPointer) { + if (IsLiteral || this is NullPointer) + return new NullPointer (targetType, loc); + + return null; + } + + // Exlude internal compiler types + if (targetType.Kind == MemberKind.InternalCompilerType && targetType.BuiltinType != BuiltinTypeSpec.Type.Dynamic) + return null; + + if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType)) + return null; + + if (TypeSpec.IsReferenceType (targetType)) + return new NullConstant (targetType, loc); + + if (targetType.IsNullableType) + return Nullable.LiftedNull.Create (targetType, loc); + + return null; + } + + public override Constant ConvertImplicitly (TypeSpec targetType) + { + return ConvertExplicitly (false, targetType); + } + + public override string GetSignatureForError () + { + return "null"; + } + + public override object GetValue () + { + return null; + } + + public override string GetValueAsLiteral () + { + return GetSignatureForError (); + } + + public override long GetValueAsLong () + { + throw new NotSupportedException (); + } + + public override bool IsDefaultValue { + get { return true; } + } + + public override bool IsNegative { + get { return false; } + } + + public override bool IsNull { + get { return true; } + } + + public override bool IsZeroInteger { + get { return true; } + } + } + + + // + // A null constant in a pointer context + // + class NullPointer : NullConstant + { + public NullPointer (TypeSpec type, Location loc) + : base (type, loc) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return base.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + // + // Emits null pointer + // + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Conv_U); + } + } + + /// + /// The value is constant, but when emitted has a side effect. This is + /// used by BitwiseAnd to ensure that the second expression is invoked + /// regardless of the value of the left side. + /// + public class SideEffectConstant : Constant { + public readonly Constant value; + Expression side_effect; + + public SideEffectConstant (Constant value, Expression side_effect, Location loc) + : base (loc) + { + this.value = value; + type = value.Type; + eclass = ExprClass.Value; + + while (side_effect is SideEffectConstant) + side_effect = ((SideEffectConstant) side_effect).side_effect; + this.side_effect = side_effect; + } + + public override object GetValue () + { + return value.GetValue (); + } + + public override string GetValueAsLiteral () + { + return value.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return value.GetValueAsLong (); + } + + public override void Emit (EmitContext ec) + { + side_effect.EmitSideEffect (ec); + value.Emit (ec); + } + + public override void EmitSideEffect (EmitContext ec) + { + side_effect.EmitSideEffect (ec); + value.EmitSideEffect (ec); + } + + public override bool IsDefaultValue { + get { return value.IsDefaultValue; } + } + + public override bool IsNegative { + get { return value.IsNegative; } + } + + public override bool IsZeroInteger { + get { return value.IsZeroInteger; } + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + Constant new_value = value.ConvertExplicitly (in_checked_context, target_type); + if (new_value == null) + return null; + + var c = new SideEffectConstant (new_value, side_effect, new_value.Location); + c.type = target_type; + c.eclass = eclass; + return c; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs new file mode 100644 index 0000000000..316968454e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs @@ -0,0 +1,741 @@ +// +// context.cs: Various compiler contexts. +// +// Author: +// Marek Safar (marek.safar@gmail.com) +// Miguel de Icaza (miguel@ximian.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2004-2009 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.IO; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public enum LookupMode + { + Normal = 0, + Probing = 1, + IgnoreAccessibility = 2 + } + + // + // Implemented by elements which can act as independent contexts + // during resolve phase. Used mostly for lookups. + // + public interface IMemberContext : IModuleContext + { + // + // A scope type context, it can be inflated for generic types + // + TypeSpec CurrentType { get; } + + // + // A scope type parameters either VAR or MVAR + // + TypeParameter[] CurrentTypeParameters { get; } + + // + // A member definition of the context. For partial types definition use + // CurrentTypeDefinition.PartialContainer otherwise the context is local + // + // TODO: Obsolete it in this context, dynamic context cannot guarantee sensible value + // + MemberCore CurrentMemberDefinition { get; } + + bool IsObsolete { get; } + bool IsUnsafe { get; } + bool IsStatic { get; } + + string GetSignatureForError (); + + IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope); + FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc); + FullNamedExpression LookupNamespaceAlias (string name); + } + + public interface IModuleContext + { + ModuleContainer Module { get; } + } + + // + // Block or statement resolving context + // + public class BlockContext : ResolveContext + { + FlowBranching current_flow_branching; + + TypeSpec return_type; + + /// + /// The location where return has to jump to return the + /// value + /// + public Label ReturnLabel; // TODO: It's emit dependant + + /// + /// If we already defined the ReturnLabel + /// + public bool HasReturnLabel; + + public int FlowOffset; + + public BlockContext (IMemberContext mc, ExplicitBlock block, TypeSpec returnType) + : base (mc) + { + if (returnType == null) + throw new ArgumentNullException ("returnType"); + + this.return_type = returnType; + + // TODO: check for null value + CurrentBlock = block; + } + + public BlockContext (ResolveContext rc, ExplicitBlock block, TypeSpec returnType) + : this (rc.MemberContext, block, returnType) + { + if (rc.IsUnsafe) + flags |= ResolveContext.Options.UnsafeScope; + + if (rc.HasSet (ResolveContext.Options.CheckedScope)) + flags |= ResolveContext.Options.CheckedScope; + } + + public override FlowBranching CurrentBranching { + get { return current_flow_branching; } + } + + // + // Starts a new code branching. This inherits the state of all local + // variables and parameters from the current branching. + // + public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc) + { + current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc); + return current_flow_branching; + } + + // + // Starts a new code branching for block `block'. + // + public FlowBranching StartFlowBranching (Block block) + { + Set (Options.DoFlowAnalysis); + + current_flow_branching = FlowBranching.CreateBranching ( + CurrentBranching, FlowBranching.BranchingType.Block, block, block.StartLocation); + return current_flow_branching; + } + + public FlowBranchingTryCatch StartFlowBranching (TryCatch stmt) + { + FlowBranchingTryCatch branching = new FlowBranchingTryCatch (CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingException StartFlowBranching (ExceptionStatement stmt) + { + FlowBranchingException branching = new FlowBranchingException (CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingLabeled StartFlowBranching (LabeledStatement stmt) + { + FlowBranchingLabeled branching = new FlowBranchingLabeled (CurrentBranching, stmt); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingIterator StartFlowBranching (StateMachineInitializer iterator, FlowBranching parent) + { + FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator); + current_flow_branching = branching; + return branching; + } + + public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent) + { + FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt); + current_flow_branching = branching; + return branching; + } + + // + // Ends a code branching. Merges the state of locals and parameters + // from all the children of the ending branching. + // + public bool EndFlowBranching () + { + FlowBranching old = current_flow_branching; + current_flow_branching = current_flow_branching.Parent; + + FlowBranching.UsageVector vector = current_flow_branching.MergeChild (old); + return vector.IsUnreachable; + } + + // + // Kills the current code branching. This throws away any changed state + // information and should only be used in case of an error. + // + // FIXME: this is evil + public void KillFlowBranching () + { + current_flow_branching = current_flow_branching.Parent; + } + + // + // This method is used during the Resolution phase to flag the + // need to define the ReturnLabel + // + public void NeedReturnLabel () + { + if (!HasReturnLabel) + HasReturnLabel = true; + } + + public TypeSpec ReturnType { + get { return return_type; } + } + } + + // + // Expression resolving context + // + public class ResolveContext : IMemberContext + { + [Flags] + public enum Options + { + /// + /// This flag tracks the `checked' state of the compilation, + /// it controls whether we should generate code that does overflow + /// checking, or if we generate code that ignores overflows. + /// + /// The default setting comes from the command line option to generate + /// checked or unchecked code plus any source code changes using the + /// checked/unchecked statements or expressions. Contrast this with + /// the ConstantCheckState flag. + /// + CheckedScope = 1 << 0, + + /// + /// The constant check state is always set to `true' and cant be changed + /// from the command line. The source code can change this setting with + /// the `checked' and `unchecked' statements and expressions. + /// + ConstantCheckState = 1 << 1, + + AllCheckStateFlags = CheckedScope | ConstantCheckState, + + // + // unsafe { ... } scope + // + UnsafeScope = 1 << 2, + CatchScope = 1 << 3, + FinallyScope = 1 << 4, + FieldInitializerScope = 1 << 5, + CompoundAssignmentScope = 1 << 6, + FixedInitializerScope = 1 << 7, + BaseInitializer = 1 << 8, + + // + // Inside an enum definition, we do not resolve enumeration values + // to their enumerations, but rather to the underlying type/value + // This is so EnumVal + EnumValB can be evaluated. + // + // There is no "E operator + (E x, E y)", so during an enum evaluation + // we relax the rules + // + EnumScope = 1 << 9, + + ConstantScope = 1 << 10, + + ConstructorScope = 1 << 11, + + UsingInitializerScope = 1 << 12, + + LockScope = 1 << 13, + + /// + /// Whether control flow analysis is enabled + /// + DoFlowAnalysis = 1 << 20, + + /// + /// Whether control flow analysis is disabled on structs + /// (only meaningful when DoFlowAnalysis is set) + /// + OmitStructFlowAnalysis = 1 << 21, + + /// + /// Indicates the current context is in probing mode, no errors are reported. + /// + ProbingMode = 1 << 22, + + // + // Return and ContextualReturn statements will set the ReturnType + // value based on the expression types of each return statement + // instead of the method return type which is initially null. + // + InferReturnType = 1 << 23, + + OmitDebuggingInfo = 1 << 24, + + ExpressionTreeConversion = 1 << 25, + + InvokeSpecialName = 1 << 26 + } + + // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements + // it's public so that we can use a struct at the callsite + public struct FlagsHandle : IDisposable + { + ResolveContext ec; + readonly Options invmask, oldval; + + public FlagsHandle (ResolveContext ec, Options flagsToSet) + : this (ec, flagsToSet, flagsToSet) + { + } + + internal FlagsHandle (ResolveContext ec, Options mask, Options val) + { + this.ec = ec; + invmask = ~mask; + oldval = ec.flags & mask; + ec.flags = (ec.flags & invmask) | (val & mask); + +// if ((mask & Options.ProbingMode) != 0) +// ec.Report.DisableReporting (); + } + + public void Dispose () + { +// if ((invmask & Options.ProbingMode) == 0) +// ec.Report.EnableReporting (); + + ec.flags = (ec.flags & invmask) | oldval; + } + } + + protected Options flags; + + // + // Whether we are inside an anonymous method. + // + public AnonymousExpression CurrentAnonymousMethod; + + // + // Holds a varible used during collection or object initialization. + // + public Expression CurrentInitializerVariable; + + public Block CurrentBlock; + + public readonly IMemberContext MemberContext; + + /// + /// If this is non-null, points to the current switch statement + /// + public Switch Switch; + + public ResolveContext (IMemberContext mc) + { + if (mc == null) + throw new ArgumentNullException (); + + MemberContext = mc; + + // + // The default setting comes from the command line option + // + if (mc.Module.Compiler.Settings.Checked) + flags |= Options.CheckedScope; + + // + // The constant check state is always set to true + // + flags |= Options.ConstantCheckState; + } + + public ResolveContext (IMemberContext mc, Options options) + : this (mc) + { + flags |= options; + } + + #region Properties + + public BuiltinTypes BuiltinTypes { + get { + return MemberContext.Module.Compiler.BuiltinTypes; + } + } + + public virtual ExplicitBlock ConstructorBlock { + get { + return CurrentBlock.Explicit; + } + } + + public virtual FlowBranching CurrentBranching { + get { return null; } + } + + // + // The current iterator + // + public Iterator CurrentIterator { + get { return CurrentAnonymousMethod as Iterator; } + } + + public TypeSpec CurrentType { + get { return MemberContext.CurrentType; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return MemberContext.CurrentTypeParameters; } + } + + public MemberCore CurrentMemberDefinition { + get { return MemberContext.CurrentMemberDefinition; } + } + + public bool ConstantCheckState { + get { return (flags & Options.ConstantCheckState) != 0; } + } + + public bool DoFlowAnalysis { + get { return (flags & Options.DoFlowAnalysis) != 0; } + } + + public bool IsInProbingMode { + get { + return (flags & Options.ProbingMode) != 0; + } + } + + public bool IsObsolete { + get { + // Disables obsolete checks when probing is on + return MemberContext.IsObsolete; + } + } + + public bool IsStatic { + get { + return MemberContext.IsStatic; + } + } + + public bool IsUnsafe { + get { + return HasSet (Options.UnsafeScope) || MemberContext.IsUnsafe; + } + } + + public bool IsRuntimeBinder { + get { + return Module.Compiler.IsRuntimeBinder; + } + } + + public bool IsVariableCapturingRequired { + get { + return !IsInProbingMode && (CurrentBranching == null || !CurrentBranching.CurrentUsageVector.IsUnreachable); + } + } + + public ModuleContainer Module { + get { + return MemberContext.Module; + } + } + + public bool OmitStructFlowAnalysis { + get { return (flags & Options.OmitStructFlowAnalysis) != 0; } + } + + public Report Report { + get { + return Module.Compiler.Report; + } + } + + #endregion + + public bool MustCaptureVariable (INamedBlockVariable local) + { + if (CurrentAnonymousMethod == null) + return false; + + // FIXME: IsIterator is too aggressive, we should capture only if child + // block contains yield + if (CurrentAnonymousMethod.IsIterator) + return true; + + return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original; + } + + public bool HasSet (Options options) + { + return (this.flags & options) == options; + } + + public bool HasAny (Options options) + { + return (this.flags & options) != 0; + } + + + // Temporarily set all the given flags to the given value. Should be used in an 'using' statement + public FlagsHandle Set (Options options) + { + return new FlagsHandle (this, options); + } + + public FlagsHandle With (Options options, bool enable) + { + return new FlagsHandle (this, options, enable ? options : 0); + } + + #region IMemberContext Members + + public string GetSignatureForError () + { + return MemberContext.GetSignatureForError (); + } + + public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return MemberContext.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + return MemberContext.LookupNamespaceOrType (name, arity, mode, loc); + } + + public FullNamedExpression LookupNamespaceAlias (string name) + { + return MemberContext.LookupNamespaceAlias (name); + } + + #endregion + } + + // + // This class is used during the Statement.Clone operation + // to remap objects that have been cloned. + // + // Since blocks are cloned by Block.Clone, we need a way for + // expressions that must reference the block to be cloned + // pointing to the new cloned block. + // + public class CloneContext + { + Dictionary block_map = new Dictionary (); + + public void AddBlockMap (Block from, Block to) + { + block_map.Add (from, to); + } + + public Block LookupBlock (Block from) + { + Block result; + if (!block_map.TryGetValue (from, out result)) { + result = (Block) from.Clone (this); + } + + return result; + } + + /// + /// Remaps block to cloned copy if one exists. + /// + public Block RemapBlockCopy (Block from) + { + Block mapped_to; + if (!block_map.TryGetValue (from, out mapped_to)) + return from; + + return mapped_to; + } + } + + // + // Main compiler context + // + public class CompilerContext + { + static readonly TimeReporter DisabledTimeReporter = new TimeReporter (false); + + readonly Report report; + readonly BuiltinTypes builtin_types; + readonly CompilerSettings settings; + + Dictionary all_source_files; + + public CompilerContext (CompilerSettings settings, Report report) + { + this.settings = settings; + this.report = report; + this.builtin_types = new BuiltinTypes (); + this.TimeReporter = DisabledTimeReporter; + } + + #region Properties + + public BuiltinTypes BuiltinTypes { + get { + return builtin_types; + } + } + + // Used for special handling of runtime dynamic context mostly + // by error reporting but also by member accessibility checks + public bool IsRuntimeBinder { + get; set; + } + + public Report Report { + get { + return report; + } + } + + public CompilerSettings Settings { + get { + return settings; + } + } + + public List SourceFiles { + get { + return settings.SourceFiles; + } + } + + internal TimeReporter TimeReporter { + get; set; + } + + #endregion + + // + // This is used when we encounter a #line preprocessing directive during parsing + // to register additional source file names + // + public SourceFile LookupFile (CompilationSourceFile comp_unit, string name) + { + if (all_source_files == null) { + all_source_files = new Dictionary (); + foreach (var source in SourceFiles) + all_source_files[source.FullPathName] = source; + } + + string path; + if (!Path.IsPathRooted (name)) { + string root = Path.GetDirectoryName (comp_unit.FullPathName); + path = Path.Combine (root, name); + } else + path = name; + + SourceFile retval; + if (all_source_files.TryGetValue (path, out retval)) + return retval; + + retval = Location.AddFile (name, path); + all_source_files.Add (path, retval); + return retval; + } + } + + // + // Generic code emitter context + // + public class BuilderContext + { + [Flags] + public enum Options + { + /// + /// This flag tracks the `checked' state of the compilation, + /// it controls whether we should generate code that does overflow + /// checking, or if we generate code that ignores overflows. + /// + /// The default setting comes from the command line option to generate + /// checked or unchecked code plus any source code changes using the + /// checked/unchecked statements or expressions. Contrast this with + /// the ConstantCheckState flag. + /// + CheckedScope = 1 << 0, + + /// + /// The constant check state is always set to `true' and cant be changed + /// from the command line. The source code can change this setting with + /// the `checked' and `unchecked' statements and expressions. + /// + ConstantCheckState = 1 << 1, + + AllCheckStateFlags = CheckedScope | ConstantCheckState, + + OmitDebugInfo = 1 << 2, + + ConstructorScope = 1 << 3 + } + + // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements + // it's public so that we can use a struct at the callsite + public struct FlagsHandle : IDisposable + { + BuilderContext ec; + readonly Options invmask, oldval; + + public FlagsHandle (BuilderContext ec, Options flagsToSet) + : this (ec, flagsToSet, flagsToSet) + { + } + + internal FlagsHandle (BuilderContext ec, Options mask, Options val) + { + this.ec = ec; + invmask = ~mask; + oldval = ec.flags & mask; + ec.flags = (ec.flags & invmask) | (val & mask); + } + + public void Dispose () + { + ec.flags = (ec.flags & invmask) | oldval; + } + } + + Options flags; + + public bool HasSet (Options options) + { + return (this.flags & options) == options; + } + + // Temporarily set all the given flags to the given value. Should be used in an 'using' statement + public FlagsHandle With (Options options, bool enable) + { + return new FlagsHandle (this, options, enable ? options : 0); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs new file mode 100644 index 0000000000..020c842755 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs @@ -0,0 +1,2150 @@ +// +// conversion.cs: various routines for implementing conversions. +// +// Authors: +// Miguel de Icaza (miguel@ximian.com) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + // + // A container class for all the conversion operations + // + static class Convert + { + // + // From a one-dimensional array-type S[] to System.Collections.IList and base + // interfaces of this interface, provided there is an implicit reference conversion + // from S to T. + // + static bool ArrayToIList (ArrayContainer array, TypeSpec list, bool isExplicit) + { + if (array.Rank != 1 || !list.IsGenericIterateInterface) + return false; + + var arg_type = list.TypeArguments[0]; + if (array.Element == arg_type) + return true; + + // + // Reject conversion from T[] to IList even if T has U dependency + // + if (arg_type.IsGenericParameter) + return false; + + if (isExplicit) + return ExplicitReferenceConversionExists (array.Element, arg_type); + + return ImplicitReferenceConversionExists (array.Element, arg_type); + } + + static bool IList_To_Array(TypeSpec list, ArrayContainer array) + { + if (array.Rank != 1 || !list.IsGenericIterateInterface) + return false; + + var arg_type = list.TypeArguments[0]; + if (array.Element == arg_type) + return true; + + return ImplicitReferenceConversionExists (array.Element, arg_type) || ExplicitReferenceConversionExists (array.Element, arg_type); + } + + public static Expression ImplicitTypeParameterConversion (Expression expr, TypeParameterSpec expr_type, TypeSpec target_type) + { + // + // From T to a type parameter U, provided T depends on U + // + if (target_type.IsGenericParameter) { + if (expr_type.TypeArguments != null) { + foreach (var targ in expr_type.TypeArguments) { + if (!TypeSpecComparer.Override.IsEqual (target_type, targ)) + continue; + + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType && !((TypeParameterSpec)target_type).IsReferenceType) + return new BoxedCast (expr, target_type); + + return new ClassCast (expr, target_type); + } + } + + return null; + } + + // + // LAMESPEC: From T to dynamic type because it's like T to object + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); + } + + // + // From T to its effective base class C + // From T to any base class of C (it cannot contain dynamic or be of dynamic type) + // From T to any interface implemented by C + // + var base_type = expr_type.GetEffectiveBase (); + if (base_type == target_type || TypeSpec.IsBaseClass (base_type, target_type, false) || base_type.ImplementsInterface (target_type, true)) { + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); + } + + if (target_type.IsInterface && expr_type.IsConvertibleToInterface (target_type)) { + if (expr == null) + return EmptyExpression.Null; + + if (expr_type.IsReferenceType) + return new ClassCast (expr, target_type); + + return new BoxedCast (expr, target_type); + } + + return null; + } + + static Expression ExplicitTypeParameterConversion (Expression source, TypeSpec source_type, TypeSpec target_type) + { + var target_tp = target_type as TypeParameterSpec; + if (target_tp != null) { + if (target_tp.TypeArguments != null) { + foreach (var targ in target_tp.TypeArguments) { + if (!TypeSpecComparer.Override.IsEqual (source_type, targ)) + continue; + + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + } +/* + if (target_tp.Interfaces != null) { + foreach (TypeSpec iface in target_tp.Interfaces) { + if (!TypeManager.IsGenericParameter (iface)) + continue; + + if (TypeManager.IsSubclassOf (source_type, iface)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true); + } + } +*/ + return null; + } + + if (target_type.IsInterface) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type, true); + + return null; + } + + public static Expression ImplicitReferenceConversion (Expression expr, TypeSpec target_type, bool explicit_cast) + { + TypeSpec expr_type = expr.Type; + + if (expr_type.Kind == MemberKind.TypeParameter) + return ImplicitTypeParameterConversion (expr, (TypeParameterSpec) expr.Type, target_type); + + // + // from the null type to any reference-type. + // + NullLiteral nl = expr as NullLiteral; + if (nl != null) { + return nl.ConvertImplicitly (target_type); + } + + if (ImplicitReferenceConversionExists (expr_type, target_type)) { + // + // Avoid wrapping implicitly convertible reference type + // + if (!explicit_cast) + return expr; + + return EmptyCast.Create (expr, target_type); + } + + return null; + } + + // + // Implicit reference conversions + // + public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type) + { + return ImplicitReferenceConversionExists (expr_type, target_type, true); + } + + static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter) + { + // It's here only to speed things up + if (target_type.IsStruct) + return false; + + switch (expr_type.Kind) { + case MemberKind.TypeParameter: + return ImplicitTypeParameterConversion (null, (TypeParameterSpec) expr_type, target_type) != null && + (!refOnlyTypeParameter || TypeSpec.IsReferenceType (expr_type)); + + case MemberKind.Class: + // + // From any class-type to dynamic (+object to speed up common path) + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + if (target_type.IsClass) { + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + // + // From any class-type S to any class-type T, provided S is derived from T + // + return TypeSpec.IsBaseClass (expr_type, target_type, true); + } + + // + // From any class-type S to any interface-type T, provided S implements T + // + if (target_type.IsInterface) + return expr_type.ImplementsInterface (target_type, true); + + return false; + + case MemberKind.ArrayType: + // + // Identity array conversion + // + if (expr_type == target_type) + return true; + + // + // From any array-type to System.Array + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Array: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } + + var expr_type_array = (ArrayContainer) expr_type; + var target_type_array = target_type as ArrayContainer; + + // + // From an array-type S to an array-type of type T + // + if (target_type_array != null && expr_type_array.Rank == target_type_array.Rank) { + + // + // Both SE and TE are reference-types. TE check is defered + // to ImplicitReferenceConversionExists + // + TypeSpec expr_element_type = expr_type_array.Element; + if (!TypeSpec.IsReferenceType (expr_element_type)) + return false; + + // + // An implicit reference conversion exists from SE to TE + // + return ImplicitReferenceConversionExists (expr_element_type, target_type_array.Element); + } + + // + // From any array-type to the interfaces it implements + // + if (target_type.IsInterface) { + if (expr_type.ImplementsInterface (target_type, false)) + return true; + + // from an array-type of type T to IList + if (ArrayToIList (expr_type_array, target_type, false)) + return true; + } + + return false; + + case MemberKind.Delegate: + // + // From any delegate-type to System.Delegate (and its base types) + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } + + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + // + // From any delegate-type to the interfaces it implements + // From any reference-type to an delegate type if is variance-convertible + // + return expr_type.ImplementsInterface (target_type, false) || TypeSpecComparer.Variant.IsEqual (expr_type, target_type); + + case MemberKind.Interface: + // + // Identity conversion, including dynamic erasure + // + if (TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + // + // From any interface type S to interface-type T + // From any reference-type to an interface if is variance-convertible + // + if (target_type.IsInterface) + return TypeSpecComparer.Variant.IsEqual (expr_type, target_type) || expr_type.ImplementsInterface (target_type, true); + + return target_type.BuiltinType == BuiltinTypeSpec.Type.Object || target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + } + + // + // from the null literal to any reference-type. + // + if (expr_type == InternalType.NullLiteral) { + // Exlude internal compiler types + if (target_type.Kind == MemberKind.InternalCompilerType) + return target_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + + return TypeSpec.IsReferenceType (target_type); + } + + return false; + } + + public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) + { + switch (target_type.BuiltinType) { + // + // From any non-nullable-value-type to the type object and dynamic + // + case BuiltinTypeSpec.Type.Object: + case BuiltinTypeSpec.Type.Dynamic: + // + // From any non-nullable-value-type to the type System.ValueType + // + case BuiltinTypeSpec.Type.ValueType: + // + // No ned to check for nullable type as underlying type is always convertible + // + if (!TypeSpec.IsValueType (expr_type)) + return null; + + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + + case BuiltinTypeSpec.Type.Enum: + // + // From any enum-type to the type System.Enum. + // + if (expr_type.IsEnum) + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + + break; + } + + // + // From a nullable-type to a reference type, if a boxing conversion exists from + // the underlying type to the reference type + // + if (expr_type.IsNullableType) { + if (!TypeSpec.IsReferenceType (target_type)) + return null; + + var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); + + // "cast" underlying type to target type to emit correct InvalidCastException when + // underlying hierarchy changes without recompilation + if (res != null && expr != null) + res = new UnboxCast (res, target_type); + + return res; + } + + // + // A value type has a boxing conversion to an interface type I if it has a boxing conversion + // to an interface or delegate type I0 and I0 is variance-convertible to I + // + if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) { + return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type); + } + + return null; + } + + public static Expression ImplicitNulableConversion (ResolveContext ec, Expression expr, TypeSpec target_type) + { + TypeSpec expr_type = expr.Type; + + // + // From null to any nullable type + // + if (expr_type == InternalType.NullLiteral) + return ec == null ? EmptyExpression.Null : Nullable.LiftedNull.Create (target_type, expr.Location); + + // S -> T? + TypeSpec t_el = Nullable.NullableInfo.GetUnderlyingType (target_type); + + // S? -> T? + if (expr_type.IsNullableType) + expr_type = Nullable.NullableInfo.GetUnderlyingType (expr_type); + + // + // Predefined implicit identity or implicit numeric conversion + // has to exist between underlying type S and underlying type T + // + + // conversion exists only mode + if (ec == null) { + if (TypeSpecComparer.IsEqual (expr_type, t_el)) + return EmptyExpression.Null; + + if (expr is Constant) + return ((Constant) expr).ConvertImplicitly (t_el); + + return ImplicitNumericConversion (null, expr_type, t_el); + } + + Expression unwrap; + if (expr_type != expr.Type) + unwrap = Nullable.Unwrap.Create (expr); + else + unwrap = expr; + + Expression conv = unwrap; + if (!TypeSpecComparer.IsEqual (expr_type, t_el)) { + if (conv is Constant) + conv = ((Constant)conv).ConvertImplicitly (t_el); + else + conv = ImplicitNumericConversion (conv, expr_type, t_el); + + if (conv == null) + return null; + } + + if (expr_type != expr.Type) + return new Nullable.Lifted (conv, unwrap, target_type).Resolve (ec); + + return Nullable.Wrap.Create (conv, target_type); + } + + /// + /// Implicit Numeric Conversions. + /// + /// expr is the expression to convert, returns a new expression of type + /// target_type or null if an implicit conversion is not possible. + /// + public static Expression ImplicitNumericConversion (Expression expr, TypeSpec target_type) + { + return ImplicitNumericConversion (expr, expr.Type, target_type); + } + + static Expression ImplicitNumericConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type) + { + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + // + // From sbyte to short, int, long, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I4); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Short: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I2); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + + } + + break; + case BuiltinTypeSpec.Type.Byte: + // + // From byte to short, ushort, int, uint, long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Short: + // + // From short to int, long, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.UShort: + // + // From ushort to int, uint, long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Int: + // + // From int to long, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.UInt: + // + // From uint to long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Long: + // + // From long to float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.ULong: + // + // From ulong to float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCastDuplex (expr, target_type, OpCodes.Conv_R_Un, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Char: + // + // From char to ushort, int, uint, long, ulong, float, double, decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + return expr == null ? EmptyExpression.Null : EmptyCast.Create (expr, target_type); + case BuiltinTypeSpec.Type.ULong: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + case BuiltinTypeSpec.Type.Long: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_I8); + case BuiltinTypeSpec.Type.Float: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + case BuiltinTypeSpec.Type.Double: + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + case BuiltinTypeSpec.Type.Decimal: + return expr == null ? EmptyExpression.Null : new OperatorCast (expr, target_type); + } + break; + case BuiltinTypeSpec.Type.Float: + // + // float to double + // + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) + return expr == null ? EmptyExpression.Null : new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + break; + } + + return null; + } + + // + // Full version of implicit conversion + // + public static bool ImplicitConversionExists (ResolveContext ec, Expression expr, TypeSpec target_type) + { + if (ImplicitStandardConversionExists (expr, target_type)) + return true; + + if (expr.Type == InternalType.AnonymousMethod) { + if (!target_type.IsDelegate && !target_type.IsExpressionTreeType) + return false; + + AnonymousMethodExpression ame = (AnonymousMethodExpression) expr; + return ame.ImplicitStandardConversionExists (ec, target_type); + } + + if (expr.eclass == ExprClass.MethodGroup) { + if (target_type.IsDelegate && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) { + MethodGroupExpr mg = expr as MethodGroupExpr; + if (mg != null) + return DelegateCreation.ImplicitStandardConversionExists (ec, mg, target_type); + } + + return false; + } + + // Conversion from __arglist to System.ArgIterator + if (expr.Type == InternalType.Arglist) + return target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec; + + return ImplicitUserConversion (ec, expr, target_type, Location.Null) != null; + } + + // + // Implicit standard conversion (only core conversions are used here) + // + public static bool ImplicitStandardConversionExists (Expression expr, TypeSpec target_type) + { + // + // Identity conversions + // Implicit numeric conversions + // Implicit nullable conversions + // Implicit reference conversions + // Boxing conversions + // Implicit constant expression conversions + // Implicit conversions involving type parameters + // + + TypeSpec expr_type = expr.Type; + + if (expr_type == target_type) + return true; + + if (target_type.IsNullableType) + return ImplicitNulableConversion (null, expr, target_type) != null; + + if (ImplicitNumericConversion (null, expr_type, target_type) != null) + return true; + + if (ImplicitReferenceConversionExists (expr_type, target_type, false)) + return true; + + if (ImplicitBoxingConversion (null, expr_type, target_type) != null) + return true; + + // + // Implicit Constant Expression Conversions + // + if (expr is IntConstant){ + int value = ((IntConstant) expr).Value; + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + if (value >= SByte.MinValue && value <= SByte.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.Byte: + if (value >= 0 && value <= Byte.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.Short: + if (value >= Int16.MinValue && value <= Int16.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.UShort: + if (value >= UInt16.MinValue && value <= UInt16.MaxValue) + return true; + break; + case BuiltinTypeSpec.Type.UInt: + if (value >= 0) + return true; + break; + case BuiltinTypeSpec.Type.ULong: + // + // we can optimize this case: a positive int32 + // always fits on a uint64. But we need an opcode + // to do it. + // + if (value >= 0) + return true; + + break; + } + } + + if (expr is LongConstant && target_type.BuiltinType == BuiltinTypeSpec.Type.ULong){ + // + // Try the implicit constant expression conversion + // from long to ulong, instead of a nice routine, + // we just inline it + // + long v = ((LongConstant) expr).Value; + if (v >= 0) + return true; + } + + 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 + // + // An implicit enumeration conversion permits the decimal-integer-literal 0 + // to be converted to any enum-type and to any nullable-type whose underlying + // type is an enum-type + // + return i.IsZeroInteger; + } + + // Implicit dynamic conversion + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + switch (target_type.Kind) { + case MemberKind.ArrayType: + case MemberKind.Class: + case MemberKind.Struct: + case MemberKind.Delegate: + case MemberKind.Enum: + case MemberKind.Interface: + case MemberKind.TypeParameter: + return true; + } + + // dynamic to __arglist + if (target_type == InternalType.Arglist) + return true; + + return false; + } + + // + // In an unsafe context implicit conversions is extended to include + // + // From any pointer-type to the type void* + // From the null literal to any pointer-type. + // + // LAMESPEC: The specification claims this conversion is allowed in implicit conversion but + // in reality implicit standard conversion uses it + // + if (target_type.IsPointer && expr.Type.IsPointer && ((PointerContainer) target_type).Element.Kind == MemberKind.Void) + return true; + + // + // Struct identity conversion, including dynamic erasure + // + if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) + return true; + + return false; + } + + /// + /// Finds "most encompassed type" according to the spec (13.4.2) + /// amongst the methods in the MethodGroupExpr + /// + public static TypeSpec FindMostEncompassedType (IEnumerable types) + { + TypeSpec best = null; + EmptyExpression expr; + + foreach (TypeSpec t in types) { + if (best == null) { + best = t; + continue; + } + + expr = new EmptyExpression (t); + if (ImplicitStandardConversionExists (expr, best)) + best = t; + } + + expr = new EmptyExpression (best); + foreach (TypeSpec t in types) { + if (best == t) + continue; + if (!ImplicitStandardConversionExists (expr, t)) { + best = null; + break; + } + } + + return best; + } + + // + // Finds the most encompassing type (type into which all other + // types can convert to) amongst the types in the given set + // + static TypeSpec FindMostEncompassingType (IList types) + { + if (types.Count == 0) + return null; + + if (types.Count == 1) + return types [0]; + + TypeSpec best = null; + for (int i = 0; i < types.Count; ++i) { + int ii = 0; + for (; ii < types.Count; ++ii) { + if (ii == i) + continue; + + var expr = new EmptyExpression (types[ii]); + if (!ImplicitStandardConversionExists (expr, types [i])) { + ii = 0; + break; + } + } + + if (ii == 0) + continue; + + if (best == null) { + best = types[i]; + continue; + } + + // Indicates multiple best types + return InternalType.FakeInternalType; + } + + return best; + } + + // + // Finds the most specific source Sx according to the rules of the spec (13.4.4) + // by making use of FindMostEncomp* methods. Applies the correct rules separately + // for explicit and implicit conversion operators. + // + static TypeSpec FindMostSpecificSource (List list, TypeSpec sourceType, Expression source, bool apply_explicit_conv_rules) + { + var src_types_set = new TypeSpec [list.Count]; + + // + // Try exact match first, if any operator converts from S then Sx = S + // + for (int i = 0; i < src_types_set.Length; ++i) { + TypeSpec param_type = list [i].Parameters.Types [0]; + + if (param_type == sourceType) + return param_type; + + src_types_set [i] = param_type; + } + + // + // Explicit Conv rules + // + if (apply_explicit_conv_rules) { + var candidate_set = new List (); + + foreach (TypeSpec param_type in src_types_set){ + if (ImplicitStandardConversionExists (source, param_type)) + candidate_set.Add (param_type); + } + + if (candidate_set.Count != 0) + return FindMostEncompassedType (candidate_set); + } + + // + // Final case + // + if (apply_explicit_conv_rules) + return FindMostEncompassingType (src_types_set); + else + return FindMostEncompassedType (src_types_set); + } + + /// + /// Finds the most specific target Tx according to section 13.4.4 + /// + static public TypeSpec FindMostSpecificTarget (IList list, + TypeSpec target, bool apply_explicit_conv_rules) + { + var tgt_types_set = new List (); + + // + // If any operator converts to T then Tx = T + // + foreach (var mi in list){ + TypeSpec ret_type = mi.ReturnType; + if (ret_type == target) + return ret_type; + + tgt_types_set.Add (ret_type); + } + + // + // Explicit conv rules + // + if (apply_explicit_conv_rules) { + var candidate_set = new List (); + + foreach (TypeSpec ret_type in tgt_types_set) { + var expr = new EmptyExpression (ret_type); + + if (ImplicitStandardConversionExists (expr, target)) + candidate_set.Add (ret_type); + } + + if (candidate_set.Count != 0) + return FindMostEncompassingType (candidate_set); + } + + // + // Okay, final case ! + // + if (apply_explicit_conv_rules) + return FindMostEncompassedType (tgt_types_set); + else + return FindMostEncompassingType (tgt_types_set); + } + + /// + /// User-defined Implicit conversions + /// + static public Expression ImplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc) + { + return UserDefinedConversion (ec, source, target, true, loc); + } + + /// + /// User-defined Explicit conversions + /// + static Expression ExplicitUserConversion (ResolveContext ec, Expression source, TypeSpec target, Location loc) + { + return UserDefinedConversion (ec, source, target, false, loc); + } + + static void FindApplicableUserDefinedConversionOperators (IList operators, Expression source, TypeSpec target, bool implicitOnly, ref List candidates) + { + if (source.Type.IsInterface) { + // Neither A nor B are interface-types + return; + } + + // For a conversion operator to be applicable, it must be possible + // to perform a standard conversion from the source type to + // the operand type of the operator, and it must be possible + // to perform a standard conversion from the result type of + // the operator to the target type. + + Expression texpr = null; + + foreach (MethodSpec op in operators) { + + // Can be null because MemberCache.GetUserOperator does not resize the array + if (op == null) + continue; + + var t = op.Parameters.Types[0]; + if (source.Type != t && !ImplicitStandardConversionExists (source, t)) { + if (implicitOnly) + continue; + + if (!ImplicitStandardConversionExists (new EmptyExpression (t), source.Type)) + continue; + } + + t = op.ReturnType; + + if (t.IsInterface) + continue; + + if (target != t) { + if (t.IsNullableType) + t = Nullable.NullableInfo.GetUnderlyingType (t); + + if (!ImplicitStandardConversionExists (new EmptyExpression (t), target)) { + if (implicitOnly) + continue; + + if (texpr == null) + texpr = new EmptyExpression (target); + + if (!ImplicitStandardConversionExists (texpr, t)) + continue; + } + } + + if (candidates == null) + candidates = new List (); + + candidates.Add (op); + } + } + + // + // User-defined conversions + // + static Expression UserDefinedConversion (ResolveContext ec, Expression source, TypeSpec target, bool implicitOnly, Location loc) + { + List candidates = null; + + // + // If S or T are nullable types, source_type and target_type are their underlying types + // otherwise source_type and target_type are equal to S and T respectively. + // + TypeSpec source_type = source.Type; + TypeSpec target_type = target; + Expression source_type_expr; + + if (source_type.IsNullableType) { + // No implicit conversion S? -> T for non-reference types + if (implicitOnly && !TypeSpec.IsReferenceType (target_type) && !target_type.IsNullableType) + return null; + + source_type_expr = Nullable.Unwrap.Create (source); + source_type = source_type_expr.Type; + } else { + source_type_expr = source; + } + + if (target_type.IsNullableType) + target_type = Nullable.NullableInfo.GetUnderlyingType (target_type); + + // Only these containers can contain a user defined implicit or explicit operators + const MemberKind user_conversion_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.TypeParameter; + + if ((source_type.Kind & user_conversion_kinds) != 0 && source_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { + bool declared_only = source_type.IsStruct; + + var operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Implicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates); + } + + if (!implicitOnly) { + operators = MemberCache.GetUserOperator (source_type, Operator.OpType.Explicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates); + } + } + } + + if ((target.Kind & user_conversion_kinds) != 0 && target_type.BuiltinType != BuiltinTypeSpec.Type.Decimal) { + bool declared_only = target.IsStruct || implicitOnly; + + var operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Implicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, implicitOnly, ref candidates); + } + + if (!implicitOnly) { + operators = MemberCache.GetUserOperator (target_type, Operator.OpType.Explicit, declared_only); + if (operators != null) { + FindApplicableUserDefinedConversionOperators (operators, source_type_expr, target_type, false, ref candidates); + } + } + } + + if (candidates == null) + return null; + + // + // Find the most specific conversion operator + // + MethodSpec most_specific_operator; + TypeSpec s_x, t_x; + if (candidates.Count == 1) { + most_specific_operator = candidates[0]; + s_x = most_specific_operator.Parameters.Types[0]; + t_x = most_specific_operator.ReturnType; + } else { + // + // Pass original source type to find the best match against input type and + // not the unwrapped expression + // + s_x = FindMostSpecificSource (candidates, source.Type, source_type_expr, !implicitOnly); + if (s_x == null) + return null; + + t_x = FindMostSpecificTarget (candidates, target, !implicitOnly); + if (t_x == null) + return null; + + most_specific_operator = null; + for (int i = 0; i < candidates.Count; ++i) { + if (candidates[i].ReturnType == t_x && candidates[i].Parameters.Types[0] == s_x) { + most_specific_operator = candidates[i]; + break; + } + } + + if (most_specific_operator == null) { + MethodSpec ambig_arg = null; + foreach (var candidate in candidates) { + if (candidate.ReturnType == t_x) + most_specific_operator = candidate; + else if (candidate.Parameters.Types[0] == s_x) + ambig_arg = candidate; + } + + ec.Report.Error (457, loc, + "Ambiguous user defined operators `{0}' and `{1}' when converting from `{2}' to `{3}'", + ambig_arg.GetSignatureForError (), most_specific_operator.GetSignatureForError (), + source.Type.GetSignatureForError (), target.GetSignatureForError ()); + + return ErrorExpression.Instance; + } + } + + // + // Convert input type when it's different to best operator argument + // + if (s_x != source_type) { + var c = source as Constant; + if (c != null) { + source = c.TryReduce (ec, s_x, loc); + } else { + source = implicitOnly ? + ImplicitConversionStandard (ec, source_type_expr, s_x, loc) : + ExplicitConversionStandard (ec, source_type_expr, s_x, loc); + } + } else { + source = source_type_expr; + } + + source = new UserCast (most_specific_operator, source, loc).Resolve (ec); + + // + // Convert result type when it's different to best operator return type + // + if (t_x != target_type) { + // + // User operator is of T?, no need to lift it + // + if (t_x == target && t_x.IsNullableType) + return source; + + source = implicitOnly ? + ImplicitConversionStandard (ec, source, target_type, loc) : + ExplicitConversionStandard (ec, source, target_type, loc); + + if (source == null) + return null; + } + + // + // Source expression is of nullable type, lift the result in the case it's null and + // not nullable/lifted user operator is used + // + if (source_type_expr is Nullable.Unwrap && !s_x.IsNullableType && (TypeSpec.IsReferenceType (target) || target_type != target)) + source = new Nullable.Lifted (source, source_type_expr, target).Resolve (ec); + else if (target_type != target) + source = Nullable.Wrap.Create (source, target); + + return source; + } + + /// + /// Converts implicitly the resolved expression `expr' into the + /// `target_type'. It returns a new expression that can be used + /// in a context that expects a `target_type'. + /// + static public Expression ImplicitConversion (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + Expression e; + + if (target_type == null) + throw new Exception ("Target type is null"); + + e = ImplicitConversionStandard (ec, expr, target_type, loc); + if (e != null) + return e; + + e = ImplicitUserConversion (ec, expr, target_type, loc); + if (e != null) + return e; + + return null; + } + + + /// + /// Attempts to apply the `Standard Implicit + /// Conversion' rules to the expression `expr' into + /// the `target_type'. It returns a new expression + /// that can be used in a context that expects a + /// `target_type'. + /// + /// This is different from `ImplicitConversion' in that the + /// user defined implicit conversions are excluded. + /// + static public Expression ImplicitConversionStandard (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + return ImplicitConversionStandard (ec, expr, target_type, loc, false); + } + + 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)){ + return null; + } + + // + // Only allow anonymous method conversions on post ISO_1 + // + if (ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1){ + MethodGroupExpr mg = expr as MethodGroupExpr; + if (mg != null) + return ImplicitDelegateCreation.Create ( + ec, mg, target_type, loc); + } + } + + TypeSpec expr_type = expr.Type; + Expression e; + + if (expr_type == target_type) { + if (expr_type != InternalType.NullLiteral && expr_type != InternalType.AnonymousMethod) + return expr; + return null; + } + + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + switch (target_type.Kind) { + case MemberKind.ArrayType: + case MemberKind.Class: + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Object) + return EmptyCast.Create (expr, target_type); + + goto case MemberKind.Struct; + case MemberKind.Struct: + case MemberKind.Delegate: + case MemberKind.Enum: + case MemberKind.Interface: + case MemberKind.TypeParameter: + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return new DynamicConversion (target_type, explicit_cast ? CSharpBinderFlags.ConvertExplicit : 0, args, loc).Resolve (ec); + } + + return null; + } + + if (target_type.IsNullableType) + return ImplicitNulableConversion (ec, expr, target_type); + + // + // Attempt to do the implicit constant expression conversions + // + Constant c = expr as Constant; + if (c != null) { + try { + c = c.ConvertImplicitly (target_type); + } catch { + Console.WriteLine ("Conversion error happened in line {0}", loc); + throw; + } + if (c != null) + return c; + } + + e = ImplicitNumericConversion (expr, expr_type, target_type); + if (e != null) + return e; + + e = ImplicitReferenceConversion (expr, target_type, explicit_cast); + if (e != null) + return e; + + e = ImplicitBoxingConversion (expr, expr_type, target_type); + if (e != null) + return e; + + if (expr is IntegralConstant && TypeManager.IsEnumType (target_type)){ + var i = (IntegralConstant) expr; + // + // LAMESPEC: csc allows any constant like 0 values to be converted, including const float f = 0.0 + // + // An implicit enumeration conversion permits the decimal-integer-literal 0 + // to be converted to any enum-type and to any nullable-type whose underlying + // type is an enum-type + // + if (i.IsZeroInteger) { + // Recreate 0 literal to remove any collected conversions + return new EnumConstant (new IntLiteral (ec.BuiltinTypes, 0, i.Location), target_type); + } + } + + if (ec.IsUnsafe) { + var target_pc = target_type as PointerContainer; + if (target_pc != null) { + if (expr_type.IsPointer) { + // + // Pointer types are same when they have same element types + // + if (expr_type == target_pc) + return expr; + + if (target_pc.Element.Kind == MemberKind.Void) + return EmptyCast.Create (expr, target_type); + + //return null; + } + + if (expr_type == InternalType.NullLiteral) + return new NullPointer (target_type, loc); + } + } + + if (expr_type == InternalType.AnonymousMethod){ + AnonymousMethodExpression ame = (AnonymousMethodExpression) expr; + Expression am = ame.Compatible (ec, target_type); + if (am != null) + return am.Resolve (ec); + } + + if (expr_type == InternalType.Arglist && target_type == ec.Module.PredefinedTypes.ArgIterator.TypeSpec) + return expr; + + // + // dynamic erasure conversion on value types + // + if (expr_type.IsStruct && TypeSpecComparer.IsEqual (expr_type, target_type)) + return expr_type == target_type ? expr : EmptyCast.Create (expr, target_type); + + return null; + } + + /// + /// Attempts to implicitly convert `source' into `target_type', using + /// ImplicitConversion. If there is no implicit conversion, then + /// an error is signaled + /// + static public Expression ImplicitConversionRequired (ResolveContext ec, Expression source, + TypeSpec target_type, Location loc) + { + Expression e = ImplicitConversion (ec, source, target_type, loc); + if (e != null) + return e; + + source.Error_ValueCannotBeConverted (ec, loc, target_type, false); + return null; + } + + /// + /// Performs the explicit numeric conversions + /// + /// There are a few conversions that are not part of the C# standard, + /// they were interim hacks in the C# compiler that were supposed to + /// become explicit operators in the UIntPtr class and IntPtr class, + /// but for historical reasons it did not happen, so the C# compiler + /// ended up with these special hacks. + /// + /// See bug 59800 for details. + /// + /// The conversion are: + /// UIntPtr->SByte + /// UIntPtr->Int16 + /// UIntPtr->Int32 + /// IntPtr->UInt64 + /// UInt64->IntPtr + /// SByte->UIntPtr + /// Int16->UIntPtr + /// + /// + public static Expression ExplicitNumericConversion (ResolveContext rc, Expression expr, TypeSpec target_type) + { + // Not all predefined explicit numeric conversion are + // defined here, for some of them (mostly IntPtr/UIntPtr) we + // defer to user-operator handling which is now perfect but + // works for now + // + // LAMESPEC: Undocumented IntPtr/UIntPtr conversions + // IntPtr -> uint uses int + // UIntPtr -> long uses ulong + // + + switch (expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + // + // From sbyte to byte, ushort, uint, ulong, char, uintptr + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U1); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U2); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I1_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I1_U8), target_type, target_type, true); + } + break; + case BuiltinTypeSpec.Type.Byte: + // + // From byte to sbyte and char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U1_I1); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U1_CH); + } + break; + case BuiltinTypeSpec.Type.Short: + // + // From short to sbyte, byte, ushort, uint, ulong, char, uintptr + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U1); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U2); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I2_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UShort: + // + // From ushort to sbyte, byte, short, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_I2); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U2_CH); + } + break; + case BuiltinTypeSpec.Type.Int: + // + // From int to sbyte, byte, short, ushort, uint, ulong, char, uintptr + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U2); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I4_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.UIntPtr: + return new OperatorCast (new ConvCast (expr, rc.BuiltinTypes.ULong, ConvCast.Mode.I2_U8), target_type, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UInt: + // + // From uint to sbyte, byte, short, ushort, int, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_I4); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U4_CH); + } + break; + case BuiltinTypeSpec.Type.Long: + // + // From long to sbyte, byte, short, ushort, int, uint, ulong, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U4); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_CH); + } + break; + case BuiltinTypeSpec.Type.ULong: + // + // From ulong to sbyte, byte, short, ushort, int, uint, long, char + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_CH); + + // One of the built-in conversions that belonged in the class library + case BuiltinTypeSpec.Type.IntPtr: + return new OperatorCast (EmptyCast.Create (expr, rc.BuiltinTypes.Long), target_type, true); + } + break; + case BuiltinTypeSpec.Type.Char: + // + // From char to sbyte, byte, short + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.CH_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.CH_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.CH_I2); + } + break; + case BuiltinTypeSpec.Type.Float: + // + // From float to sbyte, byte, short, + // ushort, int, uint, long, ulong, char + // or decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_I8); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.R4_CH); + case BuiltinTypeSpec.Type.Decimal: + return new OperatorCast (expr, target_type, true); + } + break; + case BuiltinTypeSpec.Type.Double: + // + // From double to sbyte, byte, short, + // ushort, int, uint, long, ulong, + // char, float or decimal + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I1); + case BuiltinTypeSpec.Type.Byte: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I2); + case BuiltinTypeSpec.Type.UShort: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U2); + case BuiltinTypeSpec.Type.Int: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I4); + case BuiltinTypeSpec.Type.UInt: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_I8); + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_U8); + case BuiltinTypeSpec.Type.Char: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_CH); + case BuiltinTypeSpec.Type.Float: + return new ConvCast (expr, target_type, ConvCast.Mode.R8_R4); + case BuiltinTypeSpec.Type.Decimal: + return new OperatorCast (expr, target_type, true); + } + break; + case BuiltinTypeSpec.Type.UIntPtr: + // + // Various built-in conversions that belonged in the class library + // + // from uintptr to sbyte, short, int32 + // + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I1); + case BuiltinTypeSpec.Type.Short: + return new ConvCast (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type, ConvCast.Mode.U4_I2); + case BuiltinTypeSpec.Type.Int: + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.UInt, true), target_type); + case BuiltinTypeSpec.Type.UInt: + return new OperatorCast (expr, expr.Type, target_type, true); + case BuiltinTypeSpec.Type.Long: + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.ULong, true), target_type); + } + break; + case BuiltinTypeSpec.Type.IntPtr: + if (target_type.BuiltinType == BuiltinTypeSpec.Type.UInt) + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Int, true), target_type); + if (target_type.BuiltinType == BuiltinTypeSpec.Type.ULong) + return EmptyCast.Create (new OperatorCast (expr, expr.Type, rc.BuiltinTypes.Long, true), target_type); + + break; + case BuiltinTypeSpec.Type.Decimal: + // From decimal to sbyte, byte, short, + // ushort, int, uint, long, ulong, char, + // float, or double + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + return new OperatorCast (expr, expr.Type, target_type, true); + } + + break; + } + + return null; + } + + /// + /// Returns whether an explicit reference conversion can be performed + /// from source_type to target_type + /// + public static bool ExplicitReferenceConversionExists (TypeSpec source_type, TypeSpec target_type) + { + Expression e = ExplicitReferenceConversion (null, source_type, target_type); + if (e == null) + return false; + + if (e == EmptyExpression.Null) + return true; + + throw new InternalErrorException ("Invalid probing conversion result"); + } + + /// + /// Implements Explicit Reference conversions + /// + static Expression ExplicitReferenceConversion (Expression source, TypeSpec source_type, TypeSpec target_type) + { + // + // From object to a generic parameter + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object && TypeManager.IsGenericParameter (target_type)) + return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type); + + // + // Explicit type parameter conversion. + // + if (source_type.Kind == MemberKind.TypeParameter) + return ExplicitTypeParameterConversion (source, source_type, target_type); + + bool target_is_value_type = target_type.Kind == MemberKind.Struct || target_type.Kind == MemberKind.Enum; + + // + // Unboxing conversion from System.ValueType to any non-nullable-value-type + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.ValueType && target_is_value_type) + return source == null ? EmptyExpression.Null : new UnboxCast (source, target_type); + + // + // From object or dynamic to any reference type or value type (unboxing) + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Object || source_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + if (target_type.IsPointer) + return null; + + return + source == null ? EmptyExpression.Null : + target_is_value_type ? new UnboxCast (source, target_type) : + source is Constant ? (Expression) new EmptyConstantCast ((Constant) source, target_type) : + new ClassCast (source, target_type); + } + + // + // From any class S to any class-type T, provided S is a base class of T + // + if (source_type.Kind == MemberKind.Class && TypeSpec.IsBaseClass (target_type, source_type, true)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + // + // From any interface-type S to to any class type T, provided T is not + // sealed, or provided T implements S. + // + if (source_type.Kind == MemberKind.Interface) { + if (!target_type.IsSealed || target_type.ImplementsInterface (source_type, true)) { + if (source == null) + return EmptyExpression.Null; + + // + // Unboxing conversion from any interface-type to any non-nullable-value-type that + // implements the interface-type + // + return target_is_value_type ? new UnboxCast (source, target_type) : (Expression) new ClassCast (source, target_type); + } + + // + // From System.Collections.Generic.IList and its base interfaces to a one-dimensional + // array type S[], provided there is an implicit or explicit reference conversion from S to T. + // + var target_array = target_type as ArrayContainer; + if (target_array != null && IList_To_Array (source_type, target_array)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + return null; + } + + var source_array = source_type as ArrayContainer; + if (source_array != null) { + var target_array = target_type as ArrayContainer; + if (target_array != null) { + // + // From System.Array to any array-type + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Array) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + // + // From an array type S with an element type Se to an array type T with an + // element type Te provided all the following are true: + // * S and T differe only in element type, in other words, S and T + // have the same number of dimensions. + // * Both Se and Te are reference types + // * An explicit reference conversions exist from Se to Te + // + if (source_array.Rank == target_array.Rank) { + + source_type = source_array.Element; + if (!TypeSpec.IsReferenceType (source_type)) + return null; + + var target_element = target_array.Element; + if (!TypeSpec.IsReferenceType (target_element)) + return null; + + if (ExplicitReferenceConversionExists (source_type, target_element)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + return null; + } + } + + // + // From a single-dimensional array type S[] to System.Collections.Generic.IList and its base interfaces, + // provided that there is an explicit reference conversion from S to T + // + if (ArrayToIList (source_array, target_type, true)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + return null; + } + + // + // From any class type S to any interface T, provides S is not sealed + // and provided S does not implement T. + // + if (target_type.IsInterface && !source_type.IsSealed && !source_type.ImplementsInterface (target_type, true)) { + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + + // + // From System delegate to any delegate-type + // + if (source_type.BuiltinType == BuiltinTypeSpec.Type.Delegate && TypeManager.IsDelegateType (target_type)) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + + // + // From variant generic delegate to same variant generic delegate type + // + if (source_type.IsDelegate && target_type.IsDelegate && source_type.MemberDefinition == target_type.MemberDefinition) { + var tparams = source_type.MemberDefinition.TypeParameters; + var targs_src = source_type.TypeArguments; + var targs_dst = target_type.TypeArguments; + int i; + for (i = 0; i < tparams.Length; ++i) { + // + // If TP is invariant, types have to be identical + // + if (TypeSpecComparer.IsEqual (targs_src[i], targs_dst[i])) + continue; + + if (tparams[i].Variance == Variance.Covariant) { + // + //If TP is covariant, an implicit or explicit identity or reference conversion is required + // + if (ImplicitReferenceConversionExists (targs_src[i], targs_dst[i])) + continue; + + if (ExplicitReferenceConversionExists (targs_src[i], targs_dst[i])) + continue; + + } else if (tparams[i].Variance == Variance.Contravariant) { + // + //If TP is contravariant, both are either identical or reference types + // + if (TypeSpec.IsReferenceType (targs_src[i]) && TypeSpec.IsReferenceType (targs_dst[i])) + continue; + } + + break; + } + + if (i == tparams.Length) + return source == null ? EmptyExpression.Null : new ClassCast (source, target_type); + } + + return null; + } + + /// + /// Performs an explicit conversion of the expression `expr' whose + /// type is expr.Type to `target_type'. + /// + static public Expression ExplicitConversionCore (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + TypeSpec expr_type = expr.Type; + + // Explicit conversion includes implicit conversion and it used for enum underlying types too + Expression ne = ImplicitConversionStandard (ec, expr, target_type, loc, true); + if (ne != null) + return ne; + + if (TypeManager.IsEnumType (expr_type)) { + TypeSpec real_target = TypeManager.IsEnumType (target_type) ? EnumSpec.GetUnderlyingType (target_type) : target_type; + Expression underlying = EmptyCast.Create (expr, EnumSpec.GetUnderlyingType (expr_type)); + if (underlying.Type == real_target) + ne = underlying; + + if (ne == null) + ne = ImplicitNumericConversion (underlying, real_target); + + if (ne == null) + ne = ExplicitNumericConversion (ec, underlying, real_target); + + // + // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed + // + if (ne == null && (real_target.BuiltinType == BuiltinTypeSpec.Type.IntPtr || real_target.BuiltinType == BuiltinTypeSpec.Type.UIntPtr)) + ne = ExplicitUserConversion (ec, underlying, real_target, loc); + + return ne != null ? EmptyCast.Create (ne, target_type) : null; + } + + if (TypeManager.IsEnumType (target_type)) { + // + // 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; + + if (expr_type == real_target) + return EmptyCast.Create (expr, target_type); + + ne = ImplicitNumericConversion (expr, real_target); + if (ne != null) + return EmptyCast.Create (ne, target_type); + + ne = ExplicitNumericConversion (ec, expr, real_target); + if (ne != null) + return EmptyCast.Create (ne, target_type); + + // + // LAMESPEC: IntPtr and UIntPtr conversion to any Enum is allowed + // + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.IntPtr || expr_type.BuiltinType == BuiltinTypeSpec.Type.UIntPtr) { + ne = ExplicitUserConversion (ec, expr, real_target, loc); + if (ne != null) + return ExplicitConversionCore (ec, ne, target_type, loc); + } + } else { + ne = ExplicitNumericConversion (ec, expr, target_type); + if (ne != null) + return ne; + } + + // + // Skip the ExplicitReferenceConversion because we can not convert + // from Null to a ValueType, and ExplicitReference wont check against + // null literal explicitly + // + if (expr_type != InternalType.NullLiteral) { + ne = ExplicitReferenceConversion (expr, expr_type, target_type); + if (ne != null) + return ne; + } + + if (ec.IsUnsafe){ + ne = ExplicitUnsafe (expr, target_type); + if (ne != null) + return ne; + } + + return null; + } + + public static Expression ExplicitUnsafe (Expression expr, TypeSpec target_type) + { + TypeSpec expr_type = expr.Type; + + if (target_type.IsPointer){ + if (expr_type.IsPointer) + return EmptyCast.Create (expr, target_type); + + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Int: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I); + + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Byte: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U); + + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.I8_I); + + case BuiltinTypeSpec.Type.ULong: + return new ConvCast (expr, target_type, ConvCast.Mode.U8_I); + } + } + + if (expr_type.IsPointer){ + switch (target_type.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I1); + case BuiltinTypeSpec.Type.Byte: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U1); + case BuiltinTypeSpec.Type.Short: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I2); + case BuiltinTypeSpec.Type.UShort: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U2); + case BuiltinTypeSpec.Type.Int: + return new OpcodeCast (expr, target_type, OpCodes.Conv_I4); + case BuiltinTypeSpec.Type.UInt: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U4); + case BuiltinTypeSpec.Type.Long: + return new ConvCast (expr, target_type, ConvCast.Mode.I_I8); + case BuiltinTypeSpec.Type.ULong: + return new OpcodeCast (expr, target_type, OpCodes.Conv_U8); + } + } + return null; + } + + /// + /// Same as ExplicitConversion, only it doesn't include user defined conversions + /// + static public Expression ExplicitConversionStandard (ResolveContext ec, Expression expr, + TypeSpec target_type, Location l) + { + int errors = ec.Report.Errors; + Expression ne = ImplicitConversionStandard (ec, expr, target_type, l); + if (ec.Report.Errors > errors) + return null; + + if (ne != null) + return ne; + + ne = ExplicitNumericConversion (ec, expr, target_type); + if (ne != null) + return ne; + + ne = ExplicitReferenceConversion (expr, expr.Type, target_type); + if (ne != null) + return ne; + + if (ec.IsUnsafe && expr.Type.IsPointer && target_type.IsPointer && ((PointerContainer)expr.Type).Element.Kind == MemberKind.Void) + return EmptyCast.Create (expr, target_type); + + expr.Error_ValueCannotBeConverted (ec, l, target_type, true); + return null; + } + + /// + /// Performs an explicit conversion of the expression `expr' whose + /// type is expr.Type to `target_type'. + /// + static public Expression ExplicitConversion (ResolveContext ec, Expression expr, + TypeSpec target_type, Location loc) + { + Expression e = ExplicitConversionCore (ec, expr, target_type, loc); + if (e != null) { + // + // Don't eliminate explicit precission casts + // + if (e == expr) { + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Float) + return new OpcodeCast (expr, target_type, OpCodes.Conv_R4); + + if (target_type.BuiltinType == BuiltinTypeSpec.Type.Double) + return new OpcodeCast (expr, target_type, OpCodes.Conv_R8); + } + + return e; + } + + TypeSpec expr_type = expr.Type; + if (target_type.IsNullableType) { + TypeSpec target; + + if (expr_type.IsNullableType) { + target = Nullable.NullableInfo.GetUnderlyingType (target_type); + Expression unwrap = Nullable.Unwrap.Create (expr); + e = ExplicitConversion (ec, unwrap, target, expr.Location); + if (e == null) + return null; + + return new Nullable.Lifted (e, unwrap, target_type).Resolve (ec); + } + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Object) { + return new UnboxCast (expr, target_type); + } + + target = TypeManager.GetTypeArguments (target_type) [0]; + e = ExplicitConversionCore (ec, expr, target, loc); + if (e != null) + return Nullable.Wrap.Create (e, target_type); + } else if (expr_type.IsNullableType) { + e = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type); + if (e != null) + return e; + + e = Nullable.Unwrap.Create (expr, false); + e = ExplicitConversionCore (ec, e, target_type, loc); + if (e != null) + return EmptyCast.Create (e, target_type); + } + + e = ExplicitUserConversion (ec, expr, target_type, loc); + if (e != null) + return e; + + expr.Error_ValueCannotBeConverted (ec, loc, target_type, true); + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs new file mode 100644 index 0000000000..0cee24dd0c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs @@ -0,0 +1,13108 @@ +// created by jay 0.7 (c) 1998 Axel.Schreiner@informatik.uni-osnabrueck.de + +#line 2 "cs-parser.jay" +// +// cs-parser.jay: The Parser for the C# compiler +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual Licensed under the terms of the GNU GPL and the MIT X11 license +// +// (C) 2001 Ximian, Inc (http://www.ximian.com) +// (C) 2004 Novell, Inc +// +// TODO: +// (1) Figure out why error productions dont work. `type-declaration' is a +// great spot to put an `error' because you can reproduce it with this input: +// "public X { }" +// + +using System.Text; +using System.IO; +using System; +using System.Collections.Generic; + +namespace Mono.CSharp +{ + /// + /// The C# Parser + /// + public class CSharpParser + { + [Flags] + enum ParameterModifierType + { + Ref = 1 << 1, + Out = 1 << 2, + This = 1 << 3, + Params = 1 << 4, + Arglist = 1 << 5, + DefaultValue = 1 << 6, + + All = Ref | Out | This | Params | Arglist | DefaultValue + } + + static readonly object ModifierNone = 0; + + NamespaceContainer current_namespace; + TypeContainer current_container; + DeclSpace current_class; + PropertyBase current_property; + EventProperty current_event; + EventField current_event_field; + FieldBase current_field; + + /// + /// Current block is used to add statements as we find + /// them. + /// + Block current_block; + + BlockVariableDeclaration current_variable; + + Delegate current_delegate; + + AnonymousMethodExpression current_anonymous_method; + + /// + /// This is used by the unary_expression code to resolve + /// a name against a parameter. + /// + + // FIXME: This is very ugly and it's very hard to reset it correctly + // on all places, especially when some parameters are autogenerated. + ParametersCompiled current_local_parameters; + + bool parsing_anonymous_method; + + /// + /// An out-of-band stack. + /// + static Stack oob_stack; + + /// + /// Controls the verbosity of the errors produced by the parser + /// + static public int yacc_verbose_flag; + + /// + /// Used by the interactive shell, flags whether EOF was reached + /// and an error was produced + /// + public bool UnexpectedEOF; + + /// + /// The current file. + /// + readonly CompilationSourceFile file; + + /// + /// Temporary Xml documentation cache. + /// For enum types, we need one more temporary store. + /// + string tmpComment; + string enumTypeComment; + + /// Current attribute target + string current_attr_target; + + ParameterModifierType valid_param_mod; + + bool default_parameter_used; + + /// When using the interactive parser, this holds the + /// resulting expression + public Class InteractiveResult; + + // + // Keeps track of global data changes to undo on parser error + // + public Undo undo; + + Stack linq_clause_blocks; + + ModuleContainer module; + + readonly CompilerContext compiler; + readonly LanguageVersion lang_version; + readonly bool doc_support; + readonly CompilerSettings settings; + readonly Report report; + + // + // Instead of allocating carrier array everytime we + // share the bucket for very common constructs which can never + // be recursive + // + static List parameters_bucket = new List (6); + + // + // Full AST support members + // + LocationsBag lbag; + UsingsBag ubag; + List> mod_locations; + Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; + Location savedAttrParenOpenLocation, savedAttrParenCloseLocation; + Stack> locationListStack = new Stack> (); // 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; + } + } + +#line default + + /** error output stream. + It should be changeable. + */ + public System.IO.TextWriter ErrorOutput = System.Console.Out; + + /** simplified error message. + @see yyerror + */ + public void yyerror (string message) { + yyerror(message, null); + } + + /* An EOF token */ + public int eof_token; + + /** (syntax) error message. + Can be overwritten to control message format. + @param message text to be displayed. + @param expected vector of acceptable tokens, if available. + */ + public void yyerror (string message, string[] expected) { + if ((yacc_verbose_flag > 0) && (expected != null) && (expected.Length > 0)) { + ErrorOutput.Write (message+", expecting"); + for (int n = 0; n < expected.Length; ++ n) + ErrorOutput.Write (" "+expected[n]); + ErrorOutput.WriteLine (); + } else + ErrorOutput.WriteLine (message); + } + + /** debugging support, requires the package jay.yydebug. + Set to null to suppress debugging messages. + */ +//t internal yydebug.yyDebug debug; + + protected const int yyFinal = 7; +//t // Put this array into a separate class so it is only initialized if debugging is actually used +//t // Use MarshalByRefObject to disable inlining +//t class YYRules : MarshalByRefObject { +//t public static readonly string [] yyRule = { +//t "$accept : compilation_unit", +//t "compilation_unit : outer_declaration opt_EOF", +//t "$$1 :", +//t "compilation_unit : interactive_parsing $$1 opt_EOF", +//t "compilation_unit : documentation_parsing", +//t "outer_declaration : opt_extern_alias_directives opt_using_directives", +//t "outer_declaration : opt_extern_alias_directives opt_using_directives namespace_or_type_declarations opt_attributes", +//t "outer_declaration : opt_extern_alias_directives opt_using_directives attribute_sections", +//t "outer_declaration : error", +//t "opt_EOF :", +//t "opt_EOF : EOF", +//t "extern_alias_directives : extern_alias_directive", +//t "extern_alias_directives : extern_alias_directives extern_alias_directive", +//t "extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON", +//t "extern_alias_directive : EXTERN_ALIAS error", +//t "using_directives : using_directive", +//t "using_directives : using_directives using_directive", +//t "using_directive : using_alias_directive", +//t "using_directive : using_namespace_directive", +//t "using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON", +//t "using_alias_directive : USING error", +//t "using_namespace_directive : USING namespace_name SEMICOLON", +//t "$$2 :", +//t "$$3 :", +//t "namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 OPEN_BRACE $$3 opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon", +//t "qualified_identifier : IDENTIFIER", +//t "qualified_identifier : qualified_identifier DOT IDENTIFIER", +//t "qualified_identifier : error", +//t "opt_semicolon :", +//t "opt_semicolon : SEMICOLON", +//t "opt_comma :", +//t "opt_comma : COMMA", +//t "namespace_name : namespace_or_type_name", +//t "opt_using_directives :", +//t "opt_using_directives : using_directives", +//t "opt_extern_alias_directives :", +//t "opt_extern_alias_directives : extern_alias_directives", +//t "opt_namespace_or_type_declarations :", +//t "opt_namespace_or_type_declarations : namespace_or_type_declarations", +//t "namespace_or_type_declarations : namespace_or_type_declaration", +//t "namespace_or_type_declarations : namespace_or_type_declarations namespace_or_type_declaration", +//t "namespace_or_type_declaration : type_declaration", +//t "namespace_or_type_declaration : namespace_declaration", +//t "type_declaration : class_declaration", +//t "type_declaration : struct_declaration", +//t "type_declaration : interface_declaration", +//t "type_declaration : enum_declaration", +//t "type_declaration : delegate_declaration", +//t "opt_attributes :", +//t "opt_attributes : attribute_sections", +//t "attribute_sections : attribute_section", +//t "attribute_sections : attribute_sections attribute_section", +//t "$$4 :", +//t "attribute_section : OPEN_BRACKET $$4 attribute_section_cont", +//t "$$5 :", +//t "attribute_section_cont : attribute_target COLON $$5 attribute_list opt_comma CLOSE_BRACKET", +//t "attribute_section_cont : attribute_list opt_comma CLOSE_BRACKET", +//t "attribute_target : IDENTIFIER", +//t "attribute_target : EVENT", +//t "attribute_target : RETURN", +//t "attribute_target : error", +//t "attribute_list : attribute", +//t "attribute_list : attribute_list COMMA attribute", +//t "$$6 :", +//t "attribute : attribute_name $$6 opt_attribute_arguments", +//t "attribute_name : namespace_or_type_name", +//t "opt_attribute_arguments :", +//t "opt_attribute_arguments : OPEN_PARENS attribute_arguments CLOSE_PARENS", +//t "attribute_arguments :", +//t "attribute_arguments : positional_or_named_argument", +//t "attribute_arguments : named_attribute_argument", +//t "attribute_arguments : attribute_arguments COMMA positional_or_named_argument", +//t "attribute_arguments : attribute_arguments COMMA named_attribute_argument", +//t "positional_or_named_argument : expression", +//t "positional_or_named_argument : named_argument", +//t "$$7 :", +//t "named_attribute_argument : IDENTIFIER ASSIGN $$7 expression", +//t "named_argument : IDENTIFIER COLON opt_named_modifier expression", +//t "opt_named_modifier :", +//t "opt_named_modifier : REF", +//t "opt_named_modifier : OUT", +//t "opt_class_member_declarations :", +//t "opt_class_member_declarations : class_member_declarations", +//t "class_member_declarations : class_member_declaration", +//t "class_member_declarations : class_member_declarations class_member_declaration", +//t "class_member_declaration : constant_declaration", +//t "class_member_declaration : field_declaration", +//t "class_member_declaration : method_declaration", +//t "class_member_declaration : property_declaration", +//t "class_member_declaration : event_declaration", +//t "class_member_declaration : indexer_declaration", +//t "class_member_declaration : operator_declaration", +//t "class_member_declaration : constructor_declaration", +//t "class_member_declaration : destructor_declaration", +//t "class_member_declaration : type_declaration", +//t "class_member_declaration : error", +//t "$$8 :", +//t "$$9 :", +//t "$$10 :", +//t "$$11 :", +//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$8 type_declaration_name $$9 opt_class_base opt_type_parameter_constraints_clauses $$10 struct_body $$11 opt_semicolon", +//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT error", +//t "$$12 :", +//t "struct_body : OPEN_BRACE $$12 opt_struct_member_declarations CLOSE_BRACE", +//t "opt_struct_member_declarations :", +//t "opt_struct_member_declarations : struct_member_declarations", +//t "struct_member_declarations : struct_member_declaration", +//t "struct_member_declarations : struct_member_declarations struct_member_declaration", +//t "struct_member_declaration : constant_declaration", +//t "struct_member_declaration : field_declaration", +//t "struct_member_declaration : method_declaration", +//t "struct_member_declaration : property_declaration", +//t "struct_member_declaration : event_declaration", +//t "struct_member_declaration : indexer_declaration", +//t "struct_member_declaration : operator_declaration", +//t "struct_member_declaration : constructor_declaration", +//t "struct_member_declaration : type_declaration", +//t "struct_member_declaration : destructor_declaration", +//t "$$13 :", +//t "constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$13 constant_initializer opt_constant_declarators SEMICOLON", +//t "opt_constant_declarators :", +//t "opt_constant_declarators : constant_declarators", +//t "constant_declarators : constant_declarator", +//t "constant_declarators : constant_declarators constant_declarator", +//t "constant_declarator : COMMA IDENTIFIER constant_initializer", +//t "$$14 :", +//t "constant_initializer : ASSIGN $$14 constant_initializer_expr", +//t "constant_initializer : error", +//t "constant_initializer_expr : constant_expression", +//t "constant_initializer_expr : array_initializer", +//t "$$15 :", +//t "field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$15 opt_field_initializer opt_field_declarators SEMICOLON", +//t "$$16 :", +//t "field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$16 fixed_field_size opt_fixed_field_declarators SEMICOLON", +//t "field_declaration : opt_attributes opt_modifiers FIXED simple_type error SEMICOLON", +//t "opt_field_initializer :", +//t "$$17 :", +//t "opt_field_initializer : ASSIGN $$17 variable_initializer", +//t "opt_field_declarators :", +//t "opt_field_declarators : field_declarators", +//t "field_declarators : field_declarator", +//t "field_declarators : field_declarators field_declarator", +//t "field_declarator : COMMA IDENTIFIER", +//t "$$18 :", +//t "field_declarator : COMMA IDENTIFIER ASSIGN $$18 variable_initializer", +//t "opt_fixed_field_declarators :", +//t "opt_fixed_field_declarators : fixed_field_declarators", +//t "fixed_field_declarators : fixed_field_declarator", +//t "fixed_field_declarators : fixed_field_declarators fixed_field_declarator", +//t "fixed_field_declarator : COMMA IDENTIFIER fixed_field_size", +//t "$$19 :", +//t "fixed_field_size : OPEN_BRACKET $$19 expression CLOSE_BRACKET", +//t "fixed_field_size : OPEN_BRACKET error", +//t "variable_initializer : expression", +//t "variable_initializer : array_initializer", +//t "variable_initializer : error", +//t "$$20 :", +//t "method_declaration : method_header $$20 method_body", +//t "$$21 :", +//t "$$22 :", +//t "method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$21 opt_formal_parameter_list CLOSE_PARENS $$22 opt_type_parameter_constraints_clauses", +//t "$$23 :", +//t "$$24 :", +//t "$$25 :", +//t "method_header : opt_attributes opt_modifiers PARTIAL VOID $$23 method_declaration_name OPEN_PARENS $$24 opt_formal_parameter_list CLOSE_PARENS $$25 opt_type_parameter_constraints_clauses", +//t "method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS", +//t "method_body : block", +//t "method_body : SEMICOLON", +//t "opt_formal_parameter_list :", +//t "opt_formal_parameter_list : formal_parameter_list", +//t "formal_parameter_list : fixed_parameters", +//t "formal_parameter_list : fixed_parameters COMMA parameter_array", +//t "formal_parameter_list : fixed_parameters COMMA arglist_modifier", +//t "formal_parameter_list : parameter_array COMMA error", +//t "formal_parameter_list : fixed_parameters COMMA parameter_array COMMA error", +//t "formal_parameter_list : arglist_modifier COMMA error", +//t "formal_parameter_list : fixed_parameters COMMA ARGLIST COMMA error", +//t "formal_parameter_list : parameter_array", +//t "formal_parameter_list : arglist_modifier", +//t "formal_parameter_list : error", +//t "fixed_parameters : fixed_parameter", +//t "fixed_parameters : fixed_parameters COMMA fixed_parameter", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type error", +//t "$$26 :", +//t "fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$26 constant_expression", +//t "opt_parameter_modifier :", +//t "opt_parameter_modifier : parameter_modifiers", +//t "parameter_modifiers : parameter_modifier", +//t "parameter_modifiers : parameter_modifiers parameter_modifier", +//t "parameter_modifier : REF", +//t "parameter_modifier : OUT", +//t "parameter_modifier : THIS", +//t "parameter_array : opt_attributes params_modifier type IDENTIFIER", +//t "parameter_array : opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression", +//t "parameter_array : opt_attributes params_modifier type error", +//t "params_modifier : PARAMS", +//t "params_modifier : PARAMS parameter_modifier", +//t "params_modifier : PARAMS params_modifier", +//t "arglist_modifier : ARGLIST", +//t "$$27 :", +//t "$$28 :", +//t "$$29 :", +//t "property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$27 OPEN_BRACE $$28 accessor_declarations $$29 CLOSE_BRACE", +//t "$$30 :", +//t "$$31 :", +//t "$$32 :", +//t "indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$30 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$31 accessor_declarations $$32 CLOSE_BRACE", +//t "accessor_declarations : get_accessor_declaration", +//t "accessor_declarations : get_accessor_declaration accessor_declarations", +//t "accessor_declarations : set_accessor_declaration", +//t "accessor_declarations : set_accessor_declaration accessor_declarations", +//t "accessor_declarations : error", +//t "$$33 :", +//t "get_accessor_declaration : opt_attributes opt_modifiers GET $$33 accessor_body", +//t "$$34 :", +//t "set_accessor_declaration : opt_attributes opt_modifiers SET $$34 accessor_body", +//t "accessor_body : block", +//t "accessor_body : SEMICOLON", +//t "accessor_body : error", +//t "$$35 :", +//t "$$36 :", +//t "$$37 :", +//t "$$38 :", +//t "interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$35 type_declaration_name $$36 opt_class_base opt_type_parameter_constraints_clauses $$37 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$38 opt_semicolon", +//t "interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE error", +//t "opt_interface_member_declarations :", +//t "opt_interface_member_declarations : interface_member_declarations", +//t "interface_member_declarations : interface_member_declaration", +//t "interface_member_declarations : interface_member_declarations interface_member_declaration", +//t "interface_member_declaration : constant_declaration", +//t "interface_member_declaration : field_declaration", +//t "interface_member_declaration : method_declaration", +//t "interface_member_declaration : property_declaration", +//t "interface_member_declaration : event_declaration", +//t "interface_member_declaration : indexer_declaration", +//t "interface_member_declaration : operator_declaration", +//t "interface_member_declaration : constructor_declaration", +//t "interface_member_declaration : type_declaration", +//t "$$39 :", +//t "operator_declaration : opt_attributes opt_modifiers operator_declarator $$39 operator_body", +//t "operator_body : block", +//t "operator_body : SEMICOLON", +//t "operator_type : type_expression_or_array", +//t "operator_type : VOID", +//t "$$40 :", +//t "operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS", +//t "operator_declarator : conversion_operator_declarator", +//t "overloadable_operator : BANG", +//t "overloadable_operator : TILDE", +//t "overloadable_operator : OP_INC", +//t "overloadable_operator : OP_DEC", +//t "overloadable_operator : TRUE", +//t "overloadable_operator : FALSE", +//t "overloadable_operator : PLUS", +//t "overloadable_operator : MINUS", +//t "overloadable_operator : STAR", +//t "overloadable_operator : DIV", +//t "overloadable_operator : PERCENT", +//t "overloadable_operator : BITWISE_AND", +//t "overloadable_operator : BITWISE_OR", +//t "overloadable_operator : CARRET", +//t "overloadable_operator : OP_SHIFT_LEFT", +//t "overloadable_operator : OP_SHIFT_RIGHT", +//t "overloadable_operator : OP_EQ", +//t "overloadable_operator : OP_NE", +//t "overloadable_operator : OP_GT", +//t "overloadable_operator : OP_LT", +//t "overloadable_operator : OP_GE", +//t "overloadable_operator : OP_LE", +//t "$$41 :", +//t "conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$41 opt_formal_parameter_list CLOSE_PARENS", +//t "$$42 :", +//t "conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$42 opt_formal_parameter_list CLOSE_PARENS", +//t "conversion_operator_declarator : IMPLICIT error", +//t "conversion_operator_declarator : EXPLICIT error", +//t "constructor_declaration : constructor_declarator constructor_body", +//t "$$43 :", +//t "$$44 :", +//t "constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$43 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$44 opt_constructor_initializer", +//t "constructor_body : block_prepared", +//t "constructor_body : SEMICOLON", +//t "opt_constructor_initializer :", +//t "opt_constructor_initializer : constructor_initializer", +//t "$$45 :", +//t "constructor_initializer : COLON BASE OPEN_PARENS $$45 opt_argument_list CLOSE_PARENS", +//t "$$46 :", +//t "constructor_initializer : COLON THIS OPEN_PARENS $$46 opt_argument_list CLOSE_PARENS", +//t "constructor_initializer : error", +//t "$$47 :", +//t "destructor_declaration : opt_attributes opt_modifiers TILDE $$47 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body", +//t "$$48 :", +//t "event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$48 opt_event_initializer opt_event_declarators SEMICOLON", +//t "$$49 :", +//t "$$50 :", +//t "event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$49 event_accessor_declarations $$50 CLOSE_BRACE", +//t "opt_event_initializer :", +//t "$$51 :", +//t "opt_event_initializer : ASSIGN $$51 event_variable_initializer", +//t "opt_event_declarators :", +//t "opt_event_declarators : event_declarators", +//t "event_declarators : event_declarator", +//t "event_declarators : event_declarators event_declarator", +//t "event_declarator : COMMA IDENTIFIER", +//t "$$52 :", +//t "event_declarator : COMMA IDENTIFIER ASSIGN $$52 event_variable_initializer", +//t "$$53 :", +//t "event_variable_initializer : $$53 variable_initializer", +//t "event_accessor_declarations : add_accessor_declaration remove_accessor_declaration", +//t "event_accessor_declarations : remove_accessor_declaration add_accessor_declaration", +//t "event_accessor_declarations : add_accessor_declaration", +//t "event_accessor_declarations : remove_accessor_declaration", +//t "event_accessor_declarations : error", +//t "$$54 :", +//t "add_accessor_declaration : opt_attributes opt_modifiers ADD $$54 event_accessor_block", +//t "$$55 :", +//t "remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$55 event_accessor_block", +//t "event_accessor_block : opt_semicolon", +//t "event_accessor_block : block", +//t "$$56 :", +//t "$$57 :", +//t "$$58 :", +//t "enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$56 OPEN_BRACE $$57 opt_enum_member_declarations $$58 CLOSE_BRACE opt_semicolon", +//t "opt_enum_base :", +//t "opt_enum_base : COLON type", +//t "opt_enum_base : COLON error", +//t "opt_enum_member_declarations :", +//t "opt_enum_member_declarations : enum_member_declarations", +//t "opt_enum_member_declarations : enum_member_declarations COMMA", +//t "enum_member_declarations : enum_member_declaration", +//t "enum_member_declarations : enum_member_declarations COMMA enum_member_declaration", +//t "enum_member_declaration : opt_attributes IDENTIFIER", +//t "$$59 :", +//t "enum_member_declaration : opt_attributes IDENTIFIER $$59 ASSIGN constant_expression", +//t "$$60 :", +//t "$$61 :", +//t "$$62 :", +//t "delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$60 opt_formal_parameter_list CLOSE_PARENS $$61 opt_type_parameter_constraints_clauses $$62 SEMICOLON", +//t "opt_nullable :", +//t "opt_nullable : INTERR_NULLABLE", +//t "namespace_or_type_name : member_name", +//t "namespace_or_type_name : qualified_alias_member IDENTIFIER opt_type_argument_list", +//t "member_name : type_name", +//t "member_name : namespace_or_type_name DOT IDENTIFIER opt_type_argument_list", +//t "type_name : IDENTIFIER opt_type_argument_list", +//t "opt_type_argument_list :", +//t "opt_type_argument_list : OP_GENERICS_LT type_arguments OP_GENERICS_GT", +//t "opt_type_argument_list : OP_GENERICS_LT error", +//t "type_arguments : type", +//t "type_arguments : type_arguments COMMA type", +//t "$$63 :", +//t "type_declaration_name : IDENTIFIER $$63 opt_type_parameter_list", +//t "member_declaration_name : method_declaration_name", +//t "method_declaration_name : type_declaration_name", +//t "method_declaration_name : explicit_interface IDENTIFIER opt_type_parameter_list", +//t "indexer_declaration_name : THIS", +//t "indexer_declaration_name : explicit_interface THIS", +//t "explicit_interface : IDENTIFIER opt_type_argument_list DOT", +//t "explicit_interface : qualified_alias_member IDENTIFIER opt_type_argument_list DOT", +//t "explicit_interface : explicit_interface IDENTIFIER opt_type_argument_list DOT", +//t "opt_type_parameter_list :", +//t "opt_type_parameter_list : OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT", +//t "type_parameters : type_parameter", +//t "type_parameters : type_parameters COMMA type_parameter", +//t "type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER", +//t "type_parameter : error", +//t "type_and_void : type_expression_or_array", +//t "type_and_void : VOID", +//t "member_type : type_and_void", +//t "type : type_expression_or_array", +//t "type : VOID", +//t "simple_type : type_expression", +//t "simple_type : VOID", +//t "parameter_type : type_expression_or_array", +//t "parameter_type : VOID", +//t "type_expression_or_array : type_expression", +//t "type_expression_or_array : type_expression rank_specifiers", +//t "type_expression : namespace_or_type_name opt_nullable", +//t "type_expression : namespace_or_type_name pointer_stars", +//t "type_expression : builtin_types opt_nullable", +//t "type_expression : builtin_types pointer_stars", +//t "type_expression : VOID pointer_stars", +//t "type_list : base_type_name", +//t "type_list : type_list COMMA base_type_name", +//t "base_type_name : type", +//t "base_type_name : error", +//t "builtin_types : OBJECT", +//t "builtin_types : STRING", +//t "builtin_types : BOOL", +//t "builtin_types : DECIMAL", +//t "builtin_types : FLOAT", +//t "builtin_types : DOUBLE", +//t "builtin_types : integral_type", +//t "integral_type : SBYTE", +//t "integral_type : BYTE", +//t "integral_type : SHORT", +//t "integral_type : USHORT", +//t "integral_type : INT", +//t "integral_type : UINT", +//t "integral_type : LONG", +//t "integral_type : ULONG", +//t "integral_type : CHAR", +//t "primary_expression : primary_expression_or_type", +//t "primary_expression : literal", +//t "primary_expression : array_creation_expression", +//t "primary_expression : parenthesized_expression", +//t "primary_expression : default_value_expression", +//t "primary_expression : invocation_expression", +//t "primary_expression : element_access", +//t "primary_expression : this_access", +//t "primary_expression : base_access", +//t "primary_expression : post_increment_expression", +//t "primary_expression : post_decrement_expression", +//t "primary_expression : object_or_delegate_creation_expression", +//t "primary_expression : anonymous_type_expression", +//t "primary_expression : typeof_expression", +//t "primary_expression : sizeof_expression", +//t "primary_expression : checked_expression", +//t "primary_expression : unchecked_expression", +//t "primary_expression : pointer_member_access", +//t "primary_expression : anonymous_method_expression", +//t "primary_expression : undocumented_expressions", +//t "primary_expression_or_type : IDENTIFIER opt_type_argument_list", +//t "primary_expression_or_type : IDENTIFIER GENERATE_COMPLETION", +//t "primary_expression_or_type : member_access", +//t "literal : boolean_literal", +//t "literal : LITERAL", +//t "literal : NULL", +//t "boolean_literal : TRUE", +//t "boolean_literal : FALSE", +//t "open_parens_any : OPEN_PARENS", +//t "open_parens_any : OPEN_PARENS_CAST", +//t "close_parens : CLOSE_PARENS", +//t "close_parens : COMPLETE_COMPLETION", +//t "parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS", +//t "parenthesized_expression : OPEN_PARENS expression COMPLETE_COMPLETION", +//t "member_access : primary_expression DOT IDENTIFIER opt_type_argument_list", +//t "member_access : builtin_types DOT IDENTIFIER opt_type_argument_list", +//t "member_access : BASE DOT IDENTIFIER opt_type_argument_list", +//t "member_access : qualified_alias_member IDENTIFIER opt_type_argument_list", +//t "member_access : primary_expression DOT GENERATE_COMPLETION", +//t "member_access : primary_expression DOT IDENTIFIER GENERATE_COMPLETION", +//t "member_access : builtin_types DOT GENERATE_COMPLETION", +//t "member_access : builtin_types DOT IDENTIFIER GENERATE_COMPLETION", +//t "invocation_expression : primary_expression open_parens_any opt_argument_list close_parens", +//t "opt_object_or_collection_initializer :", +//t "opt_object_or_collection_initializer : object_or_collection_initializer", +//t "object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion", +//t "object_or_collection_initializer : OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE", +//t "opt_member_initializer_list :", +//t "opt_member_initializer_list : member_initializer_list", +//t "member_initializer_list : member_initializer", +//t "member_initializer_list : member_initializer_list COMMA member_initializer", +//t "member_initializer_list : member_initializer_list error", +//t "member_initializer : IDENTIFIER ASSIGN initializer_value", +//t "member_initializer : GENERATE_COMPLETION", +//t "member_initializer : non_assignment_expression opt_COMPLETE_COMPLETION", +//t "member_initializer : OPEN_BRACE expression_list CLOSE_BRACE", +//t "member_initializer : OPEN_BRACE CLOSE_BRACE", +//t "initializer_value : expression", +//t "initializer_value : object_or_collection_initializer", +//t "opt_argument_list :", +//t "opt_argument_list : argument_list", +//t "argument_list : argument_or_named_argument", +//t "argument_list : argument_list COMMA argument", +//t "argument_list : argument_list COMMA named_argument", +//t "argument_list : argument_list COMMA", +//t "argument_list : COMMA error", +//t "argument : expression", +//t "argument : non_simple_argument", +//t "argument_or_named_argument : argument", +//t "argument_or_named_argument : named_argument", +//t "non_simple_argument : REF variable_reference", +//t "non_simple_argument : OUT variable_reference", +//t "non_simple_argument : ARGLIST OPEN_PARENS argument_list CLOSE_PARENS", +//t "non_simple_argument : ARGLIST OPEN_PARENS CLOSE_PARENS", +//t "variable_reference : expression", +//t "element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET", +//t "expression_list : expression", +//t "expression_list : expression_list COMMA expression", +//t "expression_list : expression_list error", +//t "expression_list_arguments : expression_list_argument", +//t "expression_list_arguments : expression_list_arguments COMMA expression_list_argument", +//t "expression_list_argument : expression", +//t "expression_list_argument : named_argument", +//t "this_access : THIS", +//t "base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET", +//t "base_access : BASE OPEN_BRACKET error", +//t "post_increment_expression : primary_expression OP_INC", +//t "post_decrement_expression : primary_expression OP_DEC", +//t "object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer", +//t "object_or_delegate_creation_expression : NEW new_expr_type object_or_collection_initializer", +//t "array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer", +//t "array_creation_expression : NEW new_expr_type rank_specifiers opt_array_initializer", +//t "array_creation_expression : NEW rank_specifier array_initializer", +//t "array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET", +//t "array_creation_expression : NEW new_expr_type error", +//t "$$64 :", +//t "new_expr_type : $$64 simple_type", +//t "anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE", +//t "anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt", +//t "anonymous_type_parameters_opt_comma : anonymous_type_parameters COMMA", +//t "anonymous_type_parameters_opt :", +//t "anonymous_type_parameters_opt : anonymous_type_parameters", +//t "anonymous_type_parameters : anonymous_type_parameter", +//t "anonymous_type_parameters : anonymous_type_parameters COMMA anonymous_type_parameter", +//t "anonymous_type_parameter : IDENTIFIER ASSIGN variable_initializer", +//t "anonymous_type_parameter : IDENTIFIER", +//t "anonymous_type_parameter : member_access", +//t "anonymous_type_parameter : error", +//t "opt_rank_specifier :", +//t "opt_rank_specifier : rank_specifiers", +//t "rank_specifiers : rank_specifier", +//t "rank_specifiers : rank_specifier rank_specifiers", +//t "rank_specifier : OPEN_BRACKET CLOSE_BRACKET", +//t "rank_specifier : OPEN_BRACKET dim_separators CLOSE_BRACKET", +//t "dim_separators : COMMA", +//t "dim_separators : dim_separators COMMA", +//t "opt_array_initializer :", +//t "opt_array_initializer : array_initializer", +//t "array_initializer : OPEN_BRACE CLOSE_BRACE", +//t "array_initializer : OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE", +//t "variable_initializer_list : variable_initializer", +//t "variable_initializer_list : variable_initializer_list COMMA variable_initializer", +//t "$$65 :", +//t "typeof_expression : TYPEOF $$65 open_parens_any typeof_type_expression CLOSE_PARENS", +//t "typeof_type_expression : type_and_void", +//t "typeof_type_expression : unbound_type_name", +//t "typeof_type_expression : error", +//t "unbound_type_name : IDENTIFIER generic_dimension", +//t "unbound_type_name : qualified_alias_member IDENTIFIER generic_dimension", +//t "unbound_type_name : unbound_type_name DOT IDENTIFIER", +//t "unbound_type_name : unbound_type_name DOT IDENTIFIER generic_dimension", +//t "unbound_type_name : namespace_or_type_name DOT IDENTIFIER generic_dimension", +//t "generic_dimension : GENERIC_DIMENSION", +//t "qualified_alias_member : IDENTIFIER DOUBLE_COLON", +//t "sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS", +//t "checked_expression : CHECKED open_parens_any expression CLOSE_PARENS", +//t "unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS", +//t "pointer_member_access : primary_expression OP_PTR IDENTIFIER opt_type_argument_list", +//t "$$66 :", +//t "anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$66 block", +//t "$$67 :", +//t "anonymous_method_expression : ASYNC DELEGATE opt_anonymous_method_signature $$67 block", +//t "opt_anonymous_method_signature :", +//t "opt_anonymous_method_signature : anonymous_method_signature", +//t "$$68 :", +//t "anonymous_method_signature : OPEN_PARENS $$68 opt_formal_parameter_list CLOSE_PARENS", +//t "default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS", +//t "unary_expression : primary_expression", +//t "unary_expression : BANG prefixed_unary_expression", +//t "unary_expression : TILDE prefixed_unary_expression", +//t "unary_expression : cast_expression", +//t "unary_expression : await_expression", +//t "cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression", +//t "await_expression : AWAIT unary_expression", +//t "prefixed_unary_expression : unary_expression", +//t "prefixed_unary_expression : PLUS prefixed_unary_expression", +//t "prefixed_unary_expression : MINUS prefixed_unary_expression", +//t "prefixed_unary_expression : OP_INC prefixed_unary_expression", +//t "prefixed_unary_expression : OP_DEC prefixed_unary_expression", +//t "prefixed_unary_expression : STAR prefixed_unary_expression", +//t "prefixed_unary_expression : BITWISE_AND prefixed_unary_expression", +//t "multiplicative_expression : prefixed_unary_expression", +//t "multiplicative_expression : multiplicative_expression STAR prefixed_unary_expression", +//t "multiplicative_expression : multiplicative_expression DIV prefixed_unary_expression", +//t "multiplicative_expression : multiplicative_expression PERCENT prefixed_unary_expression", +//t "additive_expression : multiplicative_expression", +//t "additive_expression : additive_expression PLUS multiplicative_expression", +//t "additive_expression : additive_expression MINUS multiplicative_expression", +//t "additive_expression : parenthesized_expression MINUS multiplicative_expression", +//t "additive_expression : additive_expression AS type", +//t "additive_expression : additive_expression IS type", +//t "shift_expression : additive_expression", +//t "shift_expression : shift_expression OP_SHIFT_LEFT additive_expression", +//t "shift_expression : shift_expression OP_SHIFT_RIGHT additive_expression", +//t "relational_expression : shift_expression", +//t "relational_expression : relational_expression OP_LT shift_expression", +//t "relational_expression : relational_expression OP_GT shift_expression", +//t "relational_expression : relational_expression OP_LE shift_expression", +//t "relational_expression : relational_expression OP_GE shift_expression", +//t "equality_expression : relational_expression", +//t "equality_expression : equality_expression OP_EQ relational_expression", +//t "equality_expression : equality_expression OP_NE relational_expression", +//t "and_expression : equality_expression", +//t "and_expression : and_expression BITWISE_AND equality_expression", +//t "exclusive_or_expression : and_expression", +//t "exclusive_or_expression : exclusive_or_expression CARRET and_expression", +//t "inclusive_or_expression : exclusive_or_expression", +//t "inclusive_or_expression : inclusive_or_expression BITWISE_OR exclusive_or_expression", +//t "conditional_and_expression : inclusive_or_expression", +//t "conditional_and_expression : conditional_and_expression OP_AND inclusive_or_expression", +//t "conditional_or_expression : conditional_and_expression", +//t "conditional_or_expression : conditional_or_expression OP_OR conditional_and_expression", +//t "null_coalescing_expression : conditional_or_expression", +//t "null_coalescing_expression : conditional_or_expression OP_COALESCING null_coalescing_expression", +//t "conditional_expression : null_coalescing_expression", +//t "conditional_expression : null_coalescing_expression INTERR expression COLON expression", +//t "assignment_expression : prefixed_unary_expression ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_MULT_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_DIV_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_MOD_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_ADD_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_SUB_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_AND_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_OR_ASSIGN expression", +//t "assignment_expression : prefixed_unary_expression OP_XOR_ASSIGN expression", +//t "lambda_parameter_list : lambda_parameter", +//t "lambda_parameter_list : lambda_parameter_list COMMA lambda_parameter", +//t "lambda_parameter : parameter_modifier parameter_type IDENTIFIER", +//t "lambda_parameter : parameter_type IDENTIFIER", +//t "lambda_parameter : IDENTIFIER", +//t "opt_lambda_parameter_list :", +//t "opt_lambda_parameter_list : lambda_parameter_list", +//t "lambda_expression_body : lambda_expression_body_simple", +//t "lambda_expression_body : block", +//t "$$69 :", +//t "lambda_expression_body_simple : $$69 expression_or_error", +//t "expression_or_error : expression", +//t "expression_or_error : error", +//t "$$70 :", +//t "lambda_expression : IDENTIFIER ARROW $$70 lambda_expression_body", +//t "$$71 :", +//t "lambda_expression : ASYNC IDENTIFIER ARROW $$71 lambda_expression_body", +//t "$$72 :", +//t "$$73 :", +//t "lambda_expression : OPEN_PARENS_LAMBDA $$72 opt_lambda_parameter_list CLOSE_PARENS ARROW $$73 lambda_expression_body", +//t "$$74 :", +//t "$$75 :", +//t "lambda_expression : ASYNC OPEN_PARENS_LAMBDA $$74 opt_lambda_parameter_list CLOSE_PARENS ARROW $$75 lambda_expression_body", +//t "expression : assignment_expression", +//t "expression : non_assignment_expression", +//t "non_assignment_expression : conditional_expression", +//t "non_assignment_expression : lambda_expression", +//t "non_assignment_expression : query_expression", +//t "non_assignment_expression : ARGLIST", +//t "undocumented_expressions : REFVALUE OPEN_PARENS non_assignment_expression COMMA type CLOSE_PARENS", +//t "undocumented_expressions : REFTYPE open_parens_any expression CLOSE_PARENS", +//t "undocumented_expressions : MAKEREF open_parens_any expression CLOSE_PARENS", +//t "constant_expression : expression", +//t "boolean_expression : expression", +//t "$$76 :", +//t "$$77 :", +//t "$$78 :", +//t "$$79 :", +//t "class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$76 type_declaration_name $$77 opt_class_base opt_type_parameter_constraints_clauses $$78 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$79 opt_semicolon", +//t "opt_partial :", +//t "opt_partial : PARTIAL", +//t "opt_modifiers :", +//t "opt_modifiers : modifiers", +//t "modifiers : modifier", +//t "modifiers : modifiers modifier", +//t "modifier : NEW", +//t "modifier : PUBLIC", +//t "modifier : PROTECTED", +//t "modifier : INTERNAL", +//t "modifier : PRIVATE", +//t "modifier : ABSTRACT", +//t "modifier : SEALED", +//t "modifier : STATIC", +//t "modifier : READONLY", +//t "modifier : VIRTUAL", +//t "modifier : OVERRIDE", +//t "modifier : EXTERN", +//t "modifier : VOLATILE", +//t "modifier : UNSAFE", +//t "modifier : ASYNC", +//t "opt_class_base :", +//t "opt_class_base : COLON type_list", +//t "opt_type_parameter_constraints_clauses :", +//t "opt_type_parameter_constraints_clauses : type_parameter_constraints_clauses", +//t "opt_type_parameter_constraints_clauses : error", +//t "type_parameter_constraints_clauses : type_parameter_constraints_clause", +//t "type_parameter_constraints_clauses : type_parameter_constraints_clauses type_parameter_constraints_clause", +//t "type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints", +//t "type_parameter_constraints : type_parameter_constraint", +//t "type_parameter_constraints : type_parameter_constraints COMMA type_parameter_constraint", +//t "type_parameter_constraint : type", +//t "type_parameter_constraint : NEW OPEN_PARENS CLOSE_PARENS", +//t "type_parameter_constraint : CLASS", +//t "type_parameter_constraint : STRUCT", +//t "opt_type_parameter_variance :", +//t "opt_type_parameter_variance : type_parameter_variance", +//t "type_parameter_variance : OUT", +//t "type_parameter_variance : IN", +//t "$$80 :", +//t "block : OPEN_BRACE $$80 opt_statement_list block_end", +//t "block_end : CLOSE_BRACE", +//t "block_end : COMPLETE_COMPLETION", +//t "$$81 :", +//t "block_prepared : OPEN_BRACE $$81 opt_statement_list CLOSE_BRACE", +//t "opt_statement_list :", +//t "opt_statement_list : statement_list", +//t "statement_list : statement", +//t "statement_list : statement_list statement", +//t "statement : block_variable_declaration", +//t "statement : valid_declaration_statement", +//t "statement : labeled_statement", +//t "statement : error", +//t "interactive_statement_list : interactive_statement", +//t "interactive_statement_list : interactive_statement_list interactive_statement", +//t "interactive_statement : block_variable_declaration", +//t "interactive_statement : interactive_valid_declaration_statement", +//t "interactive_statement : labeled_statement", +//t "valid_declaration_statement : block", +//t "valid_declaration_statement : empty_statement", +//t "valid_declaration_statement : expression_statement", +//t "valid_declaration_statement : selection_statement", +//t "valid_declaration_statement : iteration_statement", +//t "valid_declaration_statement : jump_statement", +//t "valid_declaration_statement : try_statement", +//t "valid_declaration_statement : checked_statement", +//t "valid_declaration_statement : unchecked_statement", +//t "valid_declaration_statement : lock_statement", +//t "valid_declaration_statement : using_statement", +//t "valid_declaration_statement : unsafe_statement", +//t "valid_declaration_statement : fixed_statement", +//t "interactive_valid_declaration_statement : block", +//t "interactive_valid_declaration_statement : empty_statement", +//t "interactive_valid_declaration_statement : interactive_expression_statement", +//t "interactive_valid_declaration_statement : selection_statement", +//t "interactive_valid_declaration_statement : iteration_statement", +//t "interactive_valid_declaration_statement : jump_statement", +//t "interactive_valid_declaration_statement : try_statement", +//t "interactive_valid_declaration_statement : checked_statement", +//t "interactive_valid_declaration_statement : unchecked_statement", +//t "interactive_valid_declaration_statement : lock_statement", +//t "interactive_valid_declaration_statement : using_statement", +//t "interactive_valid_declaration_statement : unsafe_statement", +//t "interactive_valid_declaration_statement : fixed_statement", +//t "embedded_statement : valid_declaration_statement", +//t "embedded_statement : block_variable_declaration", +//t "embedded_statement : labeled_statement", +//t "embedded_statement : error", +//t "empty_statement : SEMICOLON", +//t "$$82 :", +//t "labeled_statement : IDENTIFIER COLON $$82 statement", +//t "variable_type : variable_type_simple", +//t "variable_type : variable_type_simple rank_specifiers", +//t "variable_type_simple : primary_expression_or_type opt_nullable", +//t "variable_type_simple : primary_expression_or_type pointer_stars", +//t "variable_type_simple : builtin_types opt_nullable", +//t "variable_type_simple : builtin_types pointer_stars", +//t "variable_type_simple : VOID pointer_stars", +//t "variable_type_simple : VOID", +//t "pointer_stars : pointer_star", +//t "pointer_stars : pointer_star pointer_stars", +//t "pointer_star : STAR", +//t "$$83 :", +//t "block_variable_declaration : variable_type IDENTIFIER $$83 opt_local_variable_initializer opt_variable_declarators SEMICOLON", +//t "$$84 :", +//t "block_variable_declaration : CONST variable_type IDENTIFIER $$84 const_variable_initializer opt_const_declarators SEMICOLON", +//t "opt_local_variable_initializer :", +//t "opt_local_variable_initializer : ASSIGN block_variable_initializer", +//t "opt_local_variable_initializer : error", +//t "opt_variable_declarators :", +//t "opt_variable_declarators : variable_declarators", +//t "variable_declarators : variable_declarator", +//t "variable_declarators : variable_declarators variable_declarator", +//t "variable_declarator : COMMA IDENTIFIER", +//t "variable_declarator : COMMA IDENTIFIER ASSIGN block_variable_initializer", +//t "const_variable_initializer :", +//t "const_variable_initializer : ASSIGN constant_initializer_expr", +//t "opt_const_declarators :", +//t "opt_const_declarators : const_declarators", +//t "const_declarators : const_declarator", +//t "const_declarators : const_declarators const_declarator", +//t "const_declarator : COMMA IDENTIFIER ASSIGN constant_initializer_expr", +//t "block_variable_initializer : variable_initializer", +//t "block_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET", +//t "block_variable_initializer : STACKALLOC simple_type", +//t "expression_statement : statement_expression SEMICOLON", +//t "expression_statement : statement_expression COMPLETE_COMPLETION", +//t "interactive_expression_statement : interactive_statement_expression SEMICOLON", +//t "interactive_expression_statement : interactive_statement_expression COMPLETE_COMPLETION", +//t "statement_expression : expression", +//t "interactive_statement_expression : expression", +//t "interactive_statement_expression : error", +//t "selection_statement : if_statement", +//t "selection_statement : switch_statement", +//t "if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement", +//t "if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement", +//t "$$85 :", +//t "switch_statement : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE $$85 opt_switch_sections CLOSE_BRACE", +//t "opt_switch_sections :", +//t "opt_switch_sections : switch_sections", +//t "switch_sections : switch_section", +//t "switch_sections : switch_sections switch_section", +//t "switch_sections : error", +//t "$$86 :", +//t "switch_section : switch_labels $$86 statement_list", +//t "switch_labels : switch_label", +//t "switch_labels : switch_labels switch_label", +//t "switch_label : CASE constant_expression COLON", +//t "switch_label : DEFAULT_COLON", +//t "iteration_statement : while_statement", +//t "iteration_statement : do_statement", +//t "iteration_statement : for_statement", +//t "iteration_statement : foreach_statement", +//t "while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement", +//t "do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON", +//t "$$87 :", +//t "for_statement : FOR open_parens_any $$87 for_statement_cont", +//t "for_statement_cont : opt_for_initializer SEMICOLON opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement", +//t "for_statement_cont : error", +//t "opt_for_initializer :", +//t "opt_for_initializer : for_initializer", +//t "$$88 :", +//t "for_initializer : variable_type IDENTIFIER $$88 opt_local_variable_initializer opt_variable_declarators", +//t "for_initializer : statement_expression_list", +//t "opt_for_condition :", +//t "opt_for_condition : boolean_expression", +//t "opt_for_iterator :", +//t "opt_for_iterator : for_iterator", +//t "for_iterator : statement_expression_list", +//t "statement_expression_list : statement_expression", +//t "statement_expression_list : statement_expression_list COMMA statement_expression", +//t "foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS", +//t "$$89 :", +//t "foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$89 embedded_statement", +//t "jump_statement : break_statement", +//t "jump_statement : continue_statement", +//t "jump_statement : goto_statement", +//t "jump_statement : return_statement", +//t "jump_statement : throw_statement", +//t "jump_statement : yield_statement", +//t "break_statement : BREAK SEMICOLON", +//t "continue_statement : CONTINUE SEMICOLON", +//t "goto_statement : GOTO IDENTIFIER SEMICOLON", +//t "goto_statement : GOTO CASE constant_expression SEMICOLON", +//t "goto_statement : GOTO DEFAULT SEMICOLON", +//t "return_statement : RETURN opt_expression SEMICOLON", +//t "throw_statement : THROW opt_expression SEMICOLON", +//t "yield_statement : IDENTIFIER RETURN opt_expression SEMICOLON", +//t "yield_statement : IDENTIFIER BREAK SEMICOLON", +//t "opt_expression :", +//t "opt_expression : expression", +//t "try_statement : TRY block catch_clauses", +//t "try_statement : TRY block FINALLY block", +//t "try_statement : TRY block catch_clauses FINALLY block", +//t "try_statement : TRY block error", +//t "catch_clauses : catch_clause", +//t "catch_clauses : catch_clauses catch_clause", +//t "opt_identifier :", +//t "opt_identifier : IDENTIFIER", +//t "catch_clause : CATCH block", +//t "$$90 :", +//t "catch_clause : CATCH open_parens_any type opt_identifier CLOSE_PARENS $$90 block_prepared", +//t "catch_clause : CATCH open_parens_any error", +//t "checked_statement : CHECKED block", +//t "unchecked_statement : UNCHECKED block", +//t "$$91 :", +//t "unsafe_statement : UNSAFE $$91 block", +//t "lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement", +//t "$$92 :", +//t "$$93 :", +//t "fixed_statement : FIXED open_parens_any variable_type IDENTIFIER $$92 using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS $$93 embedded_statement", +//t "$$94 :", +//t "$$95 :", +//t "using_statement : USING open_parens_any variable_type IDENTIFIER $$94 using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS $$95 embedded_statement", +//t "using_statement : USING open_parens_any expression CLOSE_PARENS embedded_statement", +//t "using_or_fixed_variable_initializer :", +//t "using_or_fixed_variable_initializer : ASSIGN variable_initializer", +//t "query_expression : first_from_clause query_body", +//t "query_expression : nested_from_clause query_body", +//t "query_expression : first_from_clause COMPLETE_COMPLETION", +//t "query_expression : nested_from_clause COMPLETE_COMPLETION", +//t "first_from_clause : FROM_FIRST IDENTIFIER IN expression", +//t "first_from_clause : FROM_FIRST type IDENTIFIER IN expression", +//t "nested_from_clause : FROM IDENTIFIER IN expression", +//t "nested_from_clause : FROM type IDENTIFIER IN expression", +//t "$$96 :", +//t "from_clause : FROM IDENTIFIER IN $$96 expression", +//t "$$97 :", +//t "from_clause : FROM type IDENTIFIER IN $$97 expression", +//t "query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation", +//t "query_body : opt_query_body_clauses COMPLETE_COMPLETION", +//t "query_body : error", +//t "$$98 :", +//t "select_or_group_clause : SELECT $$98 expression", +//t "$$99 :", +//t "$$100 :", +//t "select_or_group_clause : GROUP $$99 expression $$100 BY expression", +//t "opt_query_body_clauses :", +//t "opt_query_body_clauses : query_body_clauses", +//t "query_body_clauses : query_body_clause", +//t "query_body_clauses : query_body_clauses query_body_clause", +//t "query_body_clause : from_clause", +//t "query_body_clause : let_clause", +//t "query_body_clause : where_clause", +//t "query_body_clause : join_clause", +//t "query_body_clause : orderby_clause", +//t "$$101 :", +//t "let_clause : LET IDENTIFIER ASSIGN $$101 expression", +//t "$$102 :", +//t "where_clause : WHERE $$102 expression", +//t "$$103 :", +//t "$$104 :", +//t "$$105 :", +//t "join_clause : JOIN IDENTIFIER IN $$103 expression ON $$104 expression EQUALS $$105 expression opt_join_into", +//t "$$106 :", +//t "$$107 :", +//t "$$108 :", +//t "join_clause : JOIN type IDENTIFIER IN $$106 expression ON $$107 expression EQUALS $$108 expression opt_join_into", +//t "opt_join_into :", +//t "opt_join_into : INTO IDENTIFIER", +//t "$$109 :", +//t "orderby_clause : ORDERBY $$109 orderings", +//t "orderings : order_by", +//t "$$110 :", +//t "orderings : order_by COMMA $$110 orderings_then_by", +//t "orderings_then_by : then_by", +//t "$$111 :", +//t "orderings_then_by : orderings_then_by COMMA $$111 then_by", +//t "order_by : expression", +//t "order_by : expression ASCENDING", +//t "order_by : expression DESCENDING", +//t "then_by : expression", +//t "then_by : expression ASCENDING", +//t "then_by : expression DESCENDING", +//t "opt_query_continuation :", +//t "$$112 :", +//t "opt_query_continuation : INTO IDENTIFIER $$112 query_body", +//t "interactive_parsing : EVAL_STATEMENT_PARSER EOF", +//t "interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION", +//t "$$113 :", +//t "interactive_parsing : EVAL_STATEMENT_PARSER $$113 interactive_statement_list opt_COMPLETE_COMPLETION", +//t "interactive_parsing : EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit", +//t "interactive_compilation_unit : opt_extern_alias_directives opt_using_directives", +//t "interactive_compilation_unit : opt_extern_alias_directives opt_using_directives namespace_or_type_declarations", +//t "opt_COMPLETE_COMPLETION :", +//t "opt_COMPLETE_COMPLETION : COMPLETE_COMPLETION", +//t "close_brace_or_complete_completion : CLOSE_BRACE", +//t "close_brace_or_complete_completion : COMPLETE_COMPLETION", +//t "documentation_parsing : DOC_SEE doc_cref", +//t "doc_cref : doc_type_declaration_name opt_doc_method_sig", +//t "doc_cref : builtin_types opt_doc_method_sig", +//t "doc_cref : builtin_types DOT IDENTIFIER opt_doc_method_sig", +//t "doc_cref : doc_type_declaration_name DOT THIS", +//t "$$114 :", +//t "doc_cref : doc_type_declaration_name DOT THIS OPEN_BRACKET $$114 opt_doc_parameters CLOSE_BRACKET", +//t "doc_cref : EXPLICIT OPERATOR type opt_doc_method_sig", +//t "doc_cref : IMPLICIT OPERATOR type opt_doc_method_sig", +//t "doc_cref : OPERATOR overloadable_operator opt_doc_method_sig", +//t "doc_type_declaration_name : type_declaration_name", +//t "doc_type_declaration_name : doc_type_declaration_name DOT type_declaration_name", +//t "opt_doc_method_sig :", +//t "$$115 :", +//t "opt_doc_method_sig : OPEN_PARENS $$115 opt_doc_parameters CLOSE_PARENS", +//t "opt_doc_parameters :", +//t "opt_doc_parameters : doc_parameters", +//t "doc_parameters : doc_parameter", +//t "doc_parameters : doc_parameters COMMA doc_parameter", +//t "doc_parameter : opt_parameter_modifier parameter_type", +//t }; +//t public static string getRule (int index) { +//t return yyRule [index]; +//t } +//t} + protected static readonly string [] yyNames = { + "end-of-file",null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,null,null,null,null,null,null,null, + null,null,null,null,null,null,null,"EOF","NONE","ERROR", + "FIRST_KEYWORD","ABSTRACT","AS","ADD","BASE","BOOL","BREAK","BYTE", + "CASE","CATCH","CHAR","CHECKED","CLASS","CONST","CONTINUE","DECIMAL", + "DEFAULT","DELEGATE","DO","DOUBLE","ELSE","ENUM","EVENT","EXPLICIT", + "EXTERN","FALSE","FINALLY","FIXED","FLOAT","FOR","FOREACH","GOTO", + "IF","IMPLICIT","IN","INT","INTERFACE","INTERNAL","IS","LOCK","LONG", + "NAMESPACE","NEW","NULL","OBJECT","OPERATOR","OUT","OVERRIDE", + "PARAMS","PRIVATE","PROTECTED","PUBLIC","READONLY","REF","RETURN", + "REMOVE","SBYTE","SEALED","SHORT","SIZEOF","STACKALLOC","STATIC", + "STRING","STRUCT","SWITCH","THIS","THROW","TRUE","TRY","TYPEOF", + "UINT","ULONG","UNCHECKED","UNSAFE","USHORT","USING","VIRTUAL","VOID", + "VOLATILE","WHERE","WHILE","ARGLIST","PARTIAL","ARROW","FROM", + "FROM_FIRST","JOIN","ON","EQUALS","SELECT","GROUP","BY","LET", + "ORDERBY","ASCENDING","DESCENDING","INTO","INTERR_NULLABLE", + "EXTERN_ALIAS","REFVALUE","REFTYPE","MAKEREF","ASYNC","AWAIT","GET", + "SET","LAST_KEYWORD","OPEN_BRACE","CLOSE_BRACE","OPEN_BRACKET", + "CLOSE_BRACKET","OPEN_PARENS","CLOSE_PARENS","DOT","COMMA","COLON", + "SEMICOLON","TILDE","PLUS","MINUS","BANG","ASSIGN","OP_LT","OP_GT", + "BITWISE_AND","BITWISE_OR","STAR","PERCENT","DIV","CARRET","INTERR", + "DOUBLE_COLON","OP_INC","OP_DEC","OP_SHIFT_LEFT","OP_SHIFT_RIGHT", + "OP_LE","OP_GE","OP_EQ","OP_NE","OP_AND","OP_OR","OP_MULT_ASSIGN", + "OP_DIV_ASSIGN","OP_MOD_ASSIGN","OP_ADD_ASSIGN","OP_SUB_ASSIGN", + "OP_SHIFT_LEFT_ASSIGN","OP_SHIFT_RIGHT_ASSIGN","OP_AND_ASSIGN", + "OP_XOR_ASSIGN","OP_OR_ASSIGN","OP_PTR","OP_COALESCING", + "OP_GENERICS_LT","OP_GENERICS_LT_DECL","OP_GENERICS_GT","LITERAL", + "IDENTIFIER","OPEN_PARENS_LAMBDA","OPEN_PARENS_CAST", + "GENERIC_DIMENSION","DEFAULT_COLON","OPEN_BRACKET_EXPR", + "EVAL_STATEMENT_PARSER","EVAL_COMPILATION_UNIT_PARSER", + "EVAL_USING_DECLARATIONS_UNIT_PARSER","DOC_SEE","GENERATE_COMPLETION", + "COMPLETE_COMPLETION","UMINUS", + }; + + /** index-checked interface to yyNames[]. + @param token single character or %token value. + @return token name or [illegal] or [unknown]. + */ +//t public static string yyname (int token) { +//t if ((token < 0) || (token > yyNames.Length)) return "[illegal]"; +//t string name; +//t if ((name = yyNames[token]) != null) return name; +//t return "[unknown]"; +//t } + + int yyExpectingState; + /** computes list of expected tokens on error by tracing the tables. + @param state for which to compute the list. + @return list of token names. + */ + protected int [] yyExpectingTokens (int state){ + int token, n, len = 0; + bool[] ok = new bool[yyNames.Length]; + if ((n = yySindex[state]) != 0) + for (token = n < 0 ? -n : 0; + (token < yyNames.Length) && (n+token < yyTable.Length); ++ token) + if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) { + ++ len; + ok[token] = true; + } + if ((n = yyRindex[state]) != 0) + for (token = n < 0 ? -n : 0; + (token < yyNames.Length) && (n+token < yyTable.Length); ++ token) + if (yyCheck[n+token] == token && !ok[token] && yyNames[token] != null) { + ++ len; + ok[token] = true; + } + int [] result = new int [len]; + for (n = token = 0; n < len; ++ token) + if (ok[token]) result[n++] = token; + return result; + } + protected string[] yyExpecting (int state) { + int [] tokens = yyExpectingTokens (state); + string [] result = new string[tokens.Length]; + for (int n = 0; n < tokens.Length; n++) + result[n++] = yyNames[tokens [n]]; + return result; + } + + /** the generated parser, with debugging messages. + Maintains a state and a value stack, currently with fixed maximum size. + @param yyLex scanner. + @param yydebug debug message writer implementing yyDebug, or null. + @return result of the last reduction, if any. + @throws yyException on irrecoverable parse error. + */ + internal Object yyparse (yyParser.yyInput yyLex, Object yyd) + { +//t this.debug = (yydebug.yyDebug)yyd; + return yyparse(yyLex); + } + + /** initial size and increment of the state/value stack [default 256]. + This is not final so that it can be overwritten outside of invocations + of yyparse(). + */ + protected int yyMax; + + /** executed at the beginning of a reduce action. + Used as $$ = yyDefault($1), prior to the user-specified action, if any. + Can be overwritten to provide deep copy, etc. + @param first value for $1, or null. + @return first. + */ + protected Object yyDefault (Object first) { + return first; + } + + static int[] global_yyStates; + static object[] global_yyVals; + protected bool use_global_stacks; + object[] yyVals; // value stack + object yyVal; // value stack ptr + int yyToken; // current input + int yyTop; + + /** the generated parser. + Maintains a state and a value stack, currently with fixed maximum size. + @param yyLex scanner. + @return result of the last reduction, if any. + @throws yyException on irrecoverable parse error. + */ + internal Object yyparse (yyParser.yyInput yyLex) + { + if (yyMax <= 0) yyMax = 256; // initial size + int yyState = 0; // state stack ptr + int [] yyStates; // state stack + yyVal = null; + yyToken = -1; + int yyErrorFlag = 0; // #tks to shift + if (use_global_stacks && global_yyStates != null) { + yyVals = global_yyVals; + yyStates = global_yyStates; + } else { + yyVals = new object [yyMax]; + yyStates = new int [yyMax]; + if (use_global_stacks) { + global_yyVals = yyVals; + global_yyStates = yyStates; + } + } + + /*yyLoop:*/ for (yyTop = 0;; ++ yyTop) { + if (yyTop >= yyStates.Length) { // dynamically increase + global::System.Array.Resize (ref yyStates, yyStates.Length+yyMax); + global::System.Array.Resize (ref yyVals, yyVals.Length+yyMax); + } + yyStates[yyTop] = yyState; + yyVals[yyTop] = yyVal; +//t if (debug != null) debug.push(yyState, yyVal); + + /*yyDiscarded:*/ while (true) { // discarding a token does not change stack + int yyN; + if ((yyN = yyDefRed[yyState]) == 0) { // else [default] reduce (yyN) + if (yyToken < 0) { + yyToken = yyLex.advance() ? yyLex.token() : 0; +//t if (debug != null) +//t debug.lex(yyState, yyToken, yyname(yyToken), yyLex.value()); + } + if ((yyN = yySindex[yyState]) != 0 && ((yyN += yyToken) >= 0) + && (yyN < yyTable.Length) && (yyCheck[yyN] == yyToken)) { +//t if (debug != null) +//t debug.shift(yyState, yyTable[yyN], yyErrorFlag-1); + yyState = yyTable[yyN]; // shift to yyN + yyVal = yyLex.value(); + yyToken = -1; + if (yyErrorFlag > 0) -- yyErrorFlag; + goto continue_yyLoop; + } + if ((yyN = yyRindex[yyState]) != 0 && (yyN += yyToken) >= 0 + && yyN < yyTable.Length && yyCheck[yyN] == yyToken) + yyN = yyTable[yyN]; // reduce (yyN) + else + switch (yyErrorFlag) { + + case 0: + yyExpectingState = yyState; + // yyerror(String.Format ("syntax error, got token `{0}'", yyname (yyToken)), yyExpecting(yyState)); +//t if (debug != null) debug.error("syntax error"); + if (yyToken == 0 /*eof*/ || yyToken == eof_token) throw new yyParser.yyUnexpectedEof (); + goto case 1; + case 1: case 2: + yyErrorFlag = 3; + do { + if ((yyN = yySindex[yyStates[yyTop]]) != 0 + && (yyN += Token.yyErrorCode) >= 0 && yyN < yyTable.Length + && yyCheck[yyN] == Token.yyErrorCode) { +//t if (debug != null) +//t debug.shift(yyStates[yyTop], yyTable[yyN], 3); + yyState = yyTable[yyN]; + yyVal = yyLex.value(); + goto continue_yyLoop; + } +//t if (debug != null) debug.pop(yyStates[yyTop]); + } while (-- yyTop >= 0); +//t if (debug != null) debug.reject(); + throw new yyParser.yyException("irrecoverable syntax error"); + + case 3: + if (yyToken == 0) { +//t if (debug != null) debug.reject(); + throw new yyParser.yyException("irrecoverable syntax error at end-of-file"); + } +//t if (debug != null) +//t debug.discard(yyState, yyToken, yyname(yyToken), +//t yyLex.value()); + yyToken = -1; + goto continue_yyDiscarded; // leave stack alone + } + } + int yyV = yyTop + 1-yyLen[yyN]; +//t if (debug != null) +//t debug.reduce(yyState, yyStates[yyV-1], yyN, YYRules.getRule (yyN), yyLen[yyN]); + yyVal = yyV > yyTop ? null : yyVals[yyV]; // yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]); + switch (yyN) { +case 1: +#line 395 "cs-parser.jay" + { + Lexer.check_incorrect_doc_comment (); + } + break; +case 2: +#line 396 "cs-parser.jay" + { Lexer.CompleteOnEOF = false; } + break; +case 6: + case_6(); + break; +case 7: +#line 413 "cs-parser.jay" + { + module.AddAttributes ((Attributes) yyVals[0+yyTop], current_namespace); + } + break; +case 8: + case_8(); + break; +case 13: + case_13(); + break; +case 14: +#line 451 "cs-parser.jay" + { + syntax_error (GetLocation (yyVals[-1+yyTop]), "`alias' expected"); /* TODO: better*/ + } + break; +case 17: + case_17(); + break; +case 18: + case_18(); + break; +case 19: + case_19(); + break; +case 20: + case_20(); + break; +case 21: + case_21(); + break; +case 22: + case_22(); + break; +case 23: + case_23(); + break; +case 24: + case_24(); + break; +case 25: + case_25(); + break; +case 26: + case_26(); + break; +case 27: + case_27(); + break; +case 32: + case_32(); + break; +case 41: + case_41(); + break; +case 42: +#line 640 "cs-parser.jay" + { + current_namespace.DeclarationFound = true; + } + break; +case 50: + case_50(); + break; +case 51: + case_51(); + break; +case 52: + case_52(); + break; +case 53: + case_53(); + break; +case 54: + case_54(); + break; +case 55: + case_55(); + break; +case 56: + case_56(); + break; +case 57: + case_57(); + break; +case 58: +#line 733 "cs-parser.jay" + { yyVal = "event"; } + break; +case 59: +#line 734 "cs-parser.jay" + { yyVal = "return"; } + break; +case 60: + case_60(); + break; +case 61: +#line 751 "cs-parser.jay" + { + yyVal = new List (4) { (Attribute) yyVals[0+yyTop] }; + } + break; +case 62: + case_62(); + break; +case 63: +#line 765 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 64: + case_64(); + break; +case 66: +#line 789 "cs-parser.jay" + { yyVal = null; } + break; +case 67: + case_67(); + break; +case 68: +#line 800 "cs-parser.jay" + { yyVal = null; } + break; +case 69: + case_69(); + break; +case 70: + case_70(); + break; +case 71: + case_71(); + break; +case 72: + case_72(); + break; +case 73: +#line 844 "cs-parser.jay" + { + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 75: +#line 852 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 76: + case_76(); + break; +case 77: + case_77(); + break; +case 78: +#line 877 "cs-parser.jay" + { yyVal = null; } + break; +case 79: +#line 881 "cs-parser.jay" + { + yyVal = Argument.AType.Ref; + } + break; +case 80: +#line 885 "cs-parser.jay" + { + yyVal = Argument.AType.Out; + } + break; +case 95: + case_95(); + break; +case 96: +#line 926 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 97: + case_97(); + break; +case 98: + case_98(); + break; +case 99: + case_99(); + break; +case 100: + case_100(); + break; +case 101: +#line 958 "cs-parser.jay" + { + Error_SyntaxError (yyToken); + } + break; +case 102: + case_102(); + break; +case 103: +#line 970 "cs-parser.jay" + { + lbag.AppendToMember (current_class, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + break; +case 118: + case_118(); + break; +case 119: + case_119(); + break; +case 122: +#line 1039 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 123: +#line 1043 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 124: + case_124(); + break; +case 125: +#line 1059 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 126: + case_126(); + break; +case 127: + case_127(); + break; +case 130: + case_130(); + break; +case 131: + case_131(); + break; +case 132: + case_132(); + break; +case 133: + case_133(); + break; +case 134: +#line 1138 "cs-parser.jay" + { + report.Error (1641, GetLocation (yyVals[-1+yyTop]), "A fixed size buffer field must have the array size specifier after the field name"); + } + break; +case 136: + case_136(); + break; +case 137: + case_137(); + break; +case 140: +#line 1168 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 141: +#line 1172 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 142: + case_142(); + break; +case 143: +#line 1185 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 144: + case_144(); + break; +case 147: +#line 1204 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 148: +#line 1208 "cs-parser.jay" + { + current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 149: + case_149(); + break; +case 150: +#line 1224 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 151: + case_151(); + break; +case 152: + case_152(); + break; +case 155: + case_155(); + break; +case 156: + case_156(); + break; +case 157: + case_157(); + break; +case 158: +#line 1291 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.All; + } + break; +case 159: +#line 1295 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 160: + case_160(); + break; +case 161: +#line 1335 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 162: + case_162(); + break; +case 163: +#line 1345 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 164: + case_164(); + break; +case 165: + case_165(); + break; +case 167: +#line 1419 "cs-parser.jay" + { yyVal = null; } + break; +case 168: +#line 1423 "cs-parser.jay" + { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } + break; +case 170: + case_170(); + break; +case 171: + case_171(); + break; +case 172: + case_172(); + break; +case 173: + case_173(); + break; +case 174: + case_174(); + break; +case 175: + case_175(); + break; +case 176: + case_176(); + break; +case 177: +#line 1482 "cs-parser.jay" + { + yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[0+yyTop] } ); + } + break; +case 178: +#line 1486 "cs-parser.jay" + { + yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[0+yyTop])) }, true); + } + break; +case 179: + case_179(); + break; +case 180: + case_180(); + break; +case 181: + case_181(); + break; +case 182: + case_182(); + break; +case 183: + case_183(); + break; +case 184: + case_184(); + break; +case 185: +#line 1561 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 186: + case_186(); + break; +case 187: +#line 1602 "cs-parser.jay" + { yyVal = Parameter.Modifier.NONE; } + break; +case 189: + case_189(); + break; +case 190: + case_190(); + break; +case 191: + case_191(); + break; +case 192: + case_192(); + break; +case 193: + case_193(); + break; +case 194: + case_194(); + break; +case 195: + case_195(); + break; +case 196: + case_196(); + break; +case 197: + case_197(); + break; +case 198: + case_198(); + break; +case 199: +#line 1700 "cs-parser.jay" + { + Error_DuplicateParameterModifier (GetLocation (yyVals[-1+yyTop]), Parameter.Modifier.PARAMS); + } + break; +case 200: + case_200(); + break; +case 201: + case_201(); + break; +case 202: + case_202(); + break; +case 203: + case_203(); + break; +case 204: + case_204(); + break; +case 205: +#line 1754 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + break; +case 206: + case_206(); + break; +case 207: +#line 1783 "cs-parser.jay" + { + lexer.PropertyParsing = false; + } + break; +case 208: + case_208(); + break; +case 213: + case_213(); + break; +case 214: + case_214(); + break; +case 215: + case_215(); + break; +case 216: + case_216(); + break; +case 217: + case_217(); + break; +case 219: + case_219(); + break; +case 220: + case_220(); + break; +case 221: +#line 1928 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 222: + case_222(); + break; +case 223: + case_223(); + break; +case 224: + case_224(); + break; +case 225: + case_225(); + break; +case 226: +#line 1961 "cs-parser.jay" + { + Error_SyntaxError (yyToken); + } + break; +case 231: +#line 1978 "cs-parser.jay" + { + report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); + } + break; +case 232: +#line 1982 "cs-parser.jay" + { + report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); + } + break; +case 237: +#line 1990 "cs-parser.jay" + { + report.Error (567, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain operators"); + } + break; +case 238: +#line 1994 "cs-parser.jay" + { + report.Error (526, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain contructors"); + } + break; +case 239: +#line 1998 "cs-parser.jay" + { + report.Error (524, GetLocation (yyVals[0+yyTop]), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); + } + break; +case 240: +#line 2004 "cs-parser.jay" + { + } + break; +case 241: + case_241(); + break; +case 243: +#line 2034 "cs-parser.jay" + { yyVal = null; } + break; +case 245: + case_245(); + break; +case 246: +#line 2050 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + break; +case 247: + case_247(); + break; +case 249: +#line 2096 "cs-parser.jay" + { yyVal = Operator.OpType.LogicalNot; } + break; +case 250: +#line 2097 "cs-parser.jay" + { yyVal = Operator.OpType.OnesComplement; } + break; +case 251: +#line 2098 "cs-parser.jay" + { yyVal = Operator.OpType.Increment; } + break; +case 252: +#line 2099 "cs-parser.jay" + { yyVal = Operator.OpType.Decrement; } + break; +case 253: +#line 2100 "cs-parser.jay" + { yyVal = Operator.OpType.True; } + break; +case 254: +#line 2101 "cs-parser.jay" + { yyVal = Operator.OpType.False; } + break; +case 255: +#line 2103 "cs-parser.jay" + { yyVal = Operator.OpType.Addition; } + break; +case 256: +#line 2104 "cs-parser.jay" + { yyVal = Operator.OpType.Subtraction; } + break; +case 257: +#line 2106 "cs-parser.jay" + { yyVal = Operator.OpType.Multiply; } + break; +case 258: +#line 2107 "cs-parser.jay" + { yyVal = Operator.OpType.Division; } + break; +case 259: +#line 2108 "cs-parser.jay" + { yyVal = Operator.OpType.Modulus; } + break; +case 260: +#line 2109 "cs-parser.jay" + { yyVal = Operator.OpType.BitwiseAnd; } + break; +case 261: +#line 2110 "cs-parser.jay" + { yyVal = Operator.OpType.BitwiseOr; } + break; +case 262: +#line 2111 "cs-parser.jay" + { yyVal = Operator.OpType.ExclusiveOr; } + break; +case 263: +#line 2112 "cs-parser.jay" + { yyVal = Operator.OpType.LeftShift; } + break; +case 264: +#line 2113 "cs-parser.jay" + { yyVal = Operator.OpType.RightShift; } + break; +case 265: +#line 2114 "cs-parser.jay" + { yyVal = Operator.OpType.Equality; } + break; +case 266: +#line 2115 "cs-parser.jay" + { yyVal = Operator.OpType.Inequality; } + break; +case 267: +#line 2116 "cs-parser.jay" + { yyVal = Operator.OpType.GreaterThan; } + break; +case 268: +#line 2117 "cs-parser.jay" + { yyVal = Operator.OpType.LessThan; } + break; +case 269: +#line 2118 "cs-parser.jay" + { yyVal = Operator.OpType.GreaterThanOrEqual; } + break; +case 270: +#line 2119 "cs-parser.jay" + { yyVal = Operator.OpType.LessThanOrEqual; } + break; +case 271: +#line 2126 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + break; +case 272: + case_272(); + break; +case 273: +#line 2145 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + break; +case 274: + case_274(); + break; +case 275: + case_275(); + break; +case 276: + case_276(); + break; +case 277: + case_277(); + break; +case 278: + case_278(); + break; +case 279: + case_279(); + break; +case 280: + case_280(); + break; +case 282: +#line 2248 "cs-parser.jay" + { current_block = null; yyVal = null; } + break; +case 285: +#line 2260 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 286: + case_286(); + break; +case 287: +#line 2270 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 288: + case_288(); + break; +case 289: + case_289(); + break; +case 290: + case_290(); + break; +case 291: + case_291(); + break; +case 292: + case_292(); + break; +case 293: + case_293(); + break; +case 294: + case_294(); + break; +case 295: + case_295(); + break; +case 296: + case_296(); + break; +case 298: +#line 2379 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 299: + case_299(); + break; +case 302: +#line 2396 "cs-parser.jay" + { + current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 303: +#line 2400 "cs-parser.jay" + { + current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } + break; +case 304: + case_304(); + break; +case 305: +#line 2413 "cs-parser.jay" + { + ++lexer.parsing_block; + } + break; +case 306: + case_306(); + break; +case 307: + case_307(); + break; +case 308: +#line 2438 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 311: + case_311(); + break; +case 312: + case_312(); + break; +case 313: + case_313(); + break; +case 314: + case_314(); + break; +case 315: + case_315(); + break; +case 316: + case_316(); + break; +case 317: + case_317(); + break; +case 318: + case_318(); + break; +case 320: + case_320(); + break; +case 321: + case_321(); + break; +case 322: + case_322(); + break; +case 323: + case_323(); + break; +case 325: + case_325(); + break; +case 326: + case_326(); + break; +case 329: +#line 2593 "cs-parser.jay" + { + lbag.AddLocation (yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 331: + case_331(); + break; +case 332: + case_332(); + break; +case 333: + case_333(); + break; +case 334: + case_334(); + break; +case 335: +#line 2651 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + break; +case 336: + case_336(); + break; +case 337: +#line 2673 "cs-parser.jay" + { + lexer.ConstraintsParsing = false; + } + break; +case 338: + case_338(); + break; +case 340: + case_340(); + break; +case 342: + case_342(); + break; +case 344: + case_344(); + break; +case 345: + case_345(); + break; +case 347: + case_347(); + break; +case 348: + case_348(); + break; +case 349: + case_349(); + break; +case 350: + case_350(); + break; +case 351: +#line 2777 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 352: + case_352(); + break; +case 353: + case_353(); + break; +case 355: + case_355(); + break; +case 356: + case_356(); + break; +case 357: + case_357(); + break; +case 358: + case_358(); + break; +case 359: + case_359(); + break; +case 360: + case_360(); + break; +case 362: + case_362(); + break; +case 363: + case_363(); + break; +case 364: + case_364(); + break; +case 365: + case_365(); + break; +case 366: + case_366(); + break; +case 368: +#line 2895 "cs-parser.jay" + { + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + break; +case 369: +#line 2902 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 371: + case_371(); + break; +case 373: + case_373(); + break; +case 375: + case_375(); + break; +case 377: +#line 2940 "cs-parser.jay" + { + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 378: + case_378(); + break; +case 379: +#line 2960 "cs-parser.jay" + { + yyVal = new ComposedCast (((MemberName) yyVals[-1+yyTop]).GetTypeExpression (), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 380: + case_380(); + break; +case 381: +#line 2969 "cs-parser.jay" + { + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 382: +#line 2973 "cs-parser.jay" + { + yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 383: + case_383(); + break; +case 384: + case_384(); + break; +case 385: + case_385(); + break; +case 386: + case_386(); + break; +case 387: +#line 3011 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation (yyVals[0+yyTop])); } + break; +case 388: +#line 3012 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.String, GetLocation (yyVals[0+yyTop])); } + break; +case 389: +#line 3013 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation (yyVals[0+yyTop])); } + break; +case 390: +#line 3014 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation (yyVals[0+yyTop])); } + break; +case 391: +#line 3015 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation (yyVals[0+yyTop])); } + break; +case 392: +#line 3016 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation (yyVals[0+yyTop])); } + break; +case 394: +#line 3021 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation (yyVals[0+yyTop])); } + break; +case 395: +#line 3022 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation (yyVals[0+yyTop])); } + break; +case 396: +#line 3023 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation (yyVals[0+yyTop])); } + break; +case 397: +#line 3024 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation (yyVals[0+yyTop])); } + break; +case 398: +#line 3025 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation (yyVals[0+yyTop])); } + break; +case 399: +#line 3026 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation (yyVals[0+yyTop])); } + break; +case 400: +#line 3027 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation (yyVals[0+yyTop])); } + break; +case 401: +#line 3028 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation (yyVals[0+yyTop])); } + break; +case 402: +#line 3029 "cs-parser.jay" + { yyVal = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation (yyVals[0+yyTop])); } + break; +case 423: + case_423(); + break; +case 424: + case_424(); + break; +case 428: +#line 3076 "cs-parser.jay" + { yyVal = new NullLiteral (GetLocation (yyVals[0+yyTop])); } + break; +case 429: +#line 3080 "cs-parser.jay" + { yyVal = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation (yyVals[0+yyTop])); } + break; +case 430: +#line 3081 "cs-parser.jay" + { yyVal = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation (yyVals[0+yyTop])); } + break; +case 435: + case_435(); + break; +case 436: +#line 3114 "cs-parser.jay" + { + yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); + } + break; +case 437: + case_437(); + break; +case 438: + case_438(); + break; +case 439: + case_439(); + break; +case 440: + case_440(); + break; +case 441: +#line 3146 "cs-parser.jay" + { + yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null,GetLocation (yyVals[0+yyTop])); + } + break; +case 442: + case_442(); + break; +case 443: +#line 3154 "cs-parser.jay" + { + yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null, lexer.Location); + } + break; +case 444: + case_444(); + break; +case 445: + case_445(); + break; +case 446: +#line 3170 "cs-parser.jay" + { yyVal = null; } + break; +case 448: + case_448(); + break; +case 449: + case_449(); + break; +case 450: +#line 3193 "cs-parser.jay" + { yyVal = null; } + break; +case 451: +#line 3197 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 452: + case_452(); + break; +case 453: + case_453(); + break; +case 454: + case_454(); + break; +case 455: + case_455(); + break; +case 456: +#line 3229 "cs-parser.jay" + { + yyVal = new CompletionElementInitializer (null, GetLocation (yyVals[0+yyTop])); + } + break; +case 457: + case_457(); + break; +case 458: + case_458(); + break; +case 459: + case_459(); + break; +case 462: +#line 3257 "cs-parser.jay" + { yyVal = null; } + break; +case 464: + case_464(); + break; +case 465: + case_465(); + break; +case 466: + case_466(); + break; +case 467: + case_467(); + break; +case 468: + case_468(); + break; +case 469: +#line 3309 "cs-parser.jay" + { + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 473: + case_473(); + break; +case 474: + case_474(); + break; +case 475: + case_475(); + break; +case 476: + case_476(); + break; +case 478: + case_478(); + break; +case 479: + case_479(); + break; +case 480: + case_480(); + break; +case 481: + case_481(); + break; +case 482: + case_482(); + break; +case 483: + case_483(); + break; +case 484: +#line 3396 "cs-parser.jay" + { + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 486: +#line 3404 "cs-parser.jay" + { + yyVal = new This (GetLocation (yyVals[0+yyTop])); + } + break; +case 487: + case_487(); + break; +case 488: + case_488(); + break; +case 489: +#line 3424 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 490: +#line 3431 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 491: + case_491(); + break; +case 492: + case_492(); + break; +case 493: + case_493(); + break; +case 494: + case_494(); + break; +case 495: + case_495(); + break; +case 496: + case_496(); + break; +case 497: + case_497(); + break; +case 498: +#line 3497 "cs-parser.jay" + { + ++lexer.parsing_type; + } + break; +case 499: + case_499(); + break; +case 500: + case_500(); + break; +case 503: +#line 3524 "cs-parser.jay" + { yyVal = null; } + break; +case 505: + case_505(); + break; +case 506: + case_506(); + break; +case 507: + case_507(); + break; +case 508: + case_508(); + break; +case 509: + case_509(); + break; +case 510: + case_510(); + break; +case 514: + case_514(); + break; +case 515: + case_515(); + break; +case 516: + case_516(); + break; +case 517: +#line 3600 "cs-parser.jay" + { + yyVal = 2; + } + break; +case 518: +#line 3604 "cs-parser.jay" + { + yyVal = ((int) yyVals[-1+yyTop]) + 1; + } + break; +case 519: +#line 3611 "cs-parser.jay" + { + yyVal = null; + } + break; +case 520: +#line 3615 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 521: + case_521(); + break; +case 522: + case_522(); + break; +case 523: + case_523(); + break; +case 524: + case_524(); + break; +case 525: +#line 3659 "cs-parser.jay" + { + lexer.TypeOfParsing = true; + } + break; +case 526: + case_526(); + break; +case 529: + case_529(); + break; +case 530: + case_530(); + break; +case 531: + case_531(); + break; +case 532: + case_532(); + break; +case 533: + case_533(); + break; +case 534: + case_534(); + break; +case 535: + case_535(); + break; +case 536: + case_536(); + break; +case 537: + case_537(); + break; +case 538: + case_538(); + break; +case 539: + case_539(); + break; +case 540: + case_540(); + break; +case 541: +#line 3773 "cs-parser.jay" + { + start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], false, GetLocation (yyVals[-1+yyTop])); + } + break; +case 542: + case_542(); + break; +case 543: +#line 3786 "cs-parser.jay" + { + start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], true, GetLocation (yyVals[-2+yyTop])); + } + break; +case 544: +#line 3790 "cs-parser.jay" + { + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + } + break; +case 545: +#line 3797 "cs-parser.jay" + { + yyVal = ParametersCompiled.Undefined; + } + break; +case 547: +#line 3805 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 548: + case_548(); + break; +case 549: + case_549(); + break; +case 551: +#line 3831 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.LogicalNot, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 552: +#line 3835 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.OnesComplement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 555: + case_555(); + break; +case 556: + case_556(); + break; +case 558: +#line 3865 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.UnaryPlus, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 559: +#line 3869 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.UnaryNegation, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 560: +#line 3873 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 561: +#line 3877 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 562: +#line 3881 "cs-parser.jay" + { + yyVal = new Indirection ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 563: +#line 3885 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.AddressOf, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 565: + case_565(); + break; +case 566: + case_566(); + break; +case 567: + case_567(); + break; +case 569: + case_569(); + break; +case 570: +#line 3917 "cs-parser.jay" + { + yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 571: + case_571(); + break; +case 572: +#line 3926 "cs-parser.jay" + { + yyVal = new As ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 573: +#line 3930 "cs-parser.jay" + { + yyVal = new Is ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 575: + case_575(); + break; +case 576: + case_576(); + break; +case 578: + case_578(); + break; +case 579: + case_579(); + break; +case 580: + case_580(); + break; +case 581: + case_581(); + break; +case 583: + case_583(); + break; +case 584: + case_584(); + break; +case 586: + case_586(); + break; +case 588: + case_588(); + break; +case 590: + case_590(); + break; +case 592: + case_592(); + break; +case 594: + case_594(); + break; +case 596: + case_596(); + break; +case 598: + case_598(); + break; +case 599: +#line 4054 "cs-parser.jay" + { + yyVal = new SimpleAssign ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 600: + case_600(); + break; +case 601: + case_601(); + break; +case 602: + case_602(); + break; +case 603: + case_603(); + break; +case 604: + case_604(); + break; +case 605: + case_605(); + break; +case 606: + case_606(); + break; +case 607: + case_607(); + break; +case 608: + case_608(); + break; +case 609: + case_609(); + break; +case 610: + case_610(); + break; +case 611: + case_611(); + break; +case 612: + case_612(); + break; +case 613: + case_613(); + break; +case 614: + case_614(); + break; +case 615: +#line 4149 "cs-parser.jay" + { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } + break; +case 616: + case_616(); + break; +case 619: +#line 4164 "cs-parser.jay" + { + start_block (lexer.Location); + } + break; +case 620: + case_620(); + break; +case 622: + case_622(); + break; +case 623: + case_623(); + break; +case 624: + case_624(); + break; +case 625: + case_625(); + break; +case 626: + case_626(); + break; +case 627: +#line 4209 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 628: + case_628(); + break; +case 629: + case_629(); + break; +case 630: +#line 4223 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 631: + case_631(); + break; +case 632: + case_632(); + break; +case 638: +#line 4248 "cs-parser.jay" + { + yyVal = new ArglistAccess (GetLocation (yyVals[0+yyTop])); + } + break; +case 639: + case_639(); + break; +case 640: + case_640(); + break; +case 641: + case_641(); + break; +case 643: +#line 4277 "cs-parser.jay" + { + yyVal = new BooleanExpression ((Expression) yyVals[0+yyTop]); + } + break; +case 644: +#line 4290 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 645: + case_645(); + break; +case 646: + case_646(); + break; +case 647: + case_647(); + break; +case 648: + case_648(); + break; +case 649: +#line 4329 "cs-parser.jay" + { yyVal = null; } + break; +case 650: +#line 4331 "cs-parser.jay" + { yyVal = yyVals[0+yyTop]; StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[0+yyTop])); } + break; +case 651: + case_651(); + break; +case 654: + case_654(); + break; +case 655: + case_655(); + break; +case 656: + case_656(); + break; +case 657: + case_657(); + break; +case 658: + case_658(); + break; +case 659: + case_659(); + break; +case 660: + case_660(); + break; +case 661: + case_661(); + break; +case 662: + case_662(); + break; +case 663: + case_663(); + break; +case 664: + case_664(); + break; +case 665: + case_665(); + break; +case 666: + case_666(); + break; +case 667: + case_667(); + break; +case 668: + case_668(); + break; +case 669: + case_669(); + break; +case 671: +#line 4451 "cs-parser.jay" + { + current_container.AddBasesForPart (current_class, (List) yyVals[0+yyTop]); + } + break; +case 673: +#line 4459 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 674: + case_674(); + break; +case 675: + case_675(); + break; +case 676: + case_676(); + break; +case 677: + case_677(); + break; +case 678: + case_678(); + break; +case 679: + case_679(); + break; +case 680: + case_680(); + break; +case 681: + case_681(); + break; +case 682: +#line 4548 "cs-parser.jay" + { + yyVal = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation (yyVals[0+yyTop])); + } + break; +case 683: +#line 4552 "cs-parser.jay" + { + yyVal = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation (yyVals[0+yyTop])); + } + break; +case 684: +#line 4559 "cs-parser.jay" + { + yyVal = Variance.None; + } + break; +case 685: + case_685(); + break; +case 686: +#line 4573 "cs-parser.jay" + { + yyVal = Variance.Covariant; + } + break; +case 687: +#line 4577 "cs-parser.jay" + { + yyVal = Variance.Contravariant; + } + break; +case 688: + case_688(); + break; +case 689: +#line 4602 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 690: + case_690(); + break; +case 691: + case_691(); + break; +case 692: + case_692(); + break; +case 693: + case_693(); + break; +case 698: +#line 4646 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 699: +#line 4650 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 701: + case_701(); + break; +case 704: +#line 4674 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 705: +#line 4678 "cs-parser.jay" + { + current_block.AddStatement ((Statement) yyVals[0+yyTop]); + } + break; +case 734: + case_734(); + break; +case 735: + case_735(); + break; +case 736: + case_736(); + break; +case 737: + case_737(); + break; +case 738: + case_738(); + break; +case 741: + case_741(); + break; +case 742: + case_742(); + break; +case 743: + case_743(); + break; +case 744: + case_744(); + break; +case 745: +#line 4822 "cs-parser.jay" + { + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 746: +#line 4826 "cs-parser.jay" + { + yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + break; +case 747: + case_747(); + break; +case 749: + case_749(); + break; +case 750: +#line 4847 "cs-parser.jay" + { + yyVal = ComposedTypeSpecifier.CreatePointer (GetLocation (yyVals[0+yyTop])); + } + break; +case 751: + case_751(); + break; +case 752: + case_752(); + break; +case 753: + case_753(); + break; +case 754: + case_754(); + break; +case 756: + case_756(); + break; +case 757: + case_757(); + break; +case 762: + case_762(); + break; +case 763: + case_763(); + break; +case 764: +#line 4936 "cs-parser.jay" + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + } + break; +case 765: + case_765(); + break; +case 770: + case_770(); + break; +case 772: + case_772(); + break; +case 773: + case_773(); + break; +case 774: + case_774(); + break; +case 775: +#line 4986 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 776: +#line 4990 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 777: +#line 4991 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 778: + case_778(); + break; +case 779: + case_779(); + break; +case 780: + case_780(); + break; +case 783: + case_783(); + break; +case 784: + case_784(); + break; +case 785: +#line 5059 "cs-parser.jay" + { + start_block (GetLocation (yyVals[0+yyTop])); + } + break; +case 786: + case_786(); + break; +case 787: + case_787(); + break; +case 789: + case_789(); + break; +case 790: + case_790(); + break; +case 791: + case_791(); + break; +case 792: +#line 5103 "cs-parser.jay" + { + current_block = current_block.CreateSwitchBlock (lexer.Location); + } + break; +case 793: +#line 5107 "cs-parser.jay" + { + yyVal = new SwitchSection ((List) yyVals[-2+yyTop], current_block); + } + break; +case 794: + case_794(); + break; +case 795: + case_795(); + break; +case 796: + case_796(); + break; +case 797: +#line 5136 "cs-parser.jay" + { + yyVal = new SwitchLabel (null, GetLocation (yyVals[0+yyTop])); + } + break; +case 802: + case_802(); + break; +case 803: + case_803(); + break; +case 804: + case_804(); + break; +case 805: +#line 5175 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 806: + case_806(); + break; +case 807: + case_807(); + break; +case 808: +#line 5203 "cs-parser.jay" + { yyVal = new EmptyStatement (lexer.Location); } + break; +case 810: + case_810(); + break; +case 811: + case_811(); + break; +case 813: +#line 5224 "cs-parser.jay" + { yyVal = null; } + break; +case 815: +#line 5229 "cs-parser.jay" + { yyVal = new EmptyStatement (lexer.Location); } + break; +case 819: + case_819(); + break; +case 820: + case_820(); + break; +case 821: + case_821(); + break; +case 822: + case_822(); + break; +case 829: + case_829(); + break; +case 830: + case_830(); + break; +case 831: + case_831(); + break; +case 832: + case_832(); + break; +case 833: + case_833(); + break; +case 834: + case_834(); + break; +case 835: + case_835(); + break; +case 836: + case_836(); + break; +case 837: + case_837(); + break; +case 840: +#line 5384 "cs-parser.jay" + { + yyVal = new TryCatch ((Block) yyVals[-1+yyTop], (List) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop]), false); + } + break; +case 841: + case_841(); + break; +case 842: + case_842(); + break; +case 843: + case_843(); + break; +case 844: + case_844(); + break; +case 845: + case_845(); + break; +case 848: +#line 5437 "cs-parser.jay" + { + yyVal = new Catch ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 849: + case_849(); + break; +case 850: +#line 5456 "cs-parser.jay" + { + yyVal = yyVals[-1+yyTop]; + } + break; +case 851: + case_851(); + break; +case 852: +#line 5474 "cs-parser.jay" + { + yyVal = new Checked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 853: +#line 5481 "cs-parser.jay" + { + yyVal = new Unchecked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 854: + case_854(); + break; +case 855: +#line 5491 "cs-parser.jay" + { + yyVal = new Unsafe ((Block) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } + break; +case 856: + case_856(); + break; +case 857: + case_857(); + break; +case 858: + case_858(); + break; +case 859: + case_859(); + break; +case 860: + case_860(); + break; +case 861: + case_861(); + break; +case 862: + case_862(); + break; +case 863: + case_863(); + break; +case 864: +#line 5574 "cs-parser.jay" + { + report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); + } + break; +case 865: + case_865(); + break; +case 866: + case_866(); + break; +case 867: + case_867(); + break; +case 868: + case_868(); + break; +case 869: + case_869(); + break; +case 870: + case_870(); + break; +case 871: + case_871(); + break; +case 872: + case_872(); + break; +case 873: + case_873(); + break; +case 874: +#line 5674 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 875: + case_875(); + break; +case 876: +#line 5689 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 877: + case_877(); + break; +case 878: + case_878(); + break; +case 880: + case_880(); + break; +case 881: +#line 5734 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 882: + case_882(); + break; +case 883: + case_883(); + break; +case 884: + case_884(); + break; +case 885: + case_885(); + break; +case 889: + case_889(); + break; +case 895: +#line 5793 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 896: + case_896(); + break; +case 897: +#line 5812 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 898: + case_898(); + break; +case 899: + case_899(); + break; +case 900: + case_900(); + break; +case 901: + case_901(); + break; +case 902: + case_902(); + break; +case 903: + case_903(); + break; +case 904: + case_904(); + break; +case 905: + case_905(); + break; +case 906: + case_906(); + break; +case 908: +#line 5956 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } + break; +case 909: +#line 5963 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + break; +case 910: + case_910(); + break; +case 912: + case_912(); + break; +case 913: + case_913(); + break; +case 915: + case_915(); + break; +case 916: + case_916(); + break; +case 917: +#line 6009 "cs-parser.jay" + { + yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); + } + break; +case 918: + case_918(); + break; +case 919: + case_919(); + break; +case 920: +#line 6026 "cs-parser.jay" + { + yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); + } + break; +case 921: + case_921(); + break; +case 922: + case_922(); + break; +case 924: + case_924(); + break; +case 925: + case_925(); + break; +case 928: + case_928(); + break; +case 929: + case_929(); + break; +case 937: +#line 6150 "cs-parser.jay" + { + module.DocumentationBuilder.ParsedName = (MemberName) yyVals[0+yyTop]; + } + break; +case 938: +#line 6157 "cs-parser.jay" + { + module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; + } + break; +case 939: + case_939(); + break; +case 940: + case_940(); + break; +case 941: +#line 6174 "cs-parser.jay" + { + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], new MemberName (MemberCache.IndexerNameAlias)); + } + break; +case 942: +#line 6178 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 943: + case_943(); + break; +case 944: + case_944(); + break; +case 945: + case_945(); + break; +case 946: + case_946(); + break; +case 948: +#line 6214 "cs-parser.jay" + { + yyVal = new MemberName (((MemberName) yyVals[-2+yyTop]), (MemberName) yyVals[0+yyTop]); + } + break; +case 950: +#line 6222 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + break; +case 951: +#line 6226 "cs-parser.jay" + { + yyVal = yyVals[-1+yyTop]; + } + break; +case 952: +#line 6233 "cs-parser.jay" + { + yyVal = new List (0); + } + break; +case 954: + case_954(); + break; +case 955: + case_955(); + break; +case 956: + case_956(); + break; +#line default + } + yyTop -= yyLen[yyN]; + yyState = yyStates[yyTop]; + int yyM = yyLhs[yyN]; + if (yyState == 0 && yyM == 0) { +//t if (debug != null) debug.shift(0, yyFinal); + yyState = yyFinal; + if (yyToken < 0) { + yyToken = yyLex.advance() ? yyLex.token() : 0; +//t if (debug != null) +//t debug.lex(yyState, yyToken,yyname(yyToken), yyLex.value()); + } + if (yyToken == 0) { +//t if (debug != null) debug.accept(yyVal); + return yyVal; + } + goto continue_yyLoop; + } + if (((yyN = yyGindex[yyM]) != 0) && ((yyN += yyState) >= 0) + && (yyN < yyTable.Length) && (yyCheck[yyN] == yyState)) + yyState = yyTable[yyN]; + else + yyState = yyDgoto[yyM]; +//t if (debug != null) debug.shift(yyStates[yyTop], yyState); + goto continue_yyLoop; + continue_yyDiscarded: ; // implements the named-loop continue: 'continue yyDiscarded' + } + continue_yyLoop: ; // implements the named-loop continue: 'continue yyLoop' + } + } + +/* + All more than 3 lines long rules are wrapped into a method +*/ +void case_6() +#line 403 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + Attributes attrs = (Attributes) yyVals[0+yyTop]; + report.Error (1730, attrs.Attrs [0].Location, + "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); + } + } + +void case_8() +#line 415 "cs-parser.jay" +{ + if (yyToken == Token.EXTERN_ALIAS) + report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); + else + Error_SyntaxError (yyToken); + } + +void case_13() +#line 435 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + string s = lt.Value; + if (s != "alias"){ + syntax_error (lt.Location, "`alias' expected"); + } else if (lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (lt.Location, "external alias"); + } else { + lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + current_namespace.AddUsingExternalAlias (lt.Value, lt.Location, report); + ubag.AddExternAlias (GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop]), lt, GetLocation (yyVals[0+yyTop])); + } + } + +void case_17() +#line 461 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_18() +#line 466 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_19() +#line 474 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { + report.Warning (440, 2, lt.Location, + "An alias named `global' will not be used when resolving `global::'. The global namespace will be used instead"); + } + + current_namespace.AddUsingAlias (lt.Value, (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + ubag.AddUsingAlias (GetLocation (yyVals[-4+yyTop]), lt, GetLocation (yyVals[-2+yyTop]), (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + +void case_20() +#line 485 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_21() +#line 493 "cs-parser.jay" +{ + current_namespace.AddUsing ((MemberName) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + ubag.AddUsing (GetLocation (yyVals[-2+yyTop]), (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + +void case_22() +#line 506 "cs-parser.jay" +{ + Attributes attrs = (Attributes) yyVals[-2+yyTop]; + MemberName name = (MemberName) yyVals[0+yyTop]; + if (attrs != null) { + bool valid_global_attrs = true; + if ((current_namespace.DeclarationFound || current_namespace != file.NamespaceContainer)) { + valid_global_attrs = false; + } else { + foreach (var a in attrs.Attrs) { + if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") + continue; + + valid_global_attrs = false; + break; + } + } + + if (!valid_global_attrs) + report.Error (1671, name.Location, "A namespace declaration cannot have modifiers or attributes"); + } + + module.AddAttributes (attrs, current_namespace); + + current_namespace = new NamespaceContainer (name, module, current_namespace, file); + module.AddTypesContainer (current_namespace); + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + + ubag.DeclareNamespace (GetLocation (yyVals[-1+yyTop]), name); + } + +void case_23() +#line 537 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + ubag.OpenNamespace (GetLocation (yyVals[0+yyTop])); + } + +void case_24() +#line 543 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) + lbag.AddLocation (current_namespace, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + else + lbag.AddLocation (current_namespace, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-1+yyTop])); + + current_namespace = current_namespace.Parent; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + ubag.CloseNamespace (GetLocation (yyVals[-1+yyTop])); + ubag.EndNamespace (GetLocation (yyVals[-1+yyTop])); + } + +void case_25() +#line 559 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new MemberName (lt.Value, lt.Location); + } + +void case_26() +#line 564 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, lt.Location); + } + +void case_27() +#line 569 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new MemberName ("", lexer.Location); + } + +void case_32() +#line 587 "cs-parser.jay" +{ + MemberName name = (MemberName) yyVals[0+yyTop]; + + if (name.TypeArguments != null) + syntax_error (lexer.Location, "namespace name expected"); + + yyVal = name; + } + +void case_41() +#line 619 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + TypeContainer ds = (TypeContainer)yyVals[0+yyTop]; + + if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ + report.Error (1527, ds.Location, + "Namespace elements cannot be explicitly declared as private, protected or protected internal"); + } + + /* Here is a trick, for explicit attributes we don't know where they belong to until*/ + /* we parse succeeding declaration hence we parse them as normal and re-attach them*/ + /* when we know whether they are global (assembly:, module:) or local (type:).*/ + if (ds.OptAttributes != null) { + ds.OptAttributes.ConvertGlobalAttributes (ds, current_namespace, !current_namespace.DeclarationFound && current_namespace == file.NamespaceContainer); + } + } + current_namespace.DeclarationFound = true; + } + +void case_50() +#line 669 "cs-parser.jay" +{ + var sect = (List) yyVals[0+yyTop]; + yyVal = new Attributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + } + +void case_51() +#line 675 "cs-parser.jay" +{ + Attributes attrs = yyVals[-1+yyTop] as Attributes; + var sect = (List) yyVals[0+yyTop]; + if (attrs == null) + attrs = new Attributes (sect); + else + attrs.AddAttributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + yyVal = attrs; + } + +void case_52() +#line 689 "cs-parser.jay" +{ + lexer.parsing_attribute_section = true; + savedOpenLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_53() +#line 694 "cs-parser.jay" +{ + lexer.parsing_attribute_section = false; + yyVal = yyVals[0+yyTop]; + } + +void case_54() +#line 702 "cs-parser.jay" +{ + current_attr_target = (string) yyVals[-1+yyTop]; + if (current_attr_target == "assembly" || current_attr_target == "module") { + Lexer.check_incorrect_doc_comment (); + } + } + +void case_55() +#line 709 "cs-parser.jay" +{ + /* when attribute target is invalid*/ + if (current_attr_target == string.Empty) + yyVal = new List (0); + else + yyVal = yyVals[-2+yyTop]; + + current_attr_target = null; + lexer.parsing_attribute_section = false; + savedCloseLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_56() +#line 721 "cs-parser.jay" +{ + yyVal = yyVals[-2+yyTop]; + savedCloseLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_57() +#line 729 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = CheckAttributeTarget (lt.Value, lt.Location); + } + +void case_60() +#line 736 "cs-parser.jay" +{ + if (yyToken == Token.IDENTIFIER) { + Error_SyntaxError (yyToken); + yyVal = null; + } else { + string name = GetTokenName (yyToken); + yyVal = CheckAttributeTarget (name, GetLocation (yyVals[0+yyTop])); + } + } + +void case_62() +#line 753 "cs-parser.jay" +{ + var attrs = (List) yyVals[-2+yyTop]; + attrs.Add ((Attribute) yyVals[0+yyTop]); + + yyVal = attrs; + } + +void case_64() +#line 767 "cs-parser.jay" +{ + --lexer.parsing_block; + MemberName mname = (MemberName) yyVals[-2+yyTop]; + if (mname.IsGeneric) { + report.Error (404, lexer.Location, + "'<' unexpected: attributes cannot be generic"); + } + + Arguments [] arguments = (Arguments []) yyVals[0+yyTop]; + ATypeNameExpression expr = mname.GetTypeExpression (); + yyVal = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname)); + if (arguments != null) { + lbag.AddLocation (yyVal, savedAttrParenOpenLocation, savedAttrParenCloseLocation); + } + } + +void case_67() +#line 791 "cs-parser.jay" +{ + savedAttrParenOpenLocation = GetLocation (yyVals[-2+yyTop]); + savedAttrParenCloseLocation = GetLocation (yyVals[0+yyTop]); + yyVal = yyVals[-1+yyTop]; + } + +void case_69() +#line 802 "cs-parser.jay" +{ + Arguments a = new Arguments (4); + a.Add ((Argument) yyVals[0+yyTop]); + yyVal = new Arguments [] { a, null }; + } + +void case_70() +#line 808 "cs-parser.jay" +{ + Arguments a = new Arguments (4); + a.Add ((Argument) yyVals[0+yyTop]); + yyVal = new Arguments [] { null, a }; + } + +void case_71() +#line 814 "cs-parser.jay" +{ + Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; + if (o [1] != null) { + report.Error (1016, ((Argument) yyVals[0+yyTop]).Expr.Location, "Named attribute arguments must appear after the positional arguments"); + o [0] = new Arguments (4); + } + + Arguments args = ((Arguments) o [0]); + if (args.Count > 0 && !(yyVals[0+yyTop] is NamedArgument) && args [args.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (args, GetLocation (yyVals[-1+yyTop])); + } + +void case_72() +#line 829 "cs-parser.jay" +{ + Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; + if (o [1] == null) { + o [1] = new Arguments (4); + } + + ((Arguments) o [1]).Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (o[1], GetLocation (yyVals[-1+yyTop])); + } + +void case_76() +#line 854 "cs-parser.jay" +{ + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new NamedArgument (lt.Value, lt.Location, (Expression) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation(yyVals[-2+yyTop])); + } + +void case_77() +#line 864 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "named argument"); + + /* Avoid boxing in common case (no modifier)*/ + var arg_mod = yyVals[-1+yyTop] == null ? Argument.AType.None : (Argument.AType) yyVals[-1+yyTop]; + + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new NamedArgument (lt.Value, lt.Location, (Expression) yyVals[0+yyTop], arg_mod); + } + +void case_95() +#line 911 "cs-parser.jay" +{ + report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", + GetSymbolName (yyToken)); + yyVal = null; + lexer.parsing_generic_declaration = false; + } + +void case_97() +#line 928 "cs-parser.jay" +{ + MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); + push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]), yyVals[-3+yyTop]); + } + +void case_98() +#line 934 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) yyVals[0+yyTop]); + + if (doc_support) + current_container.DocComment = Lexer.consume_doc_comment (); + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-5+yyTop])); + } + +void case_99() +#line 945 "cs-parser.jay" +{ + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_100() +#line 951 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[0+yyTop])); + yyVal = pop_current_class (); + } + +void case_102() +#line 963 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_118() +#line 1005 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var mod = (Modifiers) yyVals[-3+yyTop]; + current_field = new Const (current_class, (FullNamedExpression) yyVals[-1+yyTop], mod, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-4+yyTop]); + current_container.AddConstant ((Const) current_field); + + if ((mod & Modifiers.STATIC) != 0) { + report.Error (504, current_field.Location, "The constant `{0}' cannot be marked static", current_field.GetSignatureForError ()); + } + + yyVal = current_field; + } + +void case_119() +#line 1018 "cs-parser.jay" +{ + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) yyVals[-2+yyTop]; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + current_field = null; + } + +void case_124() +#line 1048 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_126() +#line 1061 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstInitializer (current_field, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_127() +#line 1067 "cs-parser.jay" +{ + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + yyVal = null; + } + +void case_130() +#line 1082 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + + FullNamedExpression type = (FullNamedExpression) yyVals[-1+yyTop]; + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (670, GetLocation (yyVals[-1+yyTop]), "Fields cannot have void type"); + + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + current_field = new Field (current_class, type, (Modifiers) yyVals[-2+yyTop], new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-3+yyTop]); + current_container.AddField (current_field); + yyVal = current_field; + } + +void case_131() +#line 1097 "cs-parser.jay" +{ + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_field, GetModifierLocations (), GetLocation (yyVals[0+yyTop])); + yyVal = current_field; + current_field = null; + } + +void case_132() +#line 1110 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "fixed size buffers"); + + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + current_field = new FixedField (current_class, (FullNamedExpression) yyVals[-1+yyTop], (Modifiers) yyVals[-3+yyTop], + new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-4+yyTop]); + + current_container.AddField (current_field); + } + +void case_133() +#line 1121 "cs-parser.jay" +{ + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) yyVals[-2+yyTop]; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + yyVal = current_field; + current_field = null; + } + +void case_136() +#line 1144 "cs-parser.jay" +{ + ++lexer.parsing_block; + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + start_block (GetLocation (yyVals[0+yyTop])); + } + +void case_137() +#line 1150 "cs-parser.jay" +{ + --lexer.parsing_block; + current_field.Initializer = (Expression) yyVals[0+yyTop]; + lbag.AppendToMember (current_field, GetLocation (yyVals[-2+yyTop])); + end_block (lexer.Location); + current_local_parameters = null; + } + +void case_142() +#line 1177 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_144() +#line 1187 "cs-parser.jay" +{ + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_149() +#line 1213 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_151() +#line 1226 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstInitializer (current_field, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_152() +#line 1232 "cs-parser.jay" +{ + report.Error (443, lexer.Location, "Value or constant expected"); + yyVal = null; + } + +void case_155() +#line 1242 "cs-parser.jay" +{ + /* It has to be here for the parent to safely restore artificial block*/ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_156() +#line 1251 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.NotAllowed; + + /* Add it early in the case of body being eof for full aot*/ + current_container.AddMethod ((Method) yyVals[0+yyTop]); + } + +void case_157() +#line 1259 "cs-parser.jay" +{ + Method method = (Method) yyVals[-2+yyTop]; + method.Block = (ToplevelBlock) yyVals[0+yyTop]; + + 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 ()); + } + } else { + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, method.Location, "`{0}': interface members cannot have a definition", + method.GetSignatureForError ()); + } + } + + current_local_parameters = null; + + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_160() +#line 1297 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + MemberName name = (MemberName) yyVals[-6+yyTop]; + current_local_parameters = (ParametersCompiled) yyVals[-3+yyTop]; + + GenericMethod generic = null; + if (name.TypeArguments != null) { + generic = new GenericMethod (current_namespace, current_class, name, + (FullNamedExpression) yyVals[-7+yyTop], current_local_parameters); + + generic.SetParameterInfo ((List) yyVals[0+yyTop]); + } else if (yyVals[0+yyTop] != null) { + report.Error (80, GetLocation (yyVals[0+yyTop]), + "Constraints are not allowed on non-generic declarations"); + } + + Method method = new Method (current_class, generic, (FullNamedExpression) yyVals[-7+yyTop], (Modifiers) yyVals[-8+yyTop], + name, current_local_parameters, (Attributes) yyVals[-9+yyTop]); + + if (yyVals[0+yyTop] != 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 (); + + lbag.AddMember (method, GetModifierLocations (), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = method; + } + +void case_162() +#line 1338 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + valid_param_mod = ParameterModifierType.All; + } + +void case_164() +#line 1347 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + + MemberName name = (MemberName) yyVals[-6+yyTop]; + current_local_parameters = (ParametersCompiled) yyVals[-3+yyTop]; + + if (yyVals[-1+yyTop] != null && name.TypeArguments == null) + 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, + new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-8+yyTop])), + current_local_parameters); + + generic.SetParameterInfo ((List) yyVals[-1+yyTop]); + } + + var modifiers = (Modifiers) yyVals[-10+yyTop]; + + 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 (yyVals[-8+yyTop])), + modifiers, name, current_local_parameters, (Attributes) yyVals[-11+yyTop]); + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[-9+yyTop])); + lbag.AddMember (method, mod_locations, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = method; + } + +void case_165() +#line 1400 "cs-parser.jay" +{ + MemberName name = (MemberName) yyVals[-3+yyTop]; + report.Error (1585, name.Location, + "Member modifier `{0}' must precede the member type and name", ModifiersExtensions.Name ((Modifiers) yyVals[-4+yyTop])); + + Method method = new Method (current_class, null, (FullNamedExpression) yyVals[-5+yyTop], + 0, name, (ParametersCompiled) yyVals[-1+yyTop], (Attributes) yyVals[-7+yyTop]); + + current_local_parameters = (ParametersCompiled) yyVals[-1+yyTop]; + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + yyVal = method; + } + +void case_170() +#line 1429 "cs-parser.jay" +{ + var pars_list = (List) yyVals[0+yyTop]; + yyVal = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation (yyVal, lbag.GetLocations (pars_list)); + } + +void case_171() +#line 1435 "cs-parser.jay" +{ + var pars_list = (List) yyVals[-2+yyTop]; + pars_list.Add ((Parameter) yyVals[0+yyTop]); + + yyVal = new ParametersCompiled (pars_list.ToArray ()); + } + +void case_172() +#line 1442 "cs-parser.jay" +{ + var pars_list = (List) yyVals[-2+yyTop]; + pars_list.Add (new ArglistParameter (GetLocation (yyVals[0+yyTop]))); + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + } + +void case_173() +#line 1448 "cs-parser.jay" +{ + if (yyVals[-2+yyTop] != null) + report.Error (231, ((Parameter) yyVals[-2+yyTop]).Location, "A params parameter must be the last parameter in a formal parameter list"); + + yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[-2+yyTop] } ); + } + +void case_174() +#line 1455 "cs-parser.jay" +{ + if (yyVals[-2+yyTop] != null) + report.Error (231, ((Parameter) yyVals[-2+yyTop]).Location, "A params parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) yyVals[-4+yyTop]; + pars_list.Add (new ArglistParameter (GetLocation (yyVals[-2+yyTop]))); + + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + } + +void case_175() +#line 1465 "cs-parser.jay" +{ + report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); + + yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[-2+yyTop])) }, true); + } + +void case_176() +#line 1471 "cs-parser.jay" +{ + report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) yyVals[-4+yyTop]; + pars_list.Add (new ArglistParameter (GetLocation (yyVals[-2+yyTop]))); + + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + } + +void case_179() +#line 1488 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = ParametersCompiled.EmptyReadOnlyParameters; + } + +void case_180() +#line 1496 "cs-parser.jay" +{ + parameters_bucket.Clear (); + Parameter p = (Parameter) yyVals[0+yyTop]; + parameters_bucket.Add (p); + + default_parameter_used = p.HasDefaultValue; + yyVal = parameters_bucket; + } + +void case_181() +#line 1505 "cs-parser.jay" +{ + var pars = (List) yyVals[-2+yyTop]; + Parameter p = (Parameter) yyVals[0+yyTop]; + if (p != null) { + if (p.HasExtensionMethodModifier) + report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); + else if (!p.HasDefaultValue && default_parameter_used) + report.Error (1737, p.Location, "Optional parameter cannot precede required parameters"); + + default_parameter_used |= p.HasDefaultValue; + pars.Add (p); + + lbag.AppendTo (pars, GetLocation (yyVals[-1+yyTop])); + } + + yyVal = yyVals[-2+yyTop]; + } + +void case_182() +#line 1529 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Parameter.Modifier) yyVals[-2+yyTop], (Attributes) yyVals[-3+yyTop], lt.Location); + lbag.AddLocation (yyVal, parameterModifierLocation); + } + +void case_183() +#line 1538 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); + yyVal = new Parameter ((FullNamedExpression) yyVals[-3+yyTop], lt.Value, (Parameter.Modifier) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop], lt.Location); + lbag.AddLocation (yyVal, parameterModifierLocation); + } + +void case_184() +#line 1548 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + Location l = GetLocation (yyVals[0+yyTop]); + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], null, (Parameter.Modifier) yyVals[-2+yyTop], (Attributes) yyVals[-3+yyTop], l); + lbag.AddLocation (yyVal, parameterModifierLocation); + } + +void case_186() +#line 1563 "cs-parser.jay" +{ + --lexer.parsing_block; + if (lang_version <= LanguageVersion.V_3) { + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "optional parameter"); + } + + Parameter.Modifier mod = (Parameter.Modifier) yyVals[-5+yyTop]; + if (mod != Parameter.Modifier.NONE) { + switch (mod) { + case Parameter.Modifier.REF: + case Parameter.Modifier.OUT: + report.Error (1741, GetLocation (yyVals[-5+yyTop]), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + + case Parameter.Modifier.This: + report.Error (1743, GetLocation (yyVals[-5+yyTop]), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + default: + throw new NotImplementedException (mod.ToString ()); + } + + mod = Parameter.Modifier.NONE; + } + + if ((valid_param_mod & ParameterModifierType.DefaultValue) == 0) + report.Error (1065, GetLocation (yyVals[-2+yyTop]), "Optional parameter is not valid in this context"); + + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new Parameter ((FullNamedExpression) yyVals[-4+yyTop], lt.Value, mod, (Attributes) yyVals[-6+yyTop], lt.Location); + lbag.AddLocation (yyVal, parameterModifierLocation, GetLocation (yyVals[-2+yyTop])); /* parameterModifierLocation should be ignored when mod == NONE*/ + + if (yyVals[0+yyTop] != null) + ((Parameter) yyVal).DefaultValue = new DefaultParameterValueExpression ((Expression) yyVals[0+yyTop]); + } + +void case_189() +#line 1608 "cs-parser.jay" +{ + yyVal = yyVals[0+yyTop]; + parameterModifierLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_190() +#line 1613 "cs-parser.jay" +{ + Parameter.Modifier p2 = (Parameter.Modifier)yyVals[0+yyTop]; + Parameter.Modifier mod = (Parameter.Modifier)yyVals[-1+yyTop] | p2; + if (((Parameter.Modifier)yyVals[-1+yyTop] & p2) == p2) { + Error_DuplicateParameterModifier (lexer.Location, p2); + } else { + switch (mod & ~Parameter.Modifier.This) { + case Parameter.Modifier.REF: + report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); + break; + case Parameter.Modifier.OUT: + report.Error (1102, lexer.Location, "The parameter modifiers `this' and `out' cannot be used altogether"); + break; + default: + report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); + break; + } + } + yyVal = mod; + } + +void case_191() +#line 1637 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Ref) == 0) + Error_ParameterModifierNotValid ("ref", GetLocation (yyVals[0+yyTop])); + + yyVal = Parameter.Modifier.REF; + } + +void case_192() +#line 1644 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Out) == 0) + Error_ParameterModifierNotValid ("out", GetLocation (yyVals[0+yyTop])); + + yyVal = Parameter.Modifier.OUT; + } + +void case_193() +#line 1651 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.This) == 0) + Error_ParameterModifierNotValid ("this", GetLocation (yyVals[0+yyTop])); + + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "extension methods"); + + yyVal = Parameter.Modifier.This; + } + +void case_194() +#line 1664 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new ParamsParameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Attributes) yyVals[-3+yyTop], lt.Location); + } + +void case_195() +#line 1669 "cs-parser.jay" +{ + report.Error (1751, GetLocation (yyVals[-4+yyTop]), "Cannot specify a default value for a parameter array"); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new ParamsParameter ((FullNamedExpression) yyVals[-3+yyTop], lt.Value, (Attributes) yyVals[-5+yyTop], lt.Location); + } + +void case_196() +#line 1676 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_197() +#line 1684 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Params) == 0) + report.Error (1670, (GetLocation (yyVals[0+yyTop])), "The `params' modifier is not allowed in current context"); + } + +void case_198() +#line 1689 "cs-parser.jay" +{ + Parameter.Modifier mod = (Parameter.Modifier)yyVals[0+yyTop]; + if ((mod & Parameter.Modifier.This) != 0) { + report.Error (1104, GetLocation (yyVals[-1+yyTop]), "The parameter modifiers `this' and `params' cannot be used altogether"); + } else { + report.Error (1611, GetLocation (yyVals[-1+yyTop]), "The params parameter cannot be declared as ref or out"); + } + } + +void case_200() +#line 1705 "cs-parser.jay" +{ + if ((valid_param_mod & ParameterModifierType.Arglist) == 0) + report.Error (1669, GetLocation (yyVals[0+yyTop]), "__arglist is not valid in this context"); + } + +void case_201() +#line 1716 "cs-parser.jay" +{ + if (doc_support) + tmpComment = Lexer.consume_doc_comment (); + } + +void case_202() +#line 1721 "cs-parser.jay" +{ + var type = (FullNamedExpression) yyVals[-3+yyTop]; + current_property = new Property (current_class, type, (Modifiers) yyVals[-4+yyTop], + (MemberName) yyVals[-2+yyTop], (Attributes) yyVals[-5+yyTop]); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (547, GetLocation (yyVals[-3+yyTop]), "`{0}': property or indexer cannot have void type", current_property.GetSignatureForError ()); + + current_container.AddProperty ((Property)current_property); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation (yyVals[0+yyTop])); + + lexer.PropertyParsing = true; + } + +void case_203() +#line 1735 "cs-parser.jay" +{ + lexer.PropertyParsing = false; + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + } + +void case_204() +#line 1742 "cs-parser.jay" +{ + lbag.AppendToMember (current_property, GetLocation (yyVals[0+yyTop])); + current_property = null; + } + +void case_206() +#line 1756 "cs-parser.jay" +{ + valid_param_mod = 0; + var type = (FullNamedExpression) yyVals[-6+yyTop]; + Indexer indexer = new Indexer (current_class, type, (MemberName) yyVals[-5+yyTop], (Modifiers) yyVals[-7+yyTop], (ParametersCompiled) yyVals[-2+yyTop], (Attributes) yyVals[-8+yyTop]); + + current_property = indexer; + + current_container.AddIndexer (indexer); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (620, GetLocation (yyVals[-6+yyTop]), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ()); + + if (indexer.ParameterInfo.IsEmpty) { + report.Error (1551, GetLocation (yyVals[-4+yyTop]), "Indexers must have at least one parameter"); + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lexer.PropertyParsing = true; + } + +void case_208() +#line 1785 "cs-parser.jay" +{ + if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) + ((Indexer) current_property).ParameterInfo.CheckParameters (current_property); + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + + lbag.AppendToMember (current_property, GetLocation (yyVals[-1+yyTop])); + current_property = null; + } + +void case_213() +#line 1804 "cs-parser.jay" +{ + if (yyToken == Token.CLOSE_BRACE) { + report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); + } else { + if (yyToken == Token.SEMICOLON) + report.Error (1597, lexer.Location, "Semicolon after method or accessor block is not valid"); + else + report.Error (1014, GetLocation (yyVals[0+yyTop]), "A get or set accessor expected"); + } + } + +void case_214() +#line 1818 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); + } + + if (current_property.Get != null) { + report.Error (1007, GetLocation (yyVals[0+yyTop]), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Get = new Indexer.GetIndexerMethod (current_property, (Modifiers) yyVals[-1+yyTop], ((Indexer)current_property).ParameterInfo.Clone (), + (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } else { + current_property.Get = new Property.GetMethod (current_property, + (Modifiers) yyVals[-1+yyTop], (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } + + current_local_parameters = current_property.Get.ParameterInfo; + lbag.AddMember (current_property.Get, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + +void case_215() +#line 1840 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + current_property.Get.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Get.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support) + if (Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + +void case_216() +#line 1861 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); + } + + if (current_property.Set != null) { + report.Error (1007, GetLocation (yyVals[0+yyTop]), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Set = new Indexer.SetIndexerMethod (current_property, (Modifiers) yyVals[-1+yyTop], + ParametersCompiled.MergeGenerated (compiler, + ((Indexer)current_property).ParameterInfo, true, new Parameter ( + current_property.TypeExpression, "value", Parameter.Modifier.NONE, null, GetLocation (yyVals[0+yyTop])), + null), + (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } else { + current_property.Set = new Property.SetMethod (current_property, (Modifiers) yyVals[-1+yyTop], + ParametersCompiled.CreateImplicitParameter (current_property.TypeExpression, GetLocation (yyVals[0+yyTop])), + (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + } + + current_local_parameters = current_property.Set.ParameterInfo; + lbag.AddMember (current_property.Set, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + +void case_217() +#line 1888 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + current_property.Set.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Set.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support + && Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + +void case_219() +#line 1910 "cs-parser.jay" +{ + lbag.AppendToMember (lbag.LastMember, GetLocation (yyVals[0+yyTop])); + yyVal = null; + } + +void case_220() +#line 1915 "cs-parser.jay" +{ + Error_SyntaxError (1043, yyToken, "Invalid accessor body"); + yyVal = null; + } + +void case_222() +#line 1930 "cs-parser.jay" +{ + MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); + push_current_class (new Interface (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]), yyVals[-3+yyTop]); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-2+yyTop])); + } + +void case_223() +#line 1937 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) yyVals[0+yyTop]); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + +void case_224() +#line 1948 "cs-parser.jay" +{ + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_225() +#line 1954 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = pop_current_class (); + } + +void case_241() +#line 2006 "cs-parser.jay" +{ + OperatorDeclaration decl = (OperatorDeclaration) yyVals[-2+yyTop]; + if (decl != null) { + Operator op = new Operator ( + current_class, decl.optype, decl.ret_type, (Modifiers) yyVals[-3+yyTop], + current_local_parameters, + (ToplevelBlock) yyVals[0+yyTop], (Attributes) yyVals[-4+yyTop], decl.location); + + if (op.Block == null) + op.ParameterInfo.CheckParameters (op); + + if (doc_support) { + op.DocComment = tmpComment; + Lexer.doc_state = XmlCommentState.Allowed; + } + + /* Note again, checking is done in semantic analysis*/ + current_container.AddOperator (op); + + lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); + } + + current_local_parameters = null; + } + +void case_245() +#line 2040 "cs-parser.jay" +{ + report.Error (590, GetLocation (yyVals[0+yyTop]), "User-defined operators cannot return void"); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_247() +#line 2052 "cs-parser.jay" +{ + valid_param_mod = 0; + + Location loc = GetLocation (yyVals[-5+yyTop]); + Operator.OpType op = (Operator.OpType) yyVals[-4+yyTop]; + current_local_parameters = (ParametersCompiled)yyVals[-1+yyTop]; + + int p_count = current_local_parameters.Count; + if (p_count == 1) { + if (op == Operator.OpType.Addition) + op = Operator.OpType.UnaryPlus; + else if (op == Operator.OpType.Subtraction) + op = Operator.OpType.UnaryNegation; + } + + if (IsUnaryOperator (op)) { + if (p_count == 2) { + report.Error (1020, loc, "Overloadable binary operator expected"); + } else if (p_count != 1) { + report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", + Operator.GetName (op)); + } + } else { + if (p_count > 2) { + report.Error (1534, loc, "Overloaded binary operator `{0}' takes two parameters", + Operator.GetName (op)); + } else if (p_count != 2) { + report.Error (1019, loc, "Overloadable unary operator expected"); + } + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + yyVal = new OperatorDeclaration (op, (FullNamedExpression) yyVals[-6+yyTop], loc); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_272() +#line 2128 "cs-parser.jay" +{ + valid_param_mod = 0; + + Location loc = GetLocation (yyVals[-5+yyTop]); + current_local_parameters = (ParametersCompiled)yyVals[-1+yyTop]; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + yyVal = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) yyVals[-4+yyTop], loc); + lbag.AddLocation (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_274() +#line 2147 "cs-parser.jay" +{ + valid_param_mod = 0; + + Location loc = GetLocation (yyVals[-5+yyTop]); + current_local_parameters = (ParametersCompiled)yyVals[-1+yyTop]; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + yyVal = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) yyVals[-4+yyTop], loc); + lbag.AddLocation (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_275() +#line 2162 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + yyVal = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_276() +#line 2168 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + yyVal = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_277() +#line 2178 "cs-parser.jay" +{ + Constructor c = (Constructor) yyVals[-1+yyTop]; + c.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (doc_support) + c.DocComment = ConsumeStoredComment (); + + current_container.AddConstructor (c); + + current_local_parameters = null; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_278() +#line 2197 "cs-parser.jay" +{ + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + valid_param_mod = ParameterModifierType.All; + } + +void case_279() +#line 2206 "cs-parser.jay" +{ + valid_param_mod = 0; + current_local_parameters = (ParametersCompiled) yyVals[-1+yyTop]; + + /**/ + /* start block here, so possible anonymous methods inside*/ + /* constructor initializer can get correct parent block*/ + /**/ + start_block (lexer.Location); + } + +void case_280() +#line 2217 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-6+yyTop]; + var mods = (Modifiers) yyVals[-7+yyTop]; + ConstructorInitializer ci = (ConstructorInitializer) yyVals[0+yyTop]; + + Constructor c = new Constructor (current_class, lt.Value, mods, + (Attributes) yyVals[-8+yyTop], current_local_parameters, ci, lt.Location); + + if (lt.Value != current_container.MemberName.Name) { + report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); + } else if ((mods & Modifiers.STATIC) != 0) { + if ((mods & Modifiers.AccessibilityMask) != 0){ + report.Error (515, c.Location, + "`{0}': static constructor cannot have an access modifier", + c.GetSignatureForError ()); + } + if (ci != null) { + report.Error (514, c.Location, + "`{0}': static constructor cannot have an explicit `this' or `base' constructor call", + c.GetSignatureForError ()); + + } + } + + lbag.AddMember (c, GetModifierLocations (), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = c; + } + +void case_286() +#line 2262 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstructorBaseInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_288() +#line 2272 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = new ConstructorThisInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_289() +#line 2278 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_290() +#line 2286 "cs-parser.jay" +{ + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + +void case_291() +#line 2295 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + if (lt.Value != current_container.MemberName.Name){ + report.Error (574, lt.Location, "Name of destructor must match name of class"); + } else if (current_container.Kind != MemberKind.Class){ + report.Error (575, lt.Location, "Only class types can contain destructor"); + } + + Destructor d = new Destructor (current_class, (Modifiers) yyVals[-6+yyTop], + ParametersCompiled.EmptyReadOnlyParameters, (Attributes) yyVals[-7+yyTop], lt.Location); + if (doc_support) + d.DocComment = ConsumeStoredComment (); + + d.Block = (ToplevelBlock) yyVals[0+yyTop]; + current_container.AddMethod (d); + lbag.AddMember (d, GetModifierLocations (), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[-1+yyTop])); + + current_local_parameters = null; + } + +void case_292() +#line 2320 "cs-parser.jay" +{ + current_event_field = new EventField (current_class, (FullNamedExpression) yyVals[-1+yyTop], (Modifiers) yyVals[-3+yyTop], (MemberName) yyVals[0+yyTop], (Attributes) yyVals[-4+yyTop]); + current_container.AddEvent (current_event_field); + + if (current_event_field.MemberName.Left != null) { + report.Error (71, current_event_field.Location, "`{0}': An explicit interface implementation of an event must use property syntax", + current_event_field.GetSignatureForError ()); + } + + yyVal = current_event_field; + } + +void case_293() +#line 2334 "cs-parser.jay" +{ + if (doc_support) { + current_event_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_event_field, GetModifierLocations (), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + current_event_field = null; + } + +void case_294() +#line 2347 "cs-parser.jay" +{ + current_event = new EventProperty (current_class, (FullNamedExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-4+yyTop], (MemberName) yyVals[-1+yyTop], (Attributes) yyVals[-5+yyTop]); + current_container.AddEvent (current_event); + lbag.AddMember (current_event, GetModifierLocations (), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + + lexer.EventParsing = true; + } + +void case_295() +#line 2355 "cs-parser.jay" +{ + if (current_container.Kind == MemberKind.Interface) + report.Error (69, GetLocation (yyVals[-2+yyTop]), "Event in interface cannot have add or remove accessors"); + + lexer.EventParsing = false; + } + +void case_296() +#line 2362 "cs-parser.jay" +{ + if (doc_support) { + current_event.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AppendToMember (current_event, GetLocation (yyVals[-1+yyTop])); + current_event = null; + current_local_parameters = null; + } + +void case_299() +#line 2381 "cs-parser.jay" +{ + --lexer.parsing_block; + current_event_field.Initializer = (Expression) yyVals[0+yyTop]; + } + +void case_304() +#line 2405 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_306() +#line 2415 "cs-parser.jay" +{ + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_307() +#line 2424 "cs-parser.jay" +{ + if (current_container.Kind == MemberKind.Interface) { + report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + + if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) { + report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + } + +void case_311() +#line 2445 "cs-parser.jay" +{ + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + +void case_312() +#line 2450 "cs-parser.jay" +{ + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + +void case_313() +#line 2455 "cs-parser.jay" +{ + report.Error (1055, GetLocation (yyVals[0+yyTop]), "An add or remove accessor expected"); + yyVal = null; + } + +void case_314() +#line 2463 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone) { + report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Add = new EventProperty.AddDelegateMethod (current_event, (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + current_local_parameters = current_event.Add.ParameterInfo; + + lbag.AddMember (current_event.Add, GetModifierLocations ()); + lexer.EventParsing = false; + } + +void case_315() +#line 2475 "cs-parser.jay" +{ + lexer.EventParsing = true; + + current_event.Add.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Add.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Add.GetSignatureForError ()); + } + + current_local_parameters = null; + } + +void case_316() +#line 2491 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != ModifierNone) { + report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Remove = new EventProperty.RemoveDelegateMethod (current_event, (Attributes) yyVals[-2+yyTop], GetLocation (yyVals[0+yyTop])); + current_local_parameters = current_event.Remove.ParameterInfo; + + lbag.AddMember (current_event.Remove, GetModifierLocations ()); + lexer.EventParsing = false; + } + +void case_317() +#line 2503 "cs-parser.jay" +{ + lexer.EventParsing = true; + + current_event.Remove.Block = (ToplevelBlock) yyVals[0+yyTop]; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Remove.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Remove.GetSignatureForError ()); + } + + current_local_parameters = null; + } + +void case_318() +#line 2519 "cs-parser.jay" +{ + report.Error (73, lexer.Location, "An add or remove accessor must have a body"); + yyVal = null; + } + +void case_320() +#line 2531 "cs-parser.jay" +{ + if (doc_support) + enumTypeComment = Lexer.consume_doc_comment (); + } + +void case_321() +#line 2536 "cs-parser.jay" +{ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + + MemberName name = (MemberName) yyVals[-3+yyTop]; + if (name.IsGeneric) { + report.Error (1675, name.Location, "Enums cannot have type parameters"); + } + + push_current_class (new Enum (current_namespace, current_class, (TypeExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-5+yyTop], MakeName (name), (Attributes) yyVals[-6+yyTop]), null); + } + +void case_322() +#line 2548 "cs-parser.jay" +{ + /* here will be evaluated after CLOSE_BLACE is consumed.*/ + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_323() +#line 2554 "cs-parser.jay" +{ + if (doc_support) + current_class.DocComment = enumTypeComment; + + --lexer.parsing_declaration; + +/* if (doc_support)*/ +/* em.DocComment = ev.DocComment;*/ + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-1+yyTop])); + yyVal = pop_current_class (); + } + +void case_325() +#line 2571 "cs-parser.jay" +{ + var te = yyVals[0+yyTop] as TypeExpression; + if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { + Enum.Error_1008 (GetLocation (yyVals[0+yyTop]), report); + yyVal = null; + } else { + yyVal = yyVals[0+yyTop]; + } + } + +void case_326() +#line 2581 "cs-parser.jay" +{ + Error_TypeExpected (GetLocation (yyVals[-1+yyTop])); + yyVal = null; + } + +void case_331() +#line 2599 "cs-parser.jay" +{ + lbag.AddLocation (yyVals[-2+yyTop], GetLocation (yyVals[-1+yyTop])); + yyVal = yyVals[0+yyTop]; + } + +void case_332() +#line 2607 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-1+yyTop]); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) { + em.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + yyVal = em; + } + +void case_333() +#line 2620 "cs-parser.jay" +{ + ++lexer.parsing_block; + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + } + +void case_334() +#line 2628 "cs-parser.jay" +{ + --lexer.parsing_block; + + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-4+yyTop]); + em.Initializer = new ConstInitializer (em, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) + em.DocComment = ConsumeStoredComment (); + + yyVal = em; + } + +void case_336() +#line 2653 "cs-parser.jay" +{ + valid_param_mod = 0; + + MemberName name = MakeName ((MemberName) yyVals[-4+yyTop]); + ParametersCompiled p = (ParametersCompiled) yyVals[-1+yyTop]; + + Delegate del = new Delegate (current_namespace, current_class, (FullNamedExpression) yyVals[-5+yyTop], + (Modifiers) yyVals[-7+yyTop], name, p, (Attributes) yyVals[-8+yyTop]); + p.CheckParameters (del); + + ubag.PushTypeDeclaration (del); + ubag.PopTypeDeclaration (); + + current_container.AddDelegate (del); + current_delegate = del; + lexer.ConstraintsParsing = true; + } + +void case_338() +#line 2675 "cs-parser.jay" +{ + if (doc_support) { + current_delegate.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_delegate.SetParameterInfo ((List) yyVals[-2+yyTop]); + lbag.AddMember (current_delegate, GetModifierLocations (), GetLocation (yyVals[-10+yyTop]), GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[0+yyTop])); + + yyVal = current_delegate; + + current_delegate = null; + } + +void case_340() +#line 2693 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "nullable types"); + + yyVal = ComposedTypeSpecifier.CreateNullable (GetLocation (yyVals[0+yyTop])); + } + +void case_342() +#line 2704 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new MemberName (lt1.Value, lt2.Value, (TypeArguments) yyVals[0+yyTop], lt1.Location); + } + +void case_344() +#line 2715 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_345() +#line 2724 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); + } + +void case_347() +#line 2736 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); + var list = locationListStack.Pop (); + list.Add (GetLocation (yyVals[-2+yyTop])); + list.Add (GetLocation (yyVals[-1+yyTop])); + lbag.AddLocation (yyVals[-1+yyTop], list); + + yyVal = yyVals[-1+yyTop];; + } + +void case_348() +#line 2747 "cs-parser.jay" +{ + Error_TypeExpected (lexer.Location); + yyVal = new TypeArguments (); + } + +void case_349() +#line 2755 "cs-parser.jay" +{ + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = type_args; + locationListStack.Push (new List ()); + } + +void case_350() +#line 2762 "cs-parser.jay" +{ + TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; + type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = type_args; + locationListStack.Peek ().Add (GetLocation (yyVals[-1+yyTop])); + } + +void case_352() +#line 2779 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new MemberName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); + } + +void case_353() +#line 2788 "cs-parser.jay" +{ + MemberName mn = (MemberName)yyVals[0+yyTop]; + if (mn.TypeArguments != null) + syntax_error (mn.Location, string.Format ("Member `{0}' cannot declare type arguments", + mn.GetSignatureForError ())); + } + +void case_355() +#line 2799 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + } + +void case_356() +#line 2808 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + yyVal = new MemberName (TypeContainer.DefaultIndexerName, GetLocation (yyVals[0+yyTop])); + } + +void case_357() +#line 2813 "cs-parser.jay" +{ + lexer.parsing_generic_declaration = false; + yyVal = new MemberName ((MemberName) yyVals[-1+yyTop], TypeContainer.DefaultIndexerName, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_358() +#line 2821 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new MemberName (lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_359() +#line 2827 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + + yyVal = new MemberName (lt1.Value, lt2.Value, (TypeArguments) yyVals[-1+yyTop], lt1.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_360() +#line 2835 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_362() +#line 2845 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); + + yyVal = yyVals[-1+yyTop]; + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_363() +#line 2856 "cs-parser.jay" +{ + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); + yyVal = type_args; + } + +void case_364() +#line 2862 "cs-parser.jay" +{ + TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; + type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); + yyVal = type_args; + lbag.AddLocation (yyVals[0+yyTop], GetLocation (yyVals[0+yyTop])); + } + +void case_365() +#line 2872 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; + yyVal = new TypeParameterName (lt.Value, (Attributes)yyVals[-2+yyTop], (Variance) yyVals[-1+yyTop], lt.Location); + } + +void case_366() +#line 2877 "cs-parser.jay" +{ + if (GetTokenName (yyToken) == "type") + report.Error (81, GetLocation (yyVals[0+yyTop]), "Type parameter declaration must be an identifier not a type"); + else + Error_SyntaxError (yyToken); + + yyVal = new TypeParameterName ("", null, lexer.Location); + } + +void case_371() +#line 2911 "cs-parser.jay" +{ + Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_373() +#line 2920 "cs-parser.jay" +{ + Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_375() +#line 2929 "cs-parser.jay" +{ + report.Error (1536, GetLocation (yyVals[0+yyTop]), "Invalid parameter type `void'"); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_378() +#line 2945 "cs-parser.jay" +{ + MemberName name = (MemberName) yyVals[-1+yyTop]; + + if (yyVals[0+yyTop] != null) { + yyVal = new ComposedCast (name.GetTypeExpression (), (ComposedTypeSpecifier) yyVals[0+yyTop]); + } else { + if (name.Left == null && name.Name == "var") + yyVal = new VarExpr (name.Location); + else + yyVal = name.GetTypeExpression (); + } + } + +void case_380() +#line 2962 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + +void case_383() +#line 2978 "cs-parser.jay" +{ + var types = new List (2); + types.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = types; + } + +void case_384() +#line 2984 "cs-parser.jay" +{ + var types = (List) yyVals[-2+yyTop]; + types.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = types; + } + +void case_385() +#line 2993 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is ComposedCast) { + report.Error (1521, GetLocation (yyVals[0+yyTop]), "Invalid base type `{0}'", ((ComposedCast)yyVals[0+yyTop]).GetSignatureForError ()); + } + yyVal = yyVals[0+yyTop]; + } + +void case_386() +#line 3000 "cs-parser.jay" +{ + Error_TypeExpected (lexer.Location); + yyVal = null; + } + +void case_423() +#line 3062 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new SimpleName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); + } + +void case_424() +#line 3066 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); + } + +void case_435() +#line 3107 "cs-parser.jay" +{ + yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_437() +#line 3119 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_438() +#line 3125 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_439() +#line 3131 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_440() +#line 3137 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) yyVals[0+yyTop], lt1.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_442() +#line 3147 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new CompletionMemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, lt.Location); + } + +void case_444() +#line 3155 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new CompletionMemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, lt.Location); + } + +void case_445() +#line 3163 "cs-parser.jay" +{ + yyVal = new Invocation ((Expression) yyVals[-3+yyTop], (Arguments) yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_448() +#line 3176 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] == null) { + yyVal = CollectionOrObjectInitializers.Empty; + /* TODO: lbag*/ + } else { + yyVal = new CollectionOrObjectInitializers ((List) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + } + +void case_449() +#line 3186 "cs-parser.jay" +{ + yyVal = new CollectionOrObjectInitializers ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_452() +#line 3202 "cs-parser.jay" +{ + var a = new List (); + a.Add ((Expression) yyVals[0+yyTop]); + yyVal = a; + } + +void case_453() +#line 3208 "cs-parser.jay" +{ + var a = (List)yyVals[-2+yyTop]; + a.Add ((Expression) yyVals[0+yyTop]); + yyVal = a; + } + +void case_454() +#line 3213 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = yyVals[-1+yyTop]; + } + +void case_455() +#line 3221 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new ElementInitializer (lt.Value, (Expression)yyVals[0+yyTop], lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_457() +#line 3230 "cs-parser.jay" +{ + CompletionSimpleName csn = yyVals[-1+yyTop] as CompletionSimpleName; + if (csn == null) + yyVal = new CollectionElementInitializer ((Expression)yyVals[-1+yyTop]); + else + yyVal = new CompletionElementInitializer (csn.Prefix, csn.Location); + } + +void case_458() +#line 3238 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] == null) + yyVal = null; + else + yyVal = new CollectionElementInitializer ((List)yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + } + +void case_459() +#line 3245 "cs-parser.jay" +{ + report.Error (1920, GetLocation (yyVals[-1+yyTop]), "An element initializer cannot be empty"); + yyVal = null; + } + +void case_464() +#line 3263 "cs-parser.jay" +{ + Arguments list = new Arguments (4); + list.Add ((Argument) yyVals[0+yyTop]); + yyVal = list; + } + +void case_465() +#line 3269 "cs-parser.jay" +{ + Arguments list = (Arguments) yyVals[-2+yyTop]; + if (list [list.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); + + list.Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_466() +#line 3279 "cs-parser.jay" +{ + Arguments list = (Arguments) yyVals[-2+yyTop]; + NamedArgument a = (NamedArgument) yyVals[0+yyTop]; + for (int i = 0; i < list.Count; ++i) { + NamedArgument na = list [i] as NamedArgument; + if (na != null && na.Name == a.Name) + report.Error (1740, na.Location, "Named argument `{0}' specified multiple times", + na.Name); + } + + list.Add (a); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_467() +#line 3294 "cs-parser.jay" +{ + report.Error (839, GetLocation (yyVals[0+yyTop]), "An argument is missing"); + yyVal = yyVals[-1+yyTop]; + } + +void case_468() +#line 3299 "cs-parser.jay" +{ + report.Error (839, GetLocation (yyVals[-1+yyTop]), "An argument is missing"); + yyVal = null; + } + +void case_473() +#line 3320 "cs-parser.jay" +{ + yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Ref); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_474() +#line 3325 "cs-parser.jay" +{ + yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Out); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_475() +#line 3330 "cs-parser.jay" +{ + yyVal = new Argument (new Arglist ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop]))); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_476() +#line 3335 "cs-parser.jay" +{ + yyVal = new Argument (new Arglist (GetLocation (yyVals[-2+yyTop]))); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_478() +#line 3347 "cs-parser.jay" +{ + yyVal = new ElementAccess ((Expression) yyVals[-3+yyTop], (Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_479() +#line 3355 "cs-parser.jay" +{ + var list = new List (4); + list.Add ((Expression) yyVals[0+yyTop]); + yyVal = list; + } + +void case_480() +#line 3361 "cs-parser.jay" +{ + var list = (List) yyVals[-2+yyTop]; + list.Add ((Expression) yyVals[0+yyTop]); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_481() +#line 3367 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = yyVals[-1+yyTop]; + } + +void case_482() +#line 3375 "cs-parser.jay" +{ + Arguments args = new Arguments (4); + args.Add ((Argument) yyVals[0+yyTop]); + yyVal = args; + } + +void case_483() +#line 3381 "cs-parser.jay" +{ + Arguments args = (Arguments) yyVals[-2+yyTop]; + if (args [args.Count - 1] is NamedArgument && !(yyVals[0+yyTop] is NamedArgument)) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) yyVals[0+yyTop]); + lbag.AppendTo (args, GetLocation (yyVals[-1+yyTop])); + yyVal = args; + } + +void case_487() +#line 3409 "cs-parser.jay" +{ + yyVal = new ElementAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), (Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_488() +#line 3414 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new ElementAccess (null, null, GetLocation (yyVals[-1+yyTop])); + } + +void case_491() +#line 3436 "cs-parser.jay" +{ + if (yyVals[0+yyTop] != null) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-5+yyTop]), "object initializers"); + + yyVal = new NewInitialize ((FullNamedExpression) yyVals[-4+yyTop], (Arguments) yyVals[-2+yyTop], (CollectionOrObjectInitializers) yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])); + } else { + yyVal = new New ((FullNamedExpression) yyVals[-4+yyTop], (Arguments) yyVals[-2+yyTop], GetLocation (yyVals[-5+yyTop])); + } + + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_492() +#line 3449 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "collection initializers"); + + yyVal = new NewInitialize ((FullNamedExpression) yyVals[-1+yyTop], null, (CollectionOrObjectInitializers) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } + +void case_493() +#line 3461 "cs-parser.jay" +{ + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-5+yyTop], (List) yyVals[-3+yyTop], + new ComposedTypeSpecifier (((List) yyVals[-3+yyTop]).Count, GetLocation (yyVals[-4+yyTop])) { + Next = (ComposedTypeSpecifier) yyVals[-1+yyTop] + }, (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-6+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_494() +#line 3469 "cs-parser.jay" +{ + if (yyVals[0+yyTop] == null) + report.Error (1586, GetLocation (yyVals[-3+yyTop]), "Array creation must have array size or array initializer"); + + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-2+yyTop], (ComposedTypeSpecifier) yyVals[-1+yyTop], (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + } + +void case_495() +#line 3476 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "implicitly typed arrays"); + + yyVal = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) yyVals[-1+yyTop], (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } + +void case_496() +#line 3483 "cs-parser.jay" +{ + report.Error (178, GetLocation (yyVals[-1+yyTop]), "Invalid rank specifier, expecting `,' or `]'"); + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-5+yyTop], null, GetLocation (yyVals[-6+yyTop])); + } + +void case_497() +#line 3488 "cs-parser.jay" +{ + Error_SyntaxError (1526, yyToken, "Unexpected symbol"); + yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-1+yyTop], null, GetLocation (yyVals[-2+yyTop])); + } + +void case_499() +#line 3499 "cs-parser.jay" +{ + --lexer.parsing_type; + yyVal = yyVals[0+yyTop]; + } + +void case_500() +#line 3507 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "anonymous types"); + + yyVal = new NewAnonymousType ((List) yyVals[-1+yyTop], current_container, GetLocation (yyVals[-3+yyTop])); + + /* TODO: lbag comma location*/ + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_505() +#line 3530 "cs-parser.jay" +{ + var a = new List (4); + a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); + yyVal = a; + } + +void case_506() +#line 3536 "cs-parser.jay" +{ + var a = (List) yyVals[-2+yyTop]; + a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); + yyVal = a; + } + +void case_507() +#line 3545 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken)yyVals[-2+yyTop]; + yyVal = new AnonymousTypeParameter ((Expression)yyVals[0+yyTop], lt.Value, lt.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_508() +#line 3551 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; + yyVal = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), + lt.Value, lt.Location); + } + +void case_509() +#line 3557 "cs-parser.jay" +{ + MemberAccess ma = (MemberAccess) yyVals[0+yyTop]; + yyVal = new AnonymousTypeParameter (ma, ma.Name, ma.Location); + } + +void case_510() +#line 3562 "cs-parser.jay" +{ + report.Error (746, lexer.Location, + "Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); + yyVal = null; + } + +void case_514() +#line 3577 "cs-parser.jay" +{ + ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; + yyVal = yyVals[-1+yyTop]; + } + +void case_515() +#line 3585 "cs-parser.jay" +{ + yyVal = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation (yyVals[-1+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_516() +#line 3590 "cs-parser.jay" +{ + yyVal = ComposedTypeSpecifier.CreateArrayDimension ((int)yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_521() +#line 3620 "cs-parser.jay" +{ + var ai = new ArrayInitializer (0, GetLocation (yyVals[-1+yyTop])); + ai.VariableDeclaration = current_variable; + lbag.AddLocation (ai, GetLocation (yyVals[0+yyTop])); + yyVal = ai; + } + +void case_522() +#line 3627 "cs-parser.jay" +{ + var ai = new ArrayInitializer ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); + ai.VariableDeclaration = current_variable; + if (yyVals[-1+yyTop] != null) { + lbag.AddLocation (ai, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } else { + lbag.AddLocation (ai, GetLocation (yyVals[0+yyTop])); + } + yyVal = ai; + } + +void case_523() +#line 3641 "cs-parser.jay" +{ + var list = new List (4); + list.Add ((Expression) yyVals[0+yyTop]); + yyVal = list; + } + +void case_524() +#line 3647 "cs-parser.jay" +{ + var list = (List) yyVals[-2+yyTop]; + list.Add ((Expression) yyVals[0+yyTop]); + lbag.AppendTo (list, GetLocation (yyVals[-1+yyTop])); + yyVal = list; + } + +void case_526() +#line 3661 "cs-parser.jay" +{ + lexer.TypeOfParsing = false; + yyVal = new TypeOf ((FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_529() +#line 3672 "cs-parser.jay" +{ + Error_TypeExpected (lexer.Location); + yyVal = null; + } + +void case_530() +#line 3680 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new SimpleName (lt.Value, (int) yyVals[0+yyTop], lt.Location); + } + +void case_531() +#line 3686 "cs-parser.jay" +{ + var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) yyVals[0+yyTop], lt1.Location); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_532() +#line 3694 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + + yyVal = new MemberAccess ((Expression) yyVals[-2+yyTop], lt.Value, lt.Location); + } + +void case_533() +#line 3700 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (int) yyVals[0+yyTop], lt.Location); + } + +void case_534() +#line 3706 "cs-parser.jay" +{ + var te = ((MemberName) yyVals[-3+yyTop]).GetTypeExpression (); + if (te.HasTypeArguments) + Error_TypeExpected (GetLocation (yyVals[0+yyTop])); + + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess (te, lt.Value, (int) yyVals[0+yyTop], lt.Location); + } + +void case_535() +#line 3718 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "generics"); + + yyVal = yyVals[0+yyTop]; + } + +void case_536() +#line 3728 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (lt.Location, "namespace alias qualifier"); + + yyVal = lt; + } + +void case_537() +#line 3739 "cs-parser.jay" +{ + yyVal = new SizeOf ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_538() +#line 3747 "cs-parser.jay" +{ + yyVal = new CheckedExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_539() +#line 3755 "cs-parser.jay" +{ + yyVal = new UnCheckedExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_540() +#line 3763 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberAccess (new Indirection ((Expression) yyVals[-3+yyTop], GetLocation (yyVals[-2+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); + } + +void case_542() +#line 3775 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + if ((ParametersCompiled) yyVals[-2+yyTop] != ParametersCompiled.Undefined) { + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), savedOpenLocation, savedCloseLocation); + } else { + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop])); + } + } + +void case_548() +#line 3807 "cs-parser.jay" +{ + valid_param_mod = 0; + yyVal = yyVals[-1+yyTop]; + savedOpenLocation = GetLocation (yyVals[-3+yyTop]); + savedCloseLocation = GetLocation (yyVals[-2+yyTop]); + } + +void case_549() +#line 3817 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "default value expression"); + + yyVal = new DefaultValueExpression ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_555() +#line 3842 "cs-parser.jay" +{ + yyVal = new Cast ((FullNamedExpression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_556() +#line 3850 "cs-parser.jay" +{ + current_block.ParametersBlock.IsAsync = true; + yyVal = new Await ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_565() +#line 3891 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Multiply, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_566() +#line 3896 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Division, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_567() +#line 3901 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Modulus, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_569() +#line 3910 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Addition, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_571() +#line 3919 "cs-parser.jay" +{ + /* Shift/Reduce conflict*/ + yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_575() +#line 3936 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LeftShift, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_576() +#line 3941 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.RightShift, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_578() +#line 3950 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LessThan, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_579() +#line 3955 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.GreaterThan, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_580() +#line 3960 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LessThanOrEqual, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_581() +#line 3965 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.GreaterThanOrEqual, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_583() +#line 3974 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Equality, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_584() +#line 3979 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.Inequality, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_586() +#line 3988 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.BitwiseAnd, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_588() +#line 3997 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.ExclusiveOr, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_590() +#line 4006 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.BitwiseOr, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_592() +#line 4015 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LogicalAnd, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_594() +#line 4024 "cs-parser.jay" +{ + yyVal = new Binary (Binary.Operator.LogicalOr, + (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_596() +#line 4033 "cs-parser.jay" +{ + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "null coalescing operator"); + + yyVal = new Nullable.NullCoalescingOperator ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_598() +#line 4044 "cs-parser.jay" +{ + yyVal = new Conditional (new BooleanExpression ((Expression) yyVals[-4+yyTop]), (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_600() +#line 4056 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Multiply, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_601() +#line 4061 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Division, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_602() +#line 4066 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Modulus, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_603() +#line 4071 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Addition, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_604() +#line 4076 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_605() +#line 4081 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.LeftShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_606() +#line 4086 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.RightShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_607() +#line 4091 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.BitwiseAnd, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_608() +#line 4096 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.BitwiseOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_609() +#line 4101 "cs-parser.jay" +{ + yyVal = new CompoundAssign ( + Binary.Operator.ExclusiveOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + +void case_610() +#line 4109 "cs-parser.jay" +{ + var pars = new List (4); + pars.Add ((Parameter) yyVals[0+yyTop]); + + yyVal = pars; + } + +void case_611() +#line 4116 "cs-parser.jay" +{ + var pars = (List) yyVals[-2+yyTop]; + Parameter p = (Parameter)yyVals[0+yyTop]; + if (pars[0].GetType () != p.GetType ()) { + report.Error (748, p.Location, "All lambda parameters must be typed either explicitly or implicitly"); + } + + pars.Add (p); + yyVal = pars; + } + +void case_612() +#line 4130 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Parameter.Modifier) yyVals[-2+yyTop], null, lt.Location); + } + +void case_613() +#line 4136 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + + yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, Parameter.Modifier.NONE, null, lt.Location); + } + +void case_614() +#line 4142 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + yyVal = new ImplicitLambdaParameter (lt.Value, lt.Location); + } + +void case_616() +#line 4150 "cs-parser.jay" +{ + var pars_list = (List) yyVals[0+yyTop]; + yyVal = new ParametersCompiled (pars_list.ToArray ()); + } + +void case_620() +#line 4166 "cs-parser.jay" +{ + Block b = end_block (lexer.Location); + b.IsCompilerGenerated = true; + b.AddStatement (new ContextualReturn ((Expression) yyVals[0+yyTop])); + yyVal = b; + } + +void case_622() +#line 4177 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = EmptyExpression.Null; + } + +void case_623() +#line 4185 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), false, lt.Location); + } + +void case_624() +#line 4191 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + } + +void case_625() +#line 4196 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), true, lt.Location); + } + +void case_626() +#line 4202 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_628() +#line 4211 "cs-parser.jay" +{ + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) yyVals[-2+yyTop], false, GetLocation (yyVals[-4+yyTop])); + } + +void case_629() +#line 4216 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_631() +#line 4225 "cs-parser.jay" +{ + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) yyVals[-2+yyTop], true, GetLocation (yyVals[-5+yyTop])); + } + +void case_632() +#line 4230 "cs-parser.jay" +{ + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop])); + } + +void case_639() +#line 4253 "cs-parser.jay" +{ + yyVal = new RefValueExpr ((Expression) yyVals[-3+yyTop], (FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-5+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_640() +#line 4258 "cs-parser.jay" +{ + yyVal = new RefTypeExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_641() +#line 4263 "cs-parser.jay" +{ + yyVal = new MakeRefExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_645() +#line 4292 "cs-parser.jay" +{ + MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); + Class c = new Class (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]); + if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (c.Location, "static classes"); + } + + push_current_class (c, yyVals[-3+yyTop]); + } + +void case_646() +#line 4303 "cs-parser.jay" +{ + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) yyVals[0+yyTop]); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-5+yyTop])); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + +void case_647() +#line 4315 "cs-parser.jay" +{ + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + +void case_648() +#line 4321 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + yyVal = pop_current_class (); + } + +void case_651() +#line 4336 "cs-parser.jay" +{ + mod_locations = null; + yyVal = ModifierNone; + } + +void case_654() +#line 4346 "cs-parser.jay" +{ + var m1 = (Modifiers) yyVals[-1+yyTop]; + var m2 = (Modifiers) yyVals[0+yyTop]; + + if ((m1 & m2) != 0) { + report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, + "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); + } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && + ((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { + report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, + "More than one protection modifier specified"); + } + + yyVal = m1 | m2; + } + +void case_655() +#line 4365 "cs-parser.jay" +{ + yyVal = Modifiers.NEW; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + + if (current_container == module) + report.Error (1530, GetLocation (yyVals[0+yyTop]), "Keyword `new' is not allowed on namespace elements"); + } + +void case_656() +#line 4373 "cs-parser.jay" +{ + yyVal = Modifiers.PUBLIC; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_657() +#line 4378 "cs-parser.jay" +{ + yyVal = Modifiers.PROTECTED; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_658() +#line 4383 "cs-parser.jay" +{ + yyVal = Modifiers.INTERNAL; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_659() +#line 4388 "cs-parser.jay" +{ + yyVal = Modifiers.PRIVATE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_660() +#line 4393 "cs-parser.jay" +{ + yyVal = Modifiers.ABSTRACT; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_661() +#line 4398 "cs-parser.jay" +{ + yyVal = Modifiers.SEALED; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_662() +#line 4403 "cs-parser.jay" +{ + yyVal = Modifiers.STATIC; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_663() +#line 4408 "cs-parser.jay" +{ + yyVal = Modifiers.READONLY; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_664() +#line 4413 "cs-parser.jay" +{ + yyVal = Modifiers.VIRTUAL; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_665() +#line 4418 "cs-parser.jay" +{ + yyVal = Modifiers.OVERRIDE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_666() +#line 4423 "cs-parser.jay" +{ + yyVal = Modifiers.EXTERN; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_667() +#line 4428 "cs-parser.jay" +{ + yyVal = Modifiers.VOLATILE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_668() +#line 4433 "cs-parser.jay" +{ + yyVal = Modifiers.UNSAFE; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); + } + +void case_669() +#line 4440 "cs-parser.jay" +{ + yyVal = Modifiers.ASYNC; + StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_674() +#line 4461 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_675() +#line 4469 "cs-parser.jay" +{ + var constraints = new List (1); + constraints.Add ((Constraints) yyVals[0+yyTop]); + yyVal = constraints; + } + +void case_676() +#line 4475 "cs-parser.jay" +{ + var constraints = (List) yyVals[-1+yyTop]; + Constraints new_constraint = (Constraints)yyVals[0+yyTop]; + + foreach (Constraints c in constraints) { + if (new_constraint.TypeParameter.Value == c.TypeParameter.Value) { + report.Error (409, new_constraint.Location, + "A constraint clause has already been specified for type parameter `{0}'", + new_constraint.TypeParameter.Value); + } + } + + constraints.Add (new_constraint); + yyVal = constraints; + } + +void case_677() +#line 4494 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + yyVal = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + } + +void case_678() +#line 4502 "cs-parser.jay" +{ + var constraints = new List (1); + constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = constraints; + } + +void case_679() +#line 4508 "cs-parser.jay" +{ + var constraints = (List) yyVals[-2+yyTop]; + var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Constructor) != 0) { + report.Error (401, GetLocation (yyVals[-1+yyTop]), "The `new()' constraint must be the last constraint specified"); + } + + prev = yyVals[0+yyTop] as SpecialContraintExpr; + if (prev != null) { + if ((prev.Constraint & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) { + report.Error (449, prev.Location, "The `class' or `struct' constraint must be the first constraint specified"); + } else { + prev = constraints [0] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Struct) != 0) { + report.Error (451, GetLocation (yyVals[0+yyTop]), "The `new()' constraint cannot be used with the `struct' constraint"); + } + } + } + + constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); + yyVal = constraints; + } + +void case_680() +#line 4534 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is ComposedCast) + report.Error (706, GetLocation (yyVals[0+yyTop]), "Invalid constraint type `{0}'", ((ComposedCast)yyVals[0+yyTop]).GetSignatureForError ()); + + yyVal = yyVals[0+yyTop]; + } + +void case_681() +#line 4541 "cs-parser.jay" +{ + yyVal = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_685() +#line 4561 "cs-parser.jay" +{ + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (lexer.Location, "generic type variance"); + + yyVal = yyVals[0+yyTop]; + } + +void case_688() +#line 4595 "cs-parser.jay" +{ + ++lexer.parsing_block; + start_block (GetLocation (yyVals[0+yyTop])); + } + +void case_690() +#line 4607 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = end_block (GetLocation (yyVals[0+yyTop])); + } + +void case_691() +#line 4612 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = end_block (lexer.Location); + } + +void case_692() +#line 4621 "cs-parser.jay" +{ + ++lexer.parsing_block; + current_block.StartLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_693() +#line 4626 "cs-parser.jay" +{ + --lexer.parsing_block; + yyVal = end_block (GetLocation (yyVals[0+yyTop])); + } + +void case_701() +#line 4653 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_734() +#line 4717 "cs-parser.jay" +{ + report.Error (1023, GetLocation (yyVals[0+yyTop]), "An embedded statement may not be a declaration or labeled statement"); + yyVal = null; + } + +void case_735() +#line 4722 "cs-parser.jay" +{ + report.Error (1023, GetLocation (yyVals[0+yyTop]), "An embedded statement may not be a declaration or labeled statement"); + yyVal = null; + } + +void case_736() +#line 4727 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); + } + +void case_737() +#line 4735 "cs-parser.jay" +{ + /* Uses lexer.Location because semicolon location is not kept in quick mode*/ + yyVal = new EmptyStatement (lexer.Location); + } + +void case_738() +#line 4743 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); + + current_block.AddLabel (labeled); + current_block.AddStatement (labeled); + } + +void case_741() +#line 4756 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] is VarExpr) + yyVals[-1+yyTop] = new SimpleName ("var", ((VarExpr) yyVals[-1+yyTop]).Location); + + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + +void case_742() +#line 4772 "cs-parser.jay" +{ + /* Ok, the above "primary_expression" is there to get rid of*/ + /* both reduce/reduce and shift/reduces in the grammar, it should*/ + /* really just be "type_name". If you use type_name, a reduce/reduce*/ + /* creeps up. If you use namespace_or_type_name (which is all we need*/ + /* really) two shift/reduces appear.*/ + /* */ + + /* So the super-trick is that primary_expression*/ + /* can only be either a SimpleName or a MemberAccess. */ + /* The MemberAccess case arises when you have a fully qualified type-name like :*/ + /* Foo.Bar.Blah i;*/ + /* SimpleName is when you have*/ + /* Blah i;*/ + + Expression expr = (Expression) yyVals[-1+yyTop]; + if (yyVals[0+yyTop] == null) { + SimpleName sn = expr as SimpleName; + if (sn != null && sn.Name == "var") + yyVal = new VarExpr (sn.Location); + else + yyVal = yyVals[-1+yyTop]; + } else if (expr is ATypeNameExpression) { + yyVal = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) yyVals[0+yyTop]); + } else { + Error_ExpectingTypeName (expr); + yyVal = null; + } + } + +void case_743() +#line 4802 "cs-parser.jay" +{ + ATypeNameExpression expr = yyVals[-1+yyTop] as ATypeNameExpression; + + if (expr != null) { + yyVal = new ComposedCast (expr, (ComposedTypeSpecifier) yyVals[0+yyTop]); + } else { + Error_ExpectingTypeName ((Expression)yyVals[-1+yyTop]); + yyVal = expr; + } + } + +void case_744() +#line 4813 "cs-parser.jay" +{ + if (yyVals[0+yyTop] == null) + yyVal = yyVals[-1+yyTop]; + else + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); + } + +void case_747() +#line 4828 "cs-parser.jay" +{ + Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); + yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); + } + +void case_749() +#line 4837 "cs-parser.jay" +{ + ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; + yyVal = yyVals[-1+yyTop]; + } + +void case_751() +#line 4852 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_752() +#line 4859 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + lbag.AppendTo (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_753() +#line 4865 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockConstantDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_754() +#line 4872 "cs-parser.jay" +{ + if (current_variable.Initializer != null) { + lbag.AddLocation (current_variable, GetLocation (yyVals[-6+yyTop]), savedLocation, GetLocation (yyVals[0+yyTop])); + } else { + lbag.AddLocation (current_variable, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[0+yyTop])); + } + yyVal = current_variable;; + current_variable = null; + } + +void case_756() +#line 4886 "cs-parser.jay" +{ + current_variable.Initializer = (Expression) yyVals[0+yyTop]; + lbag.AppendTo (current_variable, GetLocation (yyVals[-1+yyTop])); + } + +void case_757() +#line 4891 "cs-parser.jay" +{ + 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"); + } else { + Error_SyntaxError (yyToken); + } + } + +void case_762() +#line 4913 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, null); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation (yyVals[-1+yyTop])); + } + +void case_763() +#line 4922 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) yyVals[0+yyTop]); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_765() +#line 4938 "cs-parser.jay" +{ + savedLocation = GetLocation (yyVals[-1+yyTop]); + current_variable.Initializer = (Expression) yyVals[0+yyTop]; + } + +void case_770() +#line 4956 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) yyVals[0+yyTop]); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_772() +#line 4969 "cs-parser.jay" +{ + yyVal = new StackAlloc ((Expression) yyVals[-3+yyTop], (Expression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_773() +#line 4974 "cs-parser.jay" +{ + report.Error (1575, GetLocation (yyVals[-1+yyTop]), "A stackalloc expression requires [] after type"); + yyVal = new StackAlloc ((Expression) yyVals[0+yyTop], null, GetLocation (yyVals[-1+yyTop])); + } + +void case_774() +#line 4982 "cs-parser.jay" +{ + yyVal = yyVals[-1+yyTop]; + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_778() +#line 5000 "cs-parser.jay" +{ + ExpressionStatement s = yyVals[0+yyTop] as ExpressionStatement; + if (s == null) { + Expression.Error_InvalidExpressionStatement (report, GetLocation (yyVals[0+yyTop])); + yyVal = new StatementExpression (EmptyExpressionStatement.Instance); + } else { + yyVal = new StatementExpression (s); + } + } + +void case_779() +#line 5013 "cs-parser.jay" +{ + Expression expr = (Expression) yyVals[0+yyTop]; + ExpressionStatement s; + + s = new OptionalAssign (new SimpleName ("$retval", lexer.Location), expr, lexer.Location); + yyVal = new StatementExpression (s); + } + +void case_780() +#line 5021 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); + } + +void case_783() +#line 5035 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + yyVal = new If ((BooleanExpression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_784() +#line 5044 "cs-parser.jay" +{ + yyVal = new If ((BooleanExpression) yyVals[-4+yyTop], (Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-6+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + + if (yyVals[-2+yyTop] is EmptyStatement) + Warning_EmptyStatement (GetLocation (yyVals[-2+yyTop])); + if (yyVals[0+yyTop] is EmptyStatement) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + } + +void case_786() +#line 5061 "cs-parser.jay" +{ + yyVal = new Switch ((Expression) yyVals[-5+yyTop], (ExplicitBlock) current_block.Explicit, (List) yyVals[-1+yyTop], GetLocation (yyVals[-7+yyTop])); + end_block (GetLocation (yyVals[0+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_787() +#line 5070 "cs-parser.jay" +{ + report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); + yyVal = new List (); + } + +void case_789() +#line 5079 "cs-parser.jay" +{ + var sections = new List (4); + + sections.Add ((SwitchSection) yyVals[0+yyTop]); + yyVal = sections; + } + +void case_790() +#line 5086 "cs-parser.jay" +{ + var sections = (List) yyVals[-1+yyTop]; + + sections.Add ((SwitchSection) yyVals[0+yyTop]); + yyVal = sections; + } + +void case_791() +#line 5093 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = new List (); + } + +void case_794() +#line 5112 "cs-parser.jay" +{ + var labels = new List (2); + + labels.Add ((SwitchLabel) yyVals[0+yyTop]); + yyVal = labels; + } + +void case_795() +#line 5119 "cs-parser.jay" +{ + var labels = (List) (yyVals[-1+yyTop]); + labels.Add ((SwitchLabel) yyVals[0+yyTop]); + + yyVal = labels; + } + +void case_796() +#line 5129 "cs-parser.jay" +{ + yyVal = new SwitchLabel ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_802() +#line 5148 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + yyVal = new While ((BooleanExpression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_803() +#line 5160 "cs-parser.jay" +{ + yyVal = new Do ((Statement) yyVals[-5+yyTop], (BooleanExpression) yyVals[-2+yyTop], GetLocation (yyVals[-6+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_804() +#line 5168 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[0+yyTop])); + current_block.IsCompilerGenerated = true; + } + +void case_806() +#line 5184 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + For f = new For ((Statement) yyVals[-6+yyTop], (BooleanExpression) yyVals[-4+yyTop], (Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-9+yyTop])); + current_block.AddStatement (f); + + lbag.AddStatement (f, current_block.StartLocation, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + + yyVal = end_block (GetLocation (yyVals[-5+yyTop])); + } + +void case_807() +#line 5196 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = end_block (current_block.StartLocation); + } + +void case_810() +#line 5209 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_811() +#line 5216 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + } + +void case_819() +#line 5240 "cs-parser.jay" +{ + var sl = yyVals[-2+yyTop] as StatementList; + if (sl == null) { + sl = new StatementList ((Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop]); + lbag.AddStatement (sl, GetLocation (yyVals[-1+yyTop])); + } else { + sl.Add ((Statement) yyVals[0+yyTop]); + lbag.AppendTo (sl, GetLocation (yyVals[-1+yyTop])); + } + + yyVal = sl; + } + +void case_820() +#line 5256 "cs-parser.jay" +{ + report.Error (230, GetLocation (yyVals[-5+yyTop]), "Type and identifier are both required in a foreach statement"); + yyVal = null; + } + +void case_821() +#line 5261 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-5+yyTop])); + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + yyVal = li; + } + +void case_822() +#line 5270 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Foreach f = new Foreach ((Expression) yyVals[-6+yyTop], (LocalVariable) yyVals[-1+yyTop], (Expression) yyVals[-3+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-8+yyTop])); + current_block.AddStatement (f); + + lbag.AddStatement (f, GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = end_block (GetLocation (yyVals[-2+yyTop])); + } + +void case_829() +#line 5293 "cs-parser.jay" +{ + yyVal = new Break (GetLocation (yyVals[-1+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_830() +#line 5301 "cs-parser.jay" +{ + yyVal = new Continue (GetLocation (yyVals[-1+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_831() +#line 5309 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new Goto (lt.Value, GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_832() +#line 5315 "cs-parser.jay" +{ + yyVal = new GotoCase ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_833() +#line 5320 "cs-parser.jay" +{ + yyVal = new GotoDefault (GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_834() +#line 5328 "cs-parser.jay" +{ + yyVal = new Return ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_835() +#line 5336 "cs-parser.jay" +{ + yyVal = new Throw ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_836() +#line 5344 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if (yyVals[-1+yyTop] == null) { + report.Error (1627, GetLocation (yyVals[0+yyTop]), "Expression expected after yield return"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + yyVal = new Yield ((Expression) yyVals[-1+yyTop], lt.Location); + lbag.AddStatement (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_837() +#line 5360 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + yyVal = new YieldBreak (lt.Location); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + } + +void case_841() +#line 5386 "cs-parser.jay" +{ + yyVal = new TryFinally ((Statement) yyVals[-2+yyTop], (Block) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_842() +#line 5391 "cs-parser.jay" +{ + yyVal = new TryFinally (new TryCatch ((Block) yyVals[-3+yyTop], (List) yyVals[-2+yyTop], GetLocation (yyVals[-4+yyTop]), true), (Block) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop])); + } + +void case_843() +#line 5396 "cs-parser.jay" +{ + report.Error (1524, GetLocation (yyVals[-2+yyTop]), "Expected catch or finally"); + yyVal = null; + } + +void case_844() +#line 5404 "cs-parser.jay" +{ + var l = new List (2); + + l.Add ((Catch) yyVals[0+yyTop]); + yyVal = l; + } + +void case_845() +#line 5411 "cs-parser.jay" +{ + var l = (List) yyVals[-1+yyTop]; + + Catch c = (Catch) yyVals[0+yyTop]; + if (l [0].IsGeneral) { + report.Error (1017, c.loc, "Try statement already has an empty catch block"); + } else { + if (c.IsGeneral) + l.Insert (0, c); + else + l.Add (c); + } + + yyVal = l; + } + +void case_849() +#line 5439 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-3+yyTop])); + var c = new Catch (current_block, GetLocation (yyVals[-4+yyTop])); + c.TypeExpression = (FullNamedExpression) yyVals[-2+yyTop]; + + if (yyVals[-1+yyTop] != null) { + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + c.Variable = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (c.Variable); + } + + lbag.AddLocation (c, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + yyVal = c; + } + +void case_851() +#line 5458 "cs-parser.jay" +{ + if (yyToken == Token.CLOSE_PARENS) { + report.Error (1015, lexer.Location, + "A type that derives from `System.Exception', `object', or `string' expected"); + } else { + Error_SyntaxError (yyToken); + } + + yyVal = new Catch (null, GetLocation (yyVals[-2+yyTop])); + } + +void case_854() +#line 5486 "cs-parser.jay" +{ + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); + } + +void case_856() +#line 5496 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + yyVal = new Lock ((Expression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + } + +void case_857() +#line 5507 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-2+yyTop])); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.FixedVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_858() +#line 5517 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + } + +void case_859() +#line 5522 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Fixed f = new Fixed ((Fixed.VariableDeclaration) yyVals[-1+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-9+yyTop])); + current_block.AddStatement (f); + lbag.AddStatement (f, GetLocation (yyVals[-8+yyTop]), GetLocation (yyVals[-2+yyTop])); + yyVal = end_block (GetLocation (yyVals[-2+yyTop])); + } + +void case_860() +#line 5535 "cs-parser.jay" +{ + start_block (GetLocation (yyVals[-2+yyTop])); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.UsingVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Using.VariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); + } + +void case_861() +#line 5545 "cs-parser.jay" +{ + yyVal = current_variable; + current_variable = null; + } + +void case_862() +#line 5550 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Using u = new Using ((Using.VariableDeclaration) yyVals[-1+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-9+yyTop])); + lbag.AddStatement (u, GetLocation (yyVals[-8+yyTop]), GetLocation (yyVals[-2+yyTop])); + current_block.AddStatement (u); + yyVal = end_block (GetLocation (yyVals[-2+yyTop])); + } + +void case_863() +#line 5560 "cs-parser.jay" +{ + if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); + + Using u = new Using ((Expression) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddStatement (u, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + yyVal = u; + } + +void case_865() +#line 5576 "cs-parser.jay" +{ + current_variable.Initializer = (Expression) yyVals[0+yyTop]; + yyVal = current_variable; + } + +void case_866() +#line 5587 "cs-parser.jay" +{ + lexer.query_parsing = false; + + Linq.AQueryClause from = yyVals[-1+yyTop] as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_867() +#line 5599 "cs-parser.jay" +{ + Linq.AQueryClause from = yyVals[-1+yyTop] as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_868() +#line 5610 "cs-parser.jay" +{ + lexer.query_parsing = false; + yyVal = yyVals[-1+yyTop]; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_869() +#line 5617 "cs-parser.jay" +{ + yyVal = yyVals[-1+yyTop]; + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_870() +#line 5626 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-3+yyTop]))); + } + +void case_871() +#line 5634 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-4+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-3+yyTop] + } + ); + } + +void case_872() +#line 5649 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-3+yyTop]))); + } + +void case_873() +#line 5657 "cs-parser.jay" +{ + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-4+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-3+yyTop] + } + ); + } + +void case_875() +#line 5676 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + +void case_877() +#line 5691 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + + yyVal = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-4+yyTop] + }; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + +void case_878() +#line 5708 "cs-parser.jay" +{ + Linq.AQueryClause head = (Linq.AQueryClause)yyVals[-1+yyTop]; + + if (yyVals[0+yyTop] != null) + head.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + + if (yyVals[-2+yyTop] != null) { + Linq.AQueryClause clause = (Linq.AQueryClause)yyVals[-2+yyTop]; + clause.Tail.Next = head; + head = clause; + } + + yyVal = head; + } + +void case_880() +#line 5724 "cs-parser.jay" +{ + Error_SyntaxError (yyToken); + yyVal = null; + } + +void case_882() +#line 5736 "cs-parser.jay" +{ + yyVal = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_883() +#line 5743 "cs-parser.jay" +{ + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock)current_block); + } + +void case_884() +#line 5751 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_885() +#line 5758 "cs-parser.jay" +{ + yyVal = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)yyVals[-3+yyTop], linq_clause_blocks.Pop (), (Expression)yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_889() +#line 5775 "cs-parser.jay" +{ + ((Linq.AQueryClause)yyVals[-1+yyTop]).Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = yyVals[-1+yyTop]; + } + +void case_896() +#line 5795 "cs-parser.jay" +{ + var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + +void case_898() +#line 5814 "cs-parser.jay" +{ + yyVal = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + +void case_899() +#line 5824 "cs-parser.jay" +{ + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_900() +#line 5832 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_901() +#line 5840 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_902() +#line 5848 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) yyVals[-10+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if (yyVals[0+yyTop] == null) { + into = sn; + yyVal = new Linq.Join (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, GetLocation (yyVals[-11+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-3+yyTop])); + } else { + /**/ + /* Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions*/ + /**/ + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + into = new Linq.RangeVariable (lt.Value, lt.Location); + + yyVal = new Linq.GroupJoin (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, into, GetLocation (yyVals[-11+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + +void case_903() +#line 5886 "cs-parser.jay" +{ + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_904() +#line 5894 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_905() +#line 5902 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_906() +#line 5910 "cs-parser.jay" +{ + current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) yyVals[-10+yyTop]; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if (yyVals[0+yyTop] == null) { + into = sn; + yyVal = new Linq.Join (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, GetLocation (yyVals[-12+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-11+yyTop] + }; + } else { + /**/ + /* Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions*/ + /**/ + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; + into = new Linq.RangeVariable (lt.Value, lt.Location); /* TODO:*/ + + yyVal = new Linq.GroupJoin (block, sn, (Expression)yyVals[-7+yyTop], outer_selector, (Linq.QueryBlock) current_block, into, GetLocation (yyVals[-12+yyTop])) { + IdentifierType = (FullNamedExpression)yyVals[-11+yyTop] + }; + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + +void case_910() +#line 5965 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + yyVal = yyVals[0+yyTop]; + } + +void case_912() +#line 5976 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + +void case_913() +#line 5983 "cs-parser.jay" +{ + ((Linq.AQueryClause)yyVals[-3+yyTop]).Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = yyVals[-3+yyTop]; + } + +void case_915() +#line 5992 "cs-parser.jay" +{ + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); + } + +void case_916() +#line 5999 "cs-parser.jay" +{ + ((Linq.AQueryClause)yyVals[-3+yyTop]).Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; + yyVal = yyVals[-3+yyTop]; + } + +void case_918() +#line 6011 "cs-parser.jay" +{ + yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_919() +#line 6016 "cs-parser.jay" +{ + yyVal = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_921() +#line 6028 "cs-parser.jay" +{ + yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_922() +#line 6033 "cs-parser.jay" +{ + yyVal = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); + lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + } + +void case_924() +#line 6043 "cs-parser.jay" +{ + /* query continuation block is not linked with query block but with block*/ + /* before. This means each query can use same range variable names for*/ + /* different identifiers.*/ + + current_block.SetEndLocation (GetLocation (yyVals[-1+yyTop])); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + +void case_925() +#line 6059 "cs-parser.jay" +{ + var current_block = linq_clause_blocks.Pop (); + var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + yyVal = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, rv, GetLocation (yyVals[-3+yyTop])) { + next = (Linq.AQueryClause)yyVals[0+yyTop] + }; + } + +void case_928() +#line 6086 "cs-parser.jay" +{ + current_container = new Class (current_namespace, current_class, new MemberName (""), Modifiers.PUBLIC, null); + current_class = current_container; + + /* (ref object retval)*/ + Parameter [] mpar = new Parameter [1]; + mpar [0] = new Parameter (new TypeExpression (compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null); + + ParametersCompiled pars = new ParametersCompiled (mpar); + var mods = Modifiers.PUBLIC | Modifiers.STATIC; + if (settings.Unsafe) + mods |= Modifiers.UNSAFE; + + current_local_parameters = pars; + Method method = new Method ( + current_class, + null, /* generic*/ + new TypeExpression (compiler.BuiltinTypes.Void, Location.Null), + mods, + new MemberName ("Host"), + pars, + null /* attributes */); + + current_container.AddMethod (method); + + oob_stack.Push (method); + ++lexer.parsing_block; + start_block (lexer.Location); + } + +void case_929() +#line 6116 "cs-parser.jay" +{ + --lexer.parsing_block; + Method method = (Method) oob_stack.Pop (); + + method.Block = (ToplevelBlock) end_block(lexer.Location); + + InteractiveResult = (Class) pop_current_class (); + current_local_parameters = null; + } + +void case_939() +#line 6159 "cs-parser.jay" +{ + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-1+yyTop]; + module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; + yyVal = null; + } + +void case_940() +#line 6165 "cs-parser.jay" +{ + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-3+yyTop]; + module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; + var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; + yyVal = new MemberName (lt.Value); + } + +void case_943() +#line 6180 "cs-parser.jay" +{ + module.DocumentationBuilder.ParsedParameters = (List)yyVals[-1+yyTop]; + yyVal = new MemberName ((MemberName) yyVals[-6+yyTop], new MemberName (MemberCache.IndexerNameAlias)); + } + +void case_944() +#line 6185 "cs-parser.jay" +{ + var p = (List)yyVals[0+yyTop] ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Explicit; + yyVal = null; + } + +void case_945() +#line 6193 "cs-parser.jay" +{ + var p = (List)yyVals[0+yyTop] ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Implicit; + yyVal = null; + } + +void case_946() +#line 6201 "cs-parser.jay" +{ + var p = (List)yyVals[0+yyTop] ?? new List (1); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = (Operator.OpType) yyVals[-1+yyTop]; + yyVal = null; + } + +void case_954() +#line 6239 "cs-parser.jay" +{ + var parameters = new List (); + parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); + yyVal = parameters; + } + +void case_955() +#line 6245 "cs-parser.jay" +{ + var parameters = yyVals[-2+yyTop] as List; + parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); + yyVal = parameters; + } + +void case_956() +#line 6254 "cs-parser.jay" +{ + if (yyVals[-1+yyTop] != null) + yyVal = new DocumentationParameter ((Parameter.Modifier) yyVals[-1+yyTop], (FullNamedExpression) yyVals[0+yyTop]); + else + yyVal = new DocumentationParameter ((FullNamedExpression) yyVals[0+yyTop]); + } + +#line default + static readonly short [] yyLhs = { -1, + 0, 4, 0, 0, 1, 1, 1, 1, 2, 2, + 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 16, 21, 22, 19, 20, 20, 20, 24, 24, 25, + 25, 18, 7, 7, 6, 6, 23, 23, 8, 8, + 26, 26, 27, 27, 27, 27, 27, 9, 9, 10, + 10, 35, 33, 38, 34, 34, 36, 36, 36, 36, + 37, 37, 42, 39, 40, 41, 41, 43, 43, 43, + 43, 43, 44, 44, 48, 45, 47, 49, 49, 49, + 50, 50, 51, 51, 52, 52, 52, 52, 52, 52, + 52, 52, 52, 52, 52, 65, 67, 70, 71, 29, + 29, 73, 69, 72, 72, 74, 74, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 78, 53, 79, + 79, 80, 80, 81, 83, 77, 77, 82, 82, 88, + 54, 92, 54, 54, 87, 95, 87, 89, 89, 96, + 96, 97, 98, 97, 93, 93, 99, 99, 100, 101, + 91, 91, 94, 94, 94, 104, 55, 107, 108, 102, + 109, 110, 111, 102, 102, 103, 103, 106, 106, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, + 115, 118, 118, 118, 121, 118, 119, 119, 122, 122, + 123, 123, 123, 116, 116, 116, 124, 124, 124, 117, + 126, 128, 129, 56, 131, 132, 133, 58, 127, 127, + 127, 127, 127, 137, 134, 138, 135, 136, 136, 136, + 139, 140, 141, 143, 30, 30, 142, 142, 144, 144, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 148, + 59, 147, 147, 149, 149, 152, 146, 146, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 154, 153, 155, 153, 153, 153, 60, 158, 160, 156, + 157, 157, 159, 159, 164, 162, 165, 162, 162, 166, + 61, 168, 57, 171, 172, 57, 167, 174, 167, 169, + 169, 175, 175, 176, 177, 176, 178, 173, 170, 170, + 170, 170, 170, 182, 179, 183, 180, 181, 181, 185, + 187, 188, 31, 184, 184, 184, 186, 186, 186, 189, + 189, 190, 191, 190, 192, 193, 194, 32, 195, 195, + 17, 17, 196, 196, 199, 198, 198, 198, 200, 200, + 202, 64, 125, 105, 105, 130, 130, 203, 203, 203, + 201, 201, 204, 204, 205, 205, 207, 207, 86, 76, + 76, 90, 90, 120, 120, 150, 150, 208, 208, 208, + 208, 208, 212, 212, 213, 213, 211, 211, 211, 211, + 211, 211, 211, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 216, 216, 216, 217, 217, 217, 237, 237, + 238, 238, 239, 239, 219, 219, 236, 236, 236, 236, + 236, 236, 236, 236, 221, 240, 240, 241, 241, 242, + 242, 244, 244, 244, 245, 245, 245, 245, 245, 246, + 246, 163, 163, 250, 250, 250, 250, 250, 252, 252, + 251, 251, 253, 253, 253, 253, 254, 222, 249, 249, + 249, 255, 255, 256, 256, 223, 224, 224, 225, 226, + 227, 227, 218, 218, 218, 218, 218, 261, 257, 228, + 262, 262, 263, 263, 264, 264, 265, 265, 265, 265, + 258, 258, 209, 209, 260, 260, 266, 266, 259, 259, + 85, 85, 267, 267, 268, 229, 269, 269, 269, 270, + 270, 270, 270, 270, 271, 197, 230, 231, 232, 233, + 273, 234, 274, 234, 272, 272, 276, 275, 220, 277, + 277, 277, 277, 277, 279, 280, 278, 278, 278, 278, + 278, 278, 278, 281, 281, 281, 281, 282, 282, 282, + 282, 282, 282, 283, 283, 283, 284, 284, 284, 284, + 284, 285, 285, 285, 286, 286, 287, 287, 288, 288, + 289, 289, 290, 290, 291, 291, 292, 292, 293, 293, + 293, 293, 293, 293, 293, 293, 293, 293, 293, 294, + 294, 295, 295, 295, 296, 296, 297, 297, 300, 298, + 299, 299, 302, 301, 303, 301, 304, 305, 301, 306, + 307, 301, 46, 46, 247, 247, 247, 247, 235, 235, + 235, 84, 309, 310, 311, 312, 313, 28, 63, 63, + 62, 62, 112, 112, 314, 314, 314, 314, 314, 314, + 314, 314, 314, 314, 314, 314, 314, 314, 314, 66, + 66, 68, 68, 68, 315, 315, 316, 317, 317, 318, + 318, 318, 318, 206, 206, 319, 319, 321, 113, 322, + 322, 323, 161, 320, 320, 324, 324, 325, 325, 325, + 325, 329, 329, 330, 330, 330, 327, 327, 327, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 327, 331, + 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, + 331, 331, 345, 345, 345, 345, 332, 346, 328, 347, + 347, 348, 348, 348, 348, 348, 348, 210, 210, 349, + 351, 326, 354, 326, 350, 350, 350, 352, 352, 357, + 357, 358, 358, 353, 353, 355, 355, 359, 359, 360, + 356, 356, 356, 333, 333, 344, 344, 361, 362, 362, + 334, 334, 363, 363, 366, 364, 365, 365, 367, 367, + 367, 370, 368, 369, 369, 371, 371, 335, 335, 335, + 335, 372, 373, 377, 374, 376, 376, 378, 378, 382, + 381, 381, 379, 379, 380, 380, 384, 383, 383, 375, + 385, 375, 336, 336, 336, 336, 336, 336, 386, 387, + 388, 388, 388, 389, 390, 391, 391, 392, 392, 337, + 337, 337, 337, 393, 393, 395, 395, 394, 396, 394, + 394, 338, 339, 397, 342, 340, 399, 400, 343, 401, + 402, 341, 341, 398, 398, 308, 308, 308, 308, 403, + 403, 405, 405, 407, 406, 408, 406, 404, 404, 404, + 412, 410, 413, 414, 410, 409, 409, 415, 415, 416, + 416, 416, 416, 416, 421, 417, 422, 418, 423, 424, + 425, 419, 427, 428, 429, 419, 426, 426, 431, 420, + 430, 434, 430, 433, 436, 433, 432, 432, 432, 435, + 435, 435, 411, 437, 411, 3, 3, 438, 3, 3, + 439, 439, 248, 248, 243, 243, 5, 440, 440, 440, + 440, 444, 440, 440, 440, 440, 441, 441, 442, 445, + 442, 443, 443, 446, 446, 447, + }; + static readonly short [] yyLen = { 2, + 2, 0, 3, 1, 2, 4, 3, 1, 0, 1, + 1, 2, 4, 2, 1, 2, 1, 1, 5, 2, + 3, 0, 0, 11, 1, 3, 1, 0, 1, 0, + 1, 1, 0, 1, 0, 1, 0, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, + 2, 0, 3, 0, 6, 3, 1, 1, 1, 1, + 1, 3, 0, 3, 1, 0, 3, 0, 1, 1, + 3, 3, 1, 1, 0, 4, 4, 0, 1, 1, + 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 13, + 5, 0, 4, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 9, 0, + 1, 1, 2, 3, 0, 3, 1, 1, 1, 0, + 8, 0, 9, 6, 0, 0, 3, 0, 1, 1, + 2, 2, 0, 5, 0, 1, 1, 2, 3, 0, + 4, 2, 1, 1, 1, 0, 3, 0, 0, 10, + 0, 0, 0, 12, 8, 1, 1, 0, 1, 1, + 3, 3, 3, 5, 3, 5, 1, 1, 1, 1, + 3, 4, 6, 4, 0, 7, 0, 1, 1, 2, + 1, 1, 1, 4, 6, 4, 1, 2, 2, 1, + 0, 0, 0, 10, 0, 0, 0, 13, 1, 2, + 1, 2, 1, 0, 5, 0, 5, 1, 1, 1, + 0, 0, 0, 0, 15, 5, 0, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 5, 1, 1, 1, 1, 0, 7, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 7, 0, 7, 2, 2, 2, 0, 0, 9, + 1, 1, 0, 1, 0, 6, 0, 6, 1, 0, + 8, 0, 9, 0, 0, 10, 0, 0, 3, 0, + 1, 1, 2, 2, 0, 5, 0, 2, 2, 2, + 1, 1, 1, 0, 5, 0, 5, 1, 1, 0, + 0, 0, 12, 0, 2, 2, 0, 1, 2, 1, + 3, 2, 0, 5, 0, 0, 0, 13, 0, 1, + 1, 3, 1, 4, 2, 0, 3, 2, 1, 3, + 0, 3, 1, 1, 3, 1, 2, 3, 4, 4, + 0, 3, 1, 3, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 1, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 4, 4, 4, 3, + 3, 4, 3, 4, 4, 0, 1, 3, 4, 0, + 1, 1, 3, 2, 3, 1, 2, 3, 2, 1, + 1, 0, 1, 1, 3, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 4, 3, 1, 4, 1, 3, + 2, 1, 3, 1, 1, 1, 4, 3, 2, 2, + 6, 3, 7, 4, 3, 7, 3, 0, 2, 4, + 1, 2, 0, 1, 1, 3, 3, 1, 1, 1, + 0, 1, 1, 2, 2, 3, 1, 2, 0, 1, + 2, 4, 1, 3, 0, 5, 1, 1, 1, 2, + 3, 3, 4, 4, 1, 2, 4, 4, 4, 4, + 0, 4, 0, 5, 0, 1, 0, 4, 4, 1, + 2, 2, 1, 1, 4, 2, 1, 2, 2, 2, + 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, + 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, + 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 5, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, + 3, 3, 2, 1, 0, 1, 1, 1, 0, 2, + 1, 1, 0, 4, 0, 5, 0, 0, 7, 0, + 0, 8, 1, 1, 1, 1, 1, 1, 6, 4, + 4, 1, 1, 0, 0, 0, 0, 15, 0, 1, + 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 0, 1, 1, 1, 2, 4, 1, 3, 1, + 3, 1, 1, 0, 1, 1, 1, 0, 4, 1, + 1, 0, 4, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 4, 1, + 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, + 0, 6, 0, 7, 0, 2, 1, 0, 1, 1, + 2, 2, 4, 0, 2, 0, 1, 1, 2, 4, + 1, 5, 2, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 5, 7, 0, 8, 0, 1, 1, 2, + 1, 0, 3, 1, 2, 3, 1, 1, 1, 1, + 1, 5, 7, 0, 4, 7, 1, 0, 1, 0, + 5, 1, 0, 1, 0, 1, 1, 1, 3, 6, + 0, 9, 1, 1, 1, 1, 1, 1, 2, 2, + 3, 4, 3, 3, 3, 4, 3, 0, 1, 3, + 4, 5, 3, 1, 2, 0, 1, 2, 0, 7, + 3, 2, 2, 0, 3, 5, 0, 0, 10, 0, + 0, 10, 5, 0, 2, 2, 2, 2, 2, 4, + 5, 4, 5, 0, 5, 0, 6, 3, 2, 1, + 0, 3, 0, 0, 6, 0, 1, 1, 2, 1, + 1, 1, 1, 1, 0, 5, 0, 3, 0, 0, + 0, 12, 0, 0, 0, 13, 0, 2, 0, 3, + 1, 0, 4, 1, 0, 4, 1, 2, 2, 1, + 2, 2, 0, 0, 4, 2, 3, 0, 4, 2, + 2, 3, 0, 1, 1, 1, 2, 2, 2, 4, + 3, 0, 7, 4, 4, 3, 1, 3, 0, 0, + 4, 0, 1, 1, 3, 2, + }; + static readonly short [] yyDefRed = { 0, + 8, 0, 0, 0, 0, 0, 0, 0, 2, 4, + 0, 0, 11, 14, 0, 926, 0, 0, 930, 0, + 0, 15, 17, 18, 389, 395, 402, 390, 392, 0, + 391, 0, 398, 400, 387, 0, 394, 396, 388, 399, + 401, 397, 351, 947, 0, 393, 937, 0, 10, 1, + 0, 0, 0, 12, 0, 780, 0, 0, 0, 0, + 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, + 0, 0, 428, 0, 0, 0, 486, 0, 429, 0, + 525, 0, 854, 0, 0, 0, 638, 0, 0, 0, + 0, 0, 0, 0, 688, 0, 737, 0, 0, 0, + 0, 0, 0, 0, 0, 427, 0, 627, 0, 779, + 720, 0, 0, 0, 0, 404, 405, 0, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 421, 422, 425, 426, 634, 557, 0, 553, + 554, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 635, 633, 636, 637, 704, 706, 0, 702, + 705, 721, 723, 724, 725, 726, 727, 728, 729, 730, + 731, 732, 722, 0, 0, 0, 781, 782, 798, 799, + 800, 801, 823, 824, 825, 826, 827, 828, 0, 0, + 0, 20, 0, 0, 0, 341, 0, 343, 934, 16, + 927, 0, 0, 254, 253, 250, 255, 256, 249, 268, + 267, 260, 261, 257, 259, 258, 262, 251, 252, 263, + 264, 270, 269, 265, 266, 0, 0, 950, 0, 939, + 0, 938, 3, 52, 0, 0, 0, 42, 39, 41, + 43, 44, 45, 46, 47, 50, 13, 0, 0, 0, + 829, 431, 432, 852, 0, 0, 0, 0, 0, 0, + 406, 0, 830, 0, 547, 541, 546, 736, 778, 707, + 734, 733, 735, 708, 709, 710, 711, 712, 713, 714, + 715, 716, 717, 718, 719, 0, 0, 0, 804, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 839, 0, 403, 0, 0, 0, 0, 0, 0, + 853, 0, 0, 0, 750, 746, 0, 0, 0, 0, + 0, 0, 370, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 630, 556, 0, 0, 552, 558, 559, 551, + 563, 562, 560, 561, 0, 0, 623, 738, 536, 0, + 424, 423, 0, 0, 0, 0, 340, 0, 744, 745, + 0, 489, 490, 0, 0, 0, 742, 743, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 929, 703, 751, 741, 0, 776, 777, 880, + 897, 0, 0, 0, 909, 868, 866, 890, 0, 0, + 888, 891, 892, 893, 894, 869, 867, 0, 0, 0, + 345, 0, 21, 0, 0, 0, 946, 0, 352, 0, + 0, 0, 948, 0, 0, 40, 660, 666, 658, 0, + 655, 665, 659, 657, 656, 663, 661, 662, 668, 664, + 667, 669, 0, 0, 653, 51, 488, 0, 0, 484, + 485, 0, 482, 0, 753, 0, 0, 0, 0, 774, + 775, 0, 0, 0, 642, 0, 833, 831, 643, 0, + 0, 510, 0, 0, 0, 501, 0, 505, 515, 517, + 0, 497, 0, 0, 0, 0, 0, 492, 0, 495, + 0, 499, 372, 834, 0, 0, 835, 843, 0, 0, + 0, 844, 0, 0, 855, 0, 0, 749, 0, 382, + 0, 378, 379, 0, 377, 380, 381, 0, 0, 0, + 564, 0, 0, 543, 625, 0, 701, 0, 0, 696, + 698, 699, 700, 435, 436, 837, 0, 0, 0, 348, + 349, 0, 192, 191, 193, 0, 0, 0, 0, 374, + 0, 610, 0, 0, 440, 0, 443, 0, 441, 0, + 0, 0, 0, 0, 0, 469, 472, 0, 0, 464, + 471, 470, 0, 599, 600, 601, 602, 603, 604, 605, + 606, 607, 609, 608, 565, 567, 566, 572, 573, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 596, 0, 0, 514, 0, 0, + 0, 0, 0, 0, 0, 881, 883, 879, 0, 889, + 0, 0, 342, 944, 945, 366, 0, 0, 363, 0, + 0, 189, 0, 0, 954, 940, 942, 60, 58, 59, + 0, 0, 53, 0, 0, 61, 63, 27, 25, 0, + 0, 0, 650, 0, 654, 439, 0, 487, 0, 538, + 0, 549, 179, 200, 0, 0, 169, 0, 0, 0, + 180, 542, 0, 857, 807, 0, 818, 805, 0, 809, + 0, 0, 0, 832, 0, 0, 0, 500, 0, 516, + 518, 0, 0, 456, 0, 0, 452, 0, 0, 479, + 0, 520, 494, 0, 155, 521, 153, 154, 523, 0, + 537, 0, 848, 0, 841, 0, 845, 529, 0, 0, + 0, 367, 0, 527, 0, 0, 539, 0, 860, 0, + 872, 0, 870, 0, 0, 640, 641, 0, 0, 0, + 690, 691, 689, 697, 836, 618, 624, 617, 0, 739, + 0, 347, 613, 0, 0, 0, 555, 444, 438, 442, + 437, 540, 478, 477, 474, 473, 0, 468, 433, 434, + 445, 0, 0, 757, 0, 0, 898, 874, 0, 899, + 0, 895, 0, 910, 0, 0, 0, 0, 878, 19, + 344, 687, 686, 0, 685, 0, 362, 956, 190, 951, + 0, 0, 54, 0, 0, 0, 0, 0, 0, 369, + 0, 644, 0, 0, 80, 79, 0, 483, 0, 0, + 0, 0, 0, 548, 0, 0, 0, 0, 0, 810, + 0, 0, 0, 0, 0, 856, 507, 506, 459, 0, + 0, 935, 936, 448, 454, 0, 457, 0, 481, 0, + 0, 0, 0, 0, 785, 851, 0, 842, 535, 530, + 0, 0, 526, 0, 863, 0, 802, 873, 871, 0, + 544, 626, 0, 622, 621, 620, 350, 612, 611, 628, + 476, 0, 466, 465, 598, 0, 771, 756, 0, 0, + 0, 760, 0, 876, 0, 903, 0, 918, 919, 912, + 882, 884, 924, 365, 364, 955, 0, 0, 62, 56, + 0, 64, 26, 23, 0, 0, 320, 0, 226, 0, + 101, 0, 77, 765, 128, 129, 0, 0, 0, 768, + 198, 199, 0, 0, 0, 0, 172, 181, 173, 175, + 0, 0, 0, 0, 814, 0, 819, 820, 0, 0, + 458, 460, 461, 455, 449, 453, 0, 512, 0, 480, + 491, 447, 524, 522, 0, 847, 0, 0, 531, 0, + 0, 639, 631, 0, 475, 0, 0, 752, 761, 875, + 0, 0, 0, 896, 0, 0, 0, 943, 0, 0, + 0, 69, 70, 73, 74, 0, 335, 326, 325, 0, + 645, 222, 97, 0, 754, 769, 184, 0, 196, 0, + 0, 0, 803, 865, 0, 0, 0, 821, 784, 496, + 493, 791, 0, 797, 0, 0, 789, 0, 794, 849, + 534, 533, 0, 0, 629, 0, 0, 877, 900, 0, + 0, 0, 914, 0, 925, 0, 75, 67, 0, 0, + 0, 321, 0, 0, 0, 0, 0, 185, 0, 176, + 174, 858, 811, 0, 0, 816, 0, 0, 786, 790, + 0, 795, 0, 861, 632, 0, 763, 0, 904, 921, + 922, 915, 885, 55, 0, 71, 72, 0, 0, 0, + 0, 0, 0, 0, 770, 183, 0, 195, 0, 0, + 822, 796, 0, 692, 850, 0, 772, 0, 0, 0, + 76, 0, 0, 336, 0, 322, 0, 330, 386, 385, + 0, 383, 674, 0, 646, 0, 675, 223, 98, 186, + 859, 806, 0, 862, 901, 0, 916, 0, 0, 0, + 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, + 905, 29, 24, 337, 0, 0, 331, 384, 0, 0, + 0, 102, 99, 693, 0, 0, 0, 0, 323, 682, + 0, 683, 680, 0, 678, 95, 0, 94, 0, 0, + 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 156, 0, 0, 239, 231, 232, 233, 234, 235, 236, + 237, 238, 0, 0, 229, 0, 0, 0, 902, 0, + 338, 334, 0, 0, 0, 647, 84, 0, 282, 277, + 281, 0, 224, 230, 116, 108, 109, 110, 111, 112, + 113, 114, 115, 117, 0, 0, 106, 100, 908, 906, + 681, 679, 0, 0, 0, 0, 0, 0, 0, 290, + 0, 0, 240, 0, 0, 248, 0, 167, 157, 166, + 0, 103, 107, 0, 0, 276, 0, 0, 275, 0, + 161, 0, 0, 356, 0, 354, 0, 0, 201, 0, + 0, 0, 0, 0, 648, 225, 118, 0, 353, 0, + 0, 0, 0, 132, 0, 0, 0, 0, 0, 0, + 158, 0, 0, 205, 0, 357, 0, 243, 242, 241, + 0, 0, 294, 0, 273, 134, 0, 271, 0, 0, + 0, 136, 0, 358, 0, 0, 202, 0, 0, 0, + 355, 246, 127, 125, 0, 0, 298, 0, 0, 0, + 0, 0, 162, 0, 279, 0, 0, 0, 0, 140, + 0, 0, 0, 0, 359, 360, 0, 0, 0, 0, + 0, 122, 313, 0, 295, 0, 0, 307, 0, 0, + 0, 302, 0, 152, 0, 0, 0, 0, 147, 0, + 0, 291, 0, 137, 0, 131, 141, 159, 165, 213, + 0, 203, 0, 0, 0, 0, 126, 0, 119, 123, + 0, 0, 0, 309, 0, 310, 299, 0, 0, 293, + 303, 274, 0, 0, 133, 148, 272, 0, 289, 0, + 280, 284, 143, 0, 0, 0, 210, 212, 206, 247, + 124, 314, 316, 296, 0, 0, 308, 305, 151, 149, + 163, 0, 0, 0, 160, 214, 216, 204, 0, 0, + 0, 307, 0, 285, 287, 144, 0, 0, 207, 318, + 319, 315, 317, 306, 164, 0, 0, 220, 219, 218, + 215, 217, 0, 0, 0, 208, 286, 288, + }; + protected static readonly short [] yyDgoto = { 7, + 8, 50, 9, 51, 10, 11, 52, 235, 685, 429, + 12, 13, 53, 22, 23, 24, 321, 195, 238, 670, + 828, 1016, 1133, 1480, 825, 239, 240, 241, 242, 243, + 244, 245, 246, 663, 444, 664, 665, 928, 666, 667, + 932, 826, 1011, 1012, 1013, 269, 587, 1105, 837, 1199, + 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, + 1210, 463, 674, 1296, 942, 1112, 1075, 1145, 1183, 1168, + 1227, 1255, 1226, 1256, 1257, 1140, 1355, 1332, 1380, 1381, + 1382, 944, 1378, 945, 728, 1272, 1343, 1319, 1368, 512, + 1361, 1337, 1397, 907, 1366, 1369, 1370, 1464, 1398, 1399, + 1395, 1211, 1279, 1238, 1297, 686, 1345, 1444, 1316, 1401, + 1473, 464, 270, 687, 688, 689, 690, 691, 650, 568, + 1117, 651, 652, 843, 1299, 1323, 1412, 1373, 1446, 1300, + 1348, 1469, 1493, 1413, 1414, 1491, 1477, 1478, 940, 1074, + 1167, 1223, 1281, 1224, 1225, 1273, 1330, 1303, 1274, 323, + 226, 1377, 1276, 1362, 1359, 1212, 1240, 1293, 1441, 1403, + 1125, 1442, 588, 1486, 1487, 1292, 1358, 1334, 1390, 1385, + 1356, 1422, 1427, 1388, 1391, 1392, 1472, 1428, 1386, 1387, + 1482, 1470, 1471, 937, 1020, 1136, 1110, 1161, 1137, 1138, + 1175, 1071, 1159, 1187, 532, 196, 112, 431, 198, 562, + 439, 227, 1311, 648, 649, 814, 830, 324, 406, 530, + 303, 1141, 1142, 46, 114, 304, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 255, 791, 981, + 508, 715, 864, 716, 717, 974, 137, 201, 721, 589, + 590, 591, 592, 785, 472, 473, 298, 979, 723, 407, + 300, 495, 496, 497, 498, 501, 730, 310, 745, 746, + 880, 266, 478, 758, 267, 477, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 571, 572, 573, 767, 768, 896, 769, + 155, 558, 759, 353, 994, 546, 1054, 156, 490, 938, + 1073, 1165, 1277, 465, 1146, 1147, 1194, 1195, 815, 548, + 335, 763, 1153, 549, 550, 271, 272, 273, 159, 160, + 161, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 173, 286, 559, 174, 175, 317, 796, + 627, 910, 840, 681, 948, 908, 911, 912, 949, 950, + 287, 176, 177, 178, 1045, 985, 1046, 1047, 1048, 1091, + 1049, 179, 180, 181, 182, 698, 483, 699, 966, 1084, + 700, 964, 701, 1086, 1087, 183, 184, 185, 186, 187, + 188, 305, 521, 522, 987, 1093, 313, 963, 849, 1119, + 886, 1126, 189, 417, 190, 418, 913, 1001, 419, 639, + 809, 806, 807, 1006, 420, 421, 422, 423, 424, 425, + 917, 629, 915, 1098, 1170, 1229, 1003, 1129, 1186, 804, + 635, 805, 1062, 1005, 1063, 1130, 1007, 17, 19, 47, + 48, 230, 653, 822, 440, 654, 655, + }; + protected static readonly short [] yySindex = { -157, + 0, -201, -137, -18, 44,11653, 0, 248, 0, 0, + 44, -18, 0, 0, 104, 0, 6498, 44, 0, -196, + -237, 0, 0, 0, 0, 0, 0, 0, 0, 99, + 0, 223, 0, 0, 0, 1006, 0, 0, 0, 0, + 0, 0, 0, 0, 93, 0, 0, 544, 0, 0, + 248, 259, 44, 0, 258, 0, 87, 294, 353,11153, + 318, -29, 328, 6655, 0, -29, -29, -29, -175, -29, + -29, 587, 0,10172, -29, -29, 0,10172, 0, 388, + 0, 353, 0, -29, 330, -29, 0, 8204,11672, 390, + -29, -29, -162,10976, 0,10172, 0,10852,10852,10852, +10852,10852,10852,10852,10852, 0, -103, 0,11726, 0, + 0, 363, -260, 795, 302, 0, 0, 447, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1069, 0, + 0, 685, 66, 498, 616, 597, 456, 462, 480, 505, + 137, 548, 0, 0, 0, 0, 0, 0, 3318, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 571, 600, -285, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -105, 95, + 259, 0, 401, 606, 627, 0, 615, 0, 0, 0, + 0,11726,11726, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 674, 633, 0, 646, 0, + -249, 0, 0, 0, 259,12475, 259, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 830, 688,10308, + 0, 0, 0, 0,10172, -29, -29, 834, 512, 795, + 0, 698, 0,11726, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 801, 74,11153, 0,11726, +10172, 757, 776,10172,10172, 4520, 326, 109, 779,11743, + 264, 0, 782, 0, 822,11726,10172, 840, 516, -29, + 0,10172, 388, 9628, 0, 0, 330,10172, 330, -205, + 547, 803, 0, 600, 302, -1, 810,10172,10172,10172, + 328, 892, 0, 0, 6812, -56, 0, 0, 0, 0, + 0, 0, 0, 0, 870,10172, 0, 0, 0, 1324, + 0, 0,11582, -289, 860, 839, 0, -84, 0, 0, + 263, 0, 0, 842,10308, 9356, 0, 0,10852,10172, +10172,10172,10172,10172,10172,10172,10172,10172,10172,10172, +10852,10852,10852,11726,11726,10852,10852,10852,10852,10852, +10852,10852,10852,10852,10852,10852,10852,10852,10852,10852, +10852,10172, 0, 0, 0, 0, 600, 0, 0, 0, + 0,11797,11821, 849, 0, 0, 0, 0, 33, 856, + 0, 0, 0, 0, 0, 0, 0, 259, 259, 853, + 0, 867, 0, 839, 674, 674, 0, -86, 0, -206, + 674, 909, 0, -198,12475, 0, 0, 0, 0, -192, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 235,12518, 0, 0, 0, 839, 419, 0, + 0, 561, 0, 886, 0, 920, 67, 388, -29, 0, + 0, 881, 7735, -147, 0, 940, 0, 0, 0, 945, + 946, 0, 417, 0, 951, 0, 947, 0, 0, 0, + 680, 0, 7871, 681,10172, 779, 9356, 0, 7283, 0, + 330, 0, 0, 0, 948, 950, 0, 0, 353, 388, + 267, 0, 4201, 952, 0, 953, 908, 0, 956, 0, +10172, 0, 0, 1035, 0, 0, 0,10172, 1036, 972, + 0, 975, 976, 0, 0,11582, 0, -288, 6812, 0, + 0, 0, 0, 0, 0, 0, 974, 388, 6812, 0, + 0, -286, 0, 0, 0, 330, -289, 935,11871, 0, + 980, 0, 987,10852, 0, 275, 0, 349, 0, 839, + 793,10172,10172, 994, 1110, 0, 0, -36, 993, 0, + 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 685, + 685, 66, 66, 498, 498, 498, 498, 616, 616, 597, + 456, 462, 480, 505, 0, 995, -186, 0,10172, 80, + 955, 113, 957, 996,10172, 0, 0, 0, 1012, 0, + 200, 839, 0, 0, 0, 0, 517, 242, 0,11871, + -206, 0, 997, 1000, 0, 0, 0, 0, 0, 0, + -289, 606, 0, 1001, 1005, 0, 0, 0, 0, 1007, +11895, 963, 0, 361, 0, 0, 542, 0,10308, 0, + 1016, 0, 0, 0, 711, 1010, 0, 1041, 1042, 1044, + 0, 0,10172, 0, 0, 1002, 0, 0, 1043, 0, + 1049,10172, 1130, 0, 6655, 6655, 8030, 0, 4520, 0, + 0, 9764, 236, 0, -281, 58, 0, 999, 1003, 0, + -185, 0, 0, 1053, 0, 0, 0, 0, 0, 1055, + 0, 1063, 0, 4360, 0, 388, 0, 0, 330, 428, + 573, 0, 1013, 0, 1060, 1061, 0, 6655, 0, 6655, + 0,10172, 0,10172,11726, 0, 0, 388, 388, 1066, + 0, 0, 0, 0, 0, 0, 0, 0, 8187, 0, +11726, 0, 0, 1015,11582, 1092, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9220, 0, 0, 0, + 0, 9492,10172, 0, 7440, 1065, 0, 0, 1146, 0, + 1147, 0, 667, 0, 1068,10172,10172, 1025, 0, 0, + 0, 0, 0, 1028, 0, -86, 0, 0, 0, 0, + -206, -206, 0, 853, 1075, 1078, 1033, 1085, 963, 0, + 1079, 0, 1197, 1199, 0, 0,10172, 0, 9900, 1082, + 711,11871,11726, 0, 128, 1203, 1205, 1090, 1086, 0, +10172,10172, 1094,10172, 1188, 0, 0, 0, 0, 31, +10036, 0, 0, 0, 0, 7576, 0, 1225, 0, 600, +10172, 1115, 8030, 1116, 0, 0, 1067, 0, 0, 0, + 1072, 556, 0, 1073, 0, 1086, 0, 0, 0, 1111, + 0, 0, 1143, 0, 0, 0, 0, 0, 0, 0, + 0, 637, 0, 0, 0,11743, 0, 0, 1074, 1117, + 1065, 0,10172, 0,10172, 0,10172, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1125, 853, 0, 0, +10444, 0, 0, 0, 1136, 7300, 0, 963, 0, 963, + 0, 963, 0, 0, 0, 0, 1091, 1132, 1082, 0, + 0, 0, -188, -181, 1113, 1137, 0, 0, 0, 0, + 1134, 8030, 1065, -186, 0, 1138, 0, 0, 1140, 6655, + 0, 0, 0, 0, 0, 0, 1145, 0, 779, 0, + 0, 0, 0, 0, -203, 0, 1141, 556, 0, 1095, + 1065, 0, 0, 388, 0, 1096, 1142, 0, 0, 0, +10172, 1180,10172, 0,10172, 1179, 461, 0, 1005, 238, + 762, 0, 0, 0, 0, -18, 0, 0, 0, 1164, + 0, 0, 0, 1155, 0, 0, 0, 481, 0, 1156, + 1285, 1287, 0, 0, 1181, 1065,10172, 0, 0, 0, + 0, 0,10172, 0, 1184, -191, 0, -191, 0, 0, + 0, 0, 1182, 388, 0,10172, 7440, 0, 0, 1208, + 702, 1183, 0,10172, 0, 1186, 0, 0,10444, 44, + 67, 0, 1185, 1185, 1185, 9900, 1189, 0,10172, 0, + 0, 0, 0, 1192, 1049, 0, 6655, 1190, 0, 0, + 6812, 0, 1191, 0, 0, 1202, 0,10172, 0, 0, + 0, 0, 0, 0,10172, 0, 0, 259, 1195, 259, + 7457, 71, 71, 71, 0, 0,10172, 0, 6655, 6655, + 0, 0, 6812, 0, 0, 6655, 0, 1213,10172,10172, + 0, 259, 1201, 0, 1157, 0, 1204, 0, 0, 0, + 1207, 0, 0, 1158, 0, 1234, 0, 0, 0, 0, + 0, 0, 6812, 0, 0, 1235, 0, 1206, 71, 0, + 1216, 259, 7457, 1210, 1219, 0, 1220, 1221, 1224,10172, + 0, 0, 0, 0, 1212, 1206, 0, 0,11232, -65, + 259, 0, 0, 0, 1239,10172, 1222,10172, 0, 0, + 1226, 0, 0, 1228, 0, 0,12518, 0, 1232, -65, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -262,12518, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1238, 259, 0, 259, 1206, 1178, 0, 1239, + 0, 0, 1236,11232,11398, 0, 0, -255, 0, 0, + 0,11430, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1242, 259, 0, 0, 0, 0, + 0, 0,11726,11726, 225,11743, 316, 330, 1270, 0, + -289, 640, 0, 1306, 0, 0, 1206, 0, 0, 0, + 1206, 0, 0, 1198, 1200, 0,11726, -164, 0,11726, + 0, 1209, 1244, 0, -289, 0, 1246, 9112, 0, 1251, + 1211, -46, 351, 1006, 0, 0, 0, -289, 0, 1254, + 1214, 1252, 1237, 0, 1255, 1200, 1260, 67, 1241, 1261, + 0, 1262, 1258, 0, 839, 0, 678, 0, 0, 0, + 1264, -184, 0, 1266, 0, 0, 1267, 0, 1268, 1271, + 1273, 0, 1274, 0, 67, 67, 0, 67, 1276, 1277, + 0, 0, 0, 0, 1278, 62, 0, 1282, 67, 1401, + 1286, 67, 0, -255, 0, 8030, 1245, 1283, 1274, 0, + 1290, 1292, 77, 1295, 0, 0, 67, 9900, 1248, 1291, + 1278, 0, 0,12518, 0, 259, 259, 0, 1250, 1293, + 1282, 0, 1298, 0,10172, 1257, 1296, 1286, 0, 1301, + 67, 0, -77, 0, 1299, 0, 0, 0, 0, 0, +12518, 0, 77, 77, 1309, 1305, 0, -184, 0, 0, + 219, 1311,12518, 0,12518, 0, 0, 8030, 1300, 0, + 0, 0, 1312, 1267, 0, 0, 0, 1316, 0, 20, + 0, 0, 0, 71, 848, 1321, 0, 0, 0, 0, + 0, 0, 0, 0, 1375, 1428, 0, 0, 0, 0, + 0, 1323, 1325, 8030, 0, 0, 0, 0, 77, 412, + 412, 0, 71, 0, 0, 0, 110, 110, 0, 0, + 0, 0, 0, 0, 0, 9356, 9356, 0, 0, 0, + 0, 0, 1327, 1326, 1331, 0, 0, 0, + }; + protected static readonly short [] yyRindex = { 2851, + 0, 0, 6969, 2851, 0, 0, 0, 1704, 0, 0, + 3004, 2782, 0, 0, 0, 0, 0, 3004, 0, 0, + 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1708, 0, 0, 1708, 0, 0, + 1704, 3047, 2898, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1342, 0, 0, 0, 0, 0, 0, 0, + 0,11949, 0, 1334, 0, 0, 0, 1334, 0, 0, + 0, 0, 0, 0, 206, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3630, 0, 0, 0, + 0, 0, 313, 4518, 3789, 0, 0, 4359, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4674, 0, + 0, 4742, 5086, 5290, 5630, 358, 5902, 6038, 6174, 6310, + -194, 293, 0, 0, 0, 0, 0, 0, 42, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1294, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 939, 939, + 3090, 0, 595, 1337, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1708, 228, 0, 0, 0, + 0, 0, 0, 0, 3133, 402, 3176, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3405, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1350, 0, 0, 0, 0, + 3405, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2039, 0, 1150, 692, + 2169, 0, 0, 2316, 2169, 692, 0, 0, 0, 0, + 1342, 0, 0, 0, 145, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1334, 0, 0, 0, 0, + 0, 0, 1349, 2441, 0, 3405, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1422, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, + 0, 0, 0, 0, 0, 0, 0, 3239, 2606, 0, + 0, 0, 0, 1886, 1708, 1708, 0, -122, 0, 7752, + 1708, 1722, 0, 0, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 364,11085, 0, 0, 0, 3405, 3948, 0, + 0, 0, 0, 0, 0, 0,11474, 0, 0, 0, + 0, 0, 1354, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 731, 818, 0, 0, 1357, 0, 0, 0, + 0, 0, 191, 0, 0, 3882, 1363, 0, 0, 0, + 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1590, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1349, 0, 0, 201, 0, + 0, 0, 0, 0, 0, 0, 0, 8344, 0, 0, + 0, 0, 0, 0, 0, -197, 537, 0, 0, 0, + 1365, 0, 0, 0, 0, 3405, 0, 3405, 0, 4041, + 0, 0, 0, 127, 0, 0, 0, 0, -20, 0, + 0, 0, 4846, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 4914, + 5018, 5154, 5222, 5358, 5426, 5494, 5562, 5698, 5766, 5834, + 5970, 6106, 6242, 6366, 0, 0, 786, 0, 0, 692, + 0, 692, 0, 0, 0, 0, 0, 0, 988, 0, + 0, 1886, 0, 0, 0, 0, 1322, 0, 0, 0, +11966, 0, 0, 800, 0, 0, 0, 0, 0, 0, + 744, 664, 0, 0, 1374, 0, 0, 0, 0, 1378, + 0, 0, 0, 0, 0, 0,10580, 0, 0, 0, + 807, 0, 0, 0,12020, 0, 0, 808, 824, 833, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1370, 0, 0, 0, 0, 0, 0, 0, 1380, 0, + 0, 0, 3471, 0, 0, 202, 0, 49, 3564, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1381, + 0, 0, 0, 0, 0, 0, 0, 0, 254, 804, + 658, 0, 0, 0, 0, 1379, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8344, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 251, 0, 0, 0, 1377, 0, 0, 0, 0, + 0, 0, 641, 0, 614, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -122, 0, 0, 0, 0, +12020, 8047, 0, 1384, 0, 805, 0, 0, 0, 0, + 1383, 0, 1338, 1341, 0, 0, 0, 0, 0, 1386, +12044, 0, 0, 0,11550, 0, 0, 0, 857, 0, + 1387, 0, 0, 0, 1757, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3723, + 0, 4200, 1396, 0, 0, 0, 1393, 0, 0, 0, + 0, 804, 0, 0, 0, 857, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 821, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 871, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1391, 0, + 0, 0, 0, 0, 880, 884, 0, 0, 0, 0, + 0, 0, 1407, 786, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3882, 0, + 0, 0, 0, 0, 1412, 0, 0, 804, 0, 932, + 1407, 0, 0, 8344, 0, 632, 670, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 176, 0, 1374, 8394, + 0, 0, 0, 0, 0,12092, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 770, 0, 775, + 0, 0, 0, 0, 0, 1377, 1409, 0, 0, 0, + 0, 0, 0, 0, 0, 1414, 0, 7126, 0, 0, + 0, 0, 0, 8344, 0, 0, 0, 0, 0, 0, + 679, 730, 0, 0, 0, 0, 0, 0, 0,12135, +11474, 0, 170, 170, 170, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1411, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,12246, 0, -290, + 0, 1418, 1418, 1418, 0, 0, 0, 0, 0, 0, + 0, 0, -178, 0, 0, 0, 0, 0, 0, 0, + 0,12289, 0, 0, 0, 0, 1419, 0, 0, 0, + 216, 0, 0, 0, 0, 445, 0, 0, 0, 0, + 0, 0, 1420, 0, 0, 0, 0, 2961, 1410, -257, + 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2719, 0, 0, 0, 8548, + 8944, 0, 0, 0, 745, 0, 0, 0, 0, 0, + 0, 0, 0, -244, 0, 0,11256, 0, 0, 8647, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0,11324, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9038, 0, 8746, 2719, 0, 0, 745, + 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, + 0, 364, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8845, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 4648, 457, 0, + 9080, 0, 0, 0, 9150, 0, 2719, 0, 0, 0, + 2719, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 866, 0, 1424, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 888, 0, 551, + 0, 0, 0, 0, 0, 0, 0,11474, 889, 0, + 0, 0, 0, 0, 1426, 0, 906, 0, 0, 0, + 0, 0, 0, 900, 0, 0, 0, 0, 0, 0, + 0, 0, 1437, 0,11474,11474, 0,11506, 0, 0, + 0, 0, 0, 0, 1460, 1390, 0, 1461,11474,10716, + 1463,11474, 0, 0, 0, 0, 0, 0, 1465, 0, + 0, 0,12445, 0, 0, 0,11474, 0, 0, 0, + 1467, 0, 0, 285, 0,11007,12407, 0, 0, 0, + 1468, 0, 0, 0, 0, 0, 0, 1472, 0, 0, +11474, 0, 490, 0, 910, 0, 0, 0, 0, 0, + 942, 0,12331,12369, 0, 0, 0, 0, 0, 0, + 0, 0, 1487, 0, 1586, 0, 0, 0, 926, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 492, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,12445,10888, +12203, 0, 492, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1363, 1363, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + protected static readonly short [] yyGindex = { 0, + 0, 1799, 0, 0, 0, -2, -10, -179, -42, 1800, + 0, 1841, 1854, 83, 0, 0, -6, 0, 0, 0, + 0, 0, 0, -826, -694, -224, -431, 0, 0, 0, + 0, 0, -193, 0, 0, 0, 934, 0, 1047, 0, + 0, 0, 0, 814, 815, -17, -230, 0, 0, 0, + 0, 672,-1118, -618, -488, -460, -427, -357, -308, -219, +-1116,-1131, 0, 1, 0, 234, 0,-1073, 0, 0, + 0, 0, 0, 0, 617, 173, 458, 0, 0, 0, + 493,-1039, 0, -276, -293, 1217, 0, 0, 0, -863, + 453, 0, 0, -492, 0, 0, 522, 0, 0, 497, + 0, 0, 532, 0,-1189, -934, 0, 0, 0, 0, + 0, 625, -13, 0, 0, 1054, 1056, 1057, 1215, -521, + 0, 0, -321, 1062, 613, 0, -995, 0, 0, 0, + 0, 0, 0, 0, 0, 427, 0, 0, 0, 0, + 0, 0, 0, 0, 683, 0, 0, 0, 0, -340, + 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 701, 0, -504, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 438, 0, 0, 535, 0, 0, 541, 543, + 465, 0, 0, 0, 0, 0, 0, 0, 0, 771, + 0, 0, 0, 0, -59, 0, -15, -91, 0, 0, + 605, 0, 665, 0, 1122, 0, 1416, -291, -274, -66, + 451, 0, 777, 0, -38, 518, 0, 0, 1027, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -269, 0, 132, 0, 0, + -320, 0, 0, 0, 1076, 0, -298, -134, 1229, 1159, + 0, 1151, 0, 1361, 1580, 1269, 0, 0, 968, 1882, + 0, 0, 0, 0, 1247, 0, 0, 0, 0, 0, + -515, 1624, 0, 0, 0, 0, 1865, 489, 0, 0, + 474, 922, 905, 918, 1564, 1565, 1566, 1572, 1563, 0, + 1571, 0, 0, 0, 1218, 1427, -708, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, + 0, 0, 0, -446, 0, 819, 0, 741, 0, 825, + 0, 0, 0, 890, -526, -16, -307, 12, 0, 1818, + 0, 68, 0, 86, 101, 105, 114, 117, 122, 147, + 148, 149, 150, 0, -667, 0, -25, 0, 0, 1020, + 0, -575, 0, 0, 0, 923, 0, 1077, 0, 1030, + -457, 0, 0, 0, 0, 0, 0, 941, 0, 0, + 937, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 949, 0, 0, 0, 0, 0, 0, 0, + 0, -26, 0, 1469, 0, 0, 0, 1103, 0, 0, + 0, 0, 0, -169, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1574, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 761, 0, 0, 0, 0, + 0, 0, 0, 0, 862, 0, 0, 0, 0, 0, + 0, -14, 1173, 0, 0, 0, 1175, + }; + protected static readonly short [] yyTable = { 110, + 157, 18, 724, 111, 197, 510, 44, 191, 513, 236, + 446, 428, 570, 194, 486, 352, 729, 675, 316, 471, + 427, 260, 764, 506, 403, 697, 494, 552, 158, 540, + 529, 569, 770, 232, 262, 874, 1115, 855, 856, 1148, + 1149, 933, 996, 466, 6, 254, 360, 774, 368, 535, + 892, 308, 1042, 359, 14, 367, 302, 658, 375, 192, + 302, 595, 1215, 668, 1043, 1235, 309, 1027, 311, 794, + 869, 1353, 197, 197, 1029, 442, 1043, 327, 336, 761, + 885, 1242, 887, 659, 162, 1174, 862, 771, 531, 793, + 408, 1313, 291, 197, 677, 1309, 357, 20, 1, 563, + 292, 349, 163, 200, 1124, 1215, 564, 1246, 1322, 1254, + 332, 95, 358, 1239, 331, 660, 332, 164, 565, 16, + 1278, 165, 677, 333, 350, 315, 1339, 48, 818, 772, + 166, 677, 628, 167, 471, 200, 1109, 1246, 168, 1254, + 762, 110, 157, 409, 595, 111, 702, 863, 236, 595, + 410, 595, 595, 595, 595, 595, 595, 595, 595, 595, + 595, 595, 345, 169, 170, 171, 172, 352, 43, 646, + 158, 48, 375, 595, 375, 595, 375, 595, 1439, 595, + 595, 595, 742, 48, 870, 349, 197, 197, 871, 793, + 1196, 199, 445, 264, 795, 595, 1354, 288, 289, 290, + 2, 294, 295, 446, 718, 570, 306, 307, 350, 352, + 346, 437, 722, 312, 857, 314, 15, 318, 1044, 661, + 375, 193, 329, 330, 569, 669, 162, 361, 570, 1028, + 1044, 443, 470, 411, 595, 466, 1030, 474, 412, 347, + 413, 552, 293, 793, 163, 366, 414, 415, 197, 260, + 528, 552, 1421, 1314, 533, 332, 333, 260, 537, 164, + 322, 327, 482, 165, 575, 536, 3, 4, 5, 6, + 703, 348, 166, 485, 197, 167, 489, 491, 1326, 1445, + 168, 355, 234, 1462, 197, 1055, 869, 349, 527, 516, + 197, 1455, 538, 1456, 524, 48, 526, 1440, 933, 525, + 489, 6, 1039, 234, 933, 169, 170, 171, 172, 570, + 350, 542, 543, 865, 1066, 554, 651, 1383, 551, 557, + 953, 651, 683, 416, 351, 651, 1143, 384, 302, 819, + 742, 1173, 1410, 576, 197, 789, 462, 197, 1417, 2, + 651, 252, 643, 577, 1463, 1095, 553, 470, 586, 1189, + 410, 463, 594, 595, 596, 597, 598, 599, 600, 601, + 602, 603, 604, 385, 502, 1488, 989, 651, 197, 197, + 1465, 1327, 555, 798, 435, 436, 676, 352, 20, 373, + 983, 636, 637, 1341, 626, 236, 651, 1035, 312, 349, + 253, 366, 790, 462, 967, 647, 197, 197, 971, 1485, + 1258, 352, 1288, 202, 871, 848, 800, 684, 463, 1144, + 1371, 1372, 350, 1374, 197, 1053, 933, 1447, 1448, 1121, + 644, 645, 933, 641, 1393, 670, 656, 1400, 197, 507, + 234, 866, 329, 411, 570, 234, 476, 662, 412, 494, + 413, 523, 1416, 386, 387, 234, 414, 415, 471, 480, + 1305, 1151, 1152, 569, 1306, 248, 45, 696, 1154, 249, + 1083, 638, 484, 228, 692, 229, 1438, 113, 955, 1034, + 349, 671, 1051, 1479, 1052, 503, 95, 504, 515, 252, + 1286, 1452, 48, 361, 779, 1489, 781, 720, 782, 586, + 373, 727, 373, 350, 373, 373, 234, 373, 638, 373, + 638, 570, 481, 349, 49, 733, 735, 743, 670, 250, + 113, 671, 694, 751, 113, 672, 741, 887, 887, 951, + 753, 55, 561, 426, 886, 886, 350, 203, 253, 1287, + 197, 505, 551, 1453, 115, 519, 670, 400, 325, 325, + 973, 373, 551, 373, 766, 946, 373, 651, 597, 401, + 811, 982, 736, 197, 671, 638, 608, 609, 450, 325, + 553, 903, 1216, 965, 784, 784, 361, 718, 695, 451, + 553, 1289, 432, 694, 747, 810, 673, 115, 347, 697, + 347, 115, 671, 867, 631, 633, 337, 338, 339, 340, + 341, 342, 343, 344, 361, 978, 764, 887, 361, 651, + 361, 361, 361, 361, 886, 1216, 347, 1247, 361, 113, + 693, 797, 677, 585, 513, 816, 861, 803, 1067, 450, + 1290, 352, 467, 747, 467, 368, 349, 234, 349, 695, + 451, 597, 832, 247, 197, 649, 597, 1247, 597, 597, + 597, 597, 597, 597, 597, 597, 597, 597, 597, 350, + 734, 350, 325, 325, 349, 197, 833, 817, 357, 649, + 597, 470, 597, 351, 597, 351, 597, 597, 597, 251, + 260, 368, 831, 651, 533, 489, 115, 350, 651, 467, + 578, 339, 651, 834, 853, 722, 649, 315, 350, 727, + 579, 351, 1217, 263, 720, 499, 585, 651, 265, 500, + 1015, 585, 778, 585, 585, 585, 585, 585, 585, 585, + 585, 585, 585, 585, 325, 315, 410, 95, 197, 95, + 1218, 597, 878, 252, 651, 585, 1328, 585, 650, 585, + 339, 585, 585, 585, 888, 1217, 889, 1248, 113, 197, + 325, 585, 585, 651, 891, 766, 585, 585, 1198, 1214, + 325, 895, 650, 1219, 95, 197, 325, 585, 585, 197, + 328, 347, 350, 1218, 113, 1249, 1088, 1248, 1198, 586, + 585, 518, 253, 647, 586, 905, 780, 727, 95, 650, + 356, 430, 946, 552, 519, 113, 585, 1172, 921, 922, + 643, 349, 1214, 677, 1245, 1249, 1219, 707, 1250, 411, + 325, 520, 1118, 325, 412, 115, 413, 349, 197, 349, + 812, 673, 414, 415, 350, 552, 541, 662, 349, 943, + 673, 485, 813, 1220, 1245, 369, 197, 197, 1250, 935, + 350, 115, 350, 489, 325, 325, 969, 1065, 1015, 396, + 1150, 350, 593, 972, 351, 552, 351, 835, 879, 1077, + 397, 675, 115, 980, 836, 727, 283, 541, 672, 610, + 611, 1078, 325, 325, 398, 283, 1220, 672, 1251, 605, + 606, 607, 1221, 1404, 541, 541, 541, 541, 541, 541, + 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, + 197, 388, 389, 346, 1275, 1000, 811, 1002, 1251, 1004, + 447, 1275, 349, 357, 399, 346, 877, 446, 614, 346, + 614, 1232, 197, 1014, 228, 1221, 231, 1252, 352, 432, + 197, 662, 346, 448, 292, 350, 292, 890, 1132, 357, + 678, 292, 315, 113, 679, 1457, 449, 402, 1021, 351, + 1022, 451, 1023, 897, 727, 881, 452, 1252, 453, 454, + 455, 456, 911, 296, 346, 297, 457, 911, 315, 911, + 458, 1222, 911, 911, 1294, 911, 911, 346, 297, 350, + 346, 1476, 459, 325, 513, 460, 879, 461, 432, 917, + 766, 1494, 1495, 1058, 917, 1060, 917, 1061, 405, 917, + 917, 541, 917, 917, 394, 395, 325, 390, 391, 113, + 115, 462, 433, 773, 1222, 773, 1253, 773, 995, 113, + 792, 392, 393, 1070, 917, 954, 563, 920, 841, 325, + 918, 919, 920, 564, 920, 485, 339, 920, 920, 339, + 920, 920, 434, 65, 65, 565, 1253, 65, 1096, 727, + 766, 762, 911, 762, 228, 762, 1103, 438, 346, 710, + 719, 1014, 920, 711, 500, 1100, 1101, 1295, 485, 1108, + 346, 485, 777, 441, 346, 236, 115, 1135, 913, 917, + 381, 382, 383, 913, 551, 913, 115, 346, 913, 913, + 1128, 913, 913, 907, 946, 467, 261, 1131, 907, 236, + 907, 350, 438, 907, 907, 197, 907, 907, 508, 485, + 325, 346, 553, 346, 508, 468, 551, 920, 1019, 346, + 331, 1156, 1061, 346, 346, 475, 346, 346, 57, 1135, + 261, 325, 346, 346, 261, 261, 261, 261, 261, 261, + 261, 261, 487, 1068, 553, 1069, 551, 1197, 1213, 182, + 479, 182, 346, 182, 194, 509, 194, 197, 194, 371, + 346, 488, 1185, 346, 358, 113, 113, 1197, 913, 755, + 346, 755, 783, 197, 553, 252, 679, 361, 1230, 953, + 485, 953, 346, 907, 66, 346, 346, 170, 66, 170, + 764, 1213, 764, 1197, 325, 509, 362, 363, 425, 346, + 425, 509, 759, 177, 411, 177, 759, 514, 113, 412, + 113, 413, 178, 1320, 178, 325, 364, 414, 415, 425, + 425, 1466, 1467, 1197, 253, 517, 1320, 365, 197, 197, + 534, 325, 115, 115, 1280, 325, 197, 539, 864, 425, + 864, 574, 351, 1349, 545, 1350, 351, 425, 346, 130, + 425, 130, 68, 923, 68, 556, 130, 197, 197, 200, + 197, 200, 350, 171, 351, 171, 1301, 680, 351, 580, + 346, 351, 135, 351, 135, 115, 634, 115, 351, 1301, + 354, 197, 361, 297, 197, 297, 361, 657, 346, 361, + 351, 361, 1301, 142, 642, 142, 361, 886, 886, 1329, + 204, 682, 325, 325, 614, 615, 616, 617, 694, 304, + 1301, 304, 351, 532, 532, 651, 651, 1113, 1114, 612, + 613, 618, 619, 1384, 261, 704, 705, 706, 708, 731, + 709, 732, 261, 747, 748, 749, 923, 750, 752, 754, + 1411, 923, 205, 923, 923, 923, 923, 923, 923, 923, + 923, 923, 923, 1423, 1425, 755, 756, 757, 727, 765, + 1280, 1193, 773, 775, 541, 923, 325, 923, 776, 923, + 485, 923, 923, 923, 787, 788, 792, 808, 820, 793, + 1411, 1411, 799, 821, 801, 823, 802, 1433, 824, 827, + 43, 844, 206, 207, 208, 209, 325, 210, 211, 212, + 213, 214, 215, 216, 217, 261, 839, 218, 219, 220, + 221, 222, 223, 224, 225, 371, 1193, 261, 261, 261, + 727, 371, 261, 261, 845, 846, 923, 847, 851, 850, + 113, 513, 852, 854, 872, 868, 1411, 199, 873, 875, + 882, 883, 898, 884, 900, 1284, 1285, 893, 909, 914, + 916, 920, 923, 371, 930, 924, 727, 371, 931, 370, + 933, 934, 939, 936, 941, 947, 1481, 1481, 959, 1312, + 960, 961, 1315, 1490, 1490, 968, 962, 970, 586, 586, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 977, 503, 992, 984, 986, 993, 1031, 115, 371, 988, + 990, 997, 998, 371, 1008, 371, 371, 371, 371, 371, + 371, 371, 371, 371, 371, 371, 1017, 1025, 1024, 1033, + 1032, 1038, 1050, 1037, 1040, 879, 371, 371, 1056, 371, + 371, 371, 1057, 371, 371, 371, 1059, 371, 371, 1064, + 1072, 371, 371, 371, 371, 1076, 1079, 113, 371, 371, + 1080, 113, 1081, 371, 371, 371, 371, 371, 371, 371, + 371, 1089, 1082, 1094, 1099, 1104, 1102, 1124, 1116, 1111, + 1155, 325, 371, 1120, 1122, 371, 1134, 371, 1158, 113, + 113, 1127, 1144, 113, 1160, 1164, 113, 1162, 371, 560, + 1163, 1172, 1171, 1176, 1179, 1180, 1181, 1182, 25, 840, + 26, 1184, 1188, 27, 1228, 1259, 1233, 1231, 28, 1236, + 261, 1234, 29, 113, 115, 1243, 1291, 1261, 115, 1282, + 1304, 31, 1336, 325, 1318, 1307, 1321, 1308, 33, 1324, + 1333, 1342, 1335, 34, 1347, 1338, 1317, 35, 1325, 325, + 1340, 1327, 1346, 1344, 1352, 1360, 115, 115, 1363, 37, + 115, 38, 1364, 115, 1365, 39, 1357, 1367, 1375, 1376, + 48, 1379, 48, 40, 41, 1389, 1394, 42, 1406, 1396, + 319, 1408, 1405, 1409, 1415, 1418, 1419, 1429, 1430, 1432, + 115, 1435, 1437, 48, 1434, 1449, 1450, 513, 1454, 1443, + 1458, 1459, 513, 513, 325, 325, 48, 1461, 1468, 1453, + 1452, 48, 325, 1474, 1496, 1475, 48, 1497, 48, 48, + 48, 48, 1498, 9, 48, 513, 48, 949, 545, 838, + 48, 740, 32, 325, 325, 513, 325, 503, 513, 513, + 615, 941, 48, 513, 504, 48, 513, 48, 513, 808, + 513, 513, 513, 513, 462, 261, 616, 325, 513, 684, + 325, 354, 513, 30, 22, 812, 513, 502, 30, 324, + 528, 48, 758, 31, 513, 221, 783, 513, 96, 513, + 513, 766, 813, 31, 846, 513, 767, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 758, 787, + 815, 788, 817, 513, 672, 672, 328, 694, 513, 513, + 353, 513, 513, 513, 513, 513, 513, 513, 346, 513, + 513, 651, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 138, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513, 513, 120, 300, 513, 145, 513, + 139, 513, 121, 301, 513, 840, 840, 146, 651, 233, + 513, 237, 54, 840, 840, 840, 840, 840, 21, 840, + 840, 1009, 840, 840, 840, 840, 840, 840, 840, 840, + 929, 1237, 1283, 1420, 840, 1451, 840, 840, 840, 840, + 840, 840, 1106, 1107, 840, 346, 1460, 829, 840, 840, + 1407, 840, 840, 840, 1436, 1402, 1298, 1310, 956, 842, + 957, 958, 952, 840, 1492, 840, 1244, 840, 840, 1484, + 1331, 840, 1241, 840, 840, 840, 840, 840, 840, 840, + 840, 840, 840, 840, 840, 1431, 840, 1426, 1424, 840, + 840, 1351, 1177, 840, 840, 1483, 1302, 925, 744, 1178, + 860, 976, 904, 786, 581, 902, 1041, 838, 840, 840, + 840, 840, 840, 299, 544, 858, 840, 840, 334, 620, + 840, 621, 624, 622, 1166, 840, 840, 840, 840, 840, + 623, 625, 760, 840, 1262, 840, 404, 1169, 1026, 1097, + 1123, 840, 840, 1036, 1092, 1085, 1090, 999, 991, 737, + 1260, 1157, 899, 640, 927, 926, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 840, 840, 840, 840, + 0, 840, 783, 783, 0, 0, 0, 0, 840, 0, + 783, 783, 783, 783, 783, 0, 783, 783, 0, 783, + 783, 783, 783, 783, 783, 783, 0, 0, 748, 0, + 0, 783, 0, 783, 783, 783, 783, 783, 783, 0, + 0, 783, 0, 0, 0, 783, 783, 0, 783, 783, + 783, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 783, 0, 783, 0, 783, 783, 0, 0, 783, 0, + 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, + 783, 783, 0, 783, 0, 0, 783, 783, 0, 0, + 783, 783, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 783, 783, 783, 783, 783, + 0, 0, 0, 783, 783, 0, 0, 783, 0, 0, + 0, 0, 783, 783, 783, 783, 783, 0, 0, 0, + 783, 346, 783, 0, 0, 0, 346, 346, 783, 783, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 339, 346, + 0, 0, 0, 783, 783, 783, 783, 0, 783, 346, + 0, 0, 346, 346, 0, 783, 0, 346, 0, 0, + 346, 0, 346, 0, 346, 346, 346, 346, 0, 0, + 0, 0, 346, 0, 0, 0, 346, 0, 0, 0, + 346, 0, 0, 0, 0, 0, 0, 0, 346, 0, + 0, 346, 0, 346, 346, 0, 0, 0, 0, 346, + 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 346, 0, 0, + 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 346, 346, 0, 0, 346, 346, 346, + 346, 346, 0, 0, 346, 346, 0, 0, 0, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 748, 0, 0, 0, 346, 748, + 748, 346, 0, 346, 0, 346, 0, 0, 346, 0, + 0, 0, 0, 0, 346, 376, 0, 0, 0, 0, + 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 748, 0, 0, 748, 748, 0, 0, 0, + 748, 0, 0, 748, 0, 748, 0, 748, 748, 748, + 748, 0, 0, 0, 0, 748, 0, 0, 0, 748, + 0, 0, 0, 748, 0, 0, 0, 0, 0, 0, + 0, 748, 0, 0, 748, 0, 748, 748, 0, 0, + 0, 0, 748, 0, 748, 748, 748, 748, 748, 748, + 748, 748, 748, 748, 748, 0, 0, 0, 0, 0, + 748, 0, 0, 0, 0, 748, 748, 748, 748, 748, + 748, 0, 748, 748, 748, 0, 748, 748, 0, 0, + 748, 748, 748, 748, 339, 0, 0, 748, 748, 339, + 339, 0, 748, 748, 748, 748, 748, 748, 748, 748, + 346, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 748, 339, 0, 748, 0, 748, 0, 748, 0, + 0, 748, 339, 0, 0, 339, 339, 748, 0, 0, + 339, 0, 0, 339, 0, 339, 0, 339, 339, 339, + 339, 0, 0, 0, 0, 339, 0, 0, 0, 339, + 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, + 0, 339, 0, 0, 339, 0, 339, 339, 0, 0, + 0, 0, 339, 0, 339, 339, 339, 339, 339, 339, + 339, 339, 339, 339, 339, 0, 0, 0, 0, 0, + 339, 0, 0, 0, 0, 339, 339, 339, 339, 339, + 339, 0, 339, 339, 339, 0, 339, 339, 0, 0, + 339, 339, 339, 339, 0, 0, 0, 339, 339, 0, + 0, 0, 339, 339, 339, 339, 339, 339, 339, 339, + 0, 376, 0, 0, 0, 0, 376, 376, 0, 0, + 0, 339, 0, 0, 339, 0, 339, 0, 339, 0, + 0, 339, 0, 0, 0, 0, 0, 339, 0, 376, + 0, 0, 0, 0, 0, 49, 0, 0, 0, 376, + 0, 0, 376, 376, 0, 0, 0, 376, 0, 0, + 376, 0, 376, 0, 376, 376, 376, 376, 0, 0, + 0, 0, 376, 0, 0, 0, 376, 0, 0, 0, + 376, 0, 0, 0, 0, 0, 0, 0, 376, 0, + 0, 376, 0, 376, 376, 0, 0, 0, 0, 376, + 0, 376, 376, 376, 376, 376, 376, 376, 376, 376, + 376, 376, 0, 0, 0, 0, 0, 376, 0, 0, + 0, 0, 376, 376, 0, 376, 376, 376, 0, 376, + 376, 376, 0, 376, 376, 0, 346, 376, 376, 376, + 376, 0, 346, 0, 376, 376, 0, 0, 0, 376, + 376, 376, 376, 376, 376, 376, 376, 0, 28, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 376, 0, + 0, 376, 0, 376, 346, 0, 0, 0, 346, 0, + 0, 0, 0, 0, 376, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, + 0, 36, 0, 0, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 346, 346, + 0, 0, 346, 346, 346, 346, 346, 0, 0, 346, + 346, 0, 0, 0, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 346, 0, 0, 346, 0, 346, 0, + 346, 0, 49, 346, 0, 0, 49, 0, 49, 346, + 49, 0, 49, 0, 0, 49, 0, 49, 49, 0, + 49, 0, 49, 0, 49, 0, 49, 49, 49, 49, + 0, 0, 49, 49, 0, 0, 0, 34, 49, 49, + 49, 49, 49, 0, 0, 49, 49, 49, 0, 49, + 0, 49, 49, 49, 49, 49, 49, 49, 49, 0, + 49, 49, 49, 49, 0, 0, 49, 49, 49, 0, + 49, 0, 0, 0, 0, 49, 49, 0, 49, 49, + 0, 49, 49, 49, 0, 0, 0, 49, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 0, 0, 0, 0, 0, 0, 49, 0, 49, + 49, 0, 0, 0, 28, 28, 0, 0, 0, 28, + 0, 0, 49, 28, 0, 28, 0, 0, 28, 0, + 28, 28, 0, 28, 0, 28, 0, 28, 0, 28, + 28, 28, 28, 33, 0, 28, 28, 0, 0, 0, + 0, 28, 0, 28, 28, 28, 0, 0, 28, 28, + 28, 0, 28, 49, 0, 28, 0, 28, 28, 28, + 28, 0, 0, 0, 28, 28, 28, 0, 36, 28, + 28, 28, 36, 0, 0, 0, 5, 0, 28, 28, + 0, 28, 28, 36, 28, 28, 28, 0, 36, 0, + 28, 0, 36, 0, 0, 36, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 36, 0, + 28, 0, 36, 36, 0, 0, 28, 28, 36, 931, + 36, 36, 36, 36, 0, 28, 0, 0, 36, 0, + 0, 0, 36, 0, 36, 0, 0, 35, 0, 0, + 0, 35, 0, 0, 36, 0, 36, 36, 0, 36, + 0, 0, 35, 36, 0, 0, 0, 35, 0, 0, + 0, 35, 48, 0, 35, 0, 28, 0, 0, 0, + 0, 0, 0, 36, 0, 0, 35, 35, 0, 36, + 36, 35, 35, 0, 34, 0, 0, 35, 34, 35, + 35, 35, 35, 0, 0, 0, 0, 35, 0, 34, + 0, 35, 0, 35, 34, 7, 0, 0, 34, 0, + 0, 34, 0, 35, 0, 35, 35, 0, 35, 0, + 0, 0, 35, 34, 34, 0, 0, 0, 34, 34, + 0, 0, 0, 0, 34, 0, 34, 34, 34, 34, + 0, 0, 35, 0, 34, 0, 0, 28, 34, 35, + 34, 28, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 0, 28, 34, 0, 34, 0, 28, 932, 34, + 0, 28, 0, 0, 28, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28, 28, 0, 34, + 33, 28, 28, 0, 33, 34, 34, 28, 0, 28, + 28, 28, 28, 0, 0, 33, 0, 28, 0, 0, + 33, 28, 0, 28, 33, 0, 0, 33, 0, 0, + 0, 0, 0, 28, 0, 0, 28, 0, 28, 33, + 33, 0, 28, 5, 33, 33, 0, 48, 0, 0, + 33, 0, 33, 33, 33, 33, 0, 0, 48, 0, + 33, 0, 28, 48, 33, 0, 33, 48, 28, 28, + 48, 0, 0, 0, 0, 0, 33, 0, 0, 33, + 0, 33, 48, 48, 0, 33, 931, 48, 48, 0, + 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 48, 0, 48, 0, 33, 48, 48, 0, 48, + 48, 0, 33, 48, 0, 0, 0, 0, 0, 48, + 0, 0, 48, 0, 48, 48, 48, 0, 48, 48, + 48, 48, 0, 48, 0, 0, 48, 0, 48, 48, + 48, 48, 0, 0, 48, 0, 48, 0, 48, 48, + 48, 0, 48, 48, 0, 0, 48, 0, 0, 0, + 0, 0, 48, 0, 0, 48, 0, 48, 48, 48, + 0, 48, 7, 48, 48, 0, 49, 0, 0, 48, + 0, 48, 48, 48, 48, 0, 0, 49, 0, 48, + 0, 48, 49, 48, 0, 48, 49, 0, 0, 49, + 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, + 48, 49, 49, 0, 48, 0, 49, 49, 0, 0, + 0, 0, 49, 0, 49, 49, 49, 49, 0, 0, + 0, 0, 49, 0, 48, 932, 49, 0, 49, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, + 48, 49, 0, 49, 0, 48, 0, 49, 0, 48, + 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 48, 0, 49, 0, 48, + 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 0, 0, 48, + 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 0, 56, 48, 0, 48, 0, 0, 0, + 48, 57, 25, 58, 26, 0, 0, 27, 59, 0, + 60, 61, 28, 62, 63, 64, 29, 0, 0, 0, + 48, 0, 65, 0, 66, 31, 67, 68, 69, 70, + 0, 0, 33, 0, 0, 0, 71, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 76, 77, 78, 79, 80, 81, 40, 41, 82, + 83, 42, 84, 0, 85, 0, 0, 86, 87, 0, + 346, 88, 89, 0, 0, 0, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 95, 0, 0, 0, 96, 0, + 0, 0, 0, 97, 98, 99, 100, 101, 0, 0, + 0, 102, 346, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 346, 0, 0, 0, + 0, 0, 346, 0, 106, 107, 108, 109, 0, 0, + 0, 0, 0, 346, 0, 0, 199, 0, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, 346, 0, + 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 0, 515, + 0, 0, 346, 0, 346, 515, 0, 346, 0, 0, + 0, 0, 0, 346, 0, 0, 0, 0, 346, 0, + 0, 346, 0, 346, 346, 0, 0, 0, 346, 346, + 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 515, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 346, 346, 0, 0, 0, 0, 0, 0, + 346, 346, 0, 346, 0, 0, 0, 0, 0, 346, + 0, 0, 515, 0, 0, 0, 0, 515, 0, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, + 0, 0, 0, 0, 0, 0, 0, 346, 0, 0, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, + 0, 515, 515, 0, 515, 515, 515, 515, 515, 515, + 515, 515, 515, 515, 0, 515, 515, 515, 515, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, + 515, 515, 515, 515, 515, 515, 515, 0, 511, 0, + 0, 0, 0, 515, 511, 0, 346, 0, 0, 0, + 0, 0, 515, 0, 0, 0, 0, 0, 346, 0, + 346, 0, 346, 0, 0, 346, 0, 346, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 511, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 0, 0, 0, 0, 346, 0, 346, + 403, 0, 346, 0, 0, 0, 0, 0, 346, 0, + 0, 511, 0, 0, 0, 0, 511, 0, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511, 511, 0, + 0, 0, 0, 0, 0, 0, 403, 0, 0, 511, + 511, 0, 511, 511, 511, 511, 511, 511, 511, 0, + 511, 511, 0, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 0, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, + 511, 511, 511, 511, 511, 511, 0, 519, 0, 0, + 0, 0, 511, 519, 0, 511, 0, 0, 0, 0, + 0, 511, 0, 0, 0, 0, 0, 339, 0, 403, + 403, 403, 403, 0, 403, 0, 403, 403, 0, 403, + 403, 403, 403, 403, 0, 403, 403, 403, 403, 519, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 403, 403, 0, 0, 0, 0, 339, 0, 403, 346, + 0, 403, 0, 0, 0, 0, 0, 403, 0, 0, + 519, 0, 0, 0, 0, 519, 0, 519, 519, 519, + 519, 519, 519, 519, 519, 519, 519, 519, 0, 0, + 0, 0, 0, 0, 0, 346, 0, 0, 0, 519, + 0, 519, 519, 519, 519, 519, 519, 519, 0, 519, + 519, 0, 519, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 0, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, + 519, 519, 519, 519, 519, 0, 346, 0, 0, 0, + 0, 519, 346, 0, 519, 0, 0, 0, 0, 0, + 519, 0, 0, 0, 0, 0, 0, 346, 346, 346, + 346, 346, 0, 0, 0, 346, 346, 0, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 0, 0, 0, 0, 0, 346, 0, 0, + 346, 0, 0, 0, 0, 0, 346, 0, 0, 346, + 0, 0, 0, 0, 346, 0, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 346, 0, + 346, 346, 346, 346, 346, 346, 346, 0, 346, 346, + 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 0, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 446, 738, 0, 0, 0, + 346, 446, 0, 346, 0, 25, 0, 26, 0, 346, + 27, 0, 0, 0, 0, 28, 0, 0, 0, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 33, 0, 446, 0, 0, + 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, + 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 0, 0, 42, 0, 0, 739, 446, 0, + 0, 0, 0, 446, 0, 446, 446, 446, 446, 446, + 446, 446, 446, 446, 446, 446, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 446, 0, 446, + 446, 446, 446, 446, 446, 446, 0, 446, 446, 0, + 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, + 0, 446, 446, 446, 446, 446, 446, 446, 446, 446, + 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, + 446, 446, 446, 0, 406, 876, 0, 0, 740, 446, + 406, 0, 446, 0, 25, 0, 26, 0, 446, 27, + 0, 0, 0, 0, 28, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 406, 0, 0, 34, + 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, + 0, 39, 0, 0, 0, 0, 0, 0, 0, 40, + 41, 0, 0, 42, 0, 0, 319, 406, 0, 0, + 0, 0, 406, 0, 406, 406, 406, 406, 406, 406, + 406, 406, 406, 406, 406, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 406, 0, 406, 406, + 406, 406, 406, 406, 406, 0, 406, 0, 0, 406, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 0, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, + 406, 406, 0, 550, 0, 492, 0, 354, 406, 550, + 0, 406, 0, 57, 25, 0, 26, 406, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 0, 0, 0, 0, 65, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 550, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 550, 0, 0, 0, + 0, 550, 0, 550, 550, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 0, 0, 0, 0, 90, 91, + 92, 258, 0, 0, 0, 550, 0, 550, 0, 550, + 96, 550, 550, 550, 0, 550, 550, 0, 550, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 368, 0, + 0, 550, 550, 550, 550, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 550, 564, + 550, 368, 0, 0, 0, 564, 106, 493, 0, 0, + 0, 0, 0, 0, 368, 0, 550, 0, 0, 368, + 0, 0, 245, 0, 368, 0, 368, 368, 368, 368, + 0, 0, 0, 0, 368, 0, 0, 0, 368, 0, + 0, 564, 368, 0, 0, 0, 0, 0, 0, 0, + 368, 0, 0, 368, 0, 368, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 568, 0, 0, + 0, 0, 0, 568, 0, 0, 0, 0, 0, 368, + 0, 0, 564, 0, 0, 0, 0, 564, 0, 564, + 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 568, + 0, 564, 0, 564, 0, 564, 0, 564, 564, 564, + 0, 564, 564, 0, 0, 564, 564, 564, 564, 564, + 564, 564, 564, 564, 0, 368, 0, 564, 564, 564, + 564, 564, 564, 564, 564, 0, 0, 0, 0, 0, + 568, 0, 0, 0, 0, 568, 564, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 0, 0, + 0, 571, 564, 0, 0, 0, 0, 571, 0, 568, + 0, 568, 0, 568, 0, 568, 568, 568, 0, 568, + 568, 0, 0, 568, 568, 568, 568, 0, 0, 0, + 568, 568, 0, 0, 0, 568, 568, 568, 568, 568, + 568, 568, 568, 571, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 568, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 569, + 568, 0, 0, 0, 0, 569, 0, 0, 0, 0, + 0, 0, 0, 0, 571, 0, 0, 0, 0, 571, + 0, 571, 571, 571, 571, 571, 571, 571, 571, 571, + 571, 571, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 569, 0, 571, 0, 571, 0, 571, 0, 571, + 571, 571, 0, 571, 571, 0, 0, 571, 571, 571, + 571, 0, 0, 0, 571, 571, 0, 0, 0, 571, + 571, 571, 571, 571, 571, 571, 571, 0, 0, 0, + 0, 0, 569, 0, 0, 0, 0, 569, 571, 569, + 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, + 0, 0, 0, 570, 571, 0, 0, 0, 0, 570, + 0, 569, 0, 569, 0, 569, 0, 569, 569, 569, + 0, 569, 569, 0, 0, 569, 569, 569, 569, 0, + 0, 0, 569, 569, 0, 0, 0, 569, 569, 569, + 569, 569, 569, 569, 569, 570, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 569, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 574, 569, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 570, 0, 0, 0, + 0, 570, 0, 570, 570, 570, 570, 570, 570, 570, + 570, 570, 570, 570, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 570, 0, 570, 0, 570, + 0, 570, 570, 570, 0, 570, 570, 0, 0, 570, + 570, 570, 570, 0, 0, 0, 570, 570, 0, 575, + 0, 570, 570, 570, 570, 570, 570, 570, 570, 0, + 0, 0, 0, 0, 574, 0, 0, 0, 0, 574, + 570, 574, 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 0, 0, 0, 0, 570, 0, 0, 0, + 0, 0, 0, 574, 0, 574, 0, 574, 0, 574, + 574, 574, 0, 0, 0, 0, 0, 574, 574, 574, + 574, 0, 0, 0, 574, 574, 0, 576, 0, 574, + 574, 574, 574, 574, 574, 574, 574, 0, 0, 0, + 0, 0, 575, 0, 0, 0, 0, 575, 574, 575, + 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, + 0, 0, 0, 0, 574, 0, 0, 0, 0, 0, + 0, 575, 0, 575, 0, 575, 0, 575, 575, 575, + 0, 0, 0, 0, 0, 575, 575, 575, 575, 0, + 0, 0, 575, 575, 0, 577, 0, 575, 575, 575, + 575, 575, 575, 575, 575, 0, 0, 0, 0, 0, + 576, 0, 0, 0, 0, 576, 575, 576, 576, 576, + 576, 576, 576, 576, 576, 576, 576, 576, 0, 0, + 0, 0, 575, 0, 0, 0, 0, 0, 0, 576, + 0, 576, 0, 576, 0, 576, 576, 576, 0, 0, + 0, 0, 0, 576, 576, 576, 576, 0, 0, 0, + 576, 576, 0, 578, 0, 576, 576, 576, 576, 576, + 576, 576, 576, 0, 0, 0, 0, 0, 577, 0, + 0, 0, 0, 577, 576, 577, 577, 577, 577, 577, + 577, 577, 577, 577, 577, 577, 0, 0, 0, 0, + 576, 0, 0, 0, 0, 0, 0, 577, 0, 577, + 0, 577, 0, 577, 577, 577, 0, 0, 0, 0, + 0, 577, 577, 577, 577, 0, 0, 0, 577, 577, + 0, 579, 0, 0, 0, 577, 577, 577, 577, 577, + 577, 0, 0, 0, 0, 0, 578, 0, 0, 0, + 0, 578, 577, 578, 578, 578, 578, 578, 578, 578, + 578, 578, 578, 578, 0, 0, 0, 0, 577, 0, + 0, 0, 0, 0, 0, 578, 0, 578, 0, 578, + 0, 578, 578, 578, 0, 0, 0, 0, 0, 578, + 578, 578, 578, 0, 0, 0, 578, 578, 0, 580, + 0, 0, 0, 578, 578, 578, 578, 578, 578, 0, + 0, 0, 0, 0, 579, 0, 0, 0, 0, 579, + 578, 579, 579, 579, 579, 579, 579, 579, 579, 579, + 579, 579, 0, 0, 0, 0, 578, 0, 0, 0, + 0, 0, 0, 579, 0, 579, 0, 579, 0, 579, + 579, 579, 0, 0, 0, 0, 0, 579, 579, 579, + 579, 0, 0, 0, 579, 579, 0, 581, 0, 0, + 0, 579, 579, 579, 579, 579, 579, 0, 0, 0, + 0, 0, 580, 0, 0, 0, 0, 580, 579, 580, + 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, + 0, 0, 0, 0, 579, 0, 0, 0, 0, 0, + 0, 580, 0, 580, 0, 580, 0, 580, 580, 580, + 0, 0, 0, 0, 0, 580, 580, 580, 580, 0, + 0, 0, 580, 580, 0, 582, 0, 0, 0, 580, + 580, 580, 580, 580, 580, 0, 0, 0, 0, 0, + 581, 0, 0, 0, 0, 581, 580, 581, 581, 581, + 581, 581, 581, 581, 581, 581, 581, 581, 0, 0, + 0, 0, 580, 0, 0, 0, 0, 0, 0, 581, + 0, 581, 0, 581, 0, 581, 581, 581, 0, 0, + 0, 0, 0, 581, 581, 581, 581, 0, 0, 0, + 581, 581, 0, 583, 0, 0, 0, 581, 581, 581, + 581, 581, 581, 0, 0, 0, 0, 0, 582, 0, + 0, 0, 0, 582, 581, 582, 582, 582, 582, 582, + 582, 582, 582, 582, 582, 582, 0, 0, 0, 0, + 581, 0, 0, 0, 0, 0, 0, 582, 0, 582, + 0, 582, 0, 582, 582, 582, 0, 0, 0, 0, + 0, 0, 0, 582, 582, 0, 0, 0, 582, 582, + 0, 584, 0, 0, 0, 0, 0, 582, 582, 582, + 582, 0, 0, 0, 0, 0, 583, 0, 0, 0, + 0, 583, 582, 583, 583, 583, 583, 583, 583, 583, + 583, 583, 583, 583, 0, 0, 0, 0, 582, 0, + 0, 0, 0, 0, 0, 583, 0, 583, 0, 583, + 0, 583, 583, 583, 0, 0, 0, 0, 0, 0, + 0, 583, 583, 0, 0, 0, 583, 583, 0, 586, + 0, 0, 0, 0, 0, 583, 583, 583, 583, 0, + 0, 0, 0, 0, 584, 0, 0, 0, 0, 584, + 583, 584, 584, 584, 584, 584, 584, 584, 584, 584, + 584, 584, 0, 0, 0, 0, 583, 0, 0, 0, + 0, 0, 0, 584, 0, 584, 0, 584, 0, 584, + 584, 584, 0, 0, 0, 0, 0, 0, 0, 584, + 584, 0, 0, 0, 584, 584, 0, 587, 0, 0, + 0, 0, 0, 584, 584, 584, 584, 0, 0, 0, + 0, 0, 586, 0, 0, 0, 0, 586, 584, 586, + 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, + 0, 0, 0, 0, 584, 0, 0, 0, 0, 0, + 0, 586, 0, 586, 0, 586, 0, 586, 586, 586, + 0, 0, 0, 0, 0, 0, 0, 586, 586, 0, + 0, 0, 586, 586, 0, 588, 0, 0, 0, 0, + 0, 0, 0, 586, 586, 0, 0, 0, 0, 0, + 587, 0, 0, 0, 0, 587, 586, 587, 587, 587, + 587, 587, 587, 587, 587, 587, 587, 587, 0, 0, + 0, 0, 586, 0, 0, 0, 0, 0, 0, 587, + 0, 587, 0, 587, 0, 587, 587, 587, 0, 0, + 0, 0, 0, 0, 0, 0, 587, 0, 0, 0, + 587, 587, 0, 589, 0, 0, 0, 0, 0, 0, + 0, 587, 587, 0, 0, 0, 0, 0, 588, 0, + 0, 0, 0, 588, 587, 588, 588, 588, 588, 588, + 588, 588, 588, 588, 588, 588, 0, 0, 0, 0, + 587, 0, 0, 0, 0, 0, 0, 588, 0, 588, + 0, 588, 0, 588, 588, 588, 0, 0, 0, 0, + 0, 0, 0, 0, 588, 0, 0, 0, 588, 588, + 0, 590, 0, 0, 0, 0, 0, 0, 0, 588, + 588, 0, 0, 0, 0, 0, 589, 0, 0, 0, + 0, 589, 588, 589, 589, 589, 589, 589, 589, 589, + 589, 589, 589, 589, 0, 0, 0, 0, 588, 0, + 0, 0, 0, 0, 0, 589, 0, 589, 0, 589, + 0, 589, 589, 589, 0, 0, 0, 0, 0, 0, + 0, 0, 589, 0, 0, 0, 0, 589, 0, 591, + 0, 0, 0, 0, 0, 0, 0, 589, 589, 0, + 0, 0, 0, 0, 590, 0, 0, 0, 0, 590, + 589, 590, 590, 590, 590, 590, 590, 590, 590, 590, + 590, 590, 0, 0, 0, 0, 589, 0, 0, 0, + 0, 0, 0, 590, 0, 590, 0, 590, 0, 590, + 590, 590, 0, 0, 0, 0, 0, 0, 0, 0, + 590, 0, 0, 0, 0, 590, 0, 592, 0, 0, + 0, 0, 0, 0, 0, 590, 590, 0, 0, 0, + 0, 0, 591, 0, 0, 0, 0, 591, 590, 591, + 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, + 0, 0, 0, 0, 590, 0, 0, 0, 0, 0, + 0, 591, 0, 591, 0, 591, 0, 591, 591, 591, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 591, 0, 593, 0, 0, 0, 0, + 0, 0, 0, 591, 591, 0, 0, 0, 0, 0, + 592, 0, 0, 0, 0, 592, 591, 592, 592, 592, + 592, 592, 592, 592, 592, 592, 592, 592, 0, 0, + 0, 0, 591, 0, 0, 0, 0, 0, 0, 592, + 0, 592, 0, 592, 0, 592, 592, 592, 0, 0, + 0, 594, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 592, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 592, 592, 0, 0, 0, 0, 0, 593, 0, + 0, 0, 0, 593, 592, 593, 593, 593, 593, 593, + 593, 593, 593, 593, 593, 593, 0, 0, 0, 0, + 592, 0, 0, 0, 0, 0, 0, 593, 0, 593, + 0, 593, 0, 593, 593, 593, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 593, + 0, 0, 0, 0, 594, 0, 0, 0, 0, 594, + 593, 594, 594, 594, 594, 594, 594, 594, 594, 594, + 594, 594, 593, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 594, 0, 594, 0, 594, 593, 594, + 594, 594, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 56, 0, 594, 0, 0, 0, 0, + 0, 57, 25, 58, 26, 0, 594, 27, 59, 0, + 60, 61, 28, 62, 63, 64, 29, 0, 594, 0, + 0, 0, 65, 0, 66, 31, 67, 68, 69, 70, + 0, 0, 33, 0, 594, 0, 71, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 76, 77, 78, 79, 80, 81, 40, 41, 82, + 83, 42, 84, 0, 85, 0, 0, 86, 87, 0, + 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 95, 0, 0, 0, 96, 0, + 0, 0, 0, 97, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 268, 0, 0, 0, 106, 107, 108, 109, 57, 25, + 58, 26, 0, 0, 27, 59, 0, 60, 61, 28, + 62, 63, 64, 29, 0, 0, 0, 0, 0, 65, + 0, 66, 31, 67, 68, 69, 70, 0, 0, 33, + 0, 0, 0, 71, 34, 0, 72, 73, 35, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, + 37, 0, 38, 75, 0, 0, 39, 0, 76, 77, + 78, 79, 80, 81, 40, 41, 82, 83, 42, 84, + 0, 85, 0, 0, 86, 87, 0, 0, 88, 89, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, + 0, 95, 0, 0, 0, 96, 0, 0, 0, 0, + 97, 98, 99, 100, 101, 0, 0, 0, 102, 0, + 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, + 0, 106, 107, 108, 109, 57, 25, 58, 26, 0, + 0, 27, 59, 0, 60, 61, 28, 62, 63, 64, + 29, 0, 0, 0, 0, 0, 65, 0, 66, 31, + 67, 68, 69, 70, 0, 0, 33, 0, 0, 0, + 71, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 74, 0, 37, 0, 38, + 75, 0, 0, 39, 0, 76, 77, 78, 79, 80, + 81, 40, 41, 82, 83, 42, 84, 0, 85, 0, + 0, 86, 87, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 0, 0, 0, 95, 0, + 0, 0, 96, 0, 0, 0, 0, 97, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, + 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 928, 0, 0, 0, 106, 107, + 108, 109, 928, 928, 928, 928, 0, 0, 928, 928, + 0, 928, 928, 928, 928, 928, 928, 928, 0, 0, + 0, 0, 0, 928, 0, 928, 928, 928, 928, 928, + 928, 0, 0, 928, 0, 0, 0, 928, 928, 0, + 928, 928, 928, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 928, 0, 928, 0, 928, 928, 0, 0, + 928, 0, 928, 928, 928, 928, 928, 928, 928, 928, + 928, 928, 928, 928, 0, 928, 0, 0, 928, 928, + 0, 0, 928, 928, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 928, 928, 928, + 928, 928, 0, 0, 0, 928, 0, 0, 0, 928, + 0, 0, 0, 0, 928, 928, 928, 928, 928, 0, + 0, 0, 928, 0, 928, 0, 0, 0, 0, 0, + 928, 928, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 792, 0, 0, 0, 928, 928, 928, 928, 792, + 792, 792, 792, 0, 0, 792, 792, 0, 792, 792, + 792, 792, 792, 792, 792, 0, 0, 0, 0, 0, + 792, 0, 792, 792, 792, 792, 792, 792, 0, 0, + 792, 0, 0, 0, 792, 792, 0, 792, 792, 792, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 792, + 0, 792, 0, 792, 792, 0, 0, 792, 0, 792, + 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, + 792, 0, 792, 0, 0, 792, 792, 0, 0, 792, + 792, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 792, 792, 792, 792, 792, 0, + 0, 0, 792, 0, 0, 0, 792, 0, 0, 0, + 0, 792, 792, 792, 792, 792, 0, 0, 0, 792, + 0, 792, 0, 0, 0, 0, 0, 792, 792, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 725, 0, + 0, 0, 792, 792, 792, 792, 57, 25, 0, 26, + 0, 0, 27, 256, 0, 1018, 0, 28, 62, 63, + 0, 29, 0, 0, 25, 0, 26, 65, 0, 27, + 31, 0, 0, 0, 28, 0, 0, 33, 29, 0, + 0, 0, 34, 0, 72, 73, 35, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 37, 34, + 38, 75, 0, 35, 39, 0, 0, 77, 0, 79, + 0, 81, 40, 41, 257, 37, 42, 38, 0, 0, + 0, 39, 0, 87, 0, 0, 88, 89, 0, 40, + 41, 0, 0, 42, 0, 0, 319, 0, 0, 0, + 0, 90, 91, 92, 93, 94, 0, 0, 0, 509, + 726, 0, 0, 96, 0, 0, 0, 0, 0, 98, + 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, + 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 725, 0, 0, 0, 106, + 301, 108, 109, 57, 25, 0, 26, 0, 0, 27, + 256, 0, 1139, 0, 28, 62, 63, 354, 29, 0, + 0, 25, 0, 26, 65, 0, 27, 31, 0, 0, + 0, 28, 0, 0, 33, 29, 0, 0, 0, 34, + 0, 72, 73, 35, 31, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 37, 34, 38, 75, 906, + 35, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 37, 42, 38, 0, 0, 0, 39, 0, + 87, 0, 0, 88, 89, 0, 40, 41, 0, 0, + 42, 0, 0, 319, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 106, 301, 108, 109, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 354, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, + 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 712, 975, 0, 0, 96, 0, 0, 0, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 695, 0, 106, 713, 108, 109, 0, 0, 57, 25, + 0, 26, 0, 714, 27, 256, 0, 0, 0, 28, + 62, 63, 0, 29, 0, 0, 187, 0, 187, 65, + 0, 187, 31, 0, 0, 0, 187, 0, 0, 33, + 187, 0, 0, 0, 34, 0, 72, 73, 35, 187, + 0, 0, 0, 0, 0, 0, 187, 0, 0, 0, + 37, 187, 38, 75, 0, 187, 39, 0, 0, 77, + 0, 79, 0, 81, 40, 41, 257, 187, 42, 187, + 0, 85, 0, 187, 0, 87, 0, 0, 88, 89, + 0, 187, 187, 0, 0, 187, 0, 0, 187, 0, + 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, + 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, + 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, + 103, 0, 0, 952, 0, 0, 104, 105, 0, 0, + 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, + 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, + 0, 106, 301, 108, 109, 65, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 0, 187, + 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 37, 0, 38, 75, + 0, 0, 39, 0, 0, 77, 0, 79, 0, 81, + 40, 41, 257, 0, 42, 0, 0, 0, 0, 0, + 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, + 91, 92, 93, 94, 0, 0, 0, 712, 0, 0, + 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, + 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, + 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 725, 0, 106, 713, 108, + 109, 0, 0, 57, 25, 0, 26, 0, 714, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 0, 187, 0, 187, 65, 0, 187, 31, 0, 0, + 0, 187, 0, 0, 33, 187, 0, 0, 0, 34, + 0, 72, 73, 35, 187, 0, 0, 0, 0, 0, + 0, 187, 0, 0, 0, 37, 187, 38, 75, 0, + 187, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 187, 42, 187, 0, 0, 0, 187, 0, + 87, 0, 0, 88, 89, 0, 187, 187, 0, 0, + 187, 0, 0, 187, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 952, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 894, 0, 0, 0, 106, 301, 108, 109, + 57, 25, 0, 26, 0, 0, 27, 256, 0, 0, + 0, 28, 62, 63, 187, 29, 0, 0, 25, 0, + 26, 65, 0, 27, 31, 0, 0, 0, 28, 0, + 0, 33, 29, 0, 0, 0, 34, 0, 72, 73, + 35, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 37, 34, 38, 75, 0, 35, 39, 0, + 0, 77, 0, 79, 0, 81, 40, 41, 257, 37, + 42, 38, 0, 0, 0, 39, 0, 87, 0, 0, + 88, 89, 0, 40, 41, 0, 0, 42, 0, 0, + 319, 0, 0, 0, 0, 90, 91, 92, 93, 94, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, + 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, + 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 619, + 0, 0, 0, 106, 301, 108, 109, 619, 619, 0, + 619, 0, 0, 619, 619, 0, 0, 0, 619, 619, + 619, 320, 619, 0, 0, 0, 0, 0, 619, 0, + 0, 619, 0, 0, 0, 0, 0, 0, 619, 0, + 0, 0, 0, 619, 0, 619, 619, 619, 0, 0, + 0, 0, 0, 0, 0, 346, 0, 0, 0, 619, + 0, 619, 619, 0, 0, 619, 0, 0, 619, 0, + 619, 0, 619, 619, 619, 619, 0, 619, 0, 0, + 0, 0, 0, 0, 619, 0, 0, 619, 619, 0, + 0, 346, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 619, 619, 619, 619, 619, 0, 0, 0, + 0, 0, 0, 0, 619, 0, 0, 0, 0, 0, + 619, 619, 619, 619, 0, 0, 0, 619, 0, 619, + 0, 0, 0, 0, 0, 619, 619, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 619, 619, 619, 619, 346, 346, 346, 346, 0, 0, + 0, 346, 346, 0, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 0, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, + 346, 346, 346, 346, 346, 346, 346, 0, 48, 0, + 0, 0, 48, 346, 48, 0, 346, 48, 0, 48, + 48, 0, 48, 0, 48, 0, 48, 0, 48, 48, + 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, + 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, + 0, 48, 0, 0, 48, 0, 48, 48, 48, 48, + 0, 0, 0, 48, 48, 48, 0, 0, 48, 48, + 48, 0, 0, 0, 0, 0, 0, 48, 48, 0, + 48, 48, 0, 48, 48, 48, 0, 0, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, + 0, 48, 0, 48, 0, 81, 48, 0, 48, 48, + 0, 48, 0, 48, 48, 48, 0, 48, 48, 48, + 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, + 0, 48, 48, 48, 0, 0, 48, 0, 48, 0, + 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 0, 48, 48, 48, 48, 0, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 48, 48, 0, 48, + 48, 0, 48, 48, 48, 0, 0, 0, 48, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, + 48, 0, 48, 0, 82, 48, 0, 48, 48, 0, + 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, + 0, 0, 48, 48, 0, 0, 0, 0, 48, 0, + 48, 48, 48, 0, 0, 48, 0, 48, 0, 48, + 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, + 0, 48, 48, 48, 48, 0, 48, 48, 48, 0, + 0, 0, 0, 0, 0, 48, 48, 0, 48, 48, + 0, 48, 48, 48, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 48, 0, 48, 0, 48, + 0, 48, 0, 104, 48, 0, 48, 48, 0, 48, + 0, 48, 48, 48, 0, 48, 48, 48, 48, 0, + 0, 48, 48, 0, 0, 0, 0, 48, 0, 48, + 48, 48, 0, 0, 48, 0, 48, 0, 48, 0, + 0, 48, 0, 48, 48, 48, 48, 0, 0, 0, + 48, 48, 48, 48, 0, 48, 48, 48, 0, 0, + 0, 0, 0, 0, 48, 48, 0, 48, 48, 0, + 48, 48, 48, 0, 0, 0, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 48, 0, 48, 0, 48, 0, + 48, 0, 105, 48, 0, 48, 48, 0, 48, 0, + 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, + 48, 48, 0, 0, 0, 0, 48, 0, 48, 48, + 48, 0, 0, 48, 0, 48, 0, 48, 0, 0, + 48, 0, 48, 48, 48, 48, 0, 0, 0, 48, + 48, 48, 48, 0, 48, 48, 48, 0, 0, 0, + 0, 0, 0, 48, 48, 0, 48, 48, 0, 48, + 48, 48, 0, 0, 0, 48, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, + 0, 0, 48, 0, 48, 48, 0, 48, 0, 48, + 48, 227, 48, 0, 48, 0, 48, 0, 48, 48, + 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, + 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, + 346, 48, 0, 0, 48, 0, 48, 48, 48, 48, + 0, 0, 0, 48, 48, 48, 0, 0, 48, 48, + 48, 48, 0, 346, 0, 0, 0, 48, 48, 0, + 48, 48, 447, 48, 48, 48, 346, 0, 0, 48, + 0, 346, 0, 0, 346, 0, 346, 0, 346, 346, + 346, 346, 0, 0, 0, 448, 346, 0, 0, 48, + 346, 0, 0, 0, 346, 228, 0, 0, 449, 0, + 367, 0, 346, 451, 0, 346, 0, 346, 452, 0, + 453, 454, 455, 456, 0, 0, 0, 0, 457, 0, + 0, 0, 458, 367, 0, 0, 346, 0, 0, 0, + 0, 346, 0, 0, 459, 0, 367, 460, 346, 461, + 278, 367, 346, 0, 244, 48, 367, 0, 367, 367, + 367, 367, 0, 0, 0, 346, 367, 0, 0, 0, + 367, 0, 0, 462, 367, 0, 0, 0, 0, 0, + 0, 0, 367, 57, 25, 367, 26, 367, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 346, 29, 0, + 0, 0, 0, 0, 65, 0, 0, 31, 0, 0, + 0, 367, 0, 0, 33, 0, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 582, 0, 0, 0, 1308, + 0, 0, 583, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, + 584, 0, 0, 88, 89, 0, 0, 367, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 0, 0, 0, 0, + 96, 901, 0, 585, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 106, 469, 108, 109, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 582, 0, 0, 0, 0, 0, 0, 583, 0, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, + 0, 0, 0, 0, 0, 0, 584, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 0, 585, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, + 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, + 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, + 29, 0, 106, 469, 108, 109, 65, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, + 0, 34, 0, 72, 73, 35, 0, 582, 0, 0, + 0, 0, 0, 0, 583, 0, 0, 37, 0, 38, + 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, + 81, 40, 41, 257, 0, 42, 0, 0, 0, 0, + 0, 0, 584, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, + 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, + 0, 0, 28, 62, 63, 0, 29, 0, 106, 469, + 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, + 0, 42, 0, 0, 85, 0, 0, 0, 87, 0, + 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, + 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, + 63, 0, 29, 0, 106, 301, 108, 109, 65, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, + 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, + 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, + 0, 859, 0, 0, 96, 0, 0, 0, 0, 0, + 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, + 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, + 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 106, 301, 108, 109, 65, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, + 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 106, 301, 108, 109, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, + 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 503, 0, 0, 0, 96, 0, 0, 0, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, + 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, + 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, + 29, 0, 106, 301, 108, 109, 65, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, + 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, + 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, + 81, 40, 41, 257, 0, 42, 0, 0, 0, 0, + 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, + 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, + 0, 0, 28, 62, 63, 0, 29, 0, 106, 301, + 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, + 0, 0, 33, 0, 0, 0, 0, 34, 0, 72, + 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, + 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, + 0, 42, 0, 0, 0, 0, 0, 0, 87, 0, + 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, + 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, + 63, 0, 29, 0, 106, 469, 108, 109, 65, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, + 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, + 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, + 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, + 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, + 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, + 0, 0, 0, 78, 78, 0, 78, 0, 0, 78, + 78, 0, 0, 0, 78, 78, 78, 0, 78, 0, + 106, 1010, 108, 109, 78, 0, 0, 78, 0, 0, + 0, 0, 0, 0, 78, 0, 0, 0, 0, 78, + 0, 78, 78, 78, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 78, 0, 78, 78, 0, + 0, 78, 0, 0, 78, 0, 78, 0, 78, 78, + 78, 78, 0, 78, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 78, 78, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, + 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, + 78, 0, 0, 0, 0, 0, 78, 78, 78, 78, + 0, 0, 0, 78, 0, 78, 0, 0, 0, 0, + 0, 78, 78, 0, 0, 0, 0, 0, 0, 150, + 150, 0, 150, 0, 0, 150, 150, 0, 0, 0, + 150, 150, 150, 0, 150, 0, 78, 78, 78, 78, + 150, 0, 0, 150, 0, 0, 0, 0, 0, 0, + 150, 0, 0, 0, 0, 150, 0, 150, 150, 150, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 150, 0, 150, 150, 0, 0, 150, 0, 0, + 150, 0, 150, 0, 150, 150, 150, 150, 0, 150, + 0, 0, 0, 0, 0, 0, 150, 0, 0, 150, + 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 150, 150, 150, 150, 150, 0, + 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, + 0, 0, 150, 150, 150, 150, 0, 0, 0, 150, + 0, 150, 0, 0, 0, 0, 0, 150, 150, 0, + 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, + 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, + 29, 0, 150, 150, 150, 150, 65, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 28, 0, + 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, + 75, 28, 0, 39, 0, 0, 77, 0, 79, 0, + 81, 40, 41, 257, 28, 42, 0, 0, 0, 28, + 0, 0, 0, 0, 28, 0, 28, 28, 28, 28, + 0, 0, 28, 0, 28, 0, 0, 0, 28, 0, + 90, 91, 92, 258, 94, 0, 0, 0, 0, 0, + 28, 0, 96, 28, 0, 28, 0, 0, 98, 99, + 100, 101, 0, 0, 0, 102, 0, 103, 0, 57, + 25, 0, 26, 104, 105, 27, 256, 0, 0, 28, + 28, 62, 63, 0, 29, 28, 28, 0, 0, 0, + 65, 0, 0, 31, 0, 0, 0, 48, 106, 259, + 33, 109, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 37, 0, 38, 75, 0, 0, 39, 0, 0, + 77, 0, 79, 48, 81, 40, 41, 257, 48, 42, + 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 48, 0, 48, 0, 0, 0, 48, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 258, 94, 48, + 0, 0, 48, 0, 48, 0, 96, 652, 0, 652, + 0, 652, 98, 0, 652, 101, 652, 652, 0, 652, + 0, 652, 0, 652, 0, 652, 652, 652, 48, 0, + 0, 652, 652, 0, 311, 0, 0, 652, 0, 652, + 652, 0, 0, 0, 652, 0, 0, 0, 652, 0, + 0, 0, 106, 259, 0, 109, 0, 0, 0, 652, + 652, 0, 652, 0, 0, 0, 652, 652, 0, 0, + 0, 0, 0, 0, 652, 652, 57, 25, 652, 26, + 0, 652, 27, 256, 0, 0, 652, 28, 62, 63, + 0, 29, 0, 0, 0, 0, 0, 65, 0, 0, + 31, 0, 0, 0, 0, 0, 0, 33, 652, 652, + 0, 0, 34, 0, 72, 73, 35, 0, 0, 0, + 0, 652, 0, 0, 0, 0, 0, 0, 37, 0, + 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, + 0, 81, 40, 41, 257, 0, 42, 0, 0, 85, + 0, 0, 0, 0, 0, 0, 25, 0, 26, 0, + 0, 27, 652, 1190, 0, 0, 28, 0, 0, 0, + 29, 90, 91, 92, 258, 0, 0, 0, 0, 31, + 651, 0, 651, 96, 0, 651, 33, 651, 651, 0, + 651, 34, 651, 1191, 651, 35, 651, 651, 651, 0, + 0, 0, 651, 651, 0, 0, 0, 37, 651, 38, + 651, 651, 0, 39, 1192, 651, 0, 0, 0, 651, + 0, 40, 41, 0, 0, 42, 0, 0, 319, 106, + 259, 651, 0, 651, 0, 0, 0, 651, 651, 0, + 0, 0, 0, 0, 0, 651, 651, 0, 651, 651, + 651, 0, 651, 651, 0, 651, 651, 651, 651, 0, + 651, 0, 651, 0, 651, 651, 651, 0, 0, 0, + 651, 651, 0, 0, 0, 0, 651, 0, 651, 651, + 0, 0, 0, 651, 0, 0, 0, 651, 0, 0, + 0, 0, 651, 0, 0, 0, 0, 0, 0, 651, + 0, 651, 0, 0, 0, 651, 651, 0, 0, 354, + 0, 0, 0, 651, 651, 0, 0, 651, 0, 0, + 651, 0, 25, 0, 26, 651, 0, 27, 0, 0, + 1263, 0, 28, 651, 671, 0, 29, 0, 672, 1264, + 1265, 0, 0, 0, 1266, 31, 0, 0, 0, 0, + 1267, 0, 33, 0, 25, 0, 26, 34, 0, 27, + 0, 35, 1263, 0, 28, 0, 671, 0, 29, 0, + 672, 1264, 1265, 37, 0, 38, 1266, 31, 0, 39, + 0, 0, 1267, 0, 33, 0, 0, 40, 41, 34, + 0, 42, 0, 35, 1268, 0, 0, 0, 48, 1269, + 48, 651, 0, 48, 0, 37, 0, 38, 48, 0, + 0, 39, 48, 0, 0, 0, 0, 0, 0, 40, + 41, 48, 0, 42, 0, 0, 1268, 0, 48, 0, + 48, 1269, 48, 48, 1270, 48, 0, 48, 0, 48, + 48, 48, 0, 0, 48, 0, 48, 0, 0, 48, + 0, 48, 0, 48, 0, 48, 0, 0, 48, 0, + 48, 0, 0, 48, 48, 48, 0, 48, 0, 48, + 48, 48, 0, 48, 48, 1271, 48, 0, 48, 48, + 0, 48, 0, 48, 48, 0, 0, 48, 48, 0, + 48, 0, 0, 0, 0, 48, 48, 48, 0, 48, + 0, 0, 48, 0, 48, 168, 25, 1271, 26, 48, + 0, 27, 0, 48, 0, 48, 28, 48, 0, 0, + 29, 0, 48, 0, 0, 48, 0, 48, 0, 31, + 0, 48, 0, 0, 48, 168, 33, 0, 0, 48, + 48, 34, 0, 48, 0, 35, 48, 563, 0, 0, + 0, 48, 0, 0, 564, 0, 0, 37, 0, 38, + 0, 0, 0, 39, 0, 0, 565, 0, 0, 0, + 0, 40, 41, 0, 0, 42, 0, 25, 566, 26, + 0, 0, 27, 48, 0, 0, 0, 28, 0, 0, + 0, 29, 0, 0, 0, 30, 25, 0, 26, 0, + 31, 27, 0, 0, 0, 32, 28, 33, 0, 0, + 29, 0, 34, 0, 0, 0, 35, 36, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 48, 37, 0, + 38, 34, 0, 0, 39, 35, 0, 0, 0, 0, + 0, 0, 40, 41, 0, 0, 42, 37, 0, 38, + 25, 0, 26, 39, 0, 27, 0, 0, 0, 567, + 28, 40, 41, 0, 29, 42, 0, 25, 319, 26, + 0, 0, 27, 31, 0, 0, 0, 28, 0, 0, + 33, 29, 0, 0, 0, 34, 0, 0, 0, 35, + 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, + 0, 37, 34, 38, 0, 0, 35, 39, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 0, 37, 42, + 38, 25, 319, 26, 39, 0, 27, 0, 0, 0, + 43, 28, 40, 41, 0, 29, 42, 0, 0, 511, + 0, 0, 0, 0, 31, 25, 0, 26, 0, 326, + 27, 33, 0, 0, 0, 28, 34, 0, 0, 29, + 35, 0, 0, 0, 0, 0, 0, 0, 31, 0, + 0, 0, 37, 0, 38, 33, 0, 0, 39, 0, + 34, 0, 0, 0, 35, 0, 40, 41, 0, 0, + 42, 0, 0, 319, 0, 25, 37, 26, 38, 0, + 27, 0, 39, 354, 0, 28, 0, 0, 0, 29, + 40, 41, 0, 0, 42, 0, 0, 319, 31, 25, + 354, 26, 0, 0, 27, 33, 0, 0, 0, 28, + 34, 0, 0, 29, 35, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 0, 0, 37, 0, 38, 33, + 0, 0, 39, 0, 34, 0, 0, 0, 35, 0, + 40, 41, 0, 0, 42, 0, 0, 566, 0, 0, + 37, 0, 38, 498, 630, 498, 39, 0, 498, 0, + 0, 0, 0, 498, 40, 41, 0, 498, 42, 0, + 188, 739, 188, 0, 0, 188, 498, 0, 632, 0, + 188, 0, 0, 498, 188, 0, 0, 0, 498, 0, + 0, 0, 498, 188, 0, 0, 0, 0, 0, 0, + 188, 0, 0, 0, 498, 188, 498, 0, 0, 188, + 498, 0, 0, 0, 0, 0, 0, 0, 498, 498, + 0, 188, 498, 188, 187, 498, 187, 188, 354, 187, + 0, 0, 0, 0, 187, 188, 188, 0, 187, 188, + 0, 0, 188, 0, 0, 0, 0, 187, 197, 0, + 197, 0, 354, 197, 187, 0, 0, 0, 197, 187, + 0, 0, 197, 187, 0, 0, 0, 0, 0, 0, + 0, 197, 0, 0, 0, 187, 0, 187, 197, 0, + 0, 187, 0, 197, 0, 0, 0, 197, 0, 187, + 187, 0, 35, 187, 0, 0, 187, 0, 0, 197, + 0, 197, 0, 35, 0, 197, 498, 0, 35, 0, + 0, 0, 35, 197, 197, 35, 0, 197, 0, 0, + 197, 0, 0, 188, 0, 0, 0, 35, 35, 0, + 0, 0, 35, 35, 0, 33, 0, 0, 35, 0, + 35, 35, 35, 35, 0, 0, 33, 0, 35, 0, + 0, 33, 35, 0, 35, 33, 0, 0, 33, 0, + 0, 0, 0, 0, 35, 0, 35, 35, 0, 35, + 33, 33, 0, 35, 0, 33, 33, 187, 0, 0, + 0, 33, 0, 33, 33, 33, 33, 0, 0, 0, + 0, 33, 0, 35, 0, 33, 0, 33, 0, 35, + 35, 197, 0, 28, 0, 28, 0, 33, 0, 0, + 33, 0, 33, 0, 0, 0, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 28, + 0, 0, 33, 33, 28, 0, 48, 0, 0, 28, + 0, 28, 28, 28, 28, 0, 0, 48, 0, 28, + 0, 0, 48, 28, 0, 0, 48, 0, 0, 48, + 0, 0, 0, 0, 0, 28, 0, 0, 28, 0, + 28, 48, 48, 0, 0, 0, 48, 48, 0, 48, + 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, + 48, 0, 48, 0, 28, 48, 48, 0, 48, 48, + 28, 28, 48, 0, 0, 0, 0, 0, 48, 0, + 0, 48, 0, 48, 48, 48, 0, 48, 0, 48, + 48, 48, 0, 0, 0, 48, 0, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 48, 0, 48, + 0, 48, 0, 37, 48, 0, 0, 0, 0, 0, + 0, 48, 0, 0, 48, 0, 48, 48, 0, 48, + 48, 0, 48, 0, 0, 0, 0, 48, 0, 48, + 48, 48, 48, 0, 0, 0, 0, 48, 0, 0, + 48, 48, 48, 0, 0, 0, 38, 0, 0, 0, + 0, 0, 0, 48, 0, 48, 48, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, + 48, 0, 0, 0, 0, 48, 0, 0, 0, 48, + 48, 0, 48, 0, 48, 48, 0, 0, 209, 0, + 0, 48, 0, 48, 48, 48, 48, 0, 48, 0, + 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, + 0, 0, 0, 48, 0, 0, 0, 48, 48, 0, + 48, 0, 48, 48, 0, 447, 211, 0, 0, 48, + 0, 48, 48, 0, 48, 0, 48, 0, 0, 0, + 0, 48, 0, 48, 48, 48, 48, 0, 448, 0, + 0, 48, 0, 0, 0, 48, 0, 0, 48, 0, + 0, 449, 0, 0, 312, 450, 451, 48, 447, 0, + 48, 452, 48, 453, 454, 455, 456, 0, 0, 0, + 0, 457, 0, 0, 0, 458, 0, 0, 0, 0, + 0, 448, 0, 0, 0, 0, 48, 459, 48, 48, + 460, 0, 461, 0, 449, 0, 0, 0, 0, 451, + 0, 0, 0, 0, 452, 0, 453, 454, 455, 456, + 0, 0, 0, 0, 457, 0, 462, 0, 458, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 459, 0, 0, 460, 0, 461, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, + }; + protected static readonly short [] yyCheck = { 17, + 17, 4, 507, 17, 20, 299, 6, 18, 300, 52, + 235, 191, 353, 20, 291, 107, 509, 464, 85, 250, + 190, 60, 549, 298, 159, 483, 296, 335, 17, 328, + 318, 353, 559, 48, 60, 730, 1076, 705, 706, 1113, + 1114, 0, 906, 237, 0, 59, 113, 569, 115, 324, + 759, 78, 256, 113, 256, 115, 74, 256, 256, 256, + 78, 256, 1181, 256, 268, 1197, 80, 256, 82, 256, + 256, 256, 88, 89, 256, 325, 268, 368, 96, 368, + 748, 1213, 750, 282, 17, 1159, 368, 374, 294, 268, + 376, 256, 268, 109, 339, 1285, 357, 335, 256, 306, + 276, 391, 17, 21, 367, 1224, 313, 1226, 1298, 1226, + 368, 367, 373, 376, 277, 314, 374, 17, 325, 257, + 376, 17, 367, 381, 414, 386, 1316, 418, 650, 416, + 17, 376, 407, 17, 365, 53, 1071, 1256, 17, 1256, + 429, 159, 159, 429, 339, 159, 294, 429, 191, 344, + 256, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 266, 17, 17, 17, 17, 259, 418, 256, + 159, 294, 370, 368, 372, 370, 374, 372, 256, 374, + 375, 376, 523, 306, 370, 391, 202, 203, 374, 368, + 256, 429, 235, 62, 381, 390, 381, 66, 67, 68, + 358, 70, 71, 428, 503, 546, 75, 76, 414, 301, + 314, 226, 506, 82, 707, 84, 418, 86, 422, 418, + 418, 418, 91, 92, 546, 418, 159, 0, 569, 418, + 422, 231, 250, 339, 429, 429, 418, 255, 344, 343, + 346, 549, 418, 422, 159, 114, 352, 353, 264, 288, + 317, 559, 1384, 418, 321, 418, 419, 296, 325, 159, + 88, 89, 288, 159, 356, 325, 424, 425, 426, 427, + 418, 375, 159, 291, 290, 159, 294, 295, 325, 1411, + 159, 109, 369, 264, 300, 994, 256, 391, 314, 307, + 306, 1423, 294, 1425, 312, 418, 314, 375, 257, 313, + 318, 257, 970, 369, 256, 159, 159, 159, 159, 650, + 414, 329, 330, 256, 1009, 372, 272, 256, 335, 346, + 842, 277, 256, 429, 428, 281, 256, 262, 346, 651, + 671, 1158, 256, 418, 350, 372, 372, 353, 1378, 358, + 296, 371, 434, 428, 325, 1054, 335, 365, 366, 1176, + 256, 372, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 298, 256, 256, 882, 323, 384, 385, + 1444, 418, 429, 294, 202, 203, 468, 469, 335, 256, + 873, 349, 350, 1318, 402, 428, 342, 963, 257, 391, + 420, 260, 429, 429, 852, 438, 412, 413, 368, 1473, + 1227, 493, 1266, 305, 374, 693, 294, 341, 429, 339, + 1345, 1346, 414, 1348, 430, 991, 368, 1413, 1414, 1087, + 435, 436, 374, 430, 1359, 256, 441, 1362, 444, 298, + 369, 374, 368, 339, 775, 369, 264, 444, 344, 709, + 346, 310, 1377, 378, 379, 369, 352, 353, 679, 376, + 1277, 1119, 1120, 775, 1281, 369, 6, 483, 1126, 373, + 1036, 429, 290, 371, 478, 373, 1401, 17, 341, 962, + 391, 256, 988, 1469, 990, 367, 367, 369, 306, 371, + 256, 263, 418, 256, 576, 376, 578, 505, 580, 507, + 367, 509, 369, 414, 371, 372, 369, 374, 372, 376, + 374, 842, 429, 391, 257, 519, 520, 523, 339, 423, + 60, 277, 368, 531, 64, 281, 523, 349, 350, 841, + 538, 418, 350, 429, 349, 350, 414, 305, 420, 305, + 546, 423, 549, 315, 17, 269, 367, 401, 88, 89, + 861, 418, 559, 420, 558, 839, 423, 263, 256, 413, + 642, 872, 286, 569, 339, 429, 384, 385, 368, 109, + 549, 792, 1181, 851, 582, 583, 339, 866, 368, 368, + 559, 256, 373, 429, 369, 376, 342, 60, 343, 1037, + 343, 64, 367, 718, 412, 413, 98, 99, 100, 101, + 102, 103, 104, 105, 367, 870, 1123, 429, 371, 315, + 373, 374, 375, 376, 429, 1224, 343, 1226, 381, 159, + 479, 629, 375, 256, 906, 374, 381, 635, 381, 429, + 305, 713, 372, 418, 374, 372, 391, 369, 391, 429, + 429, 339, 272, 376, 650, 272, 344, 1256, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 414, + 519, 414, 202, 203, 391, 671, 296, 416, 357, 296, + 368, 679, 370, 428, 372, 428, 374, 375, 376, 376, + 709, 418, 672, 272, 741, 693, 159, 414, 277, 429, + 418, 369, 281, 323, 702, 979, 323, 386, 414, 707, + 428, 428, 1181, 376, 712, 370, 339, 296, 371, 374, + 931, 344, 428, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 264, 386, 256, 367, 734, 367, + 1181, 429, 736, 371, 323, 368, 376, 370, 272, 372, + 418, 374, 375, 376, 752, 1224, 754, 1226, 288, 755, + 290, 384, 385, 342, 758, 759, 389, 390, 1180, 1181, + 300, 769, 296, 1181, 367, 771, 306, 400, 401, 775, + 371, 343, 414, 1224, 314, 1226, 1043, 1256, 1200, 787, + 413, 256, 420, 816, 792, 793, 428, 795, 367, 323, + 418, 381, 1076, 1091, 269, 335, 429, 376, 806, 807, + 882, 391, 1224, 375, 1226, 1256, 1224, 381, 1226, 339, + 350, 286, 1079, 353, 344, 288, 346, 391, 824, 391, + 294, 367, 352, 353, 414, 1123, 328, 824, 391, 837, + 376, 839, 306, 1181, 1256, 379, 842, 843, 1256, 829, + 414, 314, 414, 851, 384, 385, 854, 1007, 1069, 384, + 1117, 414, 369, 861, 428, 1153, 428, 306, 421, 369, + 389, 1298, 335, 871, 313, 873, 367, 369, 367, 386, + 387, 381, 412, 413, 385, 376, 1224, 376, 1226, 381, + 382, 383, 1181, 1366, 386, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 906, 394, 395, 357, 1235, 913, 988, 915, 1256, 917, + 261, 1242, 391, 357, 400, 369, 734, 1132, 372, 373, + 374, 1188, 928, 931, 371, 1224, 373, 1226, 1010, 373, + 936, 928, 386, 284, 374, 414, 376, 755, 1108, 357, + 370, 381, 386, 483, 374, 1428, 297, 390, 938, 428, + 940, 302, 942, 771, 962, 373, 307, 1256, 309, 310, + 311, 312, 339, 367, 418, 369, 317, 344, 386, 346, + 321, 1181, 349, 350, 325, 352, 353, 373, 369, 414, + 376, 1464, 333, 523, 1266, 336, 421, 338, 373, 339, + 994, 1486, 1487, 1001, 344, 1003, 346, 1005, 418, 349, + 350, 503, 352, 353, 398, 399, 546, 382, 383, 549, + 483, 362, 376, 372, 1224, 374, 1226, 376, 372, 559, + 374, 396, 397, 1016, 374, 843, 306, 339, 308, 569, + 354, 355, 344, 313, 346, 1043, 369, 349, 350, 372, + 352, 353, 418, 370, 371, 325, 1256, 374, 1056, 1057, + 1054, 372, 429, 374, 371, 376, 1064, 415, 357, 370, + 370, 1069, 374, 374, 374, 354, 355, 418, 1076, 1070, + 369, 1079, 574, 418, 373, 1108, 549, 1110, 339, 429, + 386, 387, 388, 344, 1091, 346, 559, 386, 349, 350, + 1098, 352, 353, 339, 1378, 256, 60, 1105, 344, 1132, + 346, 414, 415, 349, 350, 1111, 352, 353, 368, 1117, + 650, 371, 1091, 373, 374, 418, 1123, 429, 936, 418, + 277, 1129, 1130, 370, 371, 418, 373, 374, 375, 1162, + 94, 671, 392, 393, 98, 99, 100, 101, 102, 103, + 104, 105, 376, 372, 1123, 374, 1153, 1180, 1181, 370, + 340, 372, 412, 374, 370, 367, 372, 1163, 374, 0, + 420, 376, 1170, 423, 373, 705, 706, 1200, 429, 374, + 357, 376, 370, 1179, 1153, 371, 374, 373, 1186, 370, + 1188, 372, 369, 429, 370, 372, 373, 370, 374, 372, + 374, 1224, 376, 1226, 734, 368, 392, 393, 371, 386, + 373, 374, 372, 370, 339, 372, 376, 376, 748, 344, + 750, 346, 370, 1295, 372, 755, 412, 352, 353, 392, + 393, 364, 365, 1256, 420, 376, 1308, 423, 1234, 1235, + 418, 771, 705, 706, 1238, 775, 1242, 418, 372, 412, + 374, 372, 367, 1325, 343, 1327, 371, 420, 373, 374, + 423, 376, 372, 256, 374, 376, 381, 1263, 1264, 370, + 1266, 372, 414, 370, 367, 372, 1272, 372, 371, 418, + 373, 374, 374, 376, 376, 748, 418, 750, 381, 1285, + 418, 1287, 367, 374, 1290, 376, 371, 369, 373, 374, + 415, 376, 1298, 374, 418, 376, 381, 349, 350, 1303, + 285, 372, 842, 843, 390, 391, 392, 393, 418, 374, + 1316, 376, 415, 372, 373, 364, 365, 1074, 1075, 388, + 389, 394, 395, 1356, 288, 376, 372, 372, 368, 372, + 374, 372, 296, 372, 372, 418, 339, 372, 294, 294, + 1373, 344, 327, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 1386, 1387, 374, 372, 372, 1366, 376, + 1364, 1179, 418, 374, 866, 368, 906, 370, 372, 372, + 1378, 374, 375, 376, 371, 256, 374, 356, 372, 375, + 1413, 1414, 418, 374, 418, 375, 381, 1395, 374, 373, + 418, 372, 377, 378, 379, 380, 936, 382, 383, 384, + 385, 386, 387, 388, 389, 369, 381, 392, 393, 394, + 395, 396, 397, 398, 399, 256, 1234, 381, 382, 383, + 1428, 262, 386, 387, 374, 374, 429, 374, 376, 418, + 970, 0, 374, 294, 372, 423, 1469, 429, 374, 367, + 418, 372, 418, 373, 343, 1263, 1264, 372, 374, 294, + 294, 374, 418, 294, 370, 418, 1464, 298, 371, 381, + 418, 367, 256, 375, 256, 374, 1470, 1471, 256, 1287, + 256, 372, 1290, 1477, 1478, 372, 381, 280, 1486, 1487, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 256, 367, 372, 368, 418, 343, 374, 970, 339, 418, + 418, 418, 376, 344, 370, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 371, 376, 418, 376, + 374, 372, 372, 376, 370, 421, 367, 368, 423, 370, + 371, 372, 381, 374, 375, 376, 347, 378, 379, 351, + 367, 382, 383, 384, 385, 381, 381, 1087, 389, 390, + 256, 1091, 256, 394, 395, 396, 397, 398, 399, 400, + 401, 368, 372, 372, 347, 370, 374, 367, 370, 375, + 348, 1111, 413, 372, 375, 416, 372, 418, 368, 1119, + 1120, 370, 339, 1123, 418, 418, 1126, 374, 429, 256, + 374, 376, 348, 368, 375, 367, 367, 367, 265, 0, + 267, 368, 381, 270, 356, 418, 371, 376, 275, 368, + 574, 374, 279, 1153, 1087, 368, 337, 372, 1091, 368, + 305, 288, 376, 1163, 371, 418, 371, 418, 295, 369, + 367, 381, 371, 300, 367, 371, 418, 304, 418, 1179, + 371, 418, 371, 373, 371, 369, 1119, 1120, 371, 316, + 1123, 318, 372, 1126, 372, 322, 381, 374, 373, 373, + 261, 374, 263, 330, 331, 374, 256, 334, 376, 374, + 337, 372, 418, 372, 370, 418, 376, 418, 376, 372, + 1153, 376, 372, 284, 418, 367, 372, 256, 368, 381, + 381, 370, 261, 262, 1234, 1235, 297, 372, 368, 315, + 263, 302, 1242, 371, 368, 371, 307, 372, 309, 310, + 311, 312, 372, 0, 315, 284, 317, 0, 367, 376, + 321, 418, 376, 1263, 1264, 294, 1266, 368, 297, 298, + 372, 0, 333, 302, 368, 336, 305, 338, 307, 376, + 309, 310, 311, 312, 372, 709, 372, 1287, 317, 418, + 1290, 418, 321, 370, 367, 376, 325, 368, 368, 367, + 372, 362, 376, 370, 333, 418, 0, 336, 418, 338, + 339, 376, 376, 368, 372, 344, 376, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, 372, 368, + 372, 368, 372, 362, 367, 376, 368, 368, 367, 368, + 367, 370, 371, 372, 373, 374, 375, 376, 373, 378, + 379, 315, 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, 376, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 376, 376, 416, 376, 418, + 376, 420, 376, 376, 423, 256, 257, 376, 263, 51, + 429, 52, 12, 264, 265, 266, 267, 268, 5, 270, + 271, 928, 273, 274, 275, 276, 277, 278, 279, 280, + 824, 1200, 1256, 1381, 285, 1418, 287, 288, 289, 290, + 291, 292, 1069, 1069, 295, 0, 1434, 671, 299, 300, + 1369, 302, 303, 304, 1398, 1364, 1272, 1285, 845, 685, + 845, 845, 841, 314, 1478, 316, 1224, 318, 319, 1472, + 1304, 322, 1212, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 1391, 337, 1387, 1386, 340, + 341, 1327, 1162, 344, 345, 1471, 1272, 816, 523, 1163, + 712, 866, 792, 583, 365, 787, 979, 679, 359, 360, + 361, 362, 363, 72, 331, 709, 367, 368, 94, 396, + 371, 397, 400, 398, 1146, 376, 377, 378, 379, 380, + 399, 401, 546, 384, 1234, 386, 159, 1153, 949, 1057, + 1091, 392, 393, 964, 1048, 1037, 1046, 911, 886, 521, + 1230, 1130, 775, 420, 822, 821, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 417, 418, 419, 420, + -1, 422, 256, 257, -1, -1, -1, -1, 429, -1, + 264, 265, 266, 267, 268, -1, 270, 271, -1, 273, + 274, 275, 276, 277, 278, 279, -1, -1, 0, -1, + -1, 285, -1, 287, 288, 289, 290, 291, 292, -1, + -1, 295, -1, -1, -1, 299, 300, -1, 302, 303, + 304, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 314, -1, 316, -1, 318, 319, -1, -1, 322, -1, + 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, -1, -1, 340, 341, -1, -1, + 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, + -1, -1, -1, 367, 368, -1, -1, 371, -1, -1, + -1, -1, 376, 377, 378, 379, 380, -1, -1, -1, + 384, 256, 386, -1, -1, -1, 261, 262, 392, 393, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 0, 284, + -1, -1, -1, 417, 418, 419, 420, -1, 422, 294, + -1, -1, 297, 298, -1, 429, -1, 302, -1, -1, + 305, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, -1, -1, 321, -1, -1, -1, + 325, -1, -1, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 339, -1, -1, -1, -1, 344, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, -1, -1, -1, -1, 362, -1, -1, + -1, -1, 367, 368, 369, 370, 371, 372, 373, 374, + 375, 376, -1, 378, 379, -1, -1, 382, 383, 384, + 385, 386, -1, -1, 389, 390, -1, -1, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, -1, -1, 256, -1, -1, -1, 413, 261, + 262, 416, -1, 418, -1, 420, -1, -1, 423, -1, + -1, -1, -1, -1, 429, 0, -1, -1, -1, -1, + -1, -1, 284, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 294, -1, -1, 297, 298, -1, -1, -1, + 302, -1, -1, 305, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + -1, -1, -1, 325, -1, -1, -1, -1, -1, -1, + -1, 333, -1, -1, 336, -1, 338, 339, -1, -1, + -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, + 362, -1, -1, -1, -1, 367, 368, 369, 370, 371, + 372, -1, 374, 375, 376, -1, 378, 379, -1, -1, + 382, 383, 384, 385, 256, -1, -1, 389, 390, 261, + 262, -1, 394, 395, 396, 397, 398, 399, 400, 401, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 413, 284, -1, 416, -1, 418, -1, 420, -1, + -1, 423, 294, -1, -1, 297, 298, 429, -1, -1, + 302, -1, -1, 305, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + -1, -1, -1, 325, -1, -1, -1, -1, -1, -1, + -1, 333, -1, -1, 336, -1, 338, 339, -1, -1, + -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, + 362, -1, -1, -1, -1, 367, 368, 369, 370, 371, + 372, -1, 374, 375, 376, -1, 378, 379, -1, -1, + 382, 383, 384, 385, -1, -1, -1, 389, 390, -1, + -1, -1, 394, 395, 396, 397, 398, 399, 400, 401, + -1, 256, -1, -1, -1, -1, 261, 262, -1, -1, + -1, 413, -1, -1, 416, -1, 418, -1, 420, -1, + -1, 423, -1, -1, -1, -1, -1, 429, -1, 284, + -1, -1, -1, -1, -1, 0, -1, -1, -1, 294, + -1, -1, 297, 298, -1, -1, -1, 302, -1, -1, + 305, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, -1, -1, 321, -1, -1, -1, + 325, -1, -1, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 339, -1, -1, -1, -1, 344, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, -1, 362, -1, -1, + -1, -1, 367, 368, -1, 370, 371, 372, -1, 374, + 375, 376, -1, 378, 379, -1, 256, 382, 383, 384, + 385, -1, 262, -1, 389, 390, -1, -1, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 413, -1, + -1, 416, -1, 418, 294, -1, -1, -1, 298, -1, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 339, + -1, 0, -1, -1, 344, -1, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 356, 357, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 367, 368, 369, + 370, 371, 372, 373, 374, 375, 376, -1, 378, 379, + -1, -1, 382, 383, 384, 385, 386, -1, -1, 389, + 390, -1, -1, -1, 394, 395, 396, 397, 398, 399, + 400, 401, -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, 413, -1, -1, 416, -1, 418, -1, + 420, -1, 257, 423, -1, -1, 261, -1, 263, 429, + 265, -1, 267, -1, -1, 270, -1, 272, 273, -1, + 275, -1, 277, -1, 279, -1, 281, 282, 283, 284, + -1, -1, 287, 288, -1, -1, -1, 0, 293, 294, + 295, 296, 297, -1, -1, 300, 301, 302, -1, 304, + -1, 306, 307, 308, 309, 310, 311, 312, 313, -1, + 315, 316, 317, 318, -1, -1, 321, 322, 323, -1, + 325, -1, -1, -1, -1, 330, 331, -1, 333, 334, + -1, 336, 337, 338, -1, -1, -1, 342, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, 362, -1, 364, + 365, -1, -1, -1, 256, 257, -1, -1, -1, 261, + -1, -1, 377, 265, -1, 267, -1, -1, 270, -1, + 272, 273, -1, 275, -1, 277, -1, 279, -1, 281, + 282, 283, 284, 0, -1, 287, 288, -1, -1, -1, + -1, 293, -1, 295, 296, 297, -1, -1, 300, 301, + 302, -1, 304, 418, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, 316, 317, 318, -1, 257, 321, + 322, 323, 261, -1, -1, -1, 0, -1, 330, 331, + -1, 333, 334, 272, 336, 337, 338, -1, 277, -1, + 342, -1, 281, -1, -1, 284, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 296, 297, -1, + 362, -1, 301, 302, -1, -1, 368, 369, 307, 0, + 309, 310, 311, 312, -1, 377, -1, -1, 317, -1, + -1, -1, 321, -1, 323, -1, -1, 257, -1, -1, + -1, 261, -1, -1, 333, -1, 335, 336, -1, 338, + -1, -1, 272, 342, -1, -1, -1, 277, -1, -1, + -1, 281, 0, -1, 284, -1, 418, -1, -1, -1, + -1, -1, -1, 362, -1, -1, 296, 297, -1, 368, + 369, 301, 302, -1, 257, -1, -1, 307, 261, 309, + 310, 311, 312, -1, -1, -1, -1, 317, -1, 272, + -1, 321, -1, 323, 277, 0, -1, -1, 281, -1, + -1, 284, -1, 333, -1, 335, 336, -1, 338, -1, + -1, -1, 342, 296, 297, -1, -1, -1, 301, 302, + -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, 362, -1, 317, -1, -1, 257, 321, 369, + 323, 261, -1, -1, -1, -1, -1, -1, -1, -1, + 333, -1, 272, 336, -1, 338, -1, 277, 0, 342, + -1, 281, -1, -1, 284, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 296, 297, -1, 362, + 257, 301, 302, -1, 261, 368, 369, 307, -1, 309, + 310, 311, 312, -1, -1, 272, -1, 317, -1, -1, + 277, 321, -1, 323, 281, -1, -1, 284, -1, -1, + -1, -1, -1, 333, -1, -1, 336, -1, 338, 296, + 297, -1, 342, 257, 301, 302, -1, 261, -1, -1, + 307, -1, 309, 310, 311, 312, -1, -1, 272, -1, + 317, -1, 362, 277, 321, -1, 323, 281, 368, 369, + 284, -1, -1, -1, -1, -1, 333, -1, -1, 336, + -1, 338, 296, 297, -1, 342, 257, 301, 302, -1, + 261, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, 272, -1, 317, -1, 362, 277, 321, -1, 323, + 281, -1, 369, 284, -1, -1, -1, -1, -1, 333, + -1, -1, 336, -1, 338, 296, 297, -1, 342, 257, + 301, 302, -1, 261, -1, -1, 307, -1, 309, 310, + 311, 312, -1, -1, 272, -1, 317, -1, 362, 277, + 321, -1, 323, 281, -1, -1, 284, -1, -1, -1, + -1, -1, 333, -1, -1, 336, -1, 338, 296, 297, + -1, 342, 257, 301, 302, -1, 261, -1, -1, 307, + -1, 309, 310, 311, 312, -1, -1, 272, -1, 317, + -1, 362, 277, 321, -1, 323, 281, -1, -1, 284, + -1, -1, -1, -1, -1, 333, -1, -1, 336, -1, + 338, 296, 297, -1, 342, -1, 301, 302, -1, -1, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, 362, 257, 321, -1, 323, 261, + -1, -1, -1, -1, -1, -1, -1, -1, 333, -1, + 272, 336, -1, 338, -1, 277, -1, 342, -1, 281, + -1, -1, 284, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 296, 297, -1, 362, -1, 301, + 302, -1, -1, -1, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + -1, 323, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 333, -1, 256, 336, -1, 338, -1, -1, -1, + 342, 264, 265, 266, 267, -1, -1, 270, 271, -1, + 273, 274, 275, 276, 277, 278, 279, -1, -1, -1, + 362, -1, 285, -1, 287, 288, 289, 290, 291, 292, + -1, -1, 295, -1, -1, -1, 299, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 314, -1, 316, -1, 318, 319, -1, -1, 322, + -1, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, -1, -1, 340, 341, -1, + 256, 344, 345, -1, -1, -1, 262, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, + -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, + -1, 384, 298, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 256, -1, -1, -1, + -1, -1, 262, -1, 417, 418, 419, 420, -1, -1, + -1, -1, -1, 339, -1, -1, 429, -1, 344, -1, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, 357, -1, -1, -1, -1, -1, -1, 298, -1, + -1, -1, 368, 369, 370, 371, 372, 373, 374, 375, + 376, -1, 378, 379, -1, 381, 382, 383, 384, 385, + 386, 387, 388, 389, 390, -1, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, -1, 256, + -1, -1, 418, -1, 420, 262, -1, 423, -1, -1, + -1, -1, -1, 429, -1, -1, -1, -1, 368, -1, + -1, 371, -1, 373, 374, -1, -1, -1, 378, 379, + -1, -1, 382, 383, 384, 385, 386, 387, 388, 389, + 390, 298, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 412, 413, -1, -1, -1, -1, -1, -1, + 420, 262, -1, 423, -1, -1, -1, -1, -1, 429, + -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, -1, -1, -1, 298, -1, -1, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + -1, 378, 379, -1, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, -1, 256, -1, + -1, -1, -1, 420, 262, -1, 357, -1, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, 369, -1, + 371, -1, 373, -1, -1, 376, -1, 378, 379, -1, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 298, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, -1, -1, -1, -1, 418, -1, 420, + 262, -1, 423, -1, -1, -1, -1, -1, 429, -1, + -1, 339, -1, -1, -1, -1, 344, -1, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, + -1, -1, -1, -1, -1, -1, 298, -1, -1, 367, + 368, -1, 370, 371, 372, 373, 374, 375, 376, -1, + 378, 379, -1, 381, 382, 383, 384, 385, 386, 387, + 388, 389, 390, -1, 392, 393, 394, 395, 396, 397, + 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, -1, 256, -1, -1, + -1, -1, 420, 262, -1, 423, -1, -1, -1, -1, + -1, 429, -1, -1, -1, -1, -1, 369, -1, 371, + 372, 373, 374, -1, 376, -1, 378, 379, -1, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 298, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, -1, -1, -1, 418, -1, 420, 262, + -1, 423, -1, -1, -1, -1, -1, 429, -1, -1, + 339, -1, -1, -1, -1, 344, -1, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, -1, -1, -1, 298, -1, -1, -1, 368, + -1, 370, 371, 372, 373, 374, 375, 376, -1, 378, + 379, -1, 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, -1, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, -1, 256, -1, -1, -1, + -1, 420, 262, -1, 423, -1, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 370, 371, 372, + 373, 374, -1, -1, -1, 378, 379, -1, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 298, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, -1, -1, -1, -1, -1, -1, 420, -1, -1, + 423, -1, -1, -1, -1, -1, 429, -1, -1, 339, + -1, -1, -1, -1, 344, -1, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 368, -1, + 370, 371, 372, 373, 374, 375, 376, -1, 378, 379, + -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, + 390, -1, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, -1, 256, 256, -1, -1, -1, + 420, 262, -1, 423, -1, 265, -1, 267, -1, 429, + 270, -1, -1, -1, -1, 275, -1, -1, -1, 279, + -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, + -1, -1, -1, -1, -1, 295, -1, 298, -1, -1, + 300, -1, -1, -1, 304, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 316, -1, 318, -1, + -1, -1, 322, -1, -1, -1, -1, -1, -1, -1, + 330, 331, -1, -1, 334, -1, -1, 337, 339, -1, + -1, -1, -1, 344, -1, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 368, -1, 370, + 371, 372, 373, 374, 375, 376, -1, 378, 379, -1, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + -1, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, -1, 256, 256, -1, -1, 418, 420, + 262, -1, 423, -1, 265, -1, 267, -1, 429, 270, + -1, -1, -1, -1, 275, -1, -1, -1, 279, -1, + -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, 298, -1, -1, 300, + -1, -1, -1, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, -1, -1, + -1, 322, -1, -1, -1, -1, -1, -1, -1, 330, + 331, -1, -1, 334, -1, -1, 337, 339, -1, -1, + -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 368, -1, 370, 371, + 372, 373, 374, 375, 376, -1, 378, -1, -1, 381, + 382, 383, 384, 385, 386, 387, 388, 389, 390, -1, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, 256, -1, 256, -1, 418, 420, 262, + -1, 423, -1, 264, 265, -1, 267, 429, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + -1, -1, -1, -1, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, 298, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, 339, -1, -1, -1, + -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 359, 360, + 361, 362, -1, -1, -1, 368, -1, 370, -1, 372, + 371, 374, 375, 376, -1, 378, 379, -1, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 261, -1, + -1, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 256, + 413, 284, -1, -1, -1, 262, 417, 418, -1, -1, + -1, -1, -1, -1, 297, -1, 429, -1, -1, 302, + -1, -1, 305, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, -1, 317, -1, -1, -1, 321, -1, + -1, 298, 325, -1, -1, -1, -1, -1, -1, -1, + 333, -1, -1, 336, -1, 338, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, + -1, -1, -1, 262, -1, -1, -1, -1, -1, 362, + -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, 378, 379, -1, -1, 382, 383, 384, 385, 386, + 387, 388, 389, 390, -1, 418, -1, 394, 395, 396, + 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, 256, 429, -1, -1, -1, -1, 262, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, 378, + 379, -1, -1, 382, 383, 384, 385, -1, -1, -1, + 389, 390, -1, -1, -1, 394, 395, 396, 397, 398, + 399, 400, 401, 298, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 413, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, + 429, -1, -1, -1, -1, 262, -1, -1, -1, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 298, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, 378, 379, -1, -1, 382, 383, 384, + 385, -1, -1, -1, 389, 390, -1, -1, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, 256, 429, -1, -1, -1, -1, 262, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, 378, 379, -1, -1, 382, 383, 384, 385, -1, + -1, -1, 389, 390, -1, -1, -1, 394, 395, 396, + 397, 398, 399, 400, 401, 298, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 413, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 256, 429, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, 378, 379, -1, -1, 382, + 383, 384, 385, -1, -1, -1, 389, 390, -1, 256, + -1, 394, 395, 396, 397, 398, 399, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, 382, 383, 384, + 385, -1, -1, -1, 389, 390, -1, 256, -1, 394, + 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, 382, 383, 384, 385, -1, + -1, -1, 389, 390, -1, 256, -1, 394, 395, 396, + 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, -1, -1, 382, 383, 384, 385, -1, -1, -1, + 389, 390, -1, 256, -1, 394, 395, 396, 397, 398, + 399, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, 382, 383, 384, 385, -1, -1, -1, 389, 390, + -1, 256, -1, -1, -1, 396, 397, 398, 399, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, 382, + 383, 384, 385, -1, -1, -1, 389, 390, -1, 256, + -1, -1, -1, 396, 397, 398, 399, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, 382, 383, 384, + 385, -1, -1, -1, 389, 390, -1, 256, -1, -1, + -1, 396, 397, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, 382, 383, 384, 385, -1, + -1, -1, 389, 390, -1, 256, -1, -1, -1, 396, + 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, -1, -1, 382, 383, 384, 385, -1, -1, -1, + 389, 390, -1, 256, -1, -1, -1, 396, 397, 398, + 399, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, 384, 385, -1, -1, -1, 389, 390, + -1, 256, -1, -1, -1, -1, -1, 398, 399, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, -1, + -1, 384, 385, -1, -1, -1, 389, 390, -1, 256, + -1, -1, -1, -1, -1, 398, 399, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, 384, + 385, -1, -1, -1, 389, 390, -1, 256, -1, -1, + -1, -1, -1, 398, 399, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, -1, -1, 384, 385, -1, + -1, -1, 389, 390, -1, 256, -1, -1, -1, -1, + -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, -1, -1, -1, -1, -1, 385, -1, -1, -1, + 389, 390, -1, 256, -1, -1, -1, -1, -1, -1, + -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, -1, 385, -1, -1, -1, 389, 390, + -1, 256, -1, -1, -1, -1, -1, -1, -1, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, -1, + -1, -1, 385, -1, -1, -1, -1, 390, -1, 256, + -1, -1, -1, -1, -1, -1, -1, 400, 401, -1, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, + 385, -1, -1, -1, -1, 390, -1, 256, -1, -1, + -1, -1, -1, -1, -1, 400, 401, -1, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 390, -1, 256, -1, -1, -1, -1, + -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, + 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, + -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, + -1, 256, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 390, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, + -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, + 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, + -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 390, + -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, + 401, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 413, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 368, -1, 370, -1, 372, 429, 374, + 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 256, -1, 390, -1, -1, -1, -1, + -1, 264, 265, 266, 267, -1, 401, 270, 271, -1, + 273, 274, 275, 276, 277, 278, 279, -1, 413, -1, + -1, -1, 285, -1, 287, 288, 289, 290, 291, 292, + -1, -1, 295, -1, 429, -1, 299, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 314, -1, 316, -1, 318, 319, -1, -1, 322, + -1, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, -1, -1, 340, 341, -1, + -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, + -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 256, -1, -1, -1, 417, 418, 419, 420, 264, 265, + 266, 267, -1, -1, 270, 271, -1, 273, 274, 275, + 276, 277, 278, 279, -1, -1, -1, -1, -1, 285, + -1, 287, 288, 289, 290, 291, 292, -1, -1, 295, + -1, -1, -1, 299, 300, -1, 302, 303, 304, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, + 316, -1, 318, 319, -1, -1, 322, -1, 324, 325, + 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, -1, -1, 340, 341, -1, -1, 344, 345, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, + -1, 367, -1, -1, -1, 371, -1, -1, -1, -1, + 376, 377, 378, 379, 380, -1, -1, -1, 384, -1, + 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, + -1, 417, 418, 419, 420, 264, 265, 266, 267, -1, + -1, 270, 271, -1, 273, 274, 275, 276, 277, 278, + 279, -1, -1, -1, -1, -1, 285, -1, 287, 288, + 289, 290, 291, 292, -1, -1, 295, -1, -1, -1, + 299, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 314, -1, 316, -1, 318, + 319, -1, -1, 322, -1, 324, 325, 326, 327, 328, + 329, 330, 331, 332, 333, 334, 335, -1, 337, -1, + -1, 340, 341, -1, -1, 344, 345, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, 367, -1, + -1, -1, 371, -1, -1, -1, -1, 376, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 256, -1, -1, -1, 417, 418, + 419, 420, 264, 265, 266, 267, -1, -1, 270, 271, + -1, 273, 274, 275, 276, 277, 278, 279, -1, -1, + -1, -1, -1, 285, -1, 287, 288, 289, 290, 291, + 292, -1, -1, 295, -1, -1, -1, 299, 300, -1, + 302, 303, 304, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 314, -1, 316, -1, 318, 319, -1, -1, + 322, -1, 324, 325, 326, 327, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, -1, -1, 340, 341, + -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, + 362, 363, -1, -1, -1, 367, -1, -1, -1, 371, + -1, -1, -1, -1, 376, 377, 378, 379, 380, -1, + -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, + 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 256, -1, -1, -1, 417, 418, 419, 420, 264, + 265, 266, 267, -1, -1, 270, 271, -1, 273, 274, + 275, 276, 277, 278, 279, -1, -1, -1, -1, -1, + 285, -1, 287, 288, 289, 290, 291, 292, -1, -1, + 295, -1, -1, -1, 299, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, + -1, 316, -1, 318, 319, -1, -1, 322, -1, 324, + 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, + 335, -1, 337, -1, -1, 340, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, 367, -1, -1, -1, 371, -1, -1, -1, + -1, 376, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 256, -1, + -1, -1, 417, 418, 419, 420, 264, 265, -1, 267, + -1, -1, 270, 271, -1, 256, -1, 275, 276, 277, + -1, 279, -1, -1, 265, -1, 267, 285, -1, 270, + 288, -1, -1, -1, 275, -1, -1, 295, 279, -1, + -1, -1, 300, -1, 302, 303, 304, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, 316, 300, + 318, 319, -1, 304, 322, -1, -1, 325, -1, 327, + -1, 329, 330, 331, 332, 316, 334, 318, -1, -1, + -1, 322, -1, 341, -1, -1, 344, 345, -1, 330, + 331, -1, -1, 334, -1, -1, 337, -1, -1, -1, + -1, 359, 360, 361, 362, 363, -1, -1, -1, 367, + 368, -1, -1, 371, -1, -1, -1, -1, -1, 377, + 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, + -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 256, -1, -1, -1, 417, + 418, 419, 420, 264, 265, -1, 267, -1, -1, 270, + 271, -1, 256, -1, 275, 276, 277, 418, 279, -1, + -1, 265, -1, 267, 285, -1, 270, 288, -1, -1, + -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, + -1, 302, 303, 304, 288, -1, -1, -1, -1, -1, + -1, 295, -1, -1, -1, 316, 300, 318, 319, 320, + 304, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, 316, 334, 318, -1, -1, -1, 322, -1, + 341, -1, -1, 344, 345, -1, 330, 331, -1, -1, + 334, -1, -1, 337, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, 418, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, 367, 368, -1, -1, 371, -1, -1, -1, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 256, -1, 417, 418, 419, 420, -1, -1, 264, 265, + -1, 267, -1, 428, 270, 271, -1, -1, -1, 275, + 276, 277, -1, 279, -1, -1, 265, -1, 267, 285, + -1, 270, 288, -1, -1, -1, 275, -1, -1, 295, + 279, -1, -1, -1, 300, -1, 302, 303, 304, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + 316, 300, 318, 319, -1, 304, 322, -1, -1, 325, + -1, 327, -1, 329, 330, 331, 332, 316, 334, 318, + -1, 337, -1, 322, -1, 341, -1, -1, 344, 345, + -1, 330, 331, -1, -1, 334, -1, -1, 337, -1, + -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, + -1, -1, -1, -1, -1, 371, -1, -1, -1, -1, + -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, + 386, -1, -1, 372, -1, -1, 392, 393, -1, -1, + -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, + 270, 271, -1, -1, -1, 275, 276, 277, -1, 279, + -1, 417, 418, 419, 420, 285, -1, -1, 288, -1, + -1, -1, -1, -1, -1, 295, -1, -1, -1, 418, + 300, -1, 302, 303, 304, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 316, -1, 318, 319, + -1, -1, 322, -1, -1, 325, -1, 327, -1, 329, + 330, 331, 332, -1, 334, -1, -1, -1, -1, -1, + -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, + 360, 361, 362, 363, -1, -1, -1, 367, -1, -1, + -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, + 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, + -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 256, -1, 417, 418, 419, + 420, -1, -1, 264, 265, -1, 267, -1, 428, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + -1, 265, -1, 267, 285, -1, 270, 288, -1, -1, + -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, + -1, 302, 303, 304, 288, -1, -1, -1, -1, -1, + -1, 295, -1, -1, -1, 316, 300, 318, 319, -1, + 304, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, 316, 334, 318, -1, -1, -1, 322, -1, + 341, -1, -1, 344, 345, -1, 330, 331, -1, -1, + 334, -1, -1, 337, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, 370, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 256, -1, -1, -1, 417, 418, 419, 420, + 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, + -1, 275, 276, 277, 418, 279, -1, -1, 265, -1, + 267, 285, -1, 270, 288, -1, -1, -1, 275, -1, + -1, 295, 279, -1, -1, -1, 300, -1, 302, 303, + 304, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, 316, 300, 318, 319, -1, 304, 322, -1, + -1, 325, -1, 327, -1, 329, 330, 331, 332, 316, + 334, 318, -1, -1, -1, 322, -1, 341, -1, -1, + 344, 345, -1, 330, 331, -1, -1, 334, -1, -1, + 337, -1, -1, -1, -1, 359, 360, 361, 362, 363, + -1, -1, -1, -1, -1, -1, -1, 371, -1, -1, + -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, + 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, + -1, -1, -1, 417, 418, 419, 420, 264, 265, -1, + 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, + 277, 418, 279, -1, -1, -1, -1, -1, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, 262, -1, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, 298, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 417, 418, 419, 420, 371, 372, 373, 374, -1, -1, + -1, 378, 379, -1, -1, 382, 383, 384, 385, 386, + 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, -1, 261, -1, + -1, -1, 265, 420, 267, -1, 423, 270, -1, 272, + 273, -1, 275, -1, 277, -1, 279, -1, 281, 282, + 283, 284, -1, -1, 287, 288, -1, -1, -1, -1, + 293, -1, 295, 296, 297, -1, -1, 300, -1, 302, + -1, 304, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, 316, 317, 318, -1, -1, 321, 322, + 323, -1, -1, -1, -1, -1, -1, 330, 331, -1, + 333, 334, -1, 336, 337, 338, -1, -1, -1, 342, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 261, -1, 362, + -1, 265, -1, 267, -1, 368, 270, -1, 272, 273, + -1, 275, -1, 277, 377, 279, -1, 281, 282, 283, + 284, -1, -1, 287, 288, -1, -1, -1, -1, 293, + -1, 295, 296, 297, -1, -1, 300, -1, 302, -1, + 304, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, -1, 316, 317, 318, 418, -1, 321, 322, 323, + -1, -1, -1, -1, -1, -1, 330, 331, -1, 333, + 334, -1, 336, 337, 338, -1, -1, -1, 342, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 261, -1, 362, -1, + 265, -1, 267, -1, 368, 270, -1, 272, 273, -1, + 275, -1, 277, 377, 279, -1, 281, 282, 283, 284, + -1, -1, 287, 288, -1, -1, -1, -1, 293, -1, + 295, 296, 297, -1, -1, 300, -1, 302, -1, 304, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, 316, 317, 318, 418, -1, 321, 322, 323, -1, + -1, -1, -1, -1, -1, 330, 331, -1, 333, 334, + -1, 336, 337, 338, -1, -1, -1, 342, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 261, -1, 362, -1, 265, + -1, 267, -1, 368, 270, -1, 272, 273, -1, 275, + -1, 277, 377, 279, -1, 281, 282, 283, 284, -1, + -1, 287, 288, -1, -1, -1, -1, 293, -1, 295, + 296, 297, -1, -1, 300, -1, 302, -1, 304, -1, + -1, 307, -1, 309, 310, 311, 312, -1, -1, -1, + 316, 317, 318, 418, -1, 321, 322, 323, -1, -1, + -1, -1, -1, -1, 330, 331, -1, 333, 334, -1, + 336, 337, 338, -1, -1, -1, 342, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 261, -1, 362, -1, 265, -1, + 267, -1, 368, 270, -1, 272, 273, -1, 275, -1, + 277, 377, 279, -1, 281, 282, 283, 284, -1, -1, + 287, 288, -1, -1, -1, -1, 293, -1, 295, 296, + 297, -1, -1, 300, -1, 302, -1, 304, -1, -1, + 307, -1, 309, 310, 311, 312, -1, -1, -1, 316, + 317, 318, 418, -1, 321, 322, 323, -1, -1, -1, + -1, -1, -1, 330, 331, -1, 333, 334, -1, 336, + 337, 338, -1, -1, -1, 342, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 261, -1, + -1, -1, 265, -1, 267, 362, -1, 270, -1, 272, + 273, 368, 275, -1, 277, -1, 279, -1, 281, 282, + 283, 284, -1, -1, 287, 288, -1, -1, -1, -1, + 293, -1, 295, 296, 297, -1, -1, 300, -1, 302, + 261, 304, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, 316, 317, 318, -1, -1, 321, 322, + 323, 418, -1, 284, -1, -1, -1, 330, 331, -1, + 333, 334, 261, 336, 337, 338, 297, -1, -1, 342, + -1, 302, -1, -1, 305, -1, 307, -1, 309, 310, + 311, 312, -1, -1, -1, 284, 317, -1, -1, 362, + 321, -1, -1, -1, 325, 368, -1, -1, 297, -1, + 261, -1, 333, 302, -1, 336, -1, 338, 307, -1, + 309, 310, 311, 312, -1, -1, -1, -1, 317, -1, + -1, -1, 321, 284, -1, -1, 357, -1, -1, -1, + -1, 362, -1, -1, 333, -1, 297, 336, 369, 338, + 371, 302, 373, -1, 305, 418, 307, -1, 309, 310, + 311, 312, -1, -1, -1, 386, 317, -1, -1, -1, + 321, -1, -1, 362, 325, -1, -1, -1, -1, -1, + -1, -1, 333, 264, 265, 336, 267, 338, -1, 270, + 271, -1, -1, -1, 275, 276, 277, 418, 279, -1, + -1, -1, -1, -1, 285, -1, -1, 288, -1, -1, + -1, 362, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, 306, -1, -1, -1, 418, + -1, -1, 313, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 344, 345, -1, -1, 418, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + 371, 372, -1, 374, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + -1, 306, -1, -1, -1, -1, -1, -1, 313, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, 371, -1, -1, 374, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, + 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + -1, 300, -1, 302, 303, 304, -1, 306, -1, -1, + -1, -1, -1, -1, 313, -1, -1, 316, -1, 318, + 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, + -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, + -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, + -1, -1, 275, 276, 277, -1, 279, -1, 417, 418, + 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, + -1, -1, 295, -1, -1, -1, -1, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, + -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, + -1, 334, -1, -1, 337, -1, -1, -1, 341, -1, + -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, 371, -1, + -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, + 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, + 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, 368, -1, -1, 371, -1, -1, -1, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, 367, -1, -1, -1, 371, -1, -1, -1, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, + 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, + 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, + -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, + -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, + -1, -1, 275, 276, 277, -1, 279, -1, 417, 418, + 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, + -1, -1, 295, -1, -1, -1, -1, 300, -1, 302, + 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, + -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, + -1, 334, -1, -1, -1, -1, -1, -1, 341, -1, + -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, 371, -1, + -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, + 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, + 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, + 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, + 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, + 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, + -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, + 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, 371, -1, -1, -1, + -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, + -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, + 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, 261, -1, + -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, + 319, 284, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, 297, 334, -1, -1, -1, 302, + -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, 315, -1, 317, -1, -1, -1, 321, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + 333, -1, 371, 336, -1, 338, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, 264, + 265, -1, 267, 392, 393, 270, 271, -1, -1, 362, + 275, 276, 277, -1, 279, 368, 369, -1, -1, -1, + 285, -1, -1, 288, -1, -1, -1, 261, 417, 418, + 295, 420, -1, -1, -1, 300, -1, 302, 303, 304, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 284, 316, -1, 318, 319, -1, -1, 322, -1, -1, + 325, -1, 327, 297, 329, 330, 331, 332, 302, 334, + -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, 315, -1, 317, -1, -1, -1, 321, -1, -1, + -1, -1, -1, -1, 359, 360, 361, 362, 363, 333, + -1, -1, 336, -1, 338, -1, 371, 263, -1, 265, + -1, 267, 377, -1, 270, 380, 272, 273, -1, 275, + -1, 277, -1, 279, -1, 281, 282, 283, 362, -1, + -1, 287, 288, -1, 368, -1, -1, 293, -1, 295, + 296, -1, -1, -1, 300, -1, -1, -1, 304, -1, + -1, -1, 417, 418, -1, 420, -1, -1, -1, 315, + 316, -1, 318, -1, -1, -1, 322, 323, -1, -1, + -1, -1, -1, -1, 330, 331, 264, 265, 334, 267, + -1, 337, 270, 271, -1, -1, 342, 275, 276, 277, + -1, 279, -1, -1, -1, -1, -1, 285, -1, -1, + 288, -1, -1, -1, -1, -1, -1, 295, 364, 365, + -1, -1, 300, -1, 302, 303, 304, -1, -1, -1, + -1, 377, -1, -1, -1, -1, -1, -1, 316, -1, + 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, + -1, 329, 330, 331, 332, -1, 334, -1, -1, 337, + -1, -1, -1, -1, -1, -1, 265, -1, 267, -1, + -1, 270, 418, 272, -1, -1, 275, -1, -1, -1, + 279, 359, 360, 361, 362, -1, -1, -1, -1, 288, + 265, -1, 267, 371, -1, 270, 295, 272, 273, -1, + 275, 300, 277, 302, 279, 304, 281, 282, 283, -1, + -1, -1, 287, 288, -1, -1, -1, 316, 293, 318, + 295, 296, -1, 322, 323, 300, -1, -1, -1, 304, + -1, 330, 331, -1, -1, 334, -1, -1, 337, 417, + 418, 316, -1, 318, -1, -1, -1, 322, 323, -1, + -1, -1, -1, -1, -1, 330, 331, -1, 265, 334, + 267, -1, 337, 270, -1, 272, 273, 342, 275, -1, + 277, -1, 279, -1, 281, 282, 283, -1, -1, -1, + 287, 288, -1, -1, -1, -1, 293, -1, 295, 296, + -1, -1, -1, 300, -1, -1, -1, 304, -1, -1, + -1, -1, 377, -1, -1, -1, -1, -1, -1, 316, + -1, 318, -1, -1, -1, 322, 323, -1, -1, 418, + -1, -1, -1, 330, 331, -1, -1, 334, -1, -1, + 337, -1, 265, -1, 267, 342, -1, 270, -1, -1, + 273, -1, 275, 418, 277, -1, 279, -1, 281, 282, + 283, -1, -1, -1, 287, 288, -1, -1, -1, -1, + 293, -1, 295, -1, 265, -1, 267, 300, -1, 270, + -1, 304, 273, -1, 275, -1, 277, -1, 279, -1, + 281, 282, 283, 316, -1, 318, 287, 288, -1, 322, + -1, -1, 293, -1, 295, -1, -1, 330, 331, 300, + -1, 334, -1, 304, 337, -1, -1, -1, 265, 342, + 267, 418, -1, 270, -1, 316, -1, 318, 275, -1, + -1, 322, 279, -1, -1, -1, -1, -1, -1, 330, + 331, 288, -1, 334, -1, -1, 337, -1, 295, -1, + 265, 342, 267, 300, 377, 270, -1, 304, -1, 306, + 275, 308, -1, -1, 279, -1, 313, -1, -1, 316, + -1, 318, -1, 288, -1, 322, -1, -1, 325, -1, + 295, -1, -1, 330, 331, 300, -1, 334, -1, 304, + 337, 306, -1, 308, 265, 418, 267, -1, 313, 270, + -1, 316, -1, 318, 275, -1, -1, 322, 279, -1, + 325, -1, -1, -1, -1, 330, 331, 288, -1, 334, + -1, -1, 337, -1, 295, 372, 265, 418, 267, 300, + -1, 270, -1, 304, -1, 306, 275, 308, -1, -1, + 279, -1, 313, -1, -1, 316, -1, 318, -1, 288, + -1, 322, -1, -1, 325, 370, 295, -1, -1, 330, + 331, 300, -1, 334, -1, 304, 337, 306, -1, -1, + -1, 418, -1, -1, 313, -1, -1, 316, -1, 318, + -1, -1, -1, 322, -1, -1, 325, -1, -1, -1, + -1, 330, 331, -1, -1, 334, -1, 265, 337, 267, + -1, -1, 270, 418, -1, -1, -1, 275, -1, -1, + -1, 279, -1, -1, -1, 283, 265, -1, 267, -1, + 288, 270, -1, -1, -1, 293, 275, 295, -1, -1, + 279, -1, 300, -1, -1, -1, 304, 305, -1, 288, + -1, -1, -1, -1, -1, -1, 295, 418, 316, -1, + 318, 300, -1, -1, 322, 304, -1, -1, -1, -1, + -1, -1, 330, 331, -1, -1, 334, 316, -1, 318, + 265, -1, 267, 322, -1, 270, -1, -1, -1, 418, + 275, 330, 331, -1, 279, 334, -1, 265, 337, 267, + -1, -1, 270, 288, -1, -1, -1, 275, -1, -1, + 295, 279, -1, -1, -1, 300, -1, -1, -1, 304, + 288, -1, -1, -1, -1, -1, -1, 295, -1, -1, + -1, 316, 300, 318, -1, -1, 304, 322, -1, -1, + -1, -1, -1, -1, -1, 330, 331, -1, 316, 334, + 318, 265, 337, 267, 322, -1, 270, -1, -1, -1, + 418, 275, 330, 331, -1, 279, 334, -1, -1, 337, + -1, -1, -1, -1, 288, 265, -1, 267, -1, 418, + 270, 295, -1, -1, -1, 275, 300, -1, -1, 279, + 304, -1, -1, -1, -1, -1, -1, -1, 288, -1, + -1, -1, 316, -1, 318, 295, -1, -1, 322, -1, + 300, -1, -1, -1, 304, -1, 330, 331, -1, -1, + 334, -1, -1, 337, -1, 265, 316, 267, 318, -1, + 270, -1, 322, 418, -1, 275, -1, -1, -1, 279, + 330, 331, -1, -1, 334, -1, -1, 337, 288, 265, + 418, 267, -1, -1, 270, 295, -1, -1, -1, 275, + 300, -1, -1, 279, 304, -1, -1, -1, -1, -1, + -1, -1, 288, -1, -1, -1, 316, -1, 318, 295, + -1, -1, 322, -1, 300, -1, -1, -1, 304, -1, + 330, 331, -1, -1, 334, -1, -1, 337, -1, -1, + 316, -1, 318, 265, 418, 267, 322, -1, 270, -1, + -1, -1, -1, 275, 330, 331, -1, 279, 334, -1, + 265, 337, 267, -1, -1, 270, 288, -1, 418, -1, + 275, -1, -1, 295, 279, -1, -1, -1, 300, -1, + -1, -1, 304, 288, -1, -1, -1, -1, -1, -1, + 295, -1, -1, -1, 316, 300, 318, -1, -1, 304, + 322, -1, -1, -1, -1, -1, -1, -1, 330, 331, + -1, 316, 334, 318, 265, 337, 267, 322, 418, 270, + -1, -1, -1, -1, 275, 330, 331, -1, 279, 334, + -1, -1, 337, -1, -1, -1, -1, 288, 265, -1, + 267, -1, 418, 270, 295, -1, -1, -1, 275, 300, + -1, -1, 279, 304, -1, -1, -1, -1, -1, -1, + -1, 288, -1, -1, -1, 316, -1, 318, 295, -1, + -1, 322, -1, 300, -1, -1, -1, 304, -1, 330, + 331, -1, 261, 334, -1, -1, 337, -1, -1, 316, + -1, 318, -1, 272, -1, 322, 418, -1, 277, -1, + -1, -1, 281, 330, 331, 284, -1, 334, -1, -1, + 337, -1, -1, 418, -1, -1, -1, 296, 297, -1, + -1, -1, 301, 302, -1, 261, -1, -1, 307, -1, + 309, 310, 311, 312, -1, -1, 272, -1, 317, -1, + -1, 277, 321, -1, 323, 281, -1, -1, 284, -1, + -1, -1, -1, -1, 333, -1, 335, 336, -1, 338, + 296, 297, -1, 342, -1, 301, 302, 418, -1, -1, + -1, 307, -1, 309, 310, 311, 312, -1, -1, -1, + -1, 317, -1, 362, -1, 321, -1, 323, -1, 368, + 369, 418, -1, 261, -1, 263, -1, 333, -1, -1, + 336, -1, 338, -1, -1, -1, 342, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 284, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 362, -1, -1, 297, + -1, -1, 368, 369, 302, -1, 261, -1, -1, 307, + -1, 309, 310, 311, 312, -1, -1, 272, -1, 317, + -1, -1, 277, 321, -1, -1, 281, -1, -1, 284, + -1, -1, -1, -1, -1, 333, -1, -1, 336, -1, + 338, 296, 297, -1, -1, -1, 301, 302, -1, 261, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + 272, -1, 317, -1, 362, 277, 321, -1, 323, 281, + 368, 369, 284, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 296, 297, -1, 342, -1, 301, + 302, 261, -1, -1, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, 362, -1, 321, + -1, 323, -1, 368, 284, -1, -1, -1, -1, -1, + -1, 333, -1, -1, 336, -1, 338, 297, -1, 261, + 342, -1, 302, -1, -1, -1, -1, 307, -1, 309, + 310, 311, 312, -1, -1, -1, -1, 317, -1, -1, + 362, 321, 284, -1, -1, -1, 368, -1, -1, -1, + -1, -1, -1, 333, -1, 297, 336, 261, 338, 263, + 302, -1, -1, -1, -1, 307, -1, 309, 310, 311, + 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, + 284, -1, 362, -1, 364, 365, -1, -1, 368, -1, + -1, 333, -1, 297, 336, 261, 338, -1, 302, -1, + -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, + -1, -1, -1, 317, -1, -1, -1, 321, 284, -1, + 362, -1, 364, 365, -1, 261, 368, -1, -1, 333, + -1, 297, 336, -1, 338, -1, 302, -1, -1, -1, + -1, 307, -1, 309, 310, 311, 312, -1, 284, -1, + -1, 317, -1, -1, -1, 321, -1, -1, 362, -1, + -1, 297, -1, -1, 368, 301, 302, 333, 261, -1, + 336, 307, 338, 309, 310, 311, 312, -1, -1, -1, + -1, 317, -1, -1, -1, 321, -1, -1, -1, -1, + -1, 284, -1, -1, -1, -1, 362, 333, 364, 365, + 336, -1, 338, -1, 297, -1, -1, -1, -1, 302, + -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, + -1, -1, -1, -1, 317, -1, 362, -1, 321, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 333, -1, -1, 336, -1, 338, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, + }; + +#line 6263 "cs-parser.jay" + +// +// A class used to hold info about an operator declarator +// +class OperatorDeclaration { + public readonly Operator.OpType optype; + public readonly FullNamedExpression ret_type; + public readonly Location location; + + public OperatorDeclaration (Operator.OpType op, FullNamedExpression ret_type, Location location) + { + optype = op; + this.ret_type = ret_type; + this.location = location; + } +} + +void Error_ExpectingTypeName (Expression expr) +{ + if (expr is Invocation){ + report.Error (1002, expr.Location, "Expecting `;'"); + } else { + Expression.Error_InvalidExpressionStatement (report, expr.Location); + } +} + +void Error_ParameterModifierNotValid (string modifier, Location loc) +{ + report.Error (631, loc, "The parameter modifier `{0}' is not valid in this context", + modifier); +} + +void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) +{ + report.Error (1107, loc, "Duplicate parameter modifier `{0}'", + Parameter.GetModifierSignature (mod)); +} + +void Error_TypeExpected (Location loc) +{ + report.Error (1031, loc, "Type expected"); +} + +void Error_UnsafeCodeNotAllowed (Location loc) +{ + report.Error (227, loc, "Unsafe code requires the `unsafe' command line option to be specified"); +} + +void Warning_EmptyStatement (Location loc) +{ + report.Warning (642, 3, loc, "Possible mistaken empty statement"); +} + +void Error_NamedArgumentExpected (NamedArgument a) +{ + report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); +} + +void push_current_class (TypeContainer tc, object partial_token) +{ + if (module.Evaluator != null && current_container is ModuleContainer){ + tc.Definition.Modifiers = tc.ModFlags = (tc.ModFlags & ~Modifiers.AccessibilityMask) | Modifiers.PUBLIC; + if (undo == null) + undo = new Undo (); + undo.AddTypeContainer (current_container, tc); + } + + if (partial_token != null) + current_container = current_container.AddPartial (tc); + else + current_container = current_container.AddTypeContainer (tc); + + ++lexer.parsing_declaration; + current_class = tc; + ubag.PushTypeDeclaration (tc); +} + +DeclSpace pop_current_class () +{ + DeclSpace retval = current_class; + + current_class = current_class.Parent; + current_container = current_class.PartialContainer; + ubag.PopTypeDeclaration (); + + return retval; +} + +// +// Given the @class_name name, it creates a fully qualified name +// based on the containing declaration space +// +MemberName +MakeName (MemberName class_name) +{ + Namespace ns = current_namespace.NS; + + if (current_container == module) { + if (ns.Name.Length != 0) + return new MemberName (ns.MemberName, class_name); + else + return class_name; + } else { + return new MemberName (current_container.MemberName, class_name); + } +} + +[System.Diagnostics.Conditional ("FULL_AST")] +void StoreModifierLocation (object token, Location loc) +{ + if (lbag == null) + return; + + if (mod_locations == null) + mod_locations = new List> (); + + mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); +} + +List> GetModifierLocations () +{ + var result = mod_locations; + mod_locations = null; + return result; +} + +string CheckAttributeTarget (string a, Location l) +{ + switch (a) { + case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : + return a; + } + + report.Warning (658, 1, l, + "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", a); + return string.Empty; +} + +static bool IsUnaryOperator (Operator.OpType op) +{ + switch (op) { + + case Operator.OpType.LogicalNot: + case Operator.OpType.OnesComplement: + case Operator.OpType.Increment: + case Operator.OpType.Decrement: + case Operator.OpType.True: + case Operator.OpType.False: + case Operator.OpType.UnaryPlus: + case Operator.OpType.UnaryNegation: + return true; + } + return false; +} + +void syntax_error (Location l, string msg) +{ + report.Error (1003, l, "Syntax error, " + msg); +} + +Tokenizer lexer; + +public Tokenizer Lexer { + get { + return lexer; + } +} + +static CSharpParser () +{ + oob_stack = new Stack (); +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file) + : this (reader, file, file.NamespaceContainer.Module.Compiler.Report) +{ +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Report report) +{ + this.file = file; + current_namespace = file.NamespaceContainer; + + this.module = current_namespace.Module; + this.compiler = module.Compiler; + this.settings = compiler.Settings; + this.report = report; + + lang_version = settings.Version; + doc_support = settings.DocumentationFile != null; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes + oob_stack.Clear (); + lexer = new Tokenizer (reader, file, compiler); + + use_global_stacks = true; +} + +public void parse () +{ + eof_token = Token.EOF; + Tokenizer.LocatedToken.Initialize (); + + try { + if (yacc_verbose_flag > 1) + yyparse (lexer, new yydebug.yyDebugSimple ()); + else + yyparse (lexer); + + Tokenizer tokenizer = lexer as Tokenizer; + tokenizer.cleanup (); + } catch (Exception e){ + if (e is yyParser.yyUnexpectedEof) { + Error_SyntaxError (yyToken); + UnexpectedEOF = true; + return; + } + + if (e is yyParser.yyException) { + report.Error (-25, lexer.Location, "Parsing error"); + } else { + // Used by compiler-tester to test internal errors + if (yacc_verbose_flag > 0) + throw; + + report.Error (589, lexer.Location, "Internal compiler error during parsing"); + } + } +} + +void CheckToken (int error, int yyToken, string msg, Location loc) +{ + if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) + report.Error (error, loc, "{0}: `{1}' is a keyword", msg, GetTokenName (yyToken)); + else + report.Error (error, loc, msg); +} + +string ConsumeStoredComment () +{ + string s = tmpComment; + tmpComment = null; + Lexer.doc_state = XmlCommentState.Allowed; + return s; +} + +void FeatureIsNotAvailable (Location loc, string feature) +{ + report.FeatureIsNotAvailable (compiler, loc, feature); +} + +Location GetLocation (object obj) +{ + var lt = obj as Tokenizer.LocatedToken; + if (lt != null) + return lt.Location; + + var mn = obj as MemberName; + if (mn != null) + return mn.Location; + + var expr = obj as Expression; + if (expr != null) + return expr.Location; + + return lexer.Location; +} + +public LocationsBag LocationsBag { + get { + return lbag; + } + set { + lbag = value; + } +} + +public UsingsBag UsingsBag { + get { + return ubag; + } + set { + ubag = value; + } +} + +void start_block (Location loc) +{ + if (current_block == null) { + current_block = new ToplevelBlock (compiler, current_local_parameters, loc); + parsing_anonymous_method = false; + } else if (parsing_anonymous_method) { + current_block = new ParametersBlock (current_block, current_local_parameters, loc); + parsing_anonymous_method = false; + } else { + current_block = new ExplicitBlock (current_block, loc, Location.Null); + } +} + +Block +end_block (Location loc) +{ + Block retval = current_block.Explicit; + retval.SetEndLocation (loc); + current_block = retval.Parent; + return retval; +} + +void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync, Location loc) +{ + oob_stack.Push (current_anonymous_method); + oob_stack.Push (current_local_parameters); + oob_stack.Push (current_variable); + + current_local_parameters = parameters; + if (isLambda) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (loc, "lambda expressions"); + + current_anonymous_method = new LambdaExpression (isAsync, loc); + } else { + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (loc, "anonymous methods"); + + current_anonymous_method = new AnonymousMethodExpression (isAsync, loc); + } + + // Force the next block to be created as a ToplevelBlock + parsing_anonymous_method = true; +} + +/* + * Completes the anonymous method processing, if lambda_expr is null, this + * means that we have a Statement instead of an Expression embedded + */ +AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) +{ + AnonymousMethodExpression retval; + + current_anonymous_method.Block = anon_block; + retval = current_anonymous_method; + + current_variable = (BlockVariableDeclaration) oob_stack.Pop (); + current_local_parameters = (ParametersCompiled) oob_stack.Pop (); + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + + return retval; +} + +void Error_SyntaxError (int token) +{ + Error_SyntaxError (0, token, "Unexpected symbol"); +} + +void Error_SyntaxError (int error_code, int token, string msg) +{ + Lexer.CompleteOnEOF = false; + + // An error message has been reported by tokenizer + if (token == Token.ERROR) + return; + + string symbol = GetSymbolName (token); + string expecting = GetExpecting (); + var loc = lexer.Location - symbol.Length; + + if (error_code == 0) { + if (expecting == "`identifier'") { + if (token > Token.FIRST_KEYWORD && token < Token.LAST_KEYWORD) { + report.Error (1041, loc, "Identifier expected, `{0}' is a keyword", symbol); + return; + } + + error_code = 1001; + expecting = "identifier"; + } else if (expecting == "`)'") { + error_code = 1026; + } else { + error_code = 1525; + } + } + + if (string.IsNullOrEmpty (expecting)) + report.Error (error_code, loc, "{1} `{0}'", symbol, msg); + else + report.Error (error_code, loc, "{2} `{0}', expecting {1}", symbol, expecting, msg); +} + +string GetExpecting () +{ + int [] tokens = yyExpectingTokens (yyExpectingState); + var names = new List (tokens.Length); + bool has_type = false; + bool has_identifier = false; + for (int i = 0; i < tokens.Length; i++){ + int token = tokens [i]; + has_identifier |= token == Token.IDENTIFIER; + + string name = GetTokenName (token); + if (name == "") + continue; + + has_type |= name == "type"; + if (names.Contains (name)) + continue; + + names.Add (name); + } + + // + // Too many tokens to enumerate + // + if (names.Count > 8) + return null; + + if (has_type && has_identifier) + names.Remove ("identifier"); + + if (names.Count == 1) + return "`" + GetTokenName (tokens [0]) + "'"; + + StringBuilder sb = new StringBuilder (); + names.Sort (); + int count = names.Count; + for (int i = 0; i < count; i++){ + bool last = i + 1 == count; + if (last) + sb.Append ("or "); + sb.Append ('`'); + sb.Append (names [i]); + sb.Append (last ? "'" : count < 3 ? "' " : "', "); + } + return sb.ToString (); +} + + +string GetSymbolName (int token) +{ + switch (token){ + case Token.LITERAL: + return ((Constant)lexer.Value).GetValue ().ToString (); + case Token.IDENTIFIER: + return ((Tokenizer.LocatedToken)lexer.Value).Value; + + case Token.BOOL: + return "bool"; + case Token.BYTE: + return "byte"; + case Token.CHAR: + return "char"; + case Token.VOID: + return "void"; + case Token.DECIMAL: + return "decimal"; + case Token.DOUBLE: + return "double"; + case Token.FLOAT: + return "float"; + case Token.INT: + return "int"; + case Token.LONG: + return "long"; + case Token.SBYTE: + return "sbyte"; + case Token.SHORT: + return "short"; + case Token.STRING: + return "string"; + case Token.UINT: + return "uint"; + case Token.ULONG: + return "ulong"; + case Token.USHORT: + return "ushort"; + case Token.OBJECT: + return "object"; + + case Token.PLUS: + return "+"; + case Token.UMINUS: + case Token.MINUS: + return "-"; + case Token.BANG: + return "!"; + case Token.BITWISE_AND: + return "&"; + case Token.BITWISE_OR: + return "|"; + case Token.STAR: + return "*"; + case Token.PERCENT: + return "%"; + case Token.DIV: + return "/"; + case Token.CARRET: + return "^"; + case Token.OP_INC: + return "++"; + case Token.OP_DEC: + return "--"; + case Token.OP_SHIFT_LEFT: + return "<<"; + case Token.OP_SHIFT_RIGHT: + return ">>"; + case Token.OP_LT: + return "<"; + case Token.OP_GT: + return ">"; + case Token.OP_LE: + return "<="; + case Token.OP_GE: + return ">="; + case Token.OP_EQ: + return "=="; + case Token.OP_NE: + return "!="; + case Token.OP_AND: + return "&&"; + case Token.OP_OR: + return "||"; + case Token.OP_PTR: + return "->"; + case Token.OP_COALESCING: + return "??"; + case Token.OP_MULT_ASSIGN: + return "*="; + case Token.OP_DIV_ASSIGN: + return "/="; + case Token.OP_MOD_ASSIGN: + return "%="; + case Token.OP_ADD_ASSIGN: + return "+="; + case Token.OP_SUB_ASSIGN: + return "-="; + case Token.OP_SHIFT_LEFT_ASSIGN: + return "<<="; + case Token.OP_SHIFT_RIGHT_ASSIGN: + return ">>="; + case Token.OP_AND_ASSIGN: + return "&="; + case Token.OP_XOR_ASSIGN: + return "^="; + case Token.OP_OR_ASSIGN: + return "|="; + } + + return GetTokenName (token); +} + +static string GetTokenName (int token) +{ + switch (token){ + case Token.ABSTRACT: + return "abstract"; + case Token.AS: + return "as"; + case Token.ADD: + return "add"; + case Token.ASYNC: + return "async"; + case Token.BASE: + return "base"; + case Token.BREAK: + return "break"; + case Token.CASE: + return "case"; + case Token.CATCH: + return "catch"; + case Token.CHECKED: + return "checked"; + case Token.CLASS: + return "class"; + case Token.CONST: + return "const"; + case Token.CONTINUE: + return "continue"; + case Token.DEFAULT: + return "default"; + case Token.DELEGATE: + return "delegate"; + case Token.DO: + return "do"; + case Token.ELSE: + return "else"; + case Token.ENUM: + return "enum"; + case Token.EVENT: + return "event"; + case Token.EXPLICIT: + return "explicit"; + case Token.EXTERN: + case Token.EXTERN_ALIAS: + return "extern"; + case Token.FALSE: + return "false"; + case Token.FINALLY: + return "finally"; + case Token.FIXED: + return "fixed"; + case Token.FOR: + return "for"; + case Token.FOREACH: + return "foreach"; + case Token.GOTO: + return "goto"; + case Token.IF: + return "if"; + case Token.IMPLICIT: + return "implicit"; + case Token.IN: + return "in"; + case Token.INTERFACE: + return "interface"; + case Token.INTERNAL: + return "internal"; + case Token.IS: + return "is"; + case Token.LOCK: + return "lock"; + case Token.NAMESPACE: + return "namespace"; + case Token.NEW: + return "new"; + case Token.NULL: + return "null"; + case Token.OPERATOR: + return "operator"; + case Token.OUT: + return "out"; + case Token.OVERRIDE: + return "override"; + case Token.PARAMS: + return "params"; + case Token.PRIVATE: + return "private"; + case Token.PROTECTED: + return "protected"; + case Token.PUBLIC: + return "public"; + case Token.READONLY: + return "readonly"; + case Token.REF: + return "ref"; + case Token.RETURN: + return "return"; + case Token.REMOVE: + return "remove"; + case Token.SEALED: + return "sealed"; + case Token.SIZEOF: + return "sizeof"; + case Token.STACKALLOC: + return "stackalloc"; + case Token.STATIC: + return "static"; + case Token.STRUCT: + return "struct"; + case Token.SWITCH: + return "switch"; + case Token.THIS: + return "this"; + case Token.THROW: + return "throw"; + case Token.TRUE: + return "true"; + case Token.TRY: + return "try"; + case Token.TYPEOF: + return "typeof"; + case Token.UNCHECKED: + return "unchecked"; + case Token.UNSAFE: + return "unsafe"; + case Token.USING: + return "using"; + case Token.VIRTUAL: + return "virtual"; + case Token.VOLATILE: + return "volatile"; + case Token.WHERE: + return "where"; + case Token.WHILE: + return "while"; + case Token.ARGLIST: + return "__arglist"; + case Token.REFVALUE: + return "__refvalue"; + case Token.REFTYPE: + return "__reftype"; + case Token.MAKEREF: + return "__makeref"; + case Token.PARTIAL: + return "partial"; + case Token.ARROW: + return "=>"; + case Token.FROM: + case Token.FROM_FIRST: + return "from"; + case Token.JOIN: + return "join"; + case Token.ON: + return "on"; + case Token.EQUALS: + return "equals"; + case Token.SELECT: + return "select"; + case Token.GROUP: + return "group"; + case Token.BY: + return "by"; + case Token.LET: + return "let"; + case Token.ORDERBY: + return "orderby"; + case Token.ASCENDING: + return "ascending"; + case Token.DESCENDING: + return "descending"; + case Token.INTO: + return "into"; + case Token.GET: + return "get"; + case Token.SET: + return "set"; + case Token.OPEN_BRACE: + return "{"; + case Token.CLOSE_BRACE: + return "}"; + case Token.OPEN_BRACKET: + case Token.OPEN_BRACKET_EXPR: + return "["; + case Token.CLOSE_BRACKET: + return "]"; + case Token.OPEN_PARENS_CAST: + case Token.OPEN_PARENS_LAMBDA: + case Token.OPEN_PARENS: + return "("; + case Token.CLOSE_PARENS: + return ")"; + case Token.DOT: + return "."; + case Token.COMMA: + return ","; + case Token.DEFAULT_COLON: + return "default:"; + case Token.COLON: + return ":"; + case Token.SEMICOLON: + return ";"; + case Token.TILDE: + return "~"; + + case Token.PLUS: + case Token.UMINUS: + case Token.MINUS: + case Token.BANG: + case Token.OP_LT: + case Token.OP_GT: + case Token.BITWISE_AND: + case Token.BITWISE_OR: + case Token.STAR: + case Token.PERCENT: + case Token.DIV: + case Token.CARRET: + case Token.OP_INC: + case Token.OP_DEC: + case Token.OP_SHIFT_LEFT: + case Token.OP_SHIFT_RIGHT: + case Token.OP_LE: + case Token.OP_GE: + case Token.OP_EQ: + case Token.OP_NE: + case Token.OP_AND: + case Token.OP_OR: + case Token.OP_PTR: + case Token.OP_COALESCING: + case Token.OP_MULT_ASSIGN: + case Token.OP_DIV_ASSIGN: + case Token.OP_MOD_ASSIGN: + case Token.OP_ADD_ASSIGN: + case Token.OP_SUB_ASSIGN: + case Token.OP_SHIFT_LEFT_ASSIGN: + case Token.OP_SHIFT_RIGHT_ASSIGN: + case Token.OP_AND_ASSIGN: + case Token.OP_XOR_ASSIGN: + case Token.OP_OR_ASSIGN: + return ""; + + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.VOID: + case Token.DECIMAL: + case Token.DOUBLE: + case Token.FLOAT: + case Token.INT: + case Token.LONG: + case Token.SBYTE: + case Token.SHORT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + case Token.USHORT: + case Token.OBJECT: + return "type"; + + case Token.ASSIGN: + return "="; + case Token.OP_GENERICS_LT: + case Token.GENERIC_DIMENSION: + return "<"; + case Token.OP_GENERICS_GT: + return ">"; + case Token.INTERR: + case Token.INTERR_NULLABLE: + return "?"; + case Token.DOUBLE_COLON: + return "::"; + case Token.LITERAL: + return "value"; + case Token.IDENTIFIER: + return "identifier"; + + case Token.EOF: + return "end-of-file"; + + // All of these are internal. + case Token.NONE: + case Token.ERROR: + case Token.FIRST_KEYWORD: + case Token.EVAL_COMPILATION_UNIT_PARSER: + case Token.EVAL_USING_DECLARATIONS_UNIT_PARSER: + case Token.EVAL_STATEMENT_PARSER: + case Token.LAST_KEYWORD: + case Token.GENERATE_COMPLETION: + case Token.COMPLETE_COMPLETION: + return ""; + + // A bit more robust. + default: + return yyNames [token]; + } +} + +/* end end end */ +} +#line default +namespace yydebug { + using System; + internal interface yyDebug { + void push (int state, Object value); + void lex (int state, int token, string name, Object value); + void shift (int from, int to, int errorFlag); + void pop (int state); + void discard (int state, int token, string name, Object value); + void reduce (int from, int to, int rule, string text, int len); + void shift (int from, int to); + void accept (Object value); + void error (string message); + void reject (); + } + + class yyDebugSimple : yyDebug { + void println (string s){ + Console.Error.WriteLine (s); + } + + public void push (int state, Object value) { + println ("push\tstate "+state+"\tvalue "+value); + } + + public void lex (int state, int token, string name, Object value) { + println("lex\tstate "+state+"\treading "+name+"\tvalue "+value); + } + + public void shift (int from, int to, int errorFlag) { + switch (errorFlag) { + default: // normally + println("shift\tfrom state "+from+" to "+to); + break; + case 0: case 1: case 2: // in error recovery + println("shift\tfrom state "+from+" to "+to + +"\t"+errorFlag+" left to recover"); + break; + case 3: // normally + println("shift\tfrom state "+from+" to "+to+"\ton error"); + break; + } + } + + public void pop (int state) { + println("pop\tstate "+state+"\ton error"); + } + + public void discard (int state, int token, string name, Object value) { + println("discard\tstate "+state+"\ttoken "+name+"\tvalue "+value); + } + + public void reduce (int from, int to, int rule, string text, int len) { + println("reduce\tstate "+from+"\tuncover "+to + +"\trule ("+rule+") "+text); + } + + public void shift (int from, int to) { + println("goto\tfrom state "+from+" to "+to); + } + + public void accept (Object value) { + println("accept\tvalue "+value); + } + + public void error (string message) { + println("error\t"+message); + } + + public void reject () { + println("reject"); + } + + } +} +// %token constants + class Token { + public const int EOF = 257; + public const int NONE = 258; + public const int ERROR = 259; + public const int FIRST_KEYWORD = 260; + public const int ABSTRACT = 261; + public const int AS = 262; + public const int ADD = 263; + public const int BASE = 264; + public const int BOOL = 265; + public const int BREAK = 266; + public const int BYTE = 267; + public const int CASE = 268; + public const int CATCH = 269; + public const int CHAR = 270; + public const int CHECKED = 271; + public const int CLASS = 272; + public const int CONST = 273; + public const int CONTINUE = 274; + public const int DECIMAL = 275; + public const int DEFAULT = 276; + public const int DELEGATE = 277; + public const int DO = 278; + public const int DOUBLE = 279; + public const int ELSE = 280; + public const int ENUM = 281; + public const int EVENT = 282; + public const int EXPLICIT = 283; + public const int EXTERN = 284; + public const int FALSE = 285; + public const int FINALLY = 286; + public const int FIXED = 287; + public const int FLOAT = 288; + public const int FOR = 289; + public const int FOREACH = 290; + public const int GOTO = 291; + public const int IF = 292; + public const int IMPLICIT = 293; + public const int IN = 294; + public const int INT = 295; + public const int INTERFACE = 296; + public const int INTERNAL = 297; + public const int IS = 298; + public const int LOCK = 299; + public const int LONG = 300; + public const int NAMESPACE = 301; + public const int NEW = 302; + public const int NULL = 303; + public const int OBJECT = 304; + public const int OPERATOR = 305; + public const int OUT = 306; + public const int OVERRIDE = 307; + public const int PARAMS = 308; + public const int PRIVATE = 309; + public const int PROTECTED = 310; + public const int PUBLIC = 311; + public const int READONLY = 312; + public const int REF = 313; + public const int RETURN = 314; + public const int REMOVE = 315; + public const int SBYTE = 316; + public const int SEALED = 317; + public const int SHORT = 318; + public const int SIZEOF = 319; + public const int STACKALLOC = 320; + public const int STATIC = 321; + public const int STRING = 322; + public const int STRUCT = 323; + public const int SWITCH = 324; + public const int THIS = 325; + public const int THROW = 326; + public const int TRUE = 327; + public const int TRY = 328; + public const int TYPEOF = 329; + public const int UINT = 330; + public const int ULONG = 331; + public const int UNCHECKED = 332; + public const int UNSAFE = 333; + public const int USHORT = 334; + public const int USING = 335; + public const int VIRTUAL = 336; + public const int VOID = 337; + public const int VOLATILE = 338; + public const int WHERE = 339; + public const int WHILE = 340; + public const int ARGLIST = 341; + public const int PARTIAL = 342; + public const int ARROW = 343; + public const int FROM = 344; + public const int FROM_FIRST = 345; + public const int JOIN = 346; + public const int ON = 347; + public const int EQUALS = 348; + public const int SELECT = 349; + public const int GROUP = 350; + public const int BY = 351; + public const int LET = 352; + public const int ORDERBY = 353; + public const int ASCENDING = 354; + public const int DESCENDING = 355; + public const int INTO = 356; + public const int INTERR_NULLABLE = 357; + public const int EXTERN_ALIAS = 358; + public const int REFVALUE = 359; + public const int REFTYPE = 360; + public const int MAKEREF = 361; + public const int ASYNC = 362; + public const int AWAIT = 363; + public const int GET = 364; + public const int SET = 365; + public const int LAST_KEYWORD = 366; + public const int OPEN_BRACE = 367; + public const int CLOSE_BRACE = 368; + public const int OPEN_BRACKET = 369; + public const int CLOSE_BRACKET = 370; + public const int OPEN_PARENS = 371; + public const int CLOSE_PARENS = 372; + public const int DOT = 373; + public const int COMMA = 374; + public const int COLON = 375; + public const int SEMICOLON = 376; + public const int TILDE = 377; + public const int PLUS = 378; + public const int MINUS = 379; + public const int BANG = 380; + public const int ASSIGN = 381; + public const int OP_LT = 382; + public const int OP_GT = 383; + public const int BITWISE_AND = 384; + public const int BITWISE_OR = 385; + public const int STAR = 386; + public const int PERCENT = 387; + public const int DIV = 388; + public const int CARRET = 389; + public const int INTERR = 390; + public const int DOUBLE_COLON = 391; + public const int OP_INC = 392; + public const int OP_DEC = 393; + public const int OP_SHIFT_LEFT = 394; + public const int OP_SHIFT_RIGHT = 395; + public const int OP_LE = 396; + public const int OP_GE = 397; + public const int OP_EQ = 398; + public const int OP_NE = 399; + public const int OP_AND = 400; + public const int OP_OR = 401; + public const int OP_MULT_ASSIGN = 402; + public const int OP_DIV_ASSIGN = 403; + public const int OP_MOD_ASSIGN = 404; + public const int OP_ADD_ASSIGN = 405; + public const int OP_SUB_ASSIGN = 406; + public const int OP_SHIFT_LEFT_ASSIGN = 407; + public const int OP_SHIFT_RIGHT_ASSIGN = 408; + public const int OP_AND_ASSIGN = 409; + public const int OP_XOR_ASSIGN = 410; + public const int OP_OR_ASSIGN = 411; + public const int OP_PTR = 412; + public const int OP_COALESCING = 413; + public const int OP_GENERICS_LT = 414; + public const int OP_GENERICS_LT_DECL = 415; + public const int OP_GENERICS_GT = 416; + public const int LITERAL = 417; + public const int IDENTIFIER = 418; + public const int OPEN_PARENS_LAMBDA = 419; + public const int OPEN_PARENS_CAST = 420; + public const int GENERIC_DIMENSION = 421; + public const int DEFAULT_COLON = 422; + public const int OPEN_BRACKET_EXPR = 423; + public const int EVAL_STATEMENT_PARSER = 424; + public const int EVAL_COMPILATION_UNIT_PARSER = 425; + public const int EVAL_USING_DECLARATIONS_UNIT_PARSER = 426; + public const int DOC_SEE = 427; + public const int GENERATE_COMPLETION = 428; + public const int COMPLETE_COMPLETION = 429; + public const int UMINUS = 430; + public const int yyErrorCode = 256; + } + namespace yyParser { + using System; + /** thrown for irrecoverable syntax errors and stack overflow. + */ + internal class yyException : System.Exception { + public yyException (string message) : base (message) { + } + } + internal class yyUnexpectedEof : yyException { + public yyUnexpectedEof (string message) : base (message) { + } + public yyUnexpectedEof () : base ("") { + } + } + + /** must be implemented by a scanner object to supply input to the parser. + */ + internal interface yyInput { + /** move on to next token. + @return false if positioned beyond tokens. + @throws IOException on input error. + */ + bool advance (); // throws java.io.IOException; + /** classifies current token. + Should not be called if advance() returned false. + @return current %token or single character. + */ + int token (); + /** associated with current token. + Should not be called if advance() returned false. + @return value for token(). + */ + Object value (); + } + } +} // close outermost namespace, that MUST HAVE BEEN opened in the prolog diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay new file mode 100644 index 0000000000..5e6f9e9095 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay @@ -0,0 +1,7108 @@ +%{ +// +// cs-parser.jay: The Parser for the C# compiler +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual Licensed under the terms of the GNU GPL and the MIT X11 license +// +// (C) 2001 Ximian, Inc (http://www.ximian.com) +// (C) 2004 Novell, Inc +// +// TODO: +// (1) Figure out why error productions dont work. `type-declaration' is a +// great spot to put an `error' because you can reproduce it with this input: +// "public X { }" +// + +using System.Text; +using System.IO; +using System; +using System.Collections.Generic; + +namespace Mono.CSharp +{ + /// + /// The C# Parser + /// + public class CSharpParser + { + [Flags] + enum ParameterModifierType + { + Ref = 1 << 1, + Out = 1 << 2, + This = 1 << 3, + Params = 1 << 4, + Arglist = 1 << 5, + DefaultValue = 1 << 6, + + All = Ref | Out | This | Params | Arglist | DefaultValue + } + + static readonly object ModifierNone = 0; + + NamespaceContainer current_namespace; + TypeContainer current_container; + DeclSpace current_class; + PropertyBase current_property; + EventProperty current_event; + EventField current_event_field; + FieldBase current_field; + + /// + /// Current block is used to add statements as we find + /// them. + /// + Block current_block; + + BlockVariableDeclaration current_variable; + + Delegate current_delegate; + + AnonymousMethodExpression current_anonymous_method; + + /// + /// This is used by the unary_expression code to resolve + /// a name against a parameter. + /// + + // FIXME: This is very ugly and it's very hard to reset it correctly + // on all places, especially when some parameters are autogenerated. + ParametersCompiled current_local_parameters; + + bool parsing_anonymous_method; + + /// + /// An out-of-band stack. + /// + static Stack oob_stack; + + /// + /// Controls the verbosity of the errors produced by the parser + /// + static public int yacc_verbose_flag; + + /// + /// Used by the interactive shell, flags whether EOF was reached + /// and an error was produced + /// + public bool UnexpectedEOF; + + /// + /// The current file. + /// + readonly CompilationSourceFile file; + + /// + /// Temporary Xml documentation cache. + /// For enum types, we need one more temporary store. + /// + string tmpComment; + string enumTypeComment; + + /// Current attribute target + string current_attr_target; + + ParameterModifierType valid_param_mod; + + bool default_parameter_used; + + /// When using the interactive parser, this holds the + /// resulting expression + public Class InteractiveResult; + + // + // Keeps track of global data changes to undo on parser error + // + public Undo undo; + + Stack linq_clause_blocks; + + ModuleContainer module; + + readonly CompilerContext compiler; + readonly LanguageVersion lang_version; + readonly bool doc_support; + readonly CompilerSettings settings; + readonly Report report; + + // + // Instead of allocating carrier array everytime we + // share the bucket for very common constructs which can never + // be recursive + // + static List parameters_bucket = new List (6); + + // + // Full AST support members + // + LocationsBag lbag; + UsingsBag ubag; + List> mod_locations; + Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; + Location savedAttrParenOpenLocation, savedAttrParenCloseLocation; + Stack> locationListStack = new Stack> (); // 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 +%token NONE /* This token is never returned by our lexer */ +%token ERROR // This is used not by the parser, but by the tokenizer. + // do not remove. + +/* + *These are the C# keywords + */ +%token FIRST_KEYWORD +%token ABSTRACT +%token AS +%token ADD +%token BASE +%token BOOL +%token BREAK +%token BYTE +%token CASE +%token CATCH +%token CHAR +%token CHECKED +%token CLASS +%token CONST +%token CONTINUE +%token DECIMAL +%token DEFAULT +%token DELEGATE +%token DO +%token DOUBLE +%token ELSE +%token ENUM +%token EVENT +%token EXPLICIT +%token EXTERN +%token FALSE +%token FINALLY +%token FIXED +%token FLOAT +%token FOR +%token FOREACH +%token GOTO +%token IF +%token IMPLICIT +%token IN +%token INT +%token INTERFACE +%token INTERNAL +%token IS +%token LOCK +%token LONG +%token NAMESPACE +%token NEW +%token NULL +%token OBJECT +%token OPERATOR +%token OUT +%token OVERRIDE +%token PARAMS +%token PRIVATE +%token PROTECTED +%token PUBLIC +%token READONLY +%token REF +%token RETURN +%token REMOVE +%token SBYTE +%token SEALED +%token SHORT +%token SIZEOF +%token STACKALLOC +%token STATIC +%token STRING +%token STRUCT +%token SWITCH +%token THIS +%token THROW +%token TRUE +%token TRY +%token TYPEOF +%token UINT +%token ULONG +%token UNCHECKED +%token UNSAFE +%token USHORT +%token USING +%token VIRTUAL +%token VOID +%token VOLATILE +%token WHERE +%token WHILE +%token ARGLIST +%token PARTIAL +%token ARROW +%token FROM +%token FROM_FIRST +%token JOIN +%token ON +%token EQUALS +%token SELECT +%token GROUP +%token BY +%token LET +%token ORDERBY +%token ASCENDING +%token DESCENDING +%token INTO +%token INTERR_NULLABLE +%token EXTERN_ALIAS +%token REFVALUE +%token REFTYPE +%token MAKEREF +%token ASYNC +%token AWAIT + +/* C# keywords which are not really keywords */ +%token GET +%token SET + +%left LAST_KEYWORD + +/* C# single character operators/punctuation. */ +%token OPEN_BRACE +%token CLOSE_BRACE +%token OPEN_BRACKET +%token CLOSE_BRACKET +%token OPEN_PARENS +%token CLOSE_PARENS + +%token DOT +%token COMMA +%token COLON +%token SEMICOLON +%token TILDE + +%token PLUS +%token MINUS +%token BANG +%token ASSIGN +%token OP_LT +%token OP_GT +%token BITWISE_AND +%token BITWISE_OR +%token STAR +%token PERCENT +%token DIV +%token CARRET +%token INTERR + +/* C# multi-character operators. */ +%token DOUBLE_COLON +%token OP_INC +%token OP_DEC +%token OP_SHIFT_LEFT +%token OP_SHIFT_RIGHT +%token OP_LE +%token OP_GE +%token OP_EQ +%token OP_NE +%token OP_AND +%token OP_OR +%token OP_MULT_ASSIGN +%token OP_DIV_ASSIGN +%token OP_MOD_ASSIGN +%token OP_ADD_ASSIGN +%token OP_SUB_ASSIGN +%token OP_SHIFT_LEFT_ASSIGN +%token OP_SHIFT_RIGHT_ASSIGN +%token OP_AND_ASSIGN +%token OP_XOR_ASSIGN +%token OP_OR_ASSIGN +%token OP_PTR +%token OP_COALESCING + +/* Generics <,> tokens */ +%token OP_GENERICS_LT +%token OP_GENERICS_LT_DECL +%token OP_GENERICS_GT + +%token LITERAL + +%token IDENTIFIER +%token OPEN_PARENS_LAMBDA +%token OPEN_PARENS_CAST +%token GENERIC_DIMENSION +%token DEFAULT_COLON +%token OPEN_BRACKET_EXPR + +// Make the parser go into eval mode parsing (statements and compilation units). +%token EVAL_STATEMENT_PARSER +%token EVAL_COMPILATION_UNIT_PARSER +%token EVAL_USING_DECLARATIONS_UNIT_PARSER + +%token DOC_SEE + +// +// This token is generated to trigger the completion engine at this point +// +%token GENERATE_COMPLETION + +// +// This token is return repeatedly after the first GENERATE_COMPLETION +// token is produced and before the final EOF +// +%token COMPLETE_COMPLETION + +/* Add precedence rules to solve dangling else s/r conflict */ +%nonassoc IF +%nonassoc ELSE + +/* Define the operator tokens and their precedences */ +%right ASSIGN +%right OP_COALESCING +%right INTERR +%left OP_OR +%left OP_AND +%left BITWISE_OR +%left BITWISE_AND +%left OP_SHIFT_LEFT OP_SHIFT_RIGHT +%left PLUS MINUS +%left STAR DIV PERCENT +%right BANG CARRET UMINUS +%nonassoc OP_INC OP_DEC +%left OPEN_PARENS +%left OPEN_BRACKET OPEN_BRACE +%left DOT + +%start compilation_unit +%% + +compilation_unit + : outer_declaration opt_EOF + { + Lexer.check_incorrect_doc_comment (); + } + | interactive_parsing { Lexer.CompleteOnEOF = false; } opt_EOF + | documentation_parsing + ; + +outer_declaration + : opt_extern_alias_directives opt_using_directives + | opt_extern_alias_directives opt_using_directives namespace_or_type_declarations opt_attributes + { + if ($4 != null) { + Attributes attrs = (Attributes) $4; + report.Error (1730, attrs.Attrs [0].Location, + "Assembly and module attributes must precede all other elements except using clauses and extern alias declarations"); + } + } + | opt_extern_alias_directives opt_using_directives attribute_sections + { + module.AddAttributes ((Attributes) $3, current_namespace); + } + | error + { + if (yyToken == Token.EXTERN_ALIAS) + report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); + else + Error_SyntaxError (yyToken); + } + ; + +opt_EOF + : /* empty */ + | EOF + ; + +extern_alias_directives + : extern_alias_directive + | extern_alias_directives extern_alias_directive + ; + +extern_alias_directive + : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $2; + string s = lt.Value; + if (s != "alias"){ + syntax_error (lt.Location, "`alias' expected"); + } else if (lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (lt.Location, "external alias"); + } else { + lt = (Tokenizer.LocatedToken) $3; + current_namespace.AddUsingExternalAlias (lt.Value, lt.Location, report); + ubag.AddExternAlias (GetLocation ($1), GetLocation ($2), lt, GetLocation ($4)); + } + } + | EXTERN_ALIAS error + { + syntax_error (GetLocation ($1), "`alias' expected"); // TODO: better + } + ; + +using_directives + : using_directive + | using_directives using_directive + ; + +using_directive + : using_alias_directive + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + | using_namespace_directive + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + ; + +using_alias_directive + : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $2; + if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { + report.Warning (440, 2, lt.Location, + "An alias named `global' will not be used when resolving `global::'. The global namespace will be used instead"); + } + + current_namespace.AddUsingAlias (lt.Value, (MemberName) $4, GetLocation ($1)); + ubag.AddUsingAlias (GetLocation ($1), lt, GetLocation ($3), (MemberName) $4, GetLocation ($5)); + } + | USING error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +using_namespace_directive + : USING namespace_name SEMICOLON + { + current_namespace.AddUsing ((MemberName) $2, GetLocation ($1)); + ubag.AddUsing (GetLocation ($1), (MemberName) $2, GetLocation ($3)); + } + ; + +// +// Strictly speaking, namespaces don't have attributes but +// we parse global attributes along with namespace declarations and then +// detach them +// +namespace_declaration + : opt_attributes NAMESPACE qualified_identifier + { + Attributes attrs = (Attributes) $1; + MemberName name = (MemberName) $3; + if (attrs != null) { + bool valid_global_attrs = true; + if ((current_namespace.DeclarationFound || current_namespace != file.NamespaceContainer)) { + valid_global_attrs = false; + } else { + foreach (var a in attrs.Attrs) { + if (a.ExplicitTarget == "assembly" || a.ExplicitTarget == "module") + continue; + + valid_global_attrs = false; + break; + } + } + + if (!valid_global_attrs) + report.Error (1671, name.Location, "A namespace declaration cannot have modifiers or attributes"); + } + + module.AddAttributes (attrs, current_namespace); + + current_namespace = new NamespaceContainer (name, module, current_namespace, file); + module.AddTypesContainer (current_namespace); + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + + ubag.DeclareNamespace (GetLocation ($2), name); + } + OPEN_BRACE + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + ubag.OpenNamespace (GetLocation ($5)); + } + opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon + { + if ($11 != null) + lbag.AddLocation (current_namespace, GetLocation ($2), GetLocation ($5), GetLocation ($10), GetLocation ($11)); + else + lbag.AddLocation (current_namespace, GetLocation ($2), GetLocation ($5), GetLocation ($10)); + + current_namespace = current_namespace.Parent; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; + ubag.CloseNamespace (GetLocation ($10)); + ubag.EndNamespace (GetLocation ($10)); + } + ; + +qualified_identifier + : IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, lt.Location); + } + | qualified_identifier DOT IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberName ((MemberName) $1, lt.Value, lt.Location); + } + | error + { + Error_SyntaxError (yyToken); + $$ = new MemberName ("", lexer.Location); + } + ; + +opt_semicolon + : /* empty */ + | SEMICOLON + ; + +opt_comma + : /* empty */ + | COMMA + ; + +namespace_name + : namespace_or_type_name + { + MemberName name = (MemberName) $1; + + if (name.TypeArguments != null) + syntax_error (lexer.Location, "namespace name expected"); + + $$ = name; + } + ; + +opt_using_directives + : /* empty */ + | using_directives + ; + +opt_extern_alias_directives + : /* empty */ + | extern_alias_directives + ; + +opt_namespace_or_type_declarations + : /* empty */ + | namespace_or_type_declarations + ; + +namespace_or_type_declarations + : namespace_or_type_declaration + | namespace_or_type_declarations namespace_or_type_declaration + ; + +namespace_or_type_declaration + : type_declaration + { + if ($1 != null) { + TypeContainer ds = (TypeContainer)$1; + + if ((ds.ModFlags & (Modifiers.PRIVATE | Modifiers.PROTECTED)) != 0){ + report.Error (1527, ds.Location, + "Namespace elements cannot be explicitly declared as private, protected or protected internal"); + } + + // Here is a trick, for explicit attributes we don't know where they belong to until + // we parse succeeding declaration hence we parse them as normal and re-attach them + // when we know whether they are global (assembly:, module:) or local (type:). + if (ds.OptAttributes != null) { + ds.OptAttributes.ConvertGlobalAttributes (ds, current_namespace, !current_namespace.DeclarationFound && current_namespace == file.NamespaceContainer); + } + } + current_namespace.DeclarationFound = true; + } + | namespace_declaration + { + current_namespace.DeclarationFound = true; + } + ; + +type_declaration + : class_declaration + | struct_declaration + | interface_declaration + | enum_declaration + | delegate_declaration +// +// Enable this when we have handled all errors, because this acts as a generic fallback +// +// | error { +// Console.WriteLine ("Token=" + yyToken); +// report.Error (1518, GetLocation ($1), "Expected class, struct, interface, enum or delegate"); +// } + ; + +// +// Attributes +// + +opt_attributes + : /* empty */ + | attribute_sections + ; + +attribute_sections + : attribute_section + { + var sect = (List) $1; + $$ = new Attributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + } + | attribute_sections attribute_section + { + Attributes attrs = $1 as Attributes; + var sect = (List) $2; + if (attrs == null) + attrs = new Attributes (sect); + else + attrs.AddAttributes (sect); + lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + $$ = attrs; + } + ; + +attribute_section + : OPEN_BRACKET + { + lexer.parsing_attribute_section = true; + savedOpenLocation = GetLocation ($1); + } + attribute_section_cont + { + lexer.parsing_attribute_section = false; + $$ = $3; + } + ; + +attribute_section_cont + : attribute_target COLON + { + current_attr_target = (string) $1; + if (current_attr_target == "assembly" || current_attr_target == "module") { + Lexer.check_incorrect_doc_comment (); + } + } + attribute_list opt_comma CLOSE_BRACKET + { + // when attribute target is invalid + if (current_attr_target == string.Empty) + $$ = new List (0); + else + $$ = $4; + + current_attr_target = null; + lexer.parsing_attribute_section = false; + savedCloseLocation = GetLocation ($6); + } + | attribute_list opt_comma CLOSE_BRACKET + { + $$ = $1; + savedCloseLocation = GetLocation ($3); + } + ; + +attribute_target + : IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = CheckAttributeTarget (lt.Value, lt.Location); + } + | EVENT { $$ = "event"; } + | RETURN { $$ = "return"; } + | error + { + if (yyToken == Token.IDENTIFIER) { + Error_SyntaxError (yyToken); + $$ = null; + } else { + string name = GetTokenName (yyToken); + $$ = CheckAttributeTarget (name, GetLocation ($1)); + } + } + ; + +attribute_list + : attribute + { + $$ = new List (4) { (Attribute) $1 }; + } + | attribute_list COMMA attribute + { + var attrs = (List) $1; + attrs.Add ((Attribute) $3); + + $$ = attrs; + } + ; + +attribute + : attribute_name + { + ++lexer.parsing_block; + } + opt_attribute_arguments + { + --lexer.parsing_block; + MemberName mname = (MemberName) $1; + if (mname.IsGeneric) { + report.Error (404, lexer.Location, + "'<' unexpected: attributes cannot be generic"); + } + + Arguments [] arguments = (Arguments []) $3; + ATypeNameExpression expr = mname.GetTypeExpression (); + $$ = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname)); + if (arguments != null) { + lbag.AddLocation ($$, savedAttrParenOpenLocation, savedAttrParenCloseLocation); + } + } + ; + +attribute_name + : namespace_or_type_name + ; + +opt_attribute_arguments + : /* empty */ { $$ = null; } + | OPEN_PARENS attribute_arguments CLOSE_PARENS + { + savedAttrParenOpenLocation = GetLocation ($1); + savedAttrParenCloseLocation = GetLocation ($3); + $$ = $2; + } + ; + + +attribute_arguments + : /* empty */ { $$ = null; } + | positional_or_named_argument + { + Arguments a = new Arguments (4); + a.Add ((Argument) $1); + $$ = new Arguments [] { a, null }; + } + | named_attribute_argument + { + Arguments a = new Arguments (4); + a.Add ((Argument) $1); + $$ = new Arguments [] { null, a }; + } + | attribute_arguments COMMA positional_or_named_argument + { + Arguments[] o = (Arguments[]) $1; + if (o [1] != null) { + report.Error (1016, ((Argument) $3).Expr.Location, "Named attribute arguments must appear after the positional arguments"); + o [0] = new Arguments (4); + } + + Arguments args = ((Arguments) o [0]); + if (args.Count > 0 && !($3 is NamedArgument) && args [args.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) $3); + lbag.AppendTo (args, GetLocation ($2)); + } + | attribute_arguments COMMA named_attribute_argument + { + Arguments[] o = (Arguments[]) $1; + if (o [1] == null) { + o [1] = new Arguments (4); + } + + ((Arguments) o [1]).Add ((Argument) $3); + lbag.AppendTo (o[1], GetLocation ($2)); + } + ; + +positional_or_named_argument + : expression + { + $$ = new Argument ((Expression) $1); + } + | named_argument + ; + +named_attribute_argument + : IDENTIFIER ASSIGN + { + ++lexer.parsing_block; + } + expression + { + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) $1; + $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4); + lbag.AddLocation ($$, GetLocation($2)); + } + ; + +named_argument + : IDENTIFIER COLON opt_named_modifier expression + { + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (GetLocation ($1), "named argument"); + + // Avoid boxing in common case (no modifier) + var arg_mod = $3 == null ? Argument.AType.None : (Argument.AType) $3; + + var lt = (Tokenizer.LocatedToken) $1; + $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod); + } + ; + +opt_named_modifier + : /* empty */ { $$ = null; } + | REF + { + $$ = Argument.AType.Ref; + } + | OUT + { + $$ = Argument.AType.Out; + } + ; + +opt_class_member_declarations + : /* empty */ + | class_member_declarations + ; + +class_member_declarations + : class_member_declaration + | class_member_declarations + class_member_declaration + ; + +class_member_declaration + : constant_declaration + | field_declaration + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | operator_declaration + | constructor_declaration + | destructor_declaration + | type_declaration + | error + { + report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", + GetSymbolName (yyToken)); + $$ = null; + lexer.parsing_generic_declaration = false; + } + ; + +struct_declaration + : opt_attributes + opt_modifiers + opt_partial + STRUCT + { + lexer.ConstraintsParsing = true; + } + type_declaration_name + { + MemberName name = MakeName ((MemberName) $6); + push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3); + } + opt_class_base + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) $9); + + if (doc_support) + current_container.DocComment = Lexer.consume_doc_comment (); + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + } + struct_body + { + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_semicolon + { + lbag.AppendToMember (current_class, GetLocation ($13)); + $$ = pop_current_class (); + } + | opt_attributes opt_modifiers opt_partial STRUCT error + { + Error_SyntaxError (yyToken); + } + ; + +struct_body + : OPEN_BRACE + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_struct_member_declarations CLOSE_BRACE + { + lbag.AppendToMember (current_class, GetLocation ($1), GetLocation ($4)); + } + ; + +opt_struct_member_declarations + : /* empty */ + | struct_member_declarations + ; + +struct_member_declarations + : struct_member_declaration + | struct_member_declarations struct_member_declaration + ; + +struct_member_declaration + : constant_declaration + | field_declaration + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | operator_declaration + | constructor_declaration + | type_declaration + + /* + * This is only included so we can flag error 575: + * destructors only allowed on class types + */ + | destructor_declaration + ; + +constant_declaration + : opt_attributes + opt_modifiers + CONST type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $5; + var mod = (Modifiers) $2; + current_field = new Const (current_class, (FullNamedExpression) $4, mod, new MemberName (lt.Value, lt.Location), (Attributes) $1); + current_container.AddConstant ((Const) current_field); + + if ((mod & Modifiers.STATIC) != 0) { + report.Error (504, current_field.Location, "The constant `{0}' cannot be marked static", current_field.GetSignatureForError ()); + } + + $$ = current_field; + } + constant_initializer opt_constant_declarators SEMICOLON + { + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) $7; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); + current_field = null; + } + ; + +opt_constant_declarators + : /* empty */ + | constant_declarators + ; + +constant_declarators + : constant_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $1); + } + | constant_declarators constant_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +constant_declarator + : COMMA IDENTIFIER constant_initializer + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); + lbag.AddLocation ($$, GetLocation ($1)); + } + ; + +constant_initializer + : ASSIGN + { + ++lexer.parsing_block; + } + constant_initializer_expr + { + --lexer.parsing_block; + $$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($1)); + } + | error + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + $$ = null; + } + ; + +constant_initializer_expr + : constant_expression + | array_initializer + ; + +field_declaration + : opt_attributes + opt_modifiers + member_type IDENTIFIER + { + lexer.parsing_generic_declaration = false; + + FullNamedExpression type = (FullNamedExpression) $3; + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (670, GetLocation ($3), "Fields cannot have void type"); + + var lt = (Tokenizer.LocatedToken) $4; + current_field = new Field (current_class, type, (Modifiers) $2, new MemberName (lt.Value, lt.Location), (Attributes) $1); + current_container.AddField (current_field); + $$ = current_field; + } + opt_field_initializer + opt_field_declarators + SEMICOLON + { + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($8)); + $$ = current_field; + current_field = null; + } + | opt_attributes + opt_modifiers + FIXED simple_type IDENTIFIER + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($3), "fixed size buffers"); + + var lt = (Tokenizer.LocatedToken) $5; + current_field = new FixedField (current_class, (FullNamedExpression) $4, (Modifiers) $2, + new MemberName (lt.Value, lt.Location), (Attributes) $1); + + current_container.AddField (current_field); + } + fixed_field_size opt_fixed_field_declarators SEMICOLON + { + if (doc_support) { + current_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_field.Initializer = (ConstInitializer) $7; + lbag.AddMember (current_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); + $$ = current_field; + current_field = null; + } + | opt_attributes + opt_modifiers + FIXED simple_type error + SEMICOLON + { + report.Error (1641, GetLocation ($5), "A fixed size buffer field must have the array size specifier after the field name"); + } + ; + +opt_field_initializer + : /* empty */ + | ASSIGN + { + ++lexer.parsing_block; + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + start_block (GetLocation ($1)); + } + variable_initializer + { + --lexer.parsing_block; + current_field.Initializer = (Expression) $3; + lbag.AppendToMember (current_field, GetLocation ($1)); + end_block (lexer.Location); + current_local_parameters = null; + } + ; + +opt_field_declarators + : /* empty */ + | field_declarators + ; + +field_declarators + : field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $1); + } + | field_declarators field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +field_declarator + : COMMA IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation ($$, GetLocation ($1)); + } + | COMMA IDENTIFIER ASSIGN + { + ++lexer.parsing_block; + } + variable_initializer + { + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + ; + +opt_fixed_field_declarators + : /* empty */ + | fixed_field_declarators + ; + +fixed_field_declarators + : fixed_field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $1); + } + | fixed_field_declarators fixed_field_declarator + { + current_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +fixed_field_declarator + : COMMA IDENTIFIER fixed_field_size + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) $3); + lbag.AddLocation ($$, GetLocation ($1)); + } + ; + +fixed_field_size + : OPEN_BRACKET + { + ++lexer.parsing_block; + } + expression CLOSE_BRACKET + { + --lexer.parsing_block; + $$ = new ConstInitializer (current_field, (Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($4)); + } + | OPEN_BRACKET error + { + report.Error (443, lexer.Location, "Value or constant expected"); + $$ = null; + } + ; + +variable_initializer + : expression + | array_initializer + | error + { + // It has to be here for the parent to safely restore artificial block + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +method_declaration + : method_header + { + if (doc_support) + Lexer.doc_state = XmlCommentState.NotAllowed; + + // Add it early in the case of body being eof for full aot + current_container.AddMethod ((Method) $1); + } + method_body + { + Method method = (Method) $1; + 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 ()); + } + } else { + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, method.Location, "`{0}': interface members cannot have a definition", + method.GetSignatureForError ()); + } + } + + current_local_parameters = null; + + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + ; + +method_header + : opt_attributes + opt_modifiers + member_type + method_declaration_name OPEN_PARENS + { + valid_param_mod = ParameterModifierType.All; + } + opt_formal_parameter_list CLOSE_PARENS + { + lexer.ConstraintsParsing = true; + } + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + MemberName name = (MemberName) $4; + current_local_parameters = (ParametersCompiled) $7; + + GenericMethod generic = null; + if (name.TypeArguments != null) { + generic = new GenericMethod (current_namespace, current_class, name, + (FullNamedExpression) $3, current_local_parameters); + + generic.SetParameterInfo ((List) $10); + } else if ($10 != null) { + report.Error (80, GetLocation ($10), + "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); + + 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 (); + + lbag.AddMember (method, GetModifierLocations (), GetLocation ($5), GetLocation ($8)); + $$ = method; + } + | opt_attributes + opt_modifiers + PARTIAL + VOID + { + lexer.parsing_generic_declaration = true; + } + method_declaration_name + OPEN_PARENS + { + lexer.parsing_generic_declaration = false; + valid_param_mod = ParameterModifierType.All; + } + opt_formal_parameter_list CLOSE_PARENS + { + lexer.ConstraintsParsing = true; + } + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + valid_param_mod = 0; + + MemberName name = (MemberName) $6; + current_local_parameters = (ParametersCompiled) $9; + + if ($11 != null && name.TypeArguments == null) + 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, + new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($4)), + current_local_parameters); + + generic.SetParameterInfo ((List) $11); + } + + var modifiers = (Modifiers) $2; + + 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); + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($3)); + lbag.AddMember (method, mod_locations, GetLocation ($7), GetLocation ($10)); + $$ = method; + } + | opt_attributes + opt_modifiers + member_type + modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + { + MemberName name = (MemberName) $5; + 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); + + current_local_parameters = (ParametersCompiled) $7; + + if (doc_support) + method.DocComment = Lexer.consume_doc_comment (); + + $$ = method; + } + ; + +method_body + : block + | SEMICOLON { $$ = null; } + ; + +opt_formal_parameter_list + : /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } + | formal_parameter_list + ; + +formal_parameter_list + : fixed_parameters + { + var pars_list = (List) $1; + $$ = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation ($$, lbag.GetLocations (pars_list)); + } + | fixed_parameters COMMA parameter_array + { + var pars_list = (List) $1; + pars_list.Add ((Parameter) $3); + + $$ = new ParametersCompiled (pars_list.ToArray ()); + } + | fixed_parameters COMMA arglist_modifier + { + var pars_list = (List) $1; + pars_list.Add (new ArglistParameter (GetLocation ($3))); + $$ = new ParametersCompiled (pars_list.ToArray (), true); + } + | parameter_array COMMA error + { + if ($1 != null) + report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list"); + + $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); + } + | fixed_parameters COMMA parameter_array COMMA error + { + if ($3 != null) + report.Error (231, ((Parameter) $3).Location, "A params parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) $1; + pars_list.Add (new ArglistParameter (GetLocation ($3))); + + $$ = new ParametersCompiled (pars_list.ToArray (), true); + } + | arglist_modifier COMMA error + { + report.Error (257, GetLocation ($1), "An __arglist parameter must be the last parameter in a formal parameter list"); + + $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); + } + | fixed_parameters COMMA ARGLIST COMMA error + { + report.Error (257, GetLocation ($3), "An __arglist parameter must be the last parameter in a formal parameter list"); + + var pars_list = (List) $1; + pars_list.Add (new ArglistParameter (GetLocation ($3))); + + $$ = new ParametersCompiled (pars_list.ToArray (), true); + } + | parameter_array + { + $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); + } + | arglist_modifier + { + $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); + } + | error + { + Error_SyntaxError (yyToken); + $$ = ParametersCompiled.EmptyReadOnlyParameters; + } + ; + +fixed_parameters + : fixed_parameter + { + parameters_bucket.Clear (); + Parameter p = (Parameter) $1; + parameters_bucket.Add (p); + + default_parameter_used = p.HasDefaultValue; + $$ = parameters_bucket; + } + | fixed_parameters COMMA fixed_parameter + { + var pars = (List) $1; + Parameter p = (Parameter) $3; + if (p != null) { + if (p.HasExtensionMethodModifier) + report.Error (1100, p.Location, "The parameter modifier `this' can only be used on the first parameter"); + else if (!p.HasDefaultValue && default_parameter_used) + report.Error (1737, p.Location, "Optional parameter cannot precede required parameters"); + + default_parameter_used |= p.HasDefaultValue; + pars.Add (p); + + lbag.AppendTo (pars, GetLocation ($2)); + } + + $$ = $1; + } + ; + +fixed_parameter + : opt_attributes + opt_parameter_modifier + parameter_type + IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $4; + $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, parameterModifierLocation); + } + | opt_attributes + opt_parameter_modifier + parameter_type + IDENTIFIER OPEN_BRACKET CLOSE_BRACKET + { + var lt = (Tokenizer.LocatedToken) $4; + report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); + $$ = new Parameter ((FullNamedExpression) $3, lt.Value, (Parameter.Modifier) $2, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, parameterModifierLocation); + } + | opt_attributes + opt_parameter_modifier + parameter_type + error + { + Error_SyntaxError (yyToken); + Location l = GetLocation ($4); + $$ = new Parameter ((FullNamedExpression) $3, null, (Parameter.Modifier) $2, (Attributes) $1, l); + lbag.AddLocation ($$, parameterModifierLocation); + } + | opt_attributes + opt_parameter_modifier + parameter_type + IDENTIFIER + ASSIGN + { + ++lexer.parsing_block; + } + constant_expression + { + --lexer.parsing_block; + if (lang_version <= LanguageVersion.V_3) { + FeatureIsNotAvailable (GetLocation ($5), "optional parameter"); + } + + Parameter.Modifier mod = (Parameter.Modifier) $2; + if (mod != Parameter.Modifier.NONE) { + switch (mod) { + case Parameter.Modifier.REF: + case Parameter.Modifier.OUT: + report.Error (1741, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + + case Parameter.Modifier.This: + report.Error (1743, GetLocation ($2), "Cannot specify a default value for the `{0}' parameter", + Parameter.GetModifierSignature (mod)); + break; + default: + throw new NotImplementedException (mod.ToString ()); + } + + mod = Parameter.Modifier.NONE; + } + + if ((valid_param_mod & ParameterModifierType.DefaultValue) == 0) + report.Error (1065, GetLocation ($5), "Optional parameter is not valid in this context"); + + var lt = (Tokenizer.LocatedToken) $4; + $$ = new Parameter ((FullNamedExpression) $3, lt.Value, mod, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, parameterModifierLocation, GetLocation ($5)); // parameterModifierLocation should be ignored when mod == NONE + + if ($7 != null) + ((Parameter) $$).DefaultValue = new DefaultParameterValueExpression ((Expression) $7); + } + ; + +opt_parameter_modifier + : /* empty */ { $$ = Parameter.Modifier.NONE; } + | parameter_modifiers + ; + +parameter_modifiers + : parameter_modifier + { + $$ = $1; + parameterModifierLocation = GetLocation ($1); + } + | parameter_modifiers parameter_modifier + { + Parameter.Modifier p2 = (Parameter.Modifier)$2; + Parameter.Modifier mod = (Parameter.Modifier)$1 | p2; + if (((Parameter.Modifier)$1 & p2) == p2) { + Error_DuplicateParameterModifier (lexer.Location, p2); + } else { + switch (mod & ~Parameter.Modifier.This) { + case Parameter.Modifier.REF: + report.Error (1101, lexer.Location, "The parameter modifiers `this' and `ref' cannot be used altogether"); + break; + case Parameter.Modifier.OUT: + report.Error (1102, lexer.Location, "The parameter modifiers `this' and `out' cannot be used altogether"); + break; + default: + report.Error (1108, lexer.Location, "A parameter cannot have specified more than one modifier"); + break; + } + } + $$ = mod; + } + ; + +parameter_modifier + : REF + { + if ((valid_param_mod & ParameterModifierType.Ref) == 0) + Error_ParameterModifierNotValid ("ref", GetLocation ($1)); + + $$ = Parameter.Modifier.REF; + } + | OUT + { + if ((valid_param_mod & ParameterModifierType.Out) == 0) + Error_ParameterModifierNotValid ("out", GetLocation ($1)); + + $$ = Parameter.Modifier.OUT; + } + | THIS + { + if ((valid_param_mod & ParameterModifierType.This) == 0) + Error_ParameterModifierNotValid ("this", GetLocation ($1)); + + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "extension methods"); + + $$ = Parameter.Modifier.This; + } + ; + +parameter_array + : opt_attributes params_modifier type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $4; + $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); + } + | opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression + { + report.Error (1751, GetLocation ($2), "Cannot specify a default value for a parameter array"); + + var lt = (Tokenizer.LocatedToken) $4; + $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); + } + | opt_attributes params_modifier type error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +params_modifier + : PARAMS + { + if ((valid_param_mod & ParameterModifierType.Params) == 0) + report.Error (1670, (GetLocation ($1)), "The `params' modifier is not allowed in current context"); + } + | PARAMS parameter_modifier + { + Parameter.Modifier mod = (Parameter.Modifier)$2; + if ((mod & Parameter.Modifier.This) != 0) { + report.Error (1104, GetLocation ($1), "The parameter modifiers `this' and `params' cannot be used altogether"); + } else { + report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref or out"); + } + } + | PARAMS params_modifier + { + Error_DuplicateParameterModifier (GetLocation ($1), Parameter.Modifier.PARAMS); + } + ; + +arglist_modifier + : ARGLIST + { + if ((valid_param_mod & ParameterModifierType.Arglist) == 0) + report.Error (1669, GetLocation ($1), "__arglist is not valid in this context"); + } + ; + +property_declaration + : opt_attributes + opt_modifiers + member_type + member_declaration_name + { + if (doc_support) + tmpComment = Lexer.consume_doc_comment (); + } + OPEN_BRACE + { + var type = (FullNamedExpression) $3; + current_property = new Property (current_class, type, (Modifiers) $2, + (MemberName) $4, (Attributes) $1); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (547, GetLocation ($3), "`{0}': property or indexer cannot have void type", current_property.GetSignatureForError ()); + + current_container.AddProperty ((Property)current_property); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation ($6)); + + lexer.PropertyParsing = true; + } + accessor_declarations + { + lexer.PropertyParsing = false; + + if (doc_support) + current_property.DocComment = ConsumeStoredComment (); + } + CLOSE_BRACE + { + lbag.AppendToMember (current_property, GetLocation ($10)); + current_property = null; + } + ; + + +indexer_declaration + : opt_attributes opt_modifiers + member_type indexer_declaration_name OPEN_BRACKET + { + valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE + { + valid_param_mod = 0; + var type = (FullNamedExpression) $3; + Indexer indexer = new Indexer (current_class, type, (MemberName) $4, (Modifiers) $2, (ParametersCompiled) $7, (Attributes) $1); + + current_property = indexer; + + current_container.AddIndexer (indexer); + lbag.AddMember (current_property, GetModifierLocations (), GetLocation ($5), GetLocation ($8), GetLocation ($9)); + + if (type.Type != null && type.Type.Kind == MemberKind.Void) + report.Error (620, GetLocation ($3), "`{0}': indexer return type cannot be `void'", indexer.GetSignatureForError ()); + + if (indexer.ParameterInfo.IsEmpty) { + report.Error (1551, GetLocation ($5), "Indexers must have at least one parameter"); + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lexer.PropertyParsing = true; + } + accessor_declarations + { + 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 (); + + lbag.AppendToMember (current_property, GetLocation ($12)); + current_property = null; + } + ; + + +accessor_declarations + : get_accessor_declaration + | get_accessor_declaration accessor_declarations + | set_accessor_declaration + | set_accessor_declaration accessor_declarations + | error + { + if (yyToken == Token.CLOSE_BRACE) { + report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); + } else { + if (yyToken == Token.SEMICOLON) + report.Error (1597, lexer.Location, "Semicolon after method or accessor block is not valid"); + else + report.Error (1014, GetLocation ($1), "A get or set accessor expected"); + } + } + ; + +get_accessor_declaration + : opt_attributes opt_modifiers GET + { + if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); + } + + if (current_property.Get != null) { + report.Error (1007, GetLocation ($3), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Get = new Indexer.GetIndexerMethod (current_property, (Modifiers) $2, ((Indexer)current_property).ParameterInfo.Clone (), + (Attributes) $1, GetLocation ($3)); + } else { + current_property.Get = new Property.GetMethod (current_property, + (Modifiers) $2, (Attributes) $1, GetLocation ($3)); + } + + current_local_parameters = current_property.Get.ParameterInfo; + lbag.AddMember (current_property.Get, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + accessor_body + { + if ($5 != null) { + current_property.Get.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Get.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support) + if (Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + ; + +set_accessor_declaration + : opt_attributes opt_modifiers SET + { + if ($2 != ModifierNone && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (GetLocation ($2), "access modifiers on properties"); + } + + if (current_property.Set != null) { + report.Error (1007, GetLocation ($3), "Property accessor already defined"); + } + + if (current_property is Indexer) { + current_property.Set = new Indexer.SetIndexerMethod (current_property, (Modifiers) $2, + ParametersCompiled.MergeGenerated (compiler, + ((Indexer)current_property).ParameterInfo, true, new Parameter ( + current_property.TypeExpression, "value", Parameter.Modifier.NONE, null, GetLocation ($3)), + null), + (Attributes) $1, GetLocation ($3)); + } else { + current_property.Set = new Property.SetMethod (current_property, (Modifiers) $2, + ParametersCompiled.CreateImplicitParameter (current_property.TypeExpression, GetLocation ($3)), + (Attributes) $1, GetLocation ($3)); + } + + current_local_parameters = current_property.Set.ParameterInfo; + lbag.AddMember (current_property.Set, GetModifierLocations ()); + lexer.PropertyParsing = false; + } + accessor_body + { + if ($5 != null) { + current_property.Set.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_property.Set.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); + } + } + + current_local_parameters = null; + lexer.PropertyParsing = true; + + if (doc_support + && Lexer.doc_state == XmlCommentState.Error) + Lexer.doc_state = XmlCommentState.NotAllowed; + } + ; + +accessor_body + : block + | SEMICOLON + { + lbag.AppendToMember (lbag.LastMember, GetLocation ($1)); + $$ = null; + } + | error + { + Error_SyntaxError (1043, yyToken, "Invalid accessor body"); + $$ = null; + } + ; + +interface_declaration + : opt_attributes + opt_modifiers + opt_partial + INTERFACE + { + lexer.ConstraintsParsing = true; + } + type_declaration_name + { + MemberName name = MakeName ((MemberName) $6); + push_current_class (new Interface (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + } + opt_class_base + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) $9); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE + { + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_semicolon + { + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13)); + $$ = pop_current_class (); + } + | opt_attributes opt_modifiers opt_partial INTERFACE error + { + Error_SyntaxError (yyToken); + } + ; + +opt_interface_member_declarations + : /* empty */ + | interface_member_declarations + ; + +interface_member_declarations + : interface_member_declaration + | interface_member_declarations interface_member_declaration + ; + +interface_member_declaration + : constant_declaration + { + report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); + } + | field_declaration + { + report.Error (525, GetLocation ($1), "Interfaces cannot contain fields or constants"); + } + | method_declaration + | property_declaration + | event_declaration + | indexer_declaration + | operator_declaration + { + report.Error (567, GetLocation ($1), "Interfaces cannot contain operators"); + } + | constructor_declaration + { + report.Error (526, GetLocation ($1), "Interfaces cannot contain contructors"); + } + | type_declaration + { + report.Error (524, GetLocation ($1), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); + } + ; + +operator_declaration + : opt_attributes opt_modifiers operator_declarator + { + } + operator_body + { + OperatorDeclaration decl = (OperatorDeclaration) $3; + if (decl != null) { + Operator op = new Operator ( + 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; + Lexer.doc_state = XmlCommentState.Allowed; + } + + // Note again, checking is done in semantic analysis + current_container.AddOperator (op); + + lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); + } + + current_local_parameters = null; + } + ; + +operator_body + : block + | SEMICOLON { $$ = null; } + ; + +operator_type + : type_expression_or_array + | VOID + { + report.Error (590, GetLocation ($1), "User-defined operators cannot return void"); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +operator_declarator + : operator_type OPERATOR overloadable_operator OPEN_PARENS + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + Location loc = GetLocation ($2); + Operator.OpType op = (Operator.OpType) $3; + current_local_parameters = (ParametersCompiled)$6; + + int p_count = current_local_parameters.Count; + if (p_count == 1) { + if (op == Operator.OpType.Addition) + op = Operator.OpType.UnaryPlus; + else if (op == Operator.OpType.Subtraction) + op = Operator.OpType.UnaryNegation; + } + + if (IsUnaryOperator (op)) { + if (p_count == 2) { + report.Error (1020, loc, "Overloadable binary operator expected"); + } else if (p_count != 1) { + report.Error (1535, loc, "Overloaded unary operator `{0}' takes one parameter", + Operator.GetName (op)); + } + } else { + if (p_count > 2) { + report.Error (1534, loc, "Overloaded binary operator `{0}' takes two parameters", + Operator.GetName (op)); + } else if (p_count != 2) { + report.Error (1019, loc, "Overloadable unary operator expected"); + } + } + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + $$ = new OperatorDeclaration (op, (FullNamedExpression) $1, loc); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3), GetLocation ($4), GetLocation ($7)); + } + | conversion_operator_declarator + ; + +overloadable_operator +// Unary operators: + : BANG { $$ = Operator.OpType.LogicalNot; } + | TILDE { $$ = Operator.OpType.OnesComplement; } + | OP_INC { $$ = Operator.OpType.Increment; } + | OP_DEC { $$ = Operator.OpType.Decrement; } + | TRUE { $$ = Operator.OpType.True; } + | FALSE { $$ = Operator.OpType.False; } +// Unary and binary: + | PLUS { $$ = Operator.OpType.Addition; } + | MINUS { $$ = Operator.OpType.Subtraction; } +// Binary: + | STAR { $$ = Operator.OpType.Multiply; } + | DIV { $$ = Operator.OpType.Division; } + | PERCENT { $$ = Operator.OpType.Modulus; } + | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; } + | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; } + | CARRET { $$ = Operator.OpType.ExclusiveOr; } + | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; } + | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; } + | OP_EQ { $$ = Operator.OpType.Equality; } + | OP_NE { $$ = Operator.OpType.Inequality; } + | OP_GT { $$ = Operator.OpType.GreaterThan; } + | OP_LT { $$ = Operator.OpType.LessThan; } + | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; } + | OP_LE { $$ = Operator.OpType.LessThanOrEqual; } + ; + +conversion_operator_declarator + : IMPLICIT OPERATOR type OPEN_PARENS + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + Location loc = GetLocation ($2); + current_local_parameters = (ParametersCompiled)$6; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + $$ = new OperatorDeclaration (Operator.OpType.Implicit, (FullNamedExpression) $3, loc); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); + } + | EXPLICIT OPERATOR type OPEN_PARENS + { + valid_param_mod = ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + Location loc = GetLocation ($2); + current_local_parameters = (ParametersCompiled)$6; + + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + $$ = new OperatorDeclaration (Operator.OpType.Explicit, (FullNamedExpression) $3, loc); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($2), GetLocation ($4), GetLocation ($7)); + } + | IMPLICIT error + { + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + $$ = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation ($1)); + } + | EXPLICIT error + { + Error_SyntaxError (yyToken); + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + $$ = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation ($1)); + } + ; + +constructor_declaration + : constructor_declarator + constructor_body + { + Constructor c = (Constructor) $1; + c.Block = (ToplevelBlock) $2; + + if (doc_support) + c.DocComment = ConsumeStoredComment (); + + current_container.AddConstructor (c); + + current_local_parameters = null; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + ; + +constructor_declarator + : opt_attributes + opt_modifiers + IDENTIFIER + { + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + valid_param_mod = ParameterModifierType.All; + } + OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + current_local_parameters = (ParametersCompiled) $6; + + // + // start block here, so possible anonymous methods inside + // constructor initializer can get correct parent block + // + start_block (lexer.Location); + } + opt_constructor_initializer + { + var lt = (Tokenizer.LocatedToken) $3; + var mods = (Modifiers) $2; + ConstructorInitializer ci = (ConstructorInitializer) $9; + + Constructor c = new Constructor (current_class, lt.Value, mods, + (Attributes) $1, current_local_parameters, ci, lt.Location); + + if (lt.Value != current_container.MemberName.Name) { + report.Error (1520, c.Location, "Class, struct, or interface method must have a return type"); + } else if ((mods & Modifiers.STATIC) != 0) { + if ((mods & Modifiers.AccessibilityMask) != 0){ + report.Error (515, c.Location, + "`{0}': static constructor cannot have an access modifier", + c.GetSignatureForError ()); + } + if (ci != null) { + report.Error (514, c.Location, + "`{0}': static constructor cannot have an explicit `this' or `base' constructor call", + c.GetSignatureForError ()); + + } + } + + lbag.AddMember (c, GetModifierLocations (), GetLocation ($5), GetLocation ($7)); + $$ = c; + } + ; + +constructor_body + : block_prepared + | SEMICOLON { current_block = null; $$ = null; } + ; + +opt_constructor_initializer + : /* Empty */ + | constructor_initializer + ; + +constructor_initializer + : COLON BASE OPEN_PARENS + { + ++lexer.parsing_block; + } + opt_argument_list CLOSE_PARENS + { + --lexer.parsing_block; + $$ = new ConstructorBaseInitializer ((Arguments) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); + } + | COLON THIS OPEN_PARENS + { + ++lexer.parsing_block; + } + opt_argument_list CLOSE_PARENS + { + --lexer.parsing_block; + $$ = new ConstructorThisInitializer ((Arguments) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($6)); + } + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +destructor_declaration + : opt_attributes opt_modifiers TILDE + { + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + + current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body + { + var lt = (Tokenizer.LocatedToken) $5; + if (lt.Value != current_container.MemberName.Name){ + report.Error (574, lt.Location, "Name of destructor must match name of class"); + } else if (current_container.Kind != MemberKind.Class){ + report.Error (575, lt.Location, "Only class types can contain destructor"); + } + + Destructor d = new Destructor (current_class, (Modifiers) $2, + ParametersCompiled.EmptyReadOnlyParameters, (Attributes) $1, lt.Location); + if (doc_support) + d.DocComment = ConsumeStoredComment (); + + d.Block = (ToplevelBlock) $8; + current_container.AddMethod (d); + lbag.AddMember (d, GetModifierLocations (), GetLocation ($3), GetLocation ($6), GetLocation ($7)); + + current_local_parameters = null; + } + ; + +event_declaration + : opt_attributes + opt_modifiers + EVENT type member_declaration_name + { + current_event_field = new EventField (current_class, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); + current_container.AddEvent (current_event_field); + + if (current_event_field.MemberName.Left != null) { + report.Error (71, current_event_field.Location, "`{0}': An explicit interface implementation of an event must use property syntax", + current_event_field.GetSignatureForError ()); + } + + $$ = current_event_field; + } + opt_event_initializer + opt_event_declarators + SEMICOLON + { + if (doc_support) { + current_event_field.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AddMember (current_event_field, GetModifierLocations (), GetLocation ($3), GetLocation ($9)); + current_event_field = null; + } + | opt_attributes + opt_modifiers + EVENT type member_declaration_name + OPEN_BRACE + { + current_event = new EventProperty (current_class, (FullNamedExpression) $4, (Modifiers) $2, (MemberName) $5, (Attributes) $1); + current_container.AddEvent (current_event); + lbag.AddMember (current_event, GetModifierLocations (), GetLocation ($3), GetLocation ($6)); + + lexer.EventParsing = true; + } + event_accessor_declarations + { + if (current_container.Kind == MemberKind.Interface) + report.Error (69, GetLocation ($6), "Event in interface cannot have add or remove accessors"); + + lexer.EventParsing = false; + } + CLOSE_BRACE + { + if (doc_support) { + current_event.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + lbag.AppendToMember (current_event, GetLocation ($9)); + current_event = null; + current_local_parameters = null; + } + ; + +opt_event_initializer + : /* empty */ + | ASSIGN + { + ++lexer.parsing_block; + } + event_variable_initializer + { + --lexer.parsing_block; + current_event_field.Initializer = (Expression) $3; + } + ; + +opt_event_declarators + : /* empty */ + | event_declarators + ; + +event_declarators + : event_declarator + { + current_event_field.AddDeclarator ((FieldDeclarator) $1); + } + | event_declarators event_declarator + { + current_event_field.AddDeclarator ((FieldDeclarator) $2); + } + ; + +event_declarator + : COMMA IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); + lbag.AddLocation ($$, GetLocation ($1)); + } + | COMMA IDENTIFIER ASSIGN + { + ++lexer.parsing_block; + } + event_variable_initializer + { + --lexer.parsing_block; + var lt = (Tokenizer.LocatedToken) $2; + $$ = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (Expression) $5); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + ; + +event_variable_initializer + : { + if (current_container.Kind == MemberKind.Interface) { + report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + + if ((current_event_field.ModFlags & Modifiers.ABSTRACT) != 0) { + report.Error (74, lexer.Location, "`{0}': abstract event cannot have an initializer", + current_event_field.GetSignatureForError ()); + } + } + variable_initializer + { + $$ = $2; + } + ; + +event_accessor_declarations + : add_accessor_declaration remove_accessor_declaration + | remove_accessor_declaration add_accessor_declaration + | add_accessor_declaration + { + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + | remove_accessor_declaration + { + report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", + current_event.GetSignatureForError ()); + } + | error + { + report.Error (1055, GetLocation ($1), "An add or remove accessor expected"); + $$ = null; + } + ; + +add_accessor_declaration + : opt_attributes opt_modifiers ADD + { + if ($2 != ModifierNone) { + report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Add = new EventProperty.AddDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); + current_local_parameters = current_event.Add.ParameterInfo; + + lbag.AddMember (current_event.Add, GetModifierLocations ()); + lexer.EventParsing = false; + } + event_accessor_block + { + lexer.EventParsing = true; + + current_event.Add.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Add.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Add.GetSignatureForError ()); + } + + current_local_parameters = null; + } + ; + +remove_accessor_declaration + : opt_attributes opt_modifiers REMOVE + { + if ($2 != ModifierNone) { + report.Error (1609, GetLocation ($2), "Modifiers cannot be placed on event accessor declarations"); + } + + current_event.Remove = new EventProperty.RemoveDelegateMethod (current_event, (Attributes) $1, GetLocation ($3)); + current_local_parameters = current_event.Remove.ParameterInfo; + + lbag.AddMember (current_event.Remove, GetModifierLocations ()); + lexer.EventParsing = false; + } + event_accessor_block + { + lexer.EventParsing = true; + + current_event.Remove.Block = (ToplevelBlock) $5; + + if (current_container.Kind == MemberKind.Interface) { + report.Error (531, current_event.Remove.Block.StartLocation, + "`{0}': interface members cannot have a definition", current_event.Remove.GetSignatureForError ()); + } + + current_local_parameters = null; + } + ; + +event_accessor_block + : opt_semicolon + { + report.Error (73, lexer.Location, "An add or remove accessor must have a body"); + $$ = null; + } + | block; + ; + +enum_declaration + : opt_attributes + opt_modifiers + ENUM type_declaration_name + opt_enum_base + { + if (doc_support) + enumTypeComment = Lexer.consume_doc_comment (); + } + OPEN_BRACE + { + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + + 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) $5, (Modifiers) $2, MakeName (name), (Attributes) $1), null); + } + opt_enum_member_declarations + { + // here will be evaluated after CLOSE_BLACE is consumed. + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + CLOSE_BRACE opt_semicolon + { + if (doc_support) + current_class.DocComment = enumTypeComment; + + --lexer.parsing_declaration; + +// if (doc_support) +// em.DocComment = ev.DocComment; + + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($3), GetLocation ($7), GetLocation ($11)); + $$ = pop_current_class (); + } + ; + +opt_enum_base + : /* empty */ + | COLON type + { + var te = $2 as TypeExpression; + if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { + Enum.Error_1008 (GetLocation ($2), report); + $$ = null; + } else { + $$ = $2; + } + } + | COLON error + { + Error_TypeExpected (GetLocation ($1)); + $$ = null; + } + ; + +opt_enum_member_declarations + : /* empty */ + | enum_member_declarations + | enum_member_declarations COMMA + { + lbag.AddLocation ($1, GetLocation ($2)); + } + ; + +enum_member_declarations + : enum_member_declaration + | enum_member_declarations COMMA enum_member_declaration + { + lbag.AddLocation ($1, GetLocation ($2)); + $$ = $3; + } + ; + +enum_member_declaration + : opt_attributes IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) $1); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) { + em.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + $$ = em; + } + | opt_attributes IDENTIFIER + { + ++lexer.parsing_block; + if (doc_support) { + tmpComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.NotAllowed; + } + } + ASSIGN constant_expression + { + --lexer.parsing_block; + + var lt = (Tokenizer.LocatedToken) $2; + var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) $1); + em.Initializer = new ConstInitializer (em, (Expression) $5, GetLocation ($4)); + ((Enum) current_class).AddEnumMember (em); + + if (doc_support) + em.DocComment = ConsumeStoredComment (); + + $$ = em; + } + ; + +delegate_declaration + : opt_attributes + opt_modifiers + DELEGATE + member_type type_declaration_name + OPEN_PARENS + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + + MemberName name = MakeName ((MemberName) $5); + ParametersCompiled p = (ParametersCompiled) $8; + + 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; + } + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + } + SEMICOLON + { + if (doc_support) { + current_delegate.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + + current_delegate.SetParameterInfo ((List) $11); + lbag.AddMember (current_delegate, GetModifierLocations (), GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($13)); + + $$ = current_delegate; + + current_delegate = null; + } + ; + +opt_nullable + : /* empty */ + | INTERR_NULLABLE + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "nullable types"); + + $$ = ComposedTypeSpecifier.CreateNullable (GetLocation ($1)); + } + ; + +namespace_or_type_name + : member_name + | qualified_alias_member IDENTIFIER opt_type_argument_list + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); + } + ; + +member_name + : type_name + | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + ; + +type_name + : IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, (TypeArguments)$2, lt.Location); + } + ; + +// +// Generics arguments (any type, without attributes) +// +opt_type_argument_list + : /* empty */ + | OP_GENERICS_LT type_arguments OP_GENERICS_GT + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "generics"); + var list = locationListStack.Pop (); + list.Add (GetLocation ($1)); + list.Add (GetLocation ($2)); + lbag.AddLocation ($2, list); + + $$ = $2;; + } + | OP_GENERICS_LT error + { + Error_TypeExpected (lexer.Location); + $$ = new TypeArguments (); + } + ; + +type_arguments + : type + { + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression) $1); + $$ = type_args; + locationListStack.Push (new List ()); + } + | type_arguments COMMA type + { + TypeArguments type_args = (TypeArguments) $1; + type_args.Add ((FullNamedExpression) $3); + $$ = type_args; + locationListStack.Peek ().Add (GetLocation ($2)); + } + ; + +// +// Generics parameters (identifiers only, with attributes), used in type or method declarations +// +type_declaration_name + : IDENTIFIER + { + lexer.parsing_generic_declaration = true; + } + opt_type_parameter_list + { + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, (TypeArguments)$3, lt.Location); + } + ; + +member_declaration_name + : method_declaration_name + { + MemberName mn = (MemberName)$1; + if (mn.TypeArguments != null) + syntax_error (mn.Location, string.Format ("Member `{0}' cannot declare type arguments", + mn.GetSignatureForError ())); + } + ; + +method_declaration_name + : type_declaration_name + | explicit_interface IDENTIFIER opt_type_parameter_list + { + lexer.parsing_generic_declaration = false; + var lt = (Tokenizer.LocatedToken) $2; + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $3, lt.Location); + } + ; + +indexer_declaration_name + : THIS + { + lexer.parsing_generic_declaration = false; + $$ = new MemberName (TypeContainer.DefaultIndexerName, GetLocation ($1)); + } + | explicit_interface THIS + { + lexer.parsing_generic_declaration = false; + $$ = new MemberName ((MemberName) $1, TypeContainer.DefaultIndexerName, null, GetLocation ($1)); + } + ; + +explicit_interface + : IDENTIFIER opt_type_argument_list DOT + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new MemberName (lt.Value, (TypeArguments) $2, lt.Location); + lbag.AddLocation ($$, GetLocation ($3)); + } + | qualified_alias_member IDENTIFIER opt_type_argument_list DOT + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new MemberName (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); + lbag.AddLocation ($$, GetLocation ($4)); + } + | explicit_interface IDENTIFIER opt_type_argument_list DOT + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $3, lt.Location); + lbag.AddLocation ($$, GetLocation ($4)); + } + ; + +opt_type_parameter_list + : /* empty */ + | OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "generics"); + + $$ = $2; + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + ; + +type_parameters + : type_parameter + { + TypeArguments type_args = new TypeArguments (); + type_args.Add ((FullNamedExpression)$1); + $$ = type_args; + } + | type_parameters COMMA type_parameter + { + TypeArguments type_args = (TypeArguments) $1; + type_args.Add ((FullNamedExpression)$3); + $$ = type_args; + lbag.AddLocation ($3, GetLocation ($3)); + } + ; + +type_parameter + : opt_attributes opt_type_parameter_variance IDENTIFIER + { + var lt = (Tokenizer.LocatedToken)$3; + $$ = new TypeParameterName (lt.Value, (Attributes)$1, (Variance) $2, lt.Location); + } + | error + { + if (GetTokenName (yyToken) == "type") + report.Error (81, GetLocation ($1), "Type parameter declaration must be an identifier not a type"); + else + Error_SyntaxError (yyToken); + + $$ = new TypeParameterName ("", null, lexer.Location); + } + ; + +// +// All types where void is allowed +// +type_and_void + : type_expression_or_array + | VOID + { + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +member_type + : type_and_void + { + lexer.parsing_generic_declaration = true; + } + ; + +// +// A type which does not allow `void' to be used +// +type + : type_expression_or_array + | VOID + { + Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +simple_type + : type_expression + | VOID + { + Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +parameter_type + : type_expression_or_array + | VOID + { + report.Error (1536, GetLocation ($1), "Invalid parameter type `void'"); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +type_expression_or_array + : type_expression + | type_expression rank_specifiers + { + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + ; + +type_expression + : namespace_or_type_name opt_nullable + { + MemberName name = (MemberName) $1; + + if ($2 != null) { + $$ = new ComposedCast (name.GetTypeExpression (), (ComposedTypeSpecifier) $2); + } else { + if (name.Left == null && name.Name == "var") + $$ = new VarExpr (name.Location); + else + $$ = name.GetTypeExpression (); + } + } + | namespace_or_type_name pointer_stars + { + $$ = new ComposedCast (((MemberName) $1).GetTypeExpression (), (ComposedTypeSpecifier) $2); + } + | builtin_types opt_nullable + { + if ($2 != null) + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | builtin_types pointer_stars + { + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | VOID pointer_stars + { + $$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); + } + ; + +type_list + : base_type_name + { + var types = new List (2); + types.Add ((FullNamedExpression) $1); + $$ = types; + } + | type_list COMMA base_type_name + { + var types = (List) $1; + types.Add ((FullNamedExpression) $3); + $$ = types; + } + ; + +base_type_name + : type + { + if ($1 is ComposedCast) { + report.Error (1521, GetLocation ($1), "Invalid base type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); + } + $$ = $1; + } + | error + { + Error_TypeExpected (lexer.Location); + $$ = null; + } + ; + +/* + * replaces all the productions for isolating the various + * simple types, but we need this to reuse it easily in variable_type + */ +builtin_types + : OBJECT { $$ = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation ($1)); } + | STRING { $$ = new TypeExpression (compiler.BuiltinTypes.String, GetLocation ($1)); } + | BOOL { $$ = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation ($1)); } + | DECIMAL { $$ = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation ($1)); } + | FLOAT { $$ = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation ($1)); } + | DOUBLE { $$ = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation ($1)); } + | integral_type + ; + +integral_type + : SBYTE { $$ = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation ($1)); } + | BYTE { $$ = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation ($1)); } + | SHORT { $$ = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation ($1)); } + | USHORT { $$ = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation ($1)); } + | INT { $$ = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation ($1)); } + | UINT { $$ = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation ($1)); } + | LONG { $$ = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation ($1)); } + | ULONG { $$ = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation ($1)); } + | CHAR { $$ = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation ($1)); } + ; + +// +// Expressions, section 7.5 +// + + +primary_expression + : primary_expression_or_type + | literal + | array_creation_expression + | parenthesized_expression + | default_value_expression + | invocation_expression + | element_access + | this_access + | base_access + | post_increment_expression + | post_decrement_expression + | object_or_delegate_creation_expression + | anonymous_type_expression + | typeof_expression + | sizeof_expression + | checked_expression + | unchecked_expression + | pointer_member_access + | anonymous_method_expression + | undocumented_expressions + ; + +primary_expression_or_type + : IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new SimpleName (lt.Value, (TypeArguments)$2, lt.Location); + } + | IDENTIFIER GENERATE_COMPLETION { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); + } + | member_access + ; + +literal + : boolean_literal + | LITERAL + | NULL { $$ = new NullLiteral (GetLocation ($1)); } + ; + +boolean_literal + : TRUE { $$ = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation ($1)); } + | FALSE { $$ = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation ($1)); } + ; + + +// +// Here is the trick, tokenizer may think that parens is a special but +// parser is interested in open parens only, so we merge them. +// Consider: if (a)foo (); +// +open_parens_any + : OPEN_PARENS + | OPEN_PARENS_CAST + ; + +// +// Use this production to accept closing parenthesis or +// performing completion +// +close_parens + : CLOSE_PARENS + | COMPLETE_COMPLETION + ; + + +parenthesized_expression + : OPEN_PARENS expression CLOSE_PARENS + { + $$ = new ParenthesizedExpression ((Expression) $2); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + | OPEN_PARENS expression COMPLETE_COMPLETION + { + $$ = new ParenthesizedExpression ((Expression) $2); + } + ; + +member_access + : primary_expression DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | builtin_types DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | BASE DOT IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | qualified_alias_member IDENTIFIER opt_type_argument_list + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (TypeArguments) $3, lt1.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | primary_expression DOT GENERATE_COMPLETION { + $$ = new CompletionMemberAccess ((Expression) $1, null,GetLocation ($3)); + } + | primary_expression DOT IDENTIFIER GENERATE_COMPLETION { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); + } + | builtin_types DOT GENERATE_COMPLETION + { + $$ = new CompletionMemberAccess ((Expression) $1, null, lexer.Location); + } + | builtin_types DOT IDENTIFIER GENERATE_COMPLETION { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new CompletionMemberAccess ((Expression) $1, lt.Value, lt.Location); + } + ; + +invocation_expression + : primary_expression open_parens_any opt_argument_list close_parens + { + $$ = new Invocation ((Expression) $1, (Arguments) $3); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +opt_object_or_collection_initializer + : /* empty */ { $$ = null; } + | object_or_collection_initializer + ; + +object_or_collection_initializer + : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion + { + if ($2 == null) { + $$ = CollectionOrObjectInitializers.Empty; + // TODO: lbag + } else { + $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + } + | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE + { + $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($4)); + } + ; + +opt_member_initializer_list + : /* empty */ { $$ = null; } + | member_initializer_list + { + $$ = $1; + } + ; + +member_initializer_list + : member_initializer + { + var a = new List (); + a.Add ((Expression) $1); + $$ = a; + } + | member_initializer_list COMMA member_initializer + { + var a = (List)$1; + a.Add ((Expression) $3); + $$ = a; + } + | member_initializer_list error { + Error_SyntaxError (yyToken); + $$ = $1; + } + ; + +member_initializer + : IDENTIFIER ASSIGN initializer_value + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new ElementInitializer (lt.Value, (Expression)$3, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | GENERATE_COMPLETION + { + $$ = new CompletionElementInitializer (null, GetLocation ($1)); + } + | non_assignment_expression opt_COMPLETE_COMPLETION { + CompletionSimpleName csn = $1 as CompletionSimpleName; + if (csn == null) + $$ = new CollectionElementInitializer ((Expression)$1); + else + $$ = new CompletionElementInitializer (csn.Prefix, csn.Location); + } + | OPEN_BRACE expression_list CLOSE_BRACE + { + if ($2 == null) + $$ = null; + else + $$ = new CollectionElementInitializer ((List)$2, GetLocation ($1)); + } + | OPEN_BRACE CLOSE_BRACE + { + report.Error (1920, GetLocation ($1), "An element initializer cannot be empty"); + $$ = null; + } + ; + +initializer_value + : expression + | object_or_collection_initializer + ; + +opt_argument_list + : /* empty */ { $$ = null; } + | argument_list + ; + +argument_list + : argument_or_named_argument + { + Arguments list = new Arguments (4); + list.Add ((Argument) $1); + $$ = list; + } + | argument_list COMMA argument + { + Arguments list = (Arguments) $1; + if (list [list.Count - 1] is NamedArgument) + Error_NamedArgumentExpected ((NamedArgument) list [list.Count - 1]); + + list.Add ((Argument) $3); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + | argument_list COMMA named_argument + { + Arguments list = (Arguments) $1; + NamedArgument a = (NamedArgument) $3; + for (int i = 0; i < list.Count; ++i) { + NamedArgument na = list [i] as NamedArgument; + if (na != null && na.Name == a.Name) + report.Error (1740, na.Location, "Named argument `{0}' specified multiple times", + na.Name); + } + + list.Add (a); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + | argument_list COMMA + { + report.Error (839, GetLocation ($2), "An argument is missing"); + $$ = $1; + } + | COMMA error + { + report.Error (839, GetLocation ($1), "An argument is missing"); + $$ = null; + } + ; + +argument + : expression + { + $$ = new Argument ((Expression) $1); + } + | non_simple_argument + ; + +argument_or_named_argument + : argument + | named_argument + ; + +non_simple_argument + : REF variable_reference + { + $$ = new Argument ((Expression) $2, Argument.AType.Ref); + lbag.AddLocation ($$, GetLocation ($1)); + } + | OUT variable_reference + { + $$ = new Argument ((Expression) $2, Argument.AType.Out); + lbag.AddLocation ($$, GetLocation ($1)); + } + | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS + { + $$ = new Argument (new Arglist ((Arguments) $3, GetLocation ($1))); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + | ARGLIST OPEN_PARENS CLOSE_PARENS + { + $$ = new Argument (new Arglist (GetLocation ($1))); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); + } + ; + +variable_reference + : expression + ; + +element_access + : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + { + $$ = new ElementAccess ((Expression) $1, (Arguments) $3, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } + ; + +expression_list + : expression + { + var list = new List (4); + list.Add ((Expression) $1); + $$ = list; + } + | expression_list COMMA expression + { + var list = (List) $1; + list.Add ((Expression) $3); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + | expression_list error { + Error_SyntaxError (yyToken); + $$ = $1; + } + ; + +expression_list_arguments + : expression_list_argument + { + Arguments args = new Arguments (4); + args.Add ((Argument) $1); + $$ = args; + } + | expression_list_arguments COMMA expression_list_argument + { + Arguments args = (Arguments) $1; + if (args [args.Count - 1] is NamedArgument && !($3 is NamedArgument)) + Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); + + args.Add ((Argument) $3); + lbag.AppendTo (args, GetLocation ($2)); + $$ = args; + } + ; + +expression_list_argument + : expression + { + $$ = new Argument ((Expression) $1); + } + | named_argument + ; + +this_access + : THIS + { + $$ = new This (GetLocation ($1)); + } + ; + +base_access + : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + { + $$ = new ElementAccess (new BaseThis (GetLocation ($1)), (Arguments) $3, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } + | BASE OPEN_BRACKET error + { + Error_SyntaxError (yyToken); + $$ = new ElementAccess (null, null, GetLocation ($2)); + } + ; + +post_increment_expression + : primary_expression OP_INC + { + $$ = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) $1, GetLocation ($2)); + } + ; + +post_decrement_expression + : primary_expression OP_DEC + { + $$ = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) $1, GetLocation ($2)); + } + ; + +object_or_delegate_creation_expression + : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer + { + if ($6 != null) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "object initializers"); + + $$ = new NewInitialize ((FullNamedExpression) $2, (Arguments) $4, (CollectionOrObjectInitializers) $6, GetLocation ($1)); + } else { + $$ = new New ((FullNamedExpression) $2, (Arguments) $4, GetLocation ($1)); + } + + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + | NEW new_expr_type object_or_collection_initializer + { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "collection initializers"); + + $$ = new NewInitialize ((FullNamedExpression) $2, null, (CollectionOrObjectInitializers) $3, GetLocation ($1)); + } + ; + +array_creation_expression + : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET + opt_rank_specifier + opt_array_initializer + { + $$ = new ArrayCreation ((FullNamedExpression) $2, (List) $4, + new ComposedTypeSpecifier (((List) $4).Count, GetLocation ($3)) { + Next = (ComposedTypeSpecifier) $6 + }, (ArrayInitializer) $7, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + | NEW new_expr_type rank_specifiers opt_array_initializer + { + if ($4 == null) + report.Error (1586, GetLocation ($1), "Array creation must have array size or array initializer"); + + $$ = new ArrayCreation ((FullNamedExpression) $2, (ComposedTypeSpecifier) $3, (ArrayInitializer) $4, GetLocation ($1)); + } + | NEW rank_specifier array_initializer + { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "implicitly typed arrays"); + + $$ = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) $2, (ArrayInitializer) $3, GetLocation ($1)); + } + | NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET + { + report.Error (178, GetLocation ($6), "Invalid rank specifier, expecting `,' or `]'"); + $$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); + } + | NEW new_expr_type error + { + Error_SyntaxError (1526, yyToken, "Unexpected symbol"); + $$ = new ArrayCreation ((FullNamedExpression) $2, null, GetLocation ($1)); + } + ; + +new_expr_type + : { + ++lexer.parsing_type; + } + simple_type + { + --lexer.parsing_type; + $$ = $2; + } + ; + +anonymous_type_expression + : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE + { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "anonymous types"); + + $$ = new NewAnonymousType ((List) $3, current_container, GetLocation ($1)); + + // TODO: lbag comma location + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +anonymous_type_parameters_opt_comma + : anonymous_type_parameters_opt + | anonymous_type_parameters COMMA + ; + +anonymous_type_parameters_opt + : { $$ = null; } + | anonymous_type_parameters + ; + +anonymous_type_parameters + : anonymous_type_parameter + { + var a = new List (4); + a.Add ((AnonymousTypeParameter) $1); + $$ = a; + } + | anonymous_type_parameters COMMA anonymous_type_parameter + { + var a = (List) $1; + a.Add ((AnonymousTypeParameter) $3); + $$ = a; + } + ; + +anonymous_type_parameter + : IDENTIFIER ASSIGN variable_initializer + { + var lt = (Tokenizer.LocatedToken)$1; + $$ = new AnonymousTypeParameter ((Expression)$3, lt.Value, lt.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | IDENTIFIER + { + var lt = (Tokenizer.LocatedToken)$1; + $$ = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), + lt.Value, lt.Location); + } + | member_access + { + MemberAccess ma = (MemberAccess) $1; + $$ = new AnonymousTypeParameter (ma, ma.Name, ma.Location); + } + | error + { + report.Error (746, lexer.Location, + "Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); + $$ = null; + } + ; + +opt_rank_specifier + : /* empty */ + | rank_specifiers + ; + +rank_specifiers + : rank_specifier + | rank_specifier rank_specifiers + { + ((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; + $$ = $1; + } + ; + +rank_specifier + : OPEN_BRACKET CLOSE_BRACKET + { + $$ = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2)); + } + | OPEN_BRACKET dim_separators CLOSE_BRACKET + { + $$ = ComposedTypeSpecifier.CreateArrayDimension ((int)$2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + ; + +dim_separators + : COMMA + { + $$ = 2; + } + | dim_separators COMMA + { + $$ = ((int) $1) + 1; + } + ; + +opt_array_initializer + : /* empty */ + { + $$ = null; + } + | array_initializer + { + $$ = $1; + } + ; + +array_initializer + : OPEN_BRACE CLOSE_BRACE + { + var ai = new ArrayInitializer (0, GetLocation ($1)); + ai.VariableDeclaration = current_variable; + lbag.AddLocation (ai, GetLocation ($2)); + $$ = ai; + } + | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE + { + var ai = new ArrayInitializer ((List) $2, GetLocation ($1)); + ai.VariableDeclaration = current_variable; + if ($3 != null) { + lbag.AddLocation (ai, GetLocation ($3), GetLocation ($4)); + } else { + lbag.AddLocation (ai, GetLocation ($4)); + } + $$ = ai; + } + ; + +variable_initializer_list + : variable_initializer + { + var list = new List (4); + list.Add ((Expression) $1); + $$ = list; + } + | variable_initializer_list COMMA variable_initializer + { + var list = (List) $1; + list.Add ((Expression) $3); + lbag.AppendTo (list, GetLocation ($2)); + $$ = list; + } + ; + +typeof_expression + : TYPEOF + { + lexer.TypeOfParsing = true; + } + open_parens_any typeof_type_expression CLOSE_PARENS + { + lexer.TypeOfParsing = false; + $$ = new TypeOf ((FullNamedExpression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + ; + +typeof_type_expression + : type_and_void + | unbound_type_name + | error + { + Error_TypeExpected (lexer.Location); + $$ = null; + } + ; + +unbound_type_name + : IDENTIFIER generic_dimension + { + var lt = (Tokenizer.LocatedToken) $1; + + $$ = new SimpleName (lt.Value, (int) $2, lt.Location); + } + | qualified_alias_member IDENTIFIER generic_dimension + { + var lt1 = (Tokenizer.LocatedToken) $1; + var lt2 = (Tokenizer.LocatedToken) $2; + + $$ = new QualifiedAliasMember (lt1.Value, lt2.Value, (int) $3, lt1.Location); + lbag.AddLocation ($$, GetLocation ($2)); + } + | unbound_type_name DOT IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + + $$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location); + } + | unbound_type_name DOT IDENTIFIER generic_dimension + { + var lt = (Tokenizer.LocatedToken) $3; + + $$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location); + } + | namespace_or_type_name DOT IDENTIFIER generic_dimension + { + var te = ((MemberName) $1).GetTypeExpression (); + if (te.HasTypeArguments) + Error_TypeExpected (GetLocation ($4)); + + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess (te, lt.Value, (int) $4, lt.Location); + } + ; + +generic_dimension + : GENERIC_DIMENSION + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "generics"); + + $$ = $1; + } + ; + +qualified_alias_member + : IDENTIFIER DOUBLE_COLON + { + var lt = (Tokenizer.LocatedToken) $1; + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (lt.Location, "namespace alias qualifier"); + + $$ = lt; + } + ; + +sizeof_expression + : SIZEOF open_parens_any type CLOSE_PARENS + { + $$ = new SizeOf ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +checked_expression + : CHECKED open_parens_any expression CLOSE_PARENS + { + $$ = new CheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +unchecked_expression + : UNCHECKED open_parens_any expression CLOSE_PARENS + { + $$ = new UnCheckedExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +pointer_member_access + : primary_expression OP_PTR IDENTIFIER opt_type_argument_list + { + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberAccess (new Indirection ((Expression) $1, GetLocation ($2)), lt.Value, (TypeArguments) $4, lt.Location); + } + ; + +anonymous_method_expression + : DELEGATE opt_anonymous_method_signature + { + start_anonymous (false, (ParametersCompiled) $2, false, GetLocation ($1)); + } + block + { + $$ = end_anonymous ((ParametersBlock) $4); + if ((ParametersCompiled) $2 != ParametersCompiled.Undefined) { + lbag.AddLocation ($$, GetLocation ($1), savedOpenLocation, savedCloseLocation); + } else { + lbag.AddLocation ($$, GetLocation ($1)); + } + } + | ASYNC DELEGATE opt_anonymous_method_signature + { + start_anonymous (false, (ParametersCompiled) $3, true, GetLocation ($1)); + } + block + { + $$ = end_anonymous ((ParametersBlock) $5); + } + ; + +opt_anonymous_method_signature + : + { + $$ = ParametersCompiled.Undefined; + } + | anonymous_method_signature + ; + +anonymous_method_signature + : OPEN_PARENS + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_formal_parameter_list CLOSE_PARENS + { + valid_param_mod = 0; + $$ = $3; + savedOpenLocation = GetLocation ($1); + savedCloseLocation = GetLocation ($2); + } + ; + +default_value_expression + : DEFAULT open_parens_any type CLOSE_PARENS + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($1), "default value expression"); + + $$ = new DefaultValueExpression ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +unary_expression + : primary_expression + | BANG prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.LogicalNot, (Expression) $2, GetLocation ($1)); + } + | TILDE prefixed_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 + { + $$ = new Cast ((FullNamedExpression) $2, (Expression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + ; + +await_expression + : AWAIT unary_expression + { + current_block.ParametersBlock.IsAsync = true; + $$ = new Await ((Expression) $2, GetLocation ($1)); + } + ; + + // + // The idea to split this out is from Rhys' grammar + // to solve the problem with casts. + // +prefixed_unary_expression + : unary_expression + | PLUS prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.UnaryPlus, (Expression) $2, GetLocation ($1)); + } + | MINUS prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.UnaryNegation, (Expression) $2, GetLocation ($1)); + } + | OP_INC prefixed_unary_expression + { + $$ = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) $2, GetLocation ($1)); + } + | OP_DEC prefixed_unary_expression + { + $$ = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) $2, GetLocation ($1)); + } + | STAR prefixed_unary_expression + { + $$ = new Indirection ((Expression) $2, GetLocation ($1)); + } + | BITWISE_AND prefixed_unary_expression + { + $$ = new Unary (Unary.Operator.AddressOf, (Expression) $2, GetLocation ($1)); + } + ; + +multiplicative_expression + : prefixed_unary_expression + | multiplicative_expression STAR prefixed_unary_expression + { + $$ = new Binary (Binary.Operator.Multiply, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | multiplicative_expression DIV prefixed_unary_expression + { + $$ = new Binary (Binary.Operator.Division, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | multiplicative_expression PERCENT prefixed_unary_expression + { + $$ = new Binary (Binary.Operator.Modulus, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +additive_expression + : multiplicative_expression + | additive_expression PLUS multiplicative_expression + { + $$ = new Binary (Binary.Operator.Addition, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | additive_expression MINUS multiplicative_expression + { + $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | parenthesized_expression MINUS multiplicative_expression + { + // Shift/Reduce conflict + $$ = new Binary (Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | additive_expression AS type + { + $$ = new As ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + | additive_expression IS type + { + $$ = new Is ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +shift_expression + : additive_expression + | shift_expression OP_SHIFT_LEFT additive_expression + { + $$ = new Binary (Binary.Operator.LeftShift, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | shift_expression OP_SHIFT_RIGHT additive_expression + { + $$ = new Binary (Binary.Operator.RightShift, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +relational_expression + : shift_expression + | relational_expression OP_LT shift_expression + { + $$ = new Binary (Binary.Operator.LessThan, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | relational_expression OP_GT shift_expression + { + $$ = new Binary (Binary.Operator.GreaterThan, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | relational_expression OP_LE shift_expression + { + $$ = new Binary (Binary.Operator.LessThanOrEqual, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | relational_expression OP_GE shift_expression + { + $$ = new Binary (Binary.Operator.GreaterThanOrEqual, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +equality_expression + : relational_expression + | equality_expression OP_EQ relational_expression + { + $$ = new Binary (Binary.Operator.Equality, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | equality_expression OP_NE relational_expression + { + $$ = new Binary (Binary.Operator.Inequality, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +and_expression + : equality_expression + | and_expression BITWISE_AND equality_expression + { + $$ = new Binary (Binary.Operator.BitwiseAnd, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +exclusive_or_expression + : and_expression + | exclusive_or_expression CARRET and_expression + { + $$ = new Binary (Binary.Operator.ExclusiveOr, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +inclusive_or_expression + : exclusive_or_expression + | inclusive_or_expression BITWISE_OR exclusive_or_expression + { + $$ = new Binary (Binary.Operator.BitwiseOr, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +conditional_and_expression + : inclusive_or_expression + | conditional_and_expression OP_AND inclusive_or_expression + { + $$ = new Binary (Binary.Operator.LogicalAnd, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +conditional_or_expression + : conditional_and_expression + | conditional_or_expression OP_OR conditional_and_expression + { + $$ = new Binary (Binary.Operator.LogicalOr, + (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +null_coalescing_expression + : conditional_or_expression + | conditional_or_expression OP_COALESCING null_coalescing_expression + { + if (lang_version < LanguageVersion.ISO_2) + FeatureIsNotAvailable (GetLocation ($2), "null coalescing operator"); + + $$ = new Nullable.NullCoalescingOperator ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +conditional_expression + : null_coalescing_expression + | null_coalescing_expression INTERR expression COLON expression + { + $$ = new Conditional (new BooleanExpression ((Expression) $1), (Expression) $3, (Expression) $5, GetLocation ($2)); + lbag.AddLocation ($$, GetLocation ($4)); + } + ; + +assignment_expression + : prefixed_unary_expression ASSIGN expression + { + $$ = new SimpleAssign ((Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_MULT_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Multiply, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_DIV_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Division, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_MOD_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Modulus, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_ADD_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Addition, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_SUB_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.Subtraction, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.LeftShift, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.RightShift, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_AND_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.BitwiseAnd, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_OR_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.BitwiseOr, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + | prefixed_unary_expression OP_XOR_ASSIGN expression + { + $$ = new CompoundAssign ( + Binary.Operator.ExclusiveOr, (Expression) $1, (Expression) $3, GetLocation ($2)); + } + ; + +lambda_parameter_list + : lambda_parameter + { + var pars = new List (4); + pars.Add ((Parameter) $1); + + $$ = pars; + } + | lambda_parameter_list COMMA lambda_parameter + { + var pars = (List) $1; + Parameter p = (Parameter)$3; + if (pars[0].GetType () != p.GetType ()) { + report.Error (748, p.Location, "All lambda parameters must be typed either explicitly or implicitly"); + } + + pars.Add (p); + $$ = pars; + } + ; + +lambda_parameter + : parameter_modifier parameter_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + + $$ = new Parameter ((FullNamedExpression) $2, lt.Value, (Parameter.Modifier) $1, null, lt.Location); + } + | parameter_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + + $$ = new Parameter ((FullNamedExpression) $1, lt.Value, Parameter.Modifier.NONE, null, lt.Location); + } + | IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $1; + $$ = new ImplicitLambdaParameter (lt.Value, lt.Location); + } + ; + +opt_lambda_parameter_list + : /* empty */ { $$ = ParametersCompiled.EmptyReadOnlyParameters; } + | lambda_parameter_list { + var pars_list = (List) $1; + $$ = new ParametersCompiled (pars_list.ToArray ()); + } + ; + +lambda_expression_body + : lambda_expression_body_simple + | block + ; + +lambda_expression_body_simple + : { + start_block (lexer.Location); + } + expression_or_error // Have to close block when error occurs + { + Block b = end_block (lexer.Location); + b.IsCompilerGenerated = true; + b.AddStatement (new ContextualReturn ((Expression) $2)); + $$ = b; + } + ; + +expression_or_error + : expression + | error + { + Error_SyntaxError (yyToken); + $$ = EmptyExpression.Null; + } + ; + +lambda_expression + : IDENTIFIER ARROW + { + var lt = (Tokenizer.LocatedToken) $1; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), false, lt.Location); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $4); + lbag.AddLocation ($$, GetLocation ($2)); + } + | ASYNC IDENTIFIER ARROW + { + var lt = (Tokenizer.LocatedToken) $2; + Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); + start_anonymous (true, new ParametersCompiled (p), true, lt.Location); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $5); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + } + | OPEN_PARENS_LAMBDA + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_lambda_parameter_list CLOSE_PARENS ARROW + { + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) $3, false, GetLocation ($1)); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $7); + lbag.AddLocation ($$, GetLocation ($4), GetLocation ($5)); + } + | ASYNC OPEN_PARENS_LAMBDA + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_lambda_parameter_list CLOSE_PARENS ARROW + { + valid_param_mod = 0; + start_anonymous (true, (ParametersCompiled) $4, true, GetLocation ($1)); + } + lambda_expression_body + { + $$ = end_anonymous ((ParametersBlock) $8); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($5), GetLocation ($6)); + } + ; + +expression + : assignment_expression + | non_assignment_expression + ; + +non_assignment_expression + : conditional_expression + | lambda_expression + | query_expression + | ARGLIST + { + $$ = new ArglistAccess (GetLocation ($1)); + } + ; + +undocumented_expressions + : REFVALUE OPEN_PARENS non_assignment_expression COMMA type CLOSE_PARENS + { + $$ = new RefValueExpr ((Expression) $3, (FullNamedExpression) $5, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); + } + | REFTYPE open_parens_any expression CLOSE_PARENS + { + $$ = new RefTypeExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + | MAKEREF open_parens_any expression CLOSE_PARENS + { + $$ = new MakeRefExpr ((Expression) $3, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +constant_expression + : expression + ; + +boolean_expression + : expression + { + $$ = new BooleanExpression ((Expression) $1); + } + ; + +// +// 10 classes +// +class_declaration + : opt_attributes + opt_modifiers + opt_partial + CLASS + { + lexer.ConstraintsParsing = true; + } + type_declaration_name + { + MemberName name = MakeName ((MemberName) $6); + Class c = new Class (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1); + if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { + FeatureIsNotAvailable (c.Location, "static classes"); + } + + push_current_class (c, $3); + } + opt_class_base + opt_type_parameter_constraints_clauses + { + lexer.ConstraintsParsing = false; + + current_class.SetParameterInfo ((List) $9); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + + if (doc_support) { + current_container.DocComment = Lexer.consume_doc_comment (); + Lexer.doc_state = XmlCommentState.Allowed; + } + } + OPEN_BRACE opt_class_member_declarations CLOSE_BRACE + { + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_semicolon + { + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13), GetLocation ($15)); + $$ = pop_current_class (); + } + ; + +opt_partial + : /* empty */ + { $$ = null; } + | PARTIAL + { $$ = $1; StoreModifierLocation (Modifiers.PARTIAL, GetLocation ($1)); } // location + ; + +opt_modifiers + : /* empty */ + { + mod_locations = null; + $$ = ModifierNone; + } + | modifiers + ; + +modifiers + : modifier + | modifiers modifier + { + var m1 = (Modifiers) $1; + var m2 = (Modifiers) $2; + + if ((m1 & m2) != 0) { + report.Error (1004, lexer.Location - ModifiersExtensions.Name (m2).Length, + "Duplicate `{0}' modifier", ModifiersExtensions.Name (m2)); + } else if ((m2 & Modifiers.AccessibilityMask) != 0 && (m1 & Modifiers.AccessibilityMask) != 0 && + ((m2 | m1 & Modifiers.AccessibilityMask) != (Modifiers.PROTECTED | Modifiers.INTERNAL))) { + report.Error (107, lexer.Location - ModifiersExtensions.Name (m2).Length, + "More than one protection modifier specified"); + } + + $$ = m1 | m2; + } + ; + +modifier + : NEW + { + $$ = Modifiers.NEW; + StoreModifierLocation ($$, GetLocation ($1)); + + if (current_container == module) + report.Error (1530, GetLocation ($1), "Keyword `new' is not allowed on namespace elements"); + } + | PUBLIC + { + $$ = Modifiers.PUBLIC; + StoreModifierLocation ($$, GetLocation ($1)); + } + | PROTECTED + { + $$ = Modifiers.PROTECTED; + StoreModifierLocation ($$, GetLocation ($1)); + } + | INTERNAL + { + $$ = Modifiers.INTERNAL; + StoreModifierLocation ($$, GetLocation ($1)); + } + | PRIVATE + { + $$ = Modifiers.PRIVATE; + StoreModifierLocation ($$, GetLocation ($1)); + } + | ABSTRACT + { + $$ = Modifiers.ABSTRACT; + StoreModifierLocation ($$, GetLocation ($1)); + } + | SEALED + { + $$ = Modifiers.SEALED; + StoreModifierLocation ($$, GetLocation ($1)); + } + | STATIC + { + $$ = Modifiers.STATIC; + StoreModifierLocation ($$, GetLocation ($1)); + } + | READONLY + { + $$ = Modifiers.READONLY; + StoreModifierLocation ($$, GetLocation ($1)); + } + | VIRTUAL + { + $$ = Modifiers.VIRTUAL; + StoreModifierLocation ($$, GetLocation ($1)); + } + | OVERRIDE + { + $$ = Modifiers.OVERRIDE; + StoreModifierLocation ($$, GetLocation ($1)); + } + | EXTERN + { + $$ = Modifiers.EXTERN; + StoreModifierLocation ($$, GetLocation ($1)); + } + | VOLATILE + { + $$ = Modifiers.VOLATILE; + StoreModifierLocation ($$, GetLocation ($1)); + } + | UNSAFE + { + $$ = Modifiers.UNSAFE; + StoreModifierLocation ($$, GetLocation ($1)); + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation ($1)); + } + | ASYNC + { + $$ = Modifiers.ASYNC; + StoreModifierLocation ($$, GetLocation ($1)); + } + ; + +opt_class_base + : /* empty */ + | COLON type_list + { + current_container.AddBasesForPart (current_class, (List) $2); + } + ; + +opt_type_parameter_constraints_clauses + : /* empty */ + | type_parameter_constraints_clauses + { + $$ = $1; + } + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +type_parameter_constraints_clauses + : type_parameter_constraints_clause + { + var constraints = new List (1); + constraints.Add ((Constraints) $1); + $$ = constraints; + } + | type_parameter_constraints_clauses type_parameter_constraints_clause + { + var constraints = (List) $1; + Constraints new_constraint = (Constraints)$2; + + foreach (Constraints c in constraints) { + if (new_constraint.TypeParameter.Value == c.TypeParameter.Value) { + report.Error (409, new_constraint.Location, + "A constraint clause has already been specified for type parameter `{0}'", + new_constraint.TypeParameter.Value); + } + } + + constraints.Add (new_constraint); + $$ = constraints; + } + ; + +type_parameter_constraints_clause + : WHERE IDENTIFIER COLON type_parameter_constraints + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) $4, GetLocation ($1)); + } + ; + +type_parameter_constraints + : type_parameter_constraint + { + var constraints = new List (1); + constraints.Add ((FullNamedExpression) $1); + $$ = constraints; + } + | type_parameter_constraints COMMA type_parameter_constraint + { + var constraints = (List) $1; + var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Constructor) != 0) { + report.Error (401, GetLocation ($2), "The `new()' constraint must be the last constraint specified"); + } + + prev = $3 as SpecialContraintExpr; + if (prev != null) { + if ((prev.Constraint & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) { + report.Error (449, prev.Location, "The `class' or `struct' constraint must be the first constraint specified"); + } else { + prev = constraints [0] as SpecialContraintExpr; + if (prev != null && (prev.Constraint & SpecialConstraint.Struct) != 0) { + report.Error (451, GetLocation ($3), "The `new()' constraint cannot be used with the `struct' constraint"); + } + } + } + + constraints.Add ((FullNamedExpression) $3); + $$ = constraints; + } + ; + +type_parameter_constraint + : type + { + if ($1 is ComposedCast) + report.Error (706, GetLocation ($1), "Invalid constraint type `{0}'", ((ComposedCast)$1).GetSignatureForError ()); + + $$ = $1; + } + | NEW OPEN_PARENS CLOSE_PARENS + { + $$ = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3)); + } + | CLASS + { + $$ = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation ($1)); + } + | STRUCT + { + $$ = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation ($1)); + } + ; + +opt_type_parameter_variance + : /* empty */ + { + $$ = Variance.None; + } + | type_parameter_variance + { + if (lang_version <= LanguageVersion.V_3) + FeatureIsNotAvailable (lexer.Location, "generic type variance"); + + $$ = $1; + } + ; + +type_parameter_variance + : OUT + { + $$ = Variance.Covariant; + } + | IN + { + $$ = Variance.Contravariant; + } + ; + +// +// Statements (8.2) +// + +// +// A block is "contained" on the following places: +// method_body +// property_declaration as part of the accessor body (get/set) +// operator_declaration +// constructor_declaration +// destructor_declaration +// event_declaration as part of add_accessor_declaration or remove_accessor_declaration +// +block + : OPEN_BRACE + { + ++lexer.parsing_block; + start_block (GetLocation ($1)); + } + opt_statement_list block_end + { + $$ = $4; + } + ; + +block_end + : CLOSE_BRACE + { + --lexer.parsing_block; + $$ = end_block (GetLocation ($1)); + } + | COMPLETE_COMPLETION + { + --lexer.parsing_block; + $$ = end_block (lexer.Location); + } + ; + + +block_prepared + : OPEN_BRACE + { + ++lexer.parsing_block; + current_block.StartLocation = GetLocation ($1); + } + opt_statement_list CLOSE_BRACE + { + --lexer.parsing_block; + $$ = end_block (GetLocation ($4)); + } + ; + +opt_statement_list + : /* empty */ + | statement_list + ; + +statement_list + : statement + | statement_list statement + ; + +statement + : block_variable_declaration + { + current_block.AddStatement ((Statement) $1); + } + | valid_declaration_statement + { + current_block.AddStatement ((Statement) $1); + } + | labeled_statement + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +// +// The interactive_statement and its derivatives are only +// used to provide a special version of `expression_statement' +// that has a side effect of assigning the expression to +// $retval +// +interactive_statement_list + : interactive_statement + | interactive_statement_list interactive_statement + ; + +interactive_statement + : block_variable_declaration + { + current_block.AddStatement ((Statement) $1); + } + | interactive_valid_declaration_statement + { + current_block.AddStatement ((Statement) $1); + } + | labeled_statement + ; + +valid_declaration_statement + : block + | empty_statement + | expression_statement + | selection_statement + | iteration_statement + | jump_statement + | try_statement + | checked_statement + | unchecked_statement + | lock_statement + | using_statement + | unsafe_statement + | fixed_statement + ; + +interactive_valid_declaration_statement + : block + | empty_statement + | interactive_expression_statement + | selection_statement + | iteration_statement + | jump_statement + | try_statement + | checked_statement + | unchecked_statement + | lock_statement + | using_statement + | unsafe_statement + | fixed_statement + ; + +embedded_statement + : valid_declaration_statement + | block_variable_declaration + { + report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); + $$ = null; + } + | labeled_statement + { + report.Error (1023, GetLocation ($1), "An embedded statement may not be a declaration or labeled statement"); + $$ = null; + } + | error + { + Error_SyntaxError (yyToken); + $$ = new EmptyStatement (GetLocation ($1)); + } + ; + +empty_statement + : SEMICOLON + { + // Uses lexer.Location because semicolon location is not kept in quick mode + $$ = new EmptyStatement (lexer.Location); + } + ; + +labeled_statement + : IDENTIFIER COLON + { + var lt = (Tokenizer.LocatedToken) $1; + LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); + + current_block.AddLabel (labeled); + current_block.AddStatement (labeled); + } + statement + ; + +variable_type + : variable_type_simple + | variable_type_simple rank_specifiers + { + if ($1 is VarExpr) + $1 = new SimpleName ("var", ((VarExpr) $1).Location); + + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + ; + +/* + * The following is from Rhys' grammar: + * > Types in local variable declarations must be recognized as + * > expressions to prevent reduce/reduce errors in the grammar. + * > The expressions are converted into types during semantic analysis. + */ +variable_type_simple + : primary_expression_or_type opt_nullable + { + // Ok, the above "primary_expression" is there to get rid of + // both reduce/reduce and shift/reduces in the grammar, it should + // really just be "type_name". If you use type_name, a reduce/reduce + // creeps up. If you use namespace_or_type_name (which is all we need + // really) two shift/reduces appear. + // + + // So the super-trick is that primary_expression + // can only be either a SimpleName or a MemberAccess. + // The MemberAccess case arises when you have a fully qualified type-name like : + // Foo.Bar.Blah i; + // SimpleName is when you have + // Blah i; + + Expression expr = (Expression) $1; + if ($2 == null) { + SimpleName sn = expr as SimpleName; + if (sn != null && sn.Name == "var") + $$ = new VarExpr (sn.Location); + else + $$ = $1; + } else if (expr is ATypeNameExpression) { + $$ = new ComposedCast ((ATypeNameExpression)expr, (ComposedTypeSpecifier) $2); + } else { + Error_ExpectingTypeName (expr); + $$ = null; + } + } + | primary_expression_or_type pointer_stars + { + ATypeNameExpression expr = $1 as ATypeNameExpression; + + if (expr != null) { + $$ = new ComposedCast (expr, (ComposedTypeSpecifier) $2); + } else { + Error_ExpectingTypeName ((Expression)$1); + $$ = expr; + } + } + | builtin_types opt_nullable + { + if ($2 == null) + $$ = $1; + else + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | builtin_types pointer_stars + { + $$ = new ComposedCast ((FullNamedExpression) $1, (ComposedTypeSpecifier) $2); + } + | VOID pointer_stars + { + $$ = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)), (ComposedTypeSpecifier) $2); + } + | VOID + { + Expression.Error_VoidInvalidInTheContext (GetLocation ($1), report); + $$ = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation ($1)); + } + ; + +pointer_stars + : pointer_star + | pointer_star pointer_stars + { + ((ComposedTypeSpecifier) $1).Next = (ComposedTypeSpecifier) $2; + $$ = $1; + } + ; + +pointer_star + : STAR + { + $$ = ComposedTypeSpecifier.CreatePointer (GetLocation ($1)); + } + ; + +block_variable_declaration + : variable_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) $1, li); + } + opt_local_variable_initializer opt_variable_declarators SEMICOLON + { + $$ = current_variable; + current_variable = null; + lbag.AppendTo ($$, GetLocation ($6)); + } + | CONST variable_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $3; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockConstantDeclaration ((FullNamedExpression) $2, li); + } + const_variable_initializer opt_const_declarators SEMICOLON + { + if (current_variable.Initializer != null) { + lbag.AddLocation (current_variable, GetLocation ($1), savedLocation, GetLocation ($7)); + } else { + lbag.AddLocation (current_variable, GetLocation ($1), GetLocation ($7)); + } + $$ = current_variable;; + current_variable = null; + } + ; + +opt_local_variable_initializer + : /* empty */ + | ASSIGN block_variable_initializer + { + current_variable.Initializer = (Expression) $2; + lbag.AppendTo (current_variable, GetLocation ($1)); + } + | 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"); + } else { + Error_SyntaxError (yyToken); + } + } + ; + +opt_variable_declarators + : /* empty */ + | variable_declarators + ; + +variable_declarators + : variable_declarator + | variable_declarators variable_declarator + ; + +variable_declarator + : COMMA IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, null); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation ($1)); + } + | COMMA IDENTIFIER ASSIGN block_variable_initializer + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) $4); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); + } + ; + +const_variable_initializer + : /* empty */ + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + } + | ASSIGN constant_initializer_expr + { + savedLocation = GetLocation ($1); + current_variable.Initializer = (Expression) $2; + } + ; + +opt_const_declarators + : /* empty */ + | const_declarators + ; + +const_declarators + : const_declarator + | const_declarators const_declarator + ; + +const_declarator + : COMMA IDENTIFIER ASSIGN constant_initializer_expr + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); + var d = new BlockVariableDeclaration.Declarator (li, (Expression) $4); + current_variable.AddDeclarator (d); + current_block.AddLocalName (li); + lbag.AddLocation (d, GetLocation ($1), GetLocation ($3)); + } + ; + +block_variable_initializer + : variable_initializer + | STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET + { + $$ = new StackAlloc ((Expression) $2, (Expression) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($5)); + } + | STACKALLOC simple_type + { + report.Error (1575, GetLocation ($1), "A stackalloc expression requires [] after type"); + $$ = new StackAlloc ((Expression) $2, null, GetLocation ($1)); + } + ; + +expression_statement + : statement_expression SEMICOLON + { + $$ = $1; + lbag.AddStatement ($$, GetLocation ($2)); + } + | statement_expression COMPLETE_COMPLETION { $$ = $1; } + ; + +interactive_expression_statement + : interactive_statement_expression SEMICOLON { $$ = $1; } + | interactive_statement_expression COMPLETE_COMPLETION { $$ = $1; } + ; + + // + // We have to do the wrapping here and not in the case above, + // because statement_expression is used for example in for_statement + // +statement_expression + : expression + { + ExpressionStatement s = $1 as ExpressionStatement; + if (s == null) { + Expression.Error_InvalidExpressionStatement (report, GetLocation ($1)); + $$ = new StatementExpression (EmptyExpressionStatement.Instance); + } else { + $$ = new StatementExpression (s); + } + } + ; + +interactive_statement_expression + : expression + { + Expression expr = (Expression) $1; + ExpressionStatement s; + + s = new OptionalAssign (new SimpleName ("$retval", lexer.Location), expr, lexer.Location); + $$ = new StatementExpression (s); + } + | error + { + Error_SyntaxError (yyToken); + $$ = new EmptyStatement (GetLocation ($1)); + } + ; + +selection_statement + : if_statement + | switch_statement + ; + +if_statement + : IF open_parens_any boolean_expression CLOSE_PARENS + embedded_statement + { + if ($5 is EmptyStatement) + Warning_EmptyStatement (GetLocation ($5)); + + $$ = new If ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + | IF open_parens_any boolean_expression CLOSE_PARENS + embedded_statement ELSE embedded_statement + { + $$ = new If ((BooleanExpression) $3, (Statement) $5, (Statement) $7, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($6)); + + if ($5 is EmptyStatement) + Warning_EmptyStatement (GetLocation ($5)); + if ($7 is EmptyStatement) + Warning_EmptyStatement (GetLocation ($7)); + } + ; + +switch_statement + : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE + { + start_block (GetLocation ($5)); + } + opt_switch_sections CLOSE_BRACE + { + $$ = new Switch ((Expression) $3, (ExplicitBlock) current_block.Explicit, (List) $7, GetLocation ($1)); + end_block (GetLocation ($8)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4), GetLocation ($5), GetLocation ($8)); + } + ; + +opt_switch_sections + : /* empty */ + { + report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); + $$ = new List (); + } + | switch_sections + ; + +switch_sections + : switch_section + { + var sections = new List (4); + + sections.Add ((SwitchSection) $1); + $$ = sections; + } + | switch_sections switch_section + { + var sections = (List) $1; + + sections.Add ((SwitchSection) $2); + $$ = sections; + } + | error + { + Error_SyntaxError (yyToken); + $$ = new List (); + } + ; + +switch_section + : switch_labels + { + current_block = current_block.CreateSwitchBlock (lexer.Location); + } + statement_list + { + $$ = new SwitchSection ((List) $1, current_block); + } + ; + +switch_labels + : switch_label + { + var labels = new List (2); + + labels.Add ((SwitchLabel) $1); + $$ = labels; + } + | switch_labels switch_label + { + var labels = (List) ($1); + labels.Add ((SwitchLabel) $2); + + $$ = labels; + } + ; + +switch_label + : CASE constant_expression COLON + { + $$ = new SwitchLabel ((Expression) $2, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + } + | DEFAULT_COLON + { + $$ = new SwitchLabel (null, GetLocation ($1)); + } + ; + +iteration_statement + : while_statement + | do_statement + | for_statement + | foreach_statement + ; + +while_statement + : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement + { + if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($5)); + + $$ = new While ((BooleanExpression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +do_statement + : DO embedded_statement + WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON + { + $$ = new Do ((Statement) $2, (BooleanExpression) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3), GetLocation ($4), GetLocation ($6), GetLocation ($7)); + } + ; + +for_statement + : FOR open_parens_any + { + start_block (GetLocation ($2)); + current_block.IsCompilerGenerated = true; + } + for_statement_cont + { + $$ = $4; + } + ; + +// Has to use be extra rule to recover started block +for_statement_cont + : opt_for_initializer SEMICOLON + opt_for_condition SEMICOLON + opt_for_iterator CLOSE_PARENS + embedded_statement + { + if ($7 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($7)); + + 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)); + + $$ = end_block (GetLocation ($2)); + } + | error + { + Error_SyntaxError (yyToken); + $$ = end_block (current_block.StartLocation); + } + ; + +opt_for_initializer + : /* empty */ { $$ = new EmptyStatement (lexer.Location); } + | for_initializer + ; + +for_initializer + : variable_type IDENTIFIER + { + var lt = (Tokenizer.LocatedToken) $2; + var li = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (li); + current_variable = new BlockVariableDeclaration ((FullNamedExpression) $1, li); + } + opt_local_variable_initializer opt_variable_declarators + { + $$ = current_variable; + current_variable = null; + } + | statement_expression_list + ; + +opt_for_condition + : /* empty */ { $$ = null; } + | boolean_expression + ; + +opt_for_iterator + : /* empty */ { $$ = new EmptyStatement (lexer.Location); } + | for_iterator + ; + +for_iterator + : statement_expression_list + ; + +statement_expression_list + : statement_expression + | statement_expression_list COMMA statement_expression + { + var sl = $1 as StatementList; + if (sl == null) { + sl = new StatementList ((Statement) $1, (Statement) $3); + lbag.AddStatement (sl, GetLocation ($2)); + } else { + sl.Add ((Statement) $3); + lbag.AppendTo (sl, GetLocation ($2)); + } + + $$ = sl; + } + ; + +foreach_statement + : FOREACH open_parens_any type IN expression CLOSE_PARENS + { + 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 + { + start_block (GetLocation ($2)); + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.ForeachVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + $$ = li; + } + embedded_statement + { + if ($9 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($9)); + + Foreach f = new Foreach ((Expression) $3, (LocalVariable) $8, (Expression) $6, (Statement) $9, GetLocation ($1)); + current_block.AddStatement (f); + + lbag.AddStatement (f, GetLocation ($2), GetLocation ($5), GetLocation ($7)); + $$ = end_block (GetLocation ($7)); + } + ; + +jump_statement + : break_statement + | continue_statement + | goto_statement + | return_statement + | throw_statement + | yield_statement + ; + +break_statement + : BREAK SEMICOLON + { + $$ = new Break (GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2)); + } + ; + +continue_statement + : CONTINUE SEMICOLON + { + $$ = new Continue (GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2)); + } + ; + +goto_statement + : GOTO IDENTIFIER SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $2; + $$ = new Goto (lt.Value, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); + } + | GOTO CASE constant_expression SEMICOLON + { + $$ = new GotoCase ((Expression) $3, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + | GOTO DEFAULT SEMICOLON + { + $$ = new GotoDefault (GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); + } + ; + +return_statement + : RETURN opt_expression SEMICOLON + { + $$ = new Return ((Expression) $2, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3)); + } + ; + +throw_statement + : THROW opt_expression SEMICOLON + { + $$ = new Throw ((Expression) $2, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3)); + } + ; + +yield_statement + : IDENTIFIER RETURN opt_expression SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $1; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if ($3 == null) { + report.Error (1627, GetLocation ($4), "Expression expected after yield return"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + $$ = new Yield ((Expression) $3, lt.Location); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + | IDENTIFIER BREAK SEMICOLON + { + var lt = (Tokenizer.LocatedToken) $1; + string s = lt.Value; + if (s != "yield"){ + report.Error (1003, lt.Location, "; expected"); + } else if (lang_version == LanguageVersion.ISO_1){ + FeatureIsNotAvailable (lt.Location, "iterators"); + } + + current_block.ParametersBlock.TopBlock.IsIterator = true; + $$ = new YieldBreak (lt.Location); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($3)); + } + ; + +opt_expression + : /* empty */ + | expression + ; + +try_statement + : TRY block catch_clauses + { + $$ = new TryCatch ((Block) $2, (List) $3, GetLocation ($1), false); + } + | TRY block FINALLY block + { + $$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($3)); + } + | TRY block catch_clauses FINALLY block + { + $$ = new TryFinally (new TryCatch ((Block) $2, (List) $3, GetLocation ($1), true), (Block) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($4)); + } + | TRY block error + { + report.Error (1524, GetLocation ($1), "Expected catch or finally"); + $$ = null; + } + ; + +catch_clauses + : catch_clause + { + var l = new List (2); + + l.Add ((Catch) $1); + $$ = l; + } + | catch_clauses catch_clause + { + var l = (List) $1; + + Catch c = (Catch) $2; + if (l [0].IsGeneral) { + report.Error (1017, c.loc, "Try statement already has an empty catch block"); + } else { + if (c.IsGeneral) + l.Insert (0, c); + else + l.Add (c); + } + + $$ = l; + } + ; + +opt_identifier + : /* empty */ + | IDENTIFIER + ; + +catch_clause + : CATCH block + { + $$ = new Catch ((Block) $2, GetLocation ($1)); + } + | CATCH open_parens_any type opt_identifier CLOSE_PARENS + { + start_block (GetLocation ($2)); + var c = new Catch (current_block, GetLocation ($1)); + c.TypeExpression = (FullNamedExpression) $3; + + if ($4 != null) { + var lt = (Tokenizer.LocatedToken) $4; + c.Variable = new LocalVariable (current_block, lt.Value, lt.Location); + current_block.AddLocalName (c.Variable); + } + + lbag.AddLocation (c, GetLocation ($2), GetLocation ($5)); + $$ = c; + } + block_prepared + { + $$ = $6; + } + | CATCH open_parens_any error + { + if (yyToken == Token.CLOSE_PARENS) { + report.Error (1015, lexer.Location, + "A type that derives from `System.Exception', `object', or `string' expected"); + } else { + Error_SyntaxError (yyToken); + } + + $$ = new Catch (null, GetLocation ($1)); + } + ; + +checked_statement + : CHECKED block + { + $$ = new Checked ((Block) $2, GetLocation ($1)); + } + ; + +unchecked_statement + : UNCHECKED block + { + $$ = new Unchecked ((Block) $2, GetLocation ($1)); + } + ; + +unsafe_statement + : UNSAFE + { + if (!settings.Unsafe) + Error_UnsafeCodeNotAllowed (GetLocation ($1)); + } block { + $$ = new Unsafe ((Block) $3, GetLocation ($1)); + } + ; + +lock_statement + : LOCK open_parens_any expression CLOSE_PARENS embedded_statement + { + if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($5)); + + $$ = new Lock ((Expression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement ($$, GetLocation ($2), GetLocation ($4)); + } + ; + +fixed_statement + : FIXED open_parens_any variable_type IDENTIFIER + { + start_block (GetLocation ($2)); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.FixedVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) $3, li); + } + using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS + { + $$ = current_variable; + current_variable = null; + } + embedded_statement + { + if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($10)); + + Fixed f = new Fixed ((Fixed.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); + current_block.AddStatement (f); + lbag.AddStatement (f, GetLocation ($2), GetLocation ($8)); + $$ = end_block (GetLocation ($8)); + } + ; + +using_statement + : USING open_parens_any variable_type IDENTIFIER + { + start_block (GetLocation ($2)); + + current_block.IsCompilerGenerated = true; + var lt = (Tokenizer.LocatedToken) $4; + var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.UsingVariable | LocalVariable.Flags.Used, lt.Location); + current_block.AddLocalName (li); + current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li); + } + using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS + { + $$ = current_variable; + current_variable = null; + } + embedded_statement + { + if ($10 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($10)); + + Using u = new Using ((Using.VariableDeclaration) $9, (Statement) $10, GetLocation ($1)); + lbag.AddStatement (u, GetLocation ($2), GetLocation ($8)); + current_block.AddStatement (u); + $$ = end_block (GetLocation ($8)); + } + | USING open_parens_any expression CLOSE_PARENS embedded_statement + { + if ($5 is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) + Warning_EmptyStatement (GetLocation ($5)); + + Using u = new Using ((Expression) $3, (Statement) $5, GetLocation ($1)); + lbag.AddStatement (u, GetLocation ($2), GetLocation ($4)); + $$ = u; + } + ; + +using_or_fixed_variable_initializer + : /* empty */ + { + report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); + } + | ASSIGN variable_initializer + { + current_variable.Initializer = (Expression) $2; + $$ = current_variable; + } + ; + + +// LINQ + +query_expression + : first_from_clause query_body + { + lexer.query_parsing = false; + + Linq.AQueryClause from = $1 as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)$2; + $$ = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + | nested_from_clause query_body + { + Linq.AQueryClause from = $1 as Linq.AQueryClause; + + from.Tail.Next = (Linq.AQueryClause)$2; + $$ = from; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + + // Bubble up COMPLETE_COMPLETION productions + | first_from_clause COMPLETE_COMPLETION { + lexer.query_parsing = false; + $$ = $1; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + | nested_from_clause COMPLETE_COMPLETION { + $$ = $1; + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + ; + +first_from_clause + : FROM_FIRST IDENTIFIER IN expression + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $2; + 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 + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $3; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + } + ); + } + ; + +nested_from_clause + : FROM IDENTIFIER IN expression + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $2; + 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 + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + var lt = (Tokenizer.LocatedToken) $3; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryExpression ( + new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)$5, rv, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + } + ); + } + ; + +from_clause + : FROM IDENTIFIER IN + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + var lt = (Tokenizer.LocatedToken) $2; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$5, GetLocation ($1)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + | FROM type IDENTIFIER IN + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + var lt = (Tokenizer.LocatedToken) $3; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + + $$ = new Linq.SelectMany ((Linq.QueryBlock)current_block, sn, (Expression)$6, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + }; + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + ; + +query_body + : opt_query_body_clauses select_or_group_clause opt_query_continuation + { + Linq.AQueryClause head = (Linq.AQueryClause)$2; + + if ($3 != null) + head.Next = (Linq.AQueryClause)$3; + + if ($1 != null) { + Linq.AQueryClause clause = (Linq.AQueryClause)$1; + clause.Tail.Next = head; + head = clause; + } + + $$ = head; + } + | opt_query_body_clauses COMPLETE_COMPLETION + | error + { + Error_SyntaxError (yyToken); + $$ = null; + } + ; + +select_or_group_clause + : SELECT + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + $$ = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + | GROUP + { + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock)current_block); + } + expression + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + BY expression + { + $$ = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)$3, linq_clause_blocks.Pop (), (Expression)$6, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($5)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + ; + +opt_query_body_clauses + : /* empty */ + | query_body_clauses + ; + +query_body_clauses + : query_body_clause + | query_body_clauses query_body_clause + { + ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$2; + $$ = $1; + } + ; + +query_body_clause + : from_clause + | let_clause + | where_clause + | join_clause + | orderby_clause + ; + +let_clause + : LET IDENTIFIER ASSIGN + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + var lt = (Tokenizer.LocatedToken) $2; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.Let ((Linq.QueryBlock) current_block, sn, (Expression)$5, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + } + ; + +where_clause + : WHERE + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression + { + $$ = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)$3, GetLocation ($1)); + + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + } + ; + +join_clause + : JOIN IDENTIFIER IN + { + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression ON + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression EQUALS + { + current_block.AddStatement (new ContextualReturn ((Expression) $8)); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression opt_join_into + { + current_block.AddStatement (new ContextualReturn ((Expression) $11)); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) $2; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if ($12 == null) { + into = sn; + $$ = new Linq.Join (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9)); + } else { + // + // Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions + // + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) $12; + into = new Linq.RangeVariable (lt.Value, lt.Location); + + $$ = new Linq.GroupJoin (block, sn, (Expression)$5, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3), GetLocation ($6), GetLocation ($9), GetLocation ($12)); + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + | JOIN type IDENTIFIER IN + { + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression ON + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + expression EQUALS + { + current_block.AddStatement (new ContextualReturn ((Expression) $9)); + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + expression opt_join_into + { + current_block.AddStatement (new ContextualReturn ((Expression) $12)); + current_block.SetEndLocation (lexer.Location); + + var outer_selector = linq_clause_blocks.Pop (); + var block = linq_clause_blocks.Pop (); + + var lt = (Tokenizer.LocatedToken) $3; + var sn = new Linq.RangeVariable (lt.Value, lt.Location); + Linq.RangeVariable into; + + if ($13 == null) { + into = sn; + $$ = new Linq.Join (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + }; + } else { + // + // Set equals right side parent to beginning of linq query, it is not accessible therefore cannot cause name collisions + // + var parent = block.Parent; + while (parent is Linq.QueryBlock) { + parent = parent.Parent; + } + current_block.Parent = parent; + + ((Linq.QueryBlock)current_block).AddRangeVariable (sn); + + lt = (Tokenizer.LocatedToken) $13; + into = new Linq.RangeVariable (lt.Value, lt.Location); // TODO: + + $$ = new Linq.GroupJoin (block, sn, (Expression)$6, outer_selector, (Linq.QueryBlock) current_block, into, GetLocation ($1)) { + IdentifierType = (FullNamedExpression)$2 + }; + } + + current_block = block.Parent; + ((Linq.QueryBlock)current_block).AddRangeVariable (into); + } + ; + +opt_join_into + : /* empty */ + | INTO IDENTIFIER + { + $$ = $2; + } + ; + +orderby_clause + : ORDERBY + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + orderings + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + $$ = $3; + } + ; + +orderings + : order_by + | order_by COMMA + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } + orderings_then_by + { + ((Linq.AQueryClause)$1).Next = (Linq.AQueryClause)$4; + $$ = $1; + } + ; + +orderings_then_by + : then_by + | orderings_then_by COMMA + { + current_block.SetEndLocation (lexer.Location); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); + } + then_by + { + ((Linq.AQueryClause)$1).Tail.Next = (Linq.AQueryClause)$4; + $$ = $1; + } + ; + +order_by + : expression + { + $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + } + | expression ASCENDING + { + $$ = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + | expression DESCENDING + { + $$ = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + ; + +then_by + : expression + { + $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + } + | expression ASCENDING + { + $$ = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + | expression DESCENDING + { + $$ = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)$1); + lbag.AddLocation ($$, GetLocation ($2)); + } + ; + + +opt_query_continuation + : /* empty */ + | INTO IDENTIFIER + { + // query continuation block is not linked with query block but with block + // before. This means each query can use same range variable names for + // different identifiers. + + current_block.SetEndLocation (GetLocation ($1)); + current_block = current_block.Parent; + + current_block = new Linq.QueryBlock (current_block, lexer.Location); + + if (linq_clause_blocks == null) + linq_clause_blocks = new Stack (); + + linq_clause_blocks.Push ((Linq.QueryBlock) current_block); + } + query_body + { + var current_block = linq_clause_blocks.Pop (); + var lt = (Tokenizer.LocatedToken) $2; + var rv = new Linq.RangeVariable (lt.Value, lt.Location); + $$ = new Linq.QueryStartClause ((Linq.QueryBlock)current_block, null, rv, GetLocation ($1)) { + next = (Linq.AQueryClause)$4 + }; + } + ; + +// +// Support for using the compiler as an interactive parser +// +// The INTERACTIVE_PARSER token is first sent to parse our +// productions; If the result is a Statement, the parsing +// is repeated, this time with INTERACTIVE_PARSE_WITH_BLOCK +// to setup the blocks in advance. +// +// This setup is here so that in the future we can add +// support for other constructs (type parsing, namespaces, etc) +// that do not require a block to be setup in advance +// + +interactive_parsing + : EVAL_STATEMENT_PARSER EOF + | EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION + | EVAL_STATEMENT_PARSER + { + current_container = new Class (current_namespace, current_class, new MemberName (""), Modifiers.PUBLIC, null); + current_class = current_container; + + // (ref object retval) + Parameter [] mpar = new Parameter [1]; + mpar [0] = new Parameter (new TypeExpression (compiler.BuiltinTypes.Object, Location.Null), "$retval", Parameter.Modifier.REF, null, Location.Null); + + ParametersCompiled pars = new ParametersCompiled (mpar); + var mods = Modifiers.PUBLIC | Modifiers.STATIC; + if (settings.Unsafe) + mods |= Modifiers.UNSAFE; + + current_local_parameters = pars; + Method method = new Method ( + current_class, + null, // generic + new TypeExpression (compiler.BuiltinTypes.Void, Location.Null), + mods, + new MemberName ("Host"), + pars, + null /* attributes */); + + current_container.AddMethod (method); + + oob_stack.Push (method); + ++lexer.parsing_block; + start_block (lexer.Location); + } + interactive_statement_list opt_COMPLETE_COMPLETION + { + --lexer.parsing_block; + Method method = (Method) oob_stack.Pop (); + + method.Block = (ToplevelBlock) end_block(lexer.Location); + + InteractiveResult = (Class) pop_current_class (); + current_local_parameters = null; + } + | EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit + ; + +interactive_compilation_unit + : opt_extern_alias_directives opt_using_directives + | opt_extern_alias_directives opt_using_directives namespace_or_type_declarations + ; + +opt_COMPLETE_COMPLETION + : /* nothing */ + | COMPLETE_COMPLETION + ; + +close_brace_or_complete_completion + : CLOSE_BRACE + | COMPLETE_COMPLETION + ; + +// +// XML documentation code references micro parser +// +documentation_parsing + : DOC_SEE doc_cref + { + module.DocumentationBuilder.ParsedName = (MemberName) $2; + } + ; + +doc_cref + : doc_type_declaration_name opt_doc_method_sig + { + module.DocumentationBuilder.ParsedParameters = (List)$2; + } + | builtin_types opt_doc_method_sig + { + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; + module.DocumentationBuilder.ParsedParameters = (List)$2; + $$ = null; + } + | builtin_types DOT IDENTIFIER opt_doc_method_sig + { + module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)$1; + module.DocumentationBuilder.ParsedParameters = (List)$4; + var lt = (Tokenizer.LocatedToken) $3; + $$ = new MemberName (lt.Value); + } + | doc_type_declaration_name DOT THIS + { + $$ = new MemberName ((MemberName) $1, new MemberName (MemberCache.IndexerNameAlias)); + } + | doc_type_declaration_name DOT THIS OPEN_BRACKET + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_doc_parameters CLOSE_BRACKET + { + module.DocumentationBuilder.ParsedParameters = (List)$6; + $$ = new MemberName ((MemberName) $1, new MemberName (MemberCache.IndexerNameAlias)); + } + | EXPLICIT OPERATOR type opt_doc_method_sig + { + var p = (List)$4 ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) $3)); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Explicit; + $$ = null; + } + | IMPLICIT OPERATOR type opt_doc_method_sig + { + var p = (List)$4 ?? new List (1); + p.Add (new DocumentationParameter ((FullNamedExpression) $3)); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = Operator.OpType.Implicit; + $$ = null; + } + | OPERATOR overloadable_operator opt_doc_method_sig + { + var p = (List)$3 ?? new List (1); + module.DocumentationBuilder.ParsedParameters = p; + module.DocumentationBuilder.ParsedOperator = (Operator.OpType) $2; + $$ = null; + } + ; + +doc_type_declaration_name + : type_declaration_name + | doc_type_declaration_name DOT type_declaration_name + { + $$ = new MemberName (((MemberName) $1), (MemberName) $3); + } + ; + +opt_doc_method_sig + : /* empty */ + | OPEN_PARENS + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } + opt_doc_parameters CLOSE_PARENS + { + $$ = $3; + } + ; + +opt_doc_parameters + : /* empty */ + { + $$ = new List (0); + } + | doc_parameters + ; + +doc_parameters + : doc_parameter + { + var parameters = new List (); + parameters.Add ((DocumentationParameter) $1); + $$ = parameters; + } + | doc_parameters COMMA doc_parameter + { + var parameters = $1 as List; + parameters.Add ((DocumentationParameter) $3); + $$ = parameters; + } + ; + +doc_parameter + : opt_parameter_modifier parameter_type + { + if ($1 != null) + $$ = new DocumentationParameter ((Parameter.Modifier) $1, (FullNamedExpression) $2); + else + $$ = new DocumentationParameter ((FullNamedExpression) $2); + } + ; + +%% + +// +// A class used to hold info about an operator declarator +// +class OperatorDeclaration { + public readonly Operator.OpType optype; + public readonly FullNamedExpression ret_type; + public readonly Location location; + + public OperatorDeclaration (Operator.OpType op, FullNamedExpression ret_type, Location location) + { + optype = op; + this.ret_type = ret_type; + this.location = location; + } +} + +void Error_ExpectingTypeName (Expression expr) +{ + if (expr is Invocation){ + report.Error (1002, expr.Location, "Expecting `;'"); + } else { + Expression.Error_InvalidExpressionStatement (report, expr.Location); + } +} + +void Error_ParameterModifierNotValid (string modifier, Location loc) +{ + report.Error (631, loc, "The parameter modifier `{0}' is not valid in this context", + modifier); +} + +void Error_DuplicateParameterModifier (Location loc, Parameter.Modifier mod) +{ + report.Error (1107, loc, "Duplicate parameter modifier `{0}'", + Parameter.GetModifierSignature (mod)); +} + +void Error_TypeExpected (Location loc) +{ + report.Error (1031, loc, "Type expected"); +} + +void Error_UnsafeCodeNotAllowed (Location loc) +{ + report.Error (227, loc, "Unsafe code requires the `unsafe' command line option to be specified"); +} + +void Warning_EmptyStatement (Location loc) +{ + report.Warning (642, 3, loc, "Possible mistaken empty statement"); +} + +void Error_NamedArgumentExpected (NamedArgument a) +{ + report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); +} + +void push_current_class (TypeContainer tc, object partial_token) +{ + if (module.Evaluator != null && current_container is ModuleContainer){ + tc.Definition.Modifiers = tc.ModFlags = (tc.ModFlags & ~Modifiers.AccessibilityMask) | Modifiers.PUBLIC; + if (undo == null) + undo = new Undo (); + undo.AddTypeContainer (current_container, tc); + } + + if (partial_token != null) + current_container = current_container.AddPartial (tc); + else + current_container = current_container.AddTypeContainer (tc); + + ++lexer.parsing_declaration; + current_class = tc; + ubag.PushTypeDeclaration (tc); +} + +DeclSpace pop_current_class () +{ + DeclSpace retval = current_class; + + current_class = current_class.Parent; + current_container = current_class.PartialContainer; + ubag.PopTypeDeclaration (); + + return retval; +} + +// +// Given the @class_name name, it creates a fully qualified name +// based on the containing declaration space +// +MemberName +MakeName (MemberName class_name) +{ + Namespace ns = current_namespace.NS; + + if (current_container == module) { + if (ns.Name.Length != 0) + return new MemberName (ns.MemberName, class_name); + else + return class_name; + } else { + return new MemberName (current_container.MemberName, class_name); + } +} + +[System.Diagnostics.Conditional ("FULL_AST")] +void StoreModifierLocation (object token, Location loc) +{ + if (lbag == null) + return; + + if (mod_locations == null) + mod_locations = new List> (); + + mod_locations.Add (Tuple.Create ((Modifiers) token, loc)); +} + +List> GetModifierLocations () +{ + var result = mod_locations; + mod_locations = null; + return result; +} + +string CheckAttributeTarget (string a, Location l) +{ + switch (a) { + case "assembly" : case "module" : case "field" : case "method" : case "param" : case "property" : case "type" : + return a; + } + + report.Warning (658, 1, l, + "`{0}' is invalid attribute target. All attributes in this attribute section will be ignored", a); + return string.Empty; +} + +static bool IsUnaryOperator (Operator.OpType op) +{ + switch (op) { + + case Operator.OpType.LogicalNot: + case Operator.OpType.OnesComplement: + case Operator.OpType.Increment: + case Operator.OpType.Decrement: + case Operator.OpType.True: + case Operator.OpType.False: + case Operator.OpType.UnaryPlus: + case Operator.OpType.UnaryNegation: + return true; + } + return false; +} + +void syntax_error (Location l, string msg) +{ + report.Error (1003, l, "Syntax error, " + msg); +} + +Tokenizer lexer; + +public Tokenizer Lexer { + get { + return lexer; + } +} + +static CSharpParser () +{ + oob_stack = new Stack (); +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file) + : this (reader, file, file.NamespaceContainer.Module.Compiler.Report) +{ +} + +public CSharpParser (SeekableStreamReader reader, CompilationSourceFile file, Report report) +{ + this.file = file; + current_namespace = file.NamespaceContainer; + + this.module = current_namespace.Module; + this.compiler = module.Compiler; + this.settings = compiler.Settings; + this.report = report; + + lang_version = settings.Version; + doc_support = settings.DocumentationFile != null; + current_class = current_namespace.SlaveDeclSpace; + current_container = current_class.PartialContainer; // == RootContest.ToplevelTypes + oob_stack.Clear (); + lexer = new Tokenizer (reader, file, compiler); + + use_global_stacks = true; +} + +public void parse () +{ + eof_token = Token.EOF; + Tokenizer.LocatedToken.Initialize (); + + try { + if (yacc_verbose_flag > 1) + yyparse (lexer, new yydebug.yyDebugSimple ()); + else + yyparse (lexer); + + Tokenizer tokenizer = lexer as Tokenizer; + tokenizer.cleanup (); + } catch (Exception e){ + if (e is yyParser.yyUnexpectedEof) { + Error_SyntaxError (yyToken); + UnexpectedEOF = true; + return; + } + + if (e is yyParser.yyException) { + report.Error (-25, lexer.Location, "Parsing error"); + } else { + // Used by compiler-tester to test internal errors + if (yacc_verbose_flag > 0) + throw; + + report.Error (589, lexer.Location, "Internal compiler error during parsing"); + } + } +} + +void CheckToken (int error, int yyToken, string msg, Location loc) +{ + if (yyToken >= Token.FIRST_KEYWORD && yyToken <= Token.LAST_KEYWORD) + report.Error (error, loc, "{0}: `{1}' is a keyword", msg, GetTokenName (yyToken)); + else + report.Error (error, loc, msg); +} + +string ConsumeStoredComment () +{ + string s = tmpComment; + tmpComment = null; + Lexer.doc_state = XmlCommentState.Allowed; + return s; +} + +void FeatureIsNotAvailable (Location loc, string feature) +{ + report.FeatureIsNotAvailable (compiler, loc, feature); +} + +Location GetLocation (object obj) +{ + var lt = obj as Tokenizer.LocatedToken; + if (lt != null) + return lt.Location; + + var mn = obj as MemberName; + if (mn != null) + return mn.Location; + + var expr = obj as Expression; + if (expr != null) + return expr.Location; + + return lexer.Location; +} + +public LocationsBag LocationsBag { + get { + return lbag; + } + set { + lbag = value; + } +} + +public UsingsBag UsingsBag { + get { + return ubag; + } + set { + ubag = value; + } +} + +void start_block (Location loc) +{ + if (current_block == null) { + current_block = new ToplevelBlock (compiler, current_local_parameters, loc); + parsing_anonymous_method = false; + } else if (parsing_anonymous_method) { + current_block = new ParametersBlock (current_block, current_local_parameters, loc); + parsing_anonymous_method = false; + } else { + current_block = new ExplicitBlock (current_block, loc, Location.Null); + } +} + +Block +end_block (Location loc) +{ + Block retval = current_block.Explicit; + retval.SetEndLocation (loc); + current_block = retval.Parent; + return retval; +} + +void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync, Location loc) +{ + oob_stack.Push (current_anonymous_method); + oob_stack.Push (current_local_parameters); + oob_stack.Push (current_variable); + + current_local_parameters = parameters; + if (isLambda) { + if (lang_version <= LanguageVersion.ISO_2) + FeatureIsNotAvailable (loc, "lambda expressions"); + + current_anonymous_method = new LambdaExpression (isAsync, loc); + } else { + if (lang_version == LanguageVersion.ISO_1) + FeatureIsNotAvailable (loc, "anonymous methods"); + + current_anonymous_method = new AnonymousMethodExpression (isAsync, loc); + } + + // Force the next block to be created as a ToplevelBlock + parsing_anonymous_method = true; +} + +/* + * Completes the anonymous method processing, if lambda_expr is null, this + * means that we have a Statement instead of an Expression embedded + */ +AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) +{ + AnonymousMethodExpression retval; + + current_anonymous_method.Block = anon_block; + retval = current_anonymous_method; + + current_variable = (BlockVariableDeclaration) oob_stack.Pop (); + current_local_parameters = (ParametersCompiled) oob_stack.Pop (); + current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); + + return retval; +} + +void Error_SyntaxError (int token) +{ + Error_SyntaxError (0, token, "Unexpected symbol"); +} + +void Error_SyntaxError (int error_code, int token, string msg) +{ + Lexer.CompleteOnEOF = false; + + // An error message has been reported by tokenizer + if (token == Token.ERROR) + return; + + string symbol = GetSymbolName (token); + string expecting = GetExpecting (); + var loc = lexer.Location - symbol.Length; + + if (error_code == 0) { + if (expecting == "`identifier'") { + if (token > Token.FIRST_KEYWORD && token < Token.LAST_KEYWORD) { + report.Error (1041, loc, "Identifier expected, `{0}' is a keyword", symbol); + return; + } + + error_code = 1001; + expecting = "identifier"; + } else if (expecting == "`)'") { + error_code = 1026; + } else { + error_code = 1525; + } + } + + if (string.IsNullOrEmpty (expecting)) + report.Error (error_code, loc, "{1} `{0}'", symbol, msg); + else + report.Error (error_code, loc, "{2} `{0}', expecting {1}", symbol, expecting, msg); +} + +string GetExpecting () +{ + int [] tokens = yyExpectingTokens (yyExpectingState); + var names = new List (tokens.Length); + bool has_type = false; + bool has_identifier = false; + for (int i = 0; i < tokens.Length; i++){ + int token = tokens [i]; + has_identifier |= token == Token.IDENTIFIER; + + string name = GetTokenName (token); + if (name == "") + continue; + + has_type |= name == "type"; + if (names.Contains (name)) + continue; + + names.Add (name); + } + + // + // Too many tokens to enumerate + // + if (names.Count > 8) + return null; + + if (has_type && has_identifier) + names.Remove ("identifier"); + + if (names.Count == 1) + return "`" + GetTokenName (tokens [0]) + "'"; + + StringBuilder sb = new StringBuilder (); + names.Sort (); + int count = names.Count; + for (int i = 0; i < count; i++){ + bool last = i + 1 == count; + if (last) + sb.Append ("or "); + sb.Append ('`'); + sb.Append (names [i]); + sb.Append (last ? "'" : count < 3 ? "' " : "', "); + } + return sb.ToString (); +} + + +string GetSymbolName (int token) +{ + switch (token){ + case Token.LITERAL: + return ((Constant)lexer.Value).GetValue ().ToString (); + case Token.IDENTIFIER: + return ((Tokenizer.LocatedToken)lexer.Value).Value; + + case Token.BOOL: + return "bool"; + case Token.BYTE: + return "byte"; + case Token.CHAR: + return "char"; + case Token.VOID: + return "void"; + case Token.DECIMAL: + return "decimal"; + case Token.DOUBLE: + return "double"; + case Token.FLOAT: + return "float"; + case Token.INT: + return "int"; + case Token.LONG: + return "long"; + case Token.SBYTE: + return "sbyte"; + case Token.SHORT: + return "short"; + case Token.STRING: + return "string"; + case Token.UINT: + return "uint"; + case Token.ULONG: + return "ulong"; + case Token.USHORT: + return "ushort"; + case Token.OBJECT: + return "object"; + + case Token.PLUS: + return "+"; + case Token.UMINUS: + case Token.MINUS: + return "-"; + case Token.BANG: + return "!"; + case Token.BITWISE_AND: + return "&"; + case Token.BITWISE_OR: + return "|"; + case Token.STAR: + return "*"; + case Token.PERCENT: + return "%"; + case Token.DIV: + return "/"; + case Token.CARRET: + return "^"; + case Token.OP_INC: + return "++"; + case Token.OP_DEC: + return "--"; + case Token.OP_SHIFT_LEFT: + return "<<"; + case Token.OP_SHIFT_RIGHT: + return ">>"; + case Token.OP_LT: + return "<"; + case Token.OP_GT: + return ">"; + case Token.OP_LE: + return "<="; + case Token.OP_GE: + return ">="; + case Token.OP_EQ: + return "=="; + case Token.OP_NE: + return "!="; + case Token.OP_AND: + return "&&"; + case Token.OP_OR: + return "||"; + case Token.OP_PTR: + return "->"; + case Token.OP_COALESCING: + return "??"; + case Token.OP_MULT_ASSIGN: + return "*="; + case Token.OP_DIV_ASSIGN: + return "/="; + case Token.OP_MOD_ASSIGN: + return "%="; + case Token.OP_ADD_ASSIGN: + return "+="; + case Token.OP_SUB_ASSIGN: + return "-="; + case Token.OP_SHIFT_LEFT_ASSIGN: + return "<<="; + case Token.OP_SHIFT_RIGHT_ASSIGN: + return ">>="; + case Token.OP_AND_ASSIGN: + return "&="; + case Token.OP_XOR_ASSIGN: + return "^="; + case Token.OP_OR_ASSIGN: + return "|="; + } + + return GetTokenName (token); +} + +static string GetTokenName (int token) +{ + switch (token){ + case Token.ABSTRACT: + return "abstract"; + case Token.AS: + return "as"; + case Token.ADD: + return "add"; + case Token.ASYNC: + return "async"; + case Token.BASE: + return "base"; + case Token.BREAK: + return "break"; + case Token.CASE: + return "case"; + case Token.CATCH: + return "catch"; + case Token.CHECKED: + return "checked"; + case Token.CLASS: + return "class"; + case Token.CONST: + return "const"; + case Token.CONTINUE: + return "continue"; + case Token.DEFAULT: + return "default"; + case Token.DELEGATE: + return "delegate"; + case Token.DO: + return "do"; + case Token.ELSE: + return "else"; + case Token.ENUM: + return "enum"; + case Token.EVENT: + return "event"; + case Token.EXPLICIT: + return "explicit"; + case Token.EXTERN: + case Token.EXTERN_ALIAS: + return "extern"; + case Token.FALSE: + return "false"; + case Token.FINALLY: + return "finally"; + case Token.FIXED: + return "fixed"; + case Token.FOR: + return "for"; + case Token.FOREACH: + return "foreach"; + case Token.GOTO: + return "goto"; + case Token.IF: + return "if"; + case Token.IMPLICIT: + return "implicit"; + case Token.IN: + return "in"; + case Token.INTERFACE: + return "interface"; + case Token.INTERNAL: + return "internal"; + case Token.IS: + return "is"; + case Token.LOCK: + return "lock"; + case Token.NAMESPACE: + return "namespace"; + case Token.NEW: + return "new"; + case Token.NULL: + return "null"; + case Token.OPERATOR: + return "operator"; + case Token.OUT: + return "out"; + case Token.OVERRIDE: + return "override"; + case Token.PARAMS: + return "params"; + case Token.PRIVATE: + return "private"; + case Token.PROTECTED: + return "protected"; + case Token.PUBLIC: + return "public"; + case Token.READONLY: + return "readonly"; + case Token.REF: + return "ref"; + case Token.RETURN: + return "return"; + case Token.REMOVE: + return "remove"; + case Token.SEALED: + return "sealed"; + case Token.SIZEOF: + return "sizeof"; + case Token.STACKALLOC: + return "stackalloc"; + case Token.STATIC: + return "static"; + case Token.STRUCT: + return "struct"; + case Token.SWITCH: + return "switch"; + case Token.THIS: + return "this"; + case Token.THROW: + return "throw"; + case Token.TRUE: + return "true"; + case Token.TRY: + return "try"; + case Token.TYPEOF: + return "typeof"; + case Token.UNCHECKED: + return "unchecked"; + case Token.UNSAFE: + return "unsafe"; + case Token.USING: + return "using"; + case Token.VIRTUAL: + return "virtual"; + case Token.VOLATILE: + return "volatile"; + case Token.WHERE: + return "where"; + case Token.WHILE: + return "while"; + case Token.ARGLIST: + return "__arglist"; + case Token.REFVALUE: + return "__refvalue"; + case Token.REFTYPE: + return "__reftype"; + case Token.MAKEREF: + return "__makeref"; + case Token.PARTIAL: + return "partial"; + case Token.ARROW: + return "=>"; + case Token.FROM: + case Token.FROM_FIRST: + return "from"; + case Token.JOIN: + return "join"; + case Token.ON: + return "on"; + case Token.EQUALS: + return "equals"; + case Token.SELECT: + return "select"; + case Token.GROUP: + return "group"; + case Token.BY: + return "by"; + case Token.LET: + return "let"; + case Token.ORDERBY: + return "orderby"; + case Token.ASCENDING: + return "ascending"; + case Token.DESCENDING: + return "descending"; + case Token.INTO: + return "into"; + case Token.GET: + return "get"; + case Token.SET: + return "set"; + case Token.OPEN_BRACE: + return "{"; + case Token.CLOSE_BRACE: + return "}"; + case Token.OPEN_BRACKET: + case Token.OPEN_BRACKET_EXPR: + return "["; + case Token.CLOSE_BRACKET: + return "]"; + case Token.OPEN_PARENS_CAST: + case Token.OPEN_PARENS_LAMBDA: + case Token.OPEN_PARENS: + return "("; + case Token.CLOSE_PARENS: + return ")"; + case Token.DOT: + return "."; + case Token.COMMA: + return ","; + case Token.DEFAULT_COLON: + return "default:"; + case Token.COLON: + return ":"; + case Token.SEMICOLON: + return ";"; + case Token.TILDE: + return "~"; + + case Token.PLUS: + case Token.UMINUS: + case Token.MINUS: + case Token.BANG: + case Token.OP_LT: + case Token.OP_GT: + case Token.BITWISE_AND: + case Token.BITWISE_OR: + case Token.STAR: + case Token.PERCENT: + case Token.DIV: + case Token.CARRET: + case Token.OP_INC: + case Token.OP_DEC: + case Token.OP_SHIFT_LEFT: + case Token.OP_SHIFT_RIGHT: + case Token.OP_LE: + case Token.OP_GE: + case Token.OP_EQ: + case Token.OP_NE: + case Token.OP_AND: + case Token.OP_OR: + case Token.OP_PTR: + case Token.OP_COALESCING: + case Token.OP_MULT_ASSIGN: + case Token.OP_DIV_ASSIGN: + case Token.OP_MOD_ASSIGN: + case Token.OP_ADD_ASSIGN: + case Token.OP_SUB_ASSIGN: + case Token.OP_SHIFT_LEFT_ASSIGN: + case Token.OP_SHIFT_RIGHT_ASSIGN: + case Token.OP_AND_ASSIGN: + case Token.OP_XOR_ASSIGN: + case Token.OP_OR_ASSIGN: + return ""; + + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.VOID: + case Token.DECIMAL: + case Token.DOUBLE: + case Token.FLOAT: + case Token.INT: + case Token.LONG: + case Token.SBYTE: + case Token.SHORT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + case Token.USHORT: + case Token.OBJECT: + return "type"; + + case Token.ASSIGN: + return "="; + case Token.OP_GENERICS_LT: + case Token.GENERIC_DIMENSION: + return "<"; + case Token.OP_GENERICS_GT: + return ">"; + case Token.INTERR: + case Token.INTERR_NULLABLE: + return "?"; + case Token.DOUBLE_COLON: + return "::"; + case Token.LITERAL: + return "value"; + case Token.IDENTIFIER: + return "identifier"; + + case Token.EOF: + return "end-of-file"; + + // All of these are internal. + case Token.NONE: + case Token.ERROR: + case Token.FIRST_KEYWORD: + case Token.EVAL_COMPILATION_UNIT_PARSER: + case Token.EVAL_USING_DECLARATIONS_UNIT_PARSER: + case Token.EVAL_STATEMENT_PARSER: + case Token.LAST_KEYWORD: + case Token.GENERATE_COMPLETION: + case Token.COMPLETE_COMPLETION: + return ""; + + // A bit more robust. + default: + return yyNames [token]; + } +} + +/* end end end */ +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs new file mode 100644 index 0000000000..6054c44625 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs @@ -0,0 +1,3584 @@ +// +// cs-tokenizer.cs: The Tokenizer for the C# compiler +// This also implements the preprocessor +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// +// +using System; +using System.Text; +using System.Collections.Generic; +using System.Globalization; +using System.Diagnostics; + +namespace Mono.CSharp +{ + /// + /// Tokenizer for C# source code. + /// + public class Tokenizer : yyParser.yyInput + { + class KeywordEntry + { + public readonly T Token; + public KeywordEntry Next; + public readonly char[] Value; + + public KeywordEntry (string value,T token) + { + this.Value = value.ToCharArray (); + this.Token = token; + } + } + + sealed class IdentifiersComparer : IEqualityComparer + { + readonly int length; + + public IdentifiersComparer (int length) + { + this.length = length; + } + + public bool Equals (char[] x, char[] y) + { + for (int i = 0; i < length; ++i) + if (x [i] != y [i]) + return false; + + return true; + } + + public int GetHashCode (char[] obj) + { + int h = 0; + for (int i = 0; i < length; ++i) + h = (h << 5) - h + obj [i]; + + return h; + } + } + + // + // This class has to be used in the parser only, it reuses token + // details after each parse + // + public class LocatedToken + { + int row, column; + string value; + static LocatedToken[] buffer; + static int pos; + + private LocatedToken () + { + } + + public static LocatedToken Create (int row, int column) + { + return Create (null, row, column); + } + + public static LocatedToken Create (string value, int row, int column) + { + // + // TODO: I am not very happy about the logic but it's the best + // what I could come up with for now. + // Ideally we should be using just tiny buffer (256 elements) which + // is enough to hold all details for currect stack and recycle elements + // poped from the stack but there is a trick needed to recycle + // them properly. + // + LocatedToken entry; + if (pos >= buffer.Length) { + entry = new LocatedToken (); + } else { + entry = buffer [pos]; + if (entry == null) { + entry = new LocatedToken (); + buffer [pos] = entry; + } + + ++pos; + } + entry.value = value; + entry.row = row; + entry.column = column; + return entry; + } + + // + // Used for token not required by expression evaluator + // + [Conditional ("FULL_AST")] + public static void CreateOptional (int row, int col, ref object token) + { + token = Create (row, col); + } + + public static void Initialize () + { + if (buffer == null) + buffer = new LocatedToken [10000]; + pos = 0; + } + + public Location Location { + get { return new Location (row, column); } + } + + public string Value { + get { return value; } + } + } + + public enum PreprocessorDirective + { + Invalid = 0, + + Region = 1, + Endregion = 2, + If = 3 | RequiresArgument, + Endif = 4, + Elif = 5 | RequiresArgument, + Else = 6, + Define = 7 | RequiresArgument, + Undef = 8 | RequiresArgument, + Error = 9, + Warning = 10, + Pragma = 11 | CustomArgumentsParsing, + Line = 12, + + CustomArgumentsParsing = 1 << 10, + RequiresArgument = 1 << 11 + } + + SeekableStreamReader reader; + SourceFile ref_name; + CompilationSourceFile file_name; + CompilerContext context; + bool hidden = false; + int ref_line = 1; + int line = 1; + int col = 0; + int previous_col; + int current_token; + int tab_size; + bool handle_get_set = false; + bool handle_remove_add = false; + bool handle_where = false; + bool handle_typeof = false; + bool lambda_arguments_parsing; + List escaped_identifiers; + int parsing_generic_less_than; + readonly bool doc_processing; + + // + // Used mainly for parser optimizations. Some expressions for instance + // can appear only in block (including initializer, base initializer) + // scope only + // + public int parsing_block; + internal bool query_parsing; + + // + // When parsing type only, useful for ambiguous nullable types + // + public int parsing_type; + + // + // Set when parsing generic declaration (type or method header) + // + public bool parsing_generic_declaration; + public bool parsing_generic_declaration_doc; + + // + // The value indicates that we have not reach any declaration or + // namespace yet + // + public int parsing_declaration; + public bool parsing_attribute_section; + + // + // The special characters to inject on streams to run the unit parser + // in the special expression mode. Using private characters from + // Plane Sixteen (U+100000 to U+10FFFD) + // + // This character is only tested just before the tokenizer is about to report + // an error; So on the regular operation mode, this addition will have no + // impact on the tokenizer's performance. + // + + public const int EvalStatementParserCharacter = 0x100000; + public const int EvalCompilationUnitParserCharacter = 0x100001; + public const int EvalUsingDeclarationsParserCharacter = 0x100002; + public const int DocumentationXref = 0x100003; + + // + // XML documentation buffer. The save point is used to divide + // comments on types and comments on members. + // + StringBuilder xml_comment_buffer; + + // + // See comment on XmlCommentState enumeration. + // + XmlCommentState xml_doc_state = XmlCommentState.Allowed; + + // + // Whether tokens have been seen on this line + // + bool tokens_seen = false; + + // + // Set to true once the GENERATE_COMPLETION token has bee + // returned. This helps produce one GENERATE_COMPLETION, + // as many COMPLETE_COMPLETION as necessary to complete the + // AST tree and one final EOF. + // + bool generated; + + // + // Whether a token has been seen on the file + // This is needed because `define' is not allowed to be used + // after a token has been seen. + // + bool any_token_seen; + + // + // Class variables + // + static readonly KeywordEntry[][] keywords; + static readonly KeywordEntry[][] keywords_preprocessor; + static readonly Dictionary keyword_strings; // TODO: HashSet + static readonly NumberStyles styles; + static readonly NumberFormatInfo csharp_format_info; + + // Pragma arguments + static readonly char[] pragma_warning = "warning".ToCharArray (); + static readonly char[] pragma_warning_disable = "disable".ToCharArray (); + static readonly char[] pragma_warning_restore = "restore".ToCharArray (); + static readonly char[] pragma_checksum = "checksum".ToCharArray (); + static readonly char[] simple_whitespaces = new char[] { ' ', '\t' }; + bool startsLine = true; + internal SpecialsBag sbag; + + public bool PropertyParsing { + get { return handle_get_set; } + set { handle_get_set = value; } + } + + public bool EventParsing { + get { return handle_remove_add; } + set { handle_remove_add = value; } + } + + public bool ConstraintsParsing { + get { return handle_where; } + set { handle_where = value; } + } + + public bool TypeOfParsing { + get { return handle_typeof; } + set { handle_typeof = value; } + } + + public int TabSize { + get { return tab_size; } + set { tab_size = value; } + } + + public XmlCommentState doc_state { + get { return xml_doc_state; } + set { + if (value == XmlCommentState.Allowed) { + check_incorrect_doc_comment (); + reset_doc_comment (); + } + xml_doc_state = value; + } + } + + // + // This is used to trigger completion generation on the parser + public bool CompleteOnEOF; + + void AddEscapedIdentifier (Location loc) + { + if (escaped_identifiers == null) + escaped_identifiers = new List (); + + escaped_identifiers.Add (loc); + } + + public bool IsEscapedIdentifier (MemberName name) + { + return escaped_identifiers != null && escaped_identifiers.Contains (name.Location); + } + + // + // Values for the associated token returned + // + internal int putback_char; // Used by repl only + object val; + + // + // Pre-processor + // + const int TAKING = 1; + const int ELSE_SEEN = 4; + const int PARENT_TAKING = 8; + const int REGION = 16; + + // + // pre-processor if stack state: + // + Stack ifstack; + + static System.Text.StringBuilder string_builder; + const int max_id_size = 512; + static readonly char[] id_builder = new char [max_id_size]; + public static Dictionary[] identifiers = new Dictionary[max_id_size + 1]; + const int max_number_size = 512; + static char[] number_builder = new char [max_number_size]; + static int number_pos; + static char[] value_builder = new char[256]; + + public int Line { + get { + return ref_line; + } + } + + // + // This is used when the tokenizer needs to save + // the current position as it needs to do some parsing + // on its own to deamiguate a token in behalf of the + // parser. + // + Stack position_stack = new Stack (2); + + class Position + { + public int position; + public int line; + public int ref_line; + public int col; + public bool hidden; + public int putback_char; + public int previous_col; + public Stack ifstack; + public int parsing_generic_less_than; + public int current_token; + public object val; + + public Position (Tokenizer t) + { + position = t.reader.Position; + line = t.line; + ref_line = t.ref_line; + col = t.col; + hidden = t.hidden; + putback_char = t.putback_char; + previous_col = t.previous_col; + if (t.ifstack != null && t.ifstack.Count != 0) { + // There is no simple way to clone Stack all + // methods reverse the order + var clone = t.ifstack.ToArray (); + Array.Reverse (clone); + ifstack = new Stack (clone); + } + parsing_generic_less_than = t.parsing_generic_less_than; + current_token = t.current_token; + val = t.val; + } + } + + public Tokenizer (SeekableStreamReader input, CompilationSourceFile file, CompilerContext ctx) + { + this.ref_name = file; + this.file_name = file; + this.context = ctx; + reader = input; + + putback_char = -1; + + xml_comment_buffer = new StringBuilder (); + doc_processing = ctx.Settings.DocumentationFile != null; + + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + tab_size = 4; + 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); + } + + public void PushPosition () + { + position_stack.Push (new Position (this)); + } + + public void PopPosition () + { + Position p = position_stack.Pop (); + + reader.Position = p.position; + ref_line = p.ref_line; + line = p.line; + col = p.col; + hidden = p.hidden; + putback_char = p.putback_char; + previous_col = p.previous_col; + ifstack = p.ifstack; + parsing_generic_less_than = p.parsing_generic_less_than; + current_token = p.current_token; + val = p.val; + } + + // Do not reset the position, ignore it. + public void DiscardPosition () + { + position_stack.Pop (); + } + + static void AddKeyword (string kw, int token) + { + keyword_strings.Add (kw, null); + + AddKeyword (keywords, kw, token); +} + + static void AddPreprocessorKeyword (string kw, PreprocessorDirective directive) + { + AddKeyword (keywords_preprocessor, kw, directive); + } + + static void AddKeyword (KeywordEntry[][] keywords, string kw, T token) + { + int length = kw.Length; + if (keywords[length] == null) { + keywords[length] = new KeywordEntry['z' - '_' + 1]; + } + + int char_index = kw[0] - '_'; + var kwe = keywords[length][char_index]; + if (kwe == null) { + keywords[length][char_index] = new KeywordEntry (kw, token); + return; + } + + while (kwe.Next != null) { + kwe = kwe.Next; + } + + kwe.Next = new KeywordEntry (kw, token); + } + + // + // Class initializer + // + static Tokenizer () + { + keyword_strings = new Dictionary (); + + // 11 is the length of the longest keyword for now + keywords = new KeywordEntry[11][]; + + AddKeyword ("__arglist", Token.ARGLIST); + AddKeyword ("__makeref", Token.MAKEREF); + AddKeyword ("__reftype", Token.REFTYPE); + AddKeyword ("__refvalue", Token.REFVALUE); + AddKeyword ("abstract", Token.ABSTRACT); + AddKeyword ("as", Token.AS); + AddKeyword ("add", Token.ADD); + AddKeyword ("base", Token.BASE); + AddKeyword ("bool", Token.BOOL); + AddKeyword ("break", Token.BREAK); + AddKeyword ("byte", Token.BYTE); + AddKeyword ("case", Token.CASE); + AddKeyword ("catch", Token.CATCH); + AddKeyword ("char", Token.CHAR); + AddKeyword ("checked", Token.CHECKED); + AddKeyword ("class", Token.CLASS); + AddKeyword ("const", Token.CONST); + AddKeyword ("continue", Token.CONTINUE); + AddKeyword ("decimal", Token.DECIMAL); + AddKeyword ("default", Token.DEFAULT); + AddKeyword ("delegate", Token.DELEGATE); + AddKeyword ("do", Token.DO); + AddKeyword ("double", Token.DOUBLE); + AddKeyword ("else", Token.ELSE); + AddKeyword ("enum", Token.ENUM); + AddKeyword ("event", Token.EVENT); + AddKeyword ("explicit", Token.EXPLICIT); + AddKeyword ("extern", Token.EXTERN); + AddKeyword ("false", Token.FALSE); + AddKeyword ("finally", Token.FINALLY); + AddKeyword ("fixed", Token.FIXED); + AddKeyword ("float", Token.FLOAT); + AddKeyword ("for", Token.FOR); + AddKeyword ("foreach", Token.FOREACH); + AddKeyword ("goto", Token.GOTO); + AddKeyword ("get", Token.GET); + AddKeyword ("if", Token.IF); + AddKeyword ("implicit", Token.IMPLICIT); + AddKeyword ("in", Token.IN); + AddKeyword ("int", Token.INT); + AddKeyword ("interface", Token.INTERFACE); + AddKeyword ("internal", Token.INTERNAL); + AddKeyword ("is", Token.IS); + AddKeyword ("lock", Token.LOCK); + AddKeyword ("long", Token.LONG); + AddKeyword ("namespace", Token.NAMESPACE); + AddKeyword ("new", Token.NEW); + AddKeyword ("null", Token.NULL); + AddKeyword ("object", Token.OBJECT); + AddKeyword ("operator", Token.OPERATOR); + AddKeyword ("out", Token.OUT); + AddKeyword ("override", Token.OVERRIDE); + AddKeyword ("params", Token.PARAMS); + AddKeyword ("private", Token.PRIVATE); + AddKeyword ("protected", Token.PROTECTED); + AddKeyword ("public", Token.PUBLIC); + AddKeyword ("readonly", Token.READONLY); + AddKeyword ("ref", Token.REF); + AddKeyword ("remove", Token.REMOVE); + AddKeyword ("return", Token.RETURN); + AddKeyword ("sbyte", Token.SBYTE); + AddKeyword ("sealed", Token.SEALED); + AddKeyword ("set", Token.SET); + AddKeyword ("short", Token.SHORT); + AddKeyword ("sizeof", Token.SIZEOF); + AddKeyword ("stackalloc", Token.STACKALLOC); + AddKeyword ("static", Token.STATIC); + AddKeyword ("string", Token.STRING); + AddKeyword ("struct", Token.STRUCT); + AddKeyword ("switch", Token.SWITCH); + AddKeyword ("this", Token.THIS); + AddKeyword ("throw", Token.THROW); + AddKeyword ("true", Token.TRUE); + AddKeyword ("try", Token.TRY); + AddKeyword ("typeof", Token.TYPEOF); + AddKeyword ("uint", Token.UINT); + AddKeyword ("ulong", Token.ULONG); + AddKeyword ("unchecked", Token.UNCHECKED); + AddKeyword ("unsafe", Token.UNSAFE); + AddKeyword ("ushort", Token.USHORT); + AddKeyword ("using", Token.USING); + AddKeyword ("virtual", Token.VIRTUAL); + AddKeyword ("void", Token.VOID); + AddKeyword ("volatile", Token.VOLATILE); + AddKeyword ("while", Token.WHILE); + AddKeyword ("partial", Token.PARTIAL); + AddKeyword ("where", Token.WHERE); + + // LINQ keywords + AddKeyword ("from", Token.FROM); + AddKeyword ("join", Token.JOIN); + AddKeyword ("on", Token.ON); + AddKeyword ("equals", Token.EQUALS); + AddKeyword ("select", Token.SELECT); + AddKeyword ("group", Token.GROUP); + AddKeyword ("by", Token.BY); + AddKeyword ("let", Token.LET); + AddKeyword ("orderby", Token.ORDERBY); + AddKeyword ("ascending", Token.ASCENDING); + AddKeyword ("descending", Token.DESCENDING); + AddKeyword ("into", Token.INTO); + + // Contextual async keywords + AddKeyword ("async", Token.ASYNC); + AddKeyword ("await", Token.AWAIT); + + keywords_preprocessor = new KeywordEntry[10][]; + + AddPreprocessorKeyword ("region", PreprocessorDirective.Region); + AddPreprocessorKeyword ("endregion", PreprocessorDirective.Endregion); + AddPreprocessorKeyword ("if", PreprocessorDirective.If); + AddPreprocessorKeyword ("endif", PreprocessorDirective.Endif); + AddPreprocessorKeyword ("elif", PreprocessorDirective.Elif); + AddPreprocessorKeyword ("else", PreprocessorDirective.Else); + AddPreprocessorKeyword ("define", PreprocessorDirective.Define); + AddPreprocessorKeyword ("undef", PreprocessorDirective.Undef); + AddPreprocessorKeyword ("error", PreprocessorDirective.Error); + AddPreprocessorKeyword ("warning", PreprocessorDirective.Warning); + AddPreprocessorKeyword ("pragma", PreprocessorDirective.Pragma); + AddPreprocessorKeyword ("line", PreprocessorDirective.Line); + + csharp_format_info = NumberFormatInfo.InvariantInfo; + styles = NumberStyles.Float; + + string_builder = new System.Text.StringBuilder (); + } + + int GetKeyword (char[] id, int id_len) + { + // + // Keywords are stored in an array of arrays grouped by their + // length and then by the first character + // + if (id_len >= keywords.Length || keywords [id_len] == null) + return -1; + + int first_index = id [0] - '_'; + if (first_index > 'z' - '_') + return -1; + + var kwe = keywords [id_len] [first_index]; + if (kwe == null) + return -1; + + int res; + do { + res = kwe.Token; + for (int i = 1; i < id_len; ++i) { + if (id [i] != kwe.Value [i]) { + res = 0; + kwe = kwe.Next; + break; + } + } + } while (res == 0 && kwe != null); + + if (res == 0) + return -1; + + int next_token; + switch (res) { + case Token.GET: + case Token.SET: + if (!handle_get_set) + res = -1; + break; + case Token.REMOVE: + case Token.ADD: + if (!handle_remove_add) + res = -1; + break; + case Token.EXTERN: + if (parsing_declaration == 0) + res = Token.EXTERN_ALIAS; + break; + case Token.DEFAULT: + if (peek_token () == Token.COLON) { + token (); + res = Token.DEFAULT_COLON; + } + break; + case Token.WHERE: + if (!handle_where && !query_parsing) + res = -1; + break; + case Token.FROM: + // + // A query expression is any expression that starts with `from identifier' + // followed by any token except ; , = + // + if (!query_parsing) { + if (lambda_arguments_parsing) { + res = -1; + break; + } + + PushPosition (); + // HACK: to disable generics micro-parser, because PushPosition does not + // store identifiers array + parsing_generic_less_than = 1; + switch (xtoken ()) { + case Token.IDENTIFIER: + case Token.INT: + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.DECIMAL: + case Token.FLOAT: + case Token.LONG: + case Token.OBJECT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + next_token = xtoken (); + if (next_token == Token.SEMICOLON || next_token == Token.COMMA || next_token == Token.EQUALS) + goto default; + + res = Token.FROM_FIRST; + query_parsing = true; + if (context.Settings.Version <= LanguageVersion.ISO_2) + Report.FeatureIsNotAvailable (context, Location, "query expressions"); + break; + case Token.VOID: + Expression.Error_VoidInvalidInTheContext (Location, Report); + break; + default: + PopPosition (); + // HACK: A token is not a keyword so we need to restore identifiers buffer + // which has been overwritten before we grabbed the identifier + id_builder [0] = 'f'; id_builder [1] = 'r'; id_builder [2] = 'o'; id_builder [3] = 'm'; + return -1; + } + PopPosition (); + } + break; + case Token.JOIN: + case Token.ON: + case Token.EQUALS: + case Token.SELECT: + case Token.GROUP: + case Token.BY: + case Token.LET: + case Token.ORDERBY: + case Token.ASCENDING: + case Token.DESCENDING: + case Token.INTO: + if (!query_parsing) + res = -1; + break; + + case Token.USING: + case Token.NAMESPACE: + // TODO: some explanation needed + check_incorrect_doc_comment (); + break; + + case Token.PARTIAL: + if (parsing_block > 0) { + res = -1; + break; + } + + // Save current position and parse next token. + PushPosition (); + + next_token = token (); + bool ok = (next_token == Token.CLASS) || + (next_token == Token.STRUCT) || + (next_token == Token.INTERFACE) || + (next_token == Token.VOID); + + PopPosition (); + + if (ok) { + if (next_token == Token.VOID) { + if (context.Settings.Version <= LanguageVersion.ISO_2) + Report.FeatureIsNotAvailable (context, Location, "partial methods"); + } else if (context.Settings.Version == LanguageVersion.ISO_1) + Report.FeatureIsNotAvailable (context, Location, "partial types"); + + return res; + } + + if (next_token < Token.LAST_KEYWORD) { + Report.Error (267, Location, + "The `partial' modifier can be used only immediately before `class', `struct', `interface', or `void' keyword"); + return token (); + } + + res = -1; + break; + + // TODO: async, it's modifiers context only + case Token.ASYNC: + if (context.Settings.Version != LanguageVersion.Future) { + res = -1; + } + break; + + // TODO: async, it's async block context only + case Token.AWAIT: + if (context.Settings.Version != LanguageVersion.Future) { + res = -1; + } + + break; + } + + return res; + return res; + } + + static PreprocessorDirective GetPreprocessorDirective (char[] id, int id_len) + { + // + // Keywords are stored in an array of arrays grouped by their + // length and then by the first character + // + if (id_len >= keywords_preprocessor.Length || keywords_preprocessor[id_len] == null) + return PreprocessorDirective.Invalid; + + int first_index = id[0] - '_'; + if (first_index > 'z' - '_') + return PreprocessorDirective.Invalid; + + var kwe = keywords_preprocessor[id_len][first_index]; + if (kwe == null) + return PreprocessorDirective.Invalid; + + PreprocessorDirective res = PreprocessorDirective.Invalid; + do { + res = kwe.Token; + for (int i = 1; i < id_len; ++i) { + if (id[i] != kwe.Value[i]) { + res = 0; + kwe = kwe.Next; + break; + } + } + } while (res == PreprocessorDirective.Invalid && kwe != null); + + return res; + } + + public Location Location { + get { + return new Location (ref_line, hidden ? -1 : col); + } + } + + static bool is_identifier_start_character (int c) + { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || Char.IsLetter ((char)c); + } + + static bool is_identifier_part_character (char c) + { + if (c >= 'a' && c <= 'z') + return true; + + if (c >= 'A' && c <= 'Z') + return true; + + if (c == '_' || (c >= '0' && c <= '9')) + return true; + + if (c < 0x80) + return false; + + return Char.IsLetter (c) || Char.GetUnicodeCategory (c) == UnicodeCategory.ConnectorPunctuation; + } + + public static bool IsKeyword (string s) + { + return keyword_strings.ContainsKey (s); + } + + // + // Open parens micro parser. Detects both lambda and cast ambiguity. + // + int TokenizeOpenParens () + { + int ptoken; + current_token = -1; + + int bracket_level = 0; + bool is_type = false; + bool can_be_type = false; + + while (true) { + ptoken = current_token; + token (); + + switch (current_token) { + case Token.CLOSE_PARENS: + token (); + + // + // Expression inside parens is lambda, (int i) => + // + if (current_token == Token.ARROW) + return Token.OPEN_PARENS_LAMBDA; + + // + // Expression inside parens is single type, (int[]) + // + if (is_type) + return Token.OPEN_PARENS_CAST; + + // + // Expression is possible cast, look at next token, (T)null + // + if (can_be_type) { + switch (current_token) { + case Token.OPEN_PARENS: + case Token.BANG: + case Token.TILDE: + case Token.IDENTIFIER: + case Token.LITERAL: + case Token.BASE: + case Token.CHECKED: + case Token.DELEGATE: + case Token.FALSE: + case Token.FIXED: + case Token.NEW: + case Token.NULL: + case Token.SIZEOF: + case Token.THIS: + case Token.THROW: + case Token.TRUE: + case Token.TYPEOF: + case Token.UNCHECKED: + case Token.UNSAFE: + case Token.DEFAULT: + + // + // These can be part of a member access + // + case Token.INT: + case Token.UINT: + case Token.SHORT: + case Token.USHORT: + case Token.LONG: + case Token.ULONG: + case Token.DOUBLE: + case Token.FLOAT: + case Token.CHAR: + case Token.BYTE: + case Token.DECIMAL: + case Token.BOOL: + return Token.OPEN_PARENS_CAST; + } + } + return Token.OPEN_PARENS; + + case Token.DOT: + case Token.DOUBLE_COLON: + if (ptoken != Token.IDENTIFIER && ptoken != Token.OP_GENERICS_GT) + goto default; + + continue; + + case Token.IDENTIFIER: + switch (ptoken) { + case Token.DOT: + if (bracket_level == 0) { + is_type = false; + can_be_type = true; + } + + continue; + case Token.OP_GENERICS_LT: + case Token.COMMA: + case Token.DOUBLE_COLON: + case -1: + if (bracket_level == 0) + can_be_type = true; + continue; + default: + can_be_type = is_type = false; + continue; + } + + case Token.OBJECT: + case Token.STRING: + case Token.BOOL: + case Token.DECIMAL: + case Token.FLOAT: + case Token.DOUBLE: + case Token.SBYTE: + case Token.BYTE: + case Token.SHORT: + case Token.USHORT: + case Token.INT: + case Token.UINT: + case Token.LONG: + case Token.ULONG: + case Token.CHAR: + case Token.VOID: + if (bracket_level == 0) + is_type = true; + continue; + + case Token.COMMA: + if (bracket_level == 0) { + bracket_level = 100; + can_be_type = is_type = false; + } + continue; + + case Token.OP_GENERICS_LT: + case Token.OPEN_BRACKET: + if (bracket_level++ == 0) + is_type = true; + continue; + + case Token.OP_GENERICS_GT: + case Token.CLOSE_BRACKET: + --bracket_level; + continue; + + case Token.INTERR_NULLABLE: + case Token.STAR: + if (bracket_level == 0) + is_type = true; + continue; + + case Token.REF: + case Token.OUT: + can_be_type = is_type = false; + continue; + + default: + return Token.OPEN_PARENS; + } + } + } + + public static bool IsValidIdentifier (string s) + { + if (s == null || s.Length == 0) + return false; + + if (!is_identifier_start_character (s [0])) + return false; + + for (int i = 1; i < s.Length; i ++) + if (! is_identifier_part_character (s [i])) + return false; + + return true; + } + + bool parse_less_than () + { + start: + int the_token = token (); + if (the_token == Token.OPEN_BRACKET) { + do { + the_token = token (); + } while (the_token != Token.CLOSE_BRACKET); + the_token = token (); + } else if (the_token == Token.IN || the_token == Token.OUT) { + the_token = token (); + } + switch (the_token) { + case Token.IDENTIFIER: + case Token.OBJECT: + case Token.STRING: + case Token.BOOL: + case Token.DECIMAL: + case Token.FLOAT: + case Token.DOUBLE: + case Token.SBYTE: + case Token.BYTE: + case Token.SHORT: + case Token.USHORT: + case Token.INT: + case Token.UINT: + case Token.LONG: + case Token.ULONG: + case Token.CHAR: + case Token.VOID: + break; + case Token.OP_GENERICS_GT: + case Token.IN: + case Token.OUT: + return true; + + default: + return false; + } + again: + the_token = token (); + + if (the_token == Token.OP_GENERICS_GT) + return true; + else if (the_token == Token.COMMA || the_token == Token.DOT || the_token == Token.DOUBLE_COLON) + goto start; + else if (the_token == Token.INTERR_NULLABLE || the_token == Token.STAR) + goto again; + else if (the_token == Token.OP_GENERICS_LT) { + if (!parse_less_than ()) + return false; + goto again; + } else if (the_token == Token.OPEN_BRACKET) { + rank_specifiers: + the_token = token (); + if (the_token == Token.CLOSE_BRACKET) + goto again; + else if (the_token == Token.COMMA) + goto rank_specifiers; + return false; + } + + return false; + } + + bool parse_generic_dimension (out int dimension) + { + dimension = 1; + + again: + int the_token = token (); + if (the_token == Token.OP_GENERICS_GT) + return true; + else if (the_token == Token.COMMA) { + dimension++; + goto again; + } + + return false; + } + + public int peek_token () + { + int the_token; + + PushPosition (); + the_token = token (); + PopPosition (); + + return the_token; + } + + // + // Tonizes `?' using custom disambiguous rules to return one + // of following tokens: INTERR_NULLABLE, OP_COALESCING, INTERR + // + // Tricky expression look like: + // + // Foo ? a = x ? b : c; + // + int TokenizePossibleNullableType () + { + if (parsing_block == 0 || parsing_type > 0) + return Token.INTERR_NULLABLE; + + int d = peek_char (); + if (d == '?') { + get_char (); + return Token.OP_COALESCING; + } + + switch (current_token) { + case Token.CLOSE_PARENS: + case Token.TRUE: + case Token.FALSE: + case Token.NULL: + case Token.LITERAL: + return Token.INTERR; + } + + if (d != ' ') { + if (d == ',' || d == ';' || d == '>') + return Token.INTERR_NULLABLE; + if (d == '*' || (d >= '0' && d <= '9')) + return Token.INTERR; + } + + PushPosition (); + current_token = Token.NONE; + int next_token; + switch (xtoken ()) { + case Token.LITERAL: + case Token.TRUE: + case Token.FALSE: + case Token.NULL: + case Token.THIS: + case Token.NEW: + next_token = Token.INTERR; + break; + + case Token.SEMICOLON: + case Token.COMMA: + case Token.CLOSE_PARENS: + case Token.OPEN_BRACKET: + case Token.OP_GENERICS_GT: + case Token.INTERR: + next_token = Token.INTERR_NULLABLE; + break; + + default: + next_token = -1; + break; + } + + if (next_token == -1) { + switch (xtoken ()) { + case Token.COMMA: + case Token.SEMICOLON: + case Token.OPEN_BRACE: + case Token.CLOSE_PARENS: + case Token.IN: + next_token = Token.INTERR_NULLABLE; + break; + + case Token.COLON: + next_token = Token.INTERR; + break; + + default: + int ntoken; + int interrs = 1; + int colons = 0; + // + // All shorcuts failed, do it hard way + // + while ((ntoken = xtoken ()) != Token.EOF) { + if (ntoken == Token.SEMICOLON) + break; + + if (ntoken == Token.COLON) { + if (++colons == interrs) + break; + continue; + } + + if (ntoken == Token.INTERR) { + ++interrs; + continue; + } + } + + next_token = colons != interrs ? Token.INTERR_NULLABLE : Token.INTERR; + break; + } + } + + PopPosition (); + return next_token; + } + + bool decimal_digits (int c) + { + int d; + bool seen_digits = false; + + if (c != -1){ + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = (char) c; + } + + // + // We use peek_char2, because decimal_digits needs to do a + // 2-character look-ahead (5.ToString for example). + // + while ((d = peek_char2 ()) != -1){ + if (d >= '0' && d <= '9'){ + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = (char) d; + get_char (); + seen_digits = true; + } else + break; + } + + return seen_digits; + } + + static bool is_hex (int e) + { + return (e >= '0' && e <= '9') || (e >= 'A' && e <= 'F') || (e >= 'a' && e <= 'f'); + } + + static TypeCode real_type_suffix (int c) + { + switch (c){ + case 'F': case 'f': + return TypeCode.Single; + case 'D': case 'd': + return TypeCode.Double; + case 'M': case 'm': + return TypeCode.Decimal; + default: + return TypeCode.Empty; + } + } + + ILiteralConstant integer_type_suffix (ulong ul, int c, Location loc) + { + bool is_unsigned = false; + bool is_long = false; + + if (c != -1){ + bool scanning = true; + do { + switch (c){ + case 'U': case 'u': + if (is_unsigned) + scanning = false; + is_unsigned = true; + get_char (); + break; + + case 'l': + if (!is_unsigned){ + // + // if we have not seen anything in between + // report this error + // + Report.Warning (78, 4, Location, "The 'l' suffix is easily confused with the digit '1' (use 'L' for clarity)"); + } + + goto case 'L'; + + case 'L': + if (is_long) + scanning = false; + is_long = true; + get_char (); + break; + + default: + scanning = false; + break; + } + c = peek_char (); + } while (scanning); + } + + if (is_long && is_unsigned){ + return new ULongLiteral (context.BuiltinTypes, ul, loc); + } + + if (is_unsigned){ + // uint if possible, or ulong else. + + if ((ul & 0xffffffff00000000) == 0) + return new UIntLiteral (context.BuiltinTypes, (uint) ul, loc); + else + return new ULongLiteral (context.BuiltinTypes, ul, loc); + } else if (is_long){ + // long if possible, ulong otherwise + if ((ul & 0x8000000000000000) != 0) + return new ULongLiteral (context.BuiltinTypes, ul, loc); + else + return new LongLiteral (context.BuiltinTypes, (long) ul, loc); + } else { + // int, uint, long or ulong in that order + if ((ul & 0xffffffff00000000) == 0){ + uint ui = (uint) ul; + + if ((ui & 0x80000000) != 0) + return new UIntLiteral (context.BuiltinTypes, ui, loc); + else + return new IntLiteral (context.BuiltinTypes, (int) ui, loc); + } else { + if ((ul & 0x8000000000000000) != 0) + return new ULongLiteral (context.BuiltinTypes, ul, loc); + else + return new LongLiteral (context.BuiltinTypes, (long) ul, loc); + } + } + } + + // + // given `c' as the next char in the input decide whether + // we need to convert to a special type, and then choose + // the best representation for the integer + // + ILiteralConstant adjust_int (int c, Location loc) + { + try { + if (number_pos > 9){ + ulong ul = (uint) (number_builder [0] - '0'); + + for (int i = 1; i < number_pos; i++){ + ul = checked ((ul * 10) + ((uint)(number_builder [i] - '0'))); + } + + return integer_type_suffix (ul, c, loc); + } else { + uint ui = (uint) (number_builder [0] - '0'); + + for (int i = 1; i < number_pos; i++){ + ui = checked ((ui * 10) + ((uint)(number_builder [i] - '0'))); + } + + return integer_type_suffix (ui, c, loc); + } + } catch (OverflowException) { + Error_NumericConstantTooLong (); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + catch (FormatException) { + Report.Error (1013, Location, "Invalid number"); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + } + + ILiteralConstant adjust_real (TypeCode t, Location loc) + { + string s = new string (number_builder, 0, number_pos); + const string error_details = "Floating-point constant is outside the range of type `{0}'"; + + switch (t){ + case TypeCode.Decimal: + try { + return new DecimalLiteral (context.BuiltinTypes, decimal.Parse (s, styles, csharp_format_info), loc); + } catch (OverflowException) { + Report.Error (594, Location, error_details, "decimal"); + return new DecimalLiteral (context.BuiltinTypes, 0, loc); + } + case TypeCode.Single: + try { + return new FloatLiteral (context.BuiltinTypes, float.Parse (s, styles, csharp_format_info), loc); + } catch (OverflowException) { + Report.Error (594, Location, error_details, "float"); + return new FloatLiteral (context.BuiltinTypes, 0, loc); + } + default: + try { + return new DoubleLiteral (context.BuiltinTypes, double.Parse (s, styles, csharp_format_info), loc); + } catch (OverflowException) { + Report.Error (594, loc, error_details, "double"); + return new DoubleLiteral (context.BuiltinTypes, 0, loc); + } + } + } + + ILiteralConstant handle_hex (Location loc) + { + int d; + ulong ul; + + get_char (); + while ((d = peek_char ()) != -1){ + if (is_hex (d)){ + number_builder [number_pos++] = (char) d; + get_char (); + } else + break; + } + + string s = new String (number_builder, 0, number_pos); + + try { + if (number_pos <= 8) + ul = System.UInt32.Parse (s, NumberStyles.HexNumber); + else + ul = System.UInt64.Parse (s, NumberStyles.HexNumber); + + return integer_type_suffix (ul, peek_char (), loc); + } catch (OverflowException){ + Error_NumericConstantTooLong (); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + catch (FormatException) { + Report.Error (1013, Location, "Invalid number"); + return new IntLiteral (context.BuiltinTypes, 0, loc); + } + } + + // + // Invoked if we know we have .digits or digits + // + int is_number (int c) + { + ILiteralConstant res; + +#if FULL_AST + int read_start = reader.Position - 1; +#endif + number_pos = 0; + var loc = Location; + + if (c >= '0' && c <= '9'){ + if (c == '0'){ + int peek = peek_char (); + + if (peek == 'x' || peek == 'X') { + val = res = handle_hex (loc); +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1); +#endif + + return Token.LITERAL; + } + } + decimal_digits (c); + c = get_char (); + } + + // + // We need to handle the case of + // "1.1" vs "1.string" (LITERAL_FLOAT vs NUMBER DOT IDENTIFIER) + // + bool is_real = false; + if (c == '.'){ + if (decimal_digits ('.')){ + is_real = true; + c = get_char (); + } else { + putback ('.'); + number_pos--; + val = res = adjust_int (-1, loc); + +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start, reader.Position - 1); +#endif + return Token.LITERAL; + } + } + + if (c == 'e' || c == 'E'){ + is_real = true; + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = (char) c; + c = get_char (); + + if (c == '+'){ + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '+'; + c = -1; + } else if (c == '-') { + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '-'; + c = -1; + } else { + if (number_pos == max_number_size) + Error_NumericConstantTooLong (); + number_builder [number_pos++] = '+'; + } + + decimal_digits (c); + c = get_char (); + } + + var type = real_type_suffix (c); + if (type == TypeCode.Empty && !is_real) { + putback (c); + res = adjust_int (c, loc); + } else { + is_real = true; + + if (type == TypeCode.Empty) { + putback (c); + } + + res = adjust_real (type, loc); + } + + val = res; + +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start, reader.Position - (type == TypeCode.Empty ? 1 : 0)); +#endif + + return Token.LITERAL; + } + + // + // Accepts exactly count (4 or 8) hex, no more no less + // + int getHex (int count, out int surrogate, out bool error) + { + int i; + int total = 0; + int c; + int top = count != -1 ? count : 4; + + get_char (); + error = false; + surrogate = 0; + for (i = 0; i < top; i++){ + c = get_char (); + + if (c >= '0' && c <= '9') + c = (int) c - (int) '0'; + else if (c >= 'A' && c <= 'F') + c = (int) c - (int) 'A' + 10; + else if (c >= 'a' && c <= 'f') + c = (int) c - (int) 'a' + 10; + else { + error = true; + return 0; + } + + total = (total * 16) + c; + if (count == -1){ + int p = peek_char (); + if (p == -1) + break; + if (!is_hex ((char)p)) + break; + } + } + + if (top == 8) { + if (total > 0x0010FFFF) { + error = true; + return 0; + } + + if (total >= 0x00010000) { + surrogate = ((total - 0x00010000) % 0x0400 + 0xDC00); + total = ((total - 0x00010000) / 0x0400 + 0xD800); + } + } + + return total; + } + + int escape (int c, out int surrogate) + { + bool error; + int d; + int v; + + d = peek_char (); + if (c != '\\') { + surrogate = 0; + return c; + } + + switch (d){ + case 'a': + v = '\a'; break; + case 'b': + v = '\b'; break; + case 'n': + v = '\n'; break; + case 't': + v = '\t'; break; + case 'v': + v = '\v'; break; + case 'r': + v = '\r'; break; + case '\\': + v = '\\'; break; + case 'f': + v = '\f'; break; + case '0': + v = 0; break; + case '"': + v = '"'; break; + case '\'': + v = '\''; break; + case 'x': + v = getHex (-1, out surrogate, out error); + if (error) + goto default; + return v; + case 'u': + case 'U': + return EscapeUnicode (d, out surrogate); + default: + surrogate = 0; + Report.Error (1009, Location, "Unrecognized escape sequence `\\{0}'", ((char)d).ToString ()); + return d; + } + + get_char (); + surrogate = 0; + return v; + } + + int EscapeUnicode (int ch, out int surrogate) + { + bool error; + if (ch == 'U') { + ch = getHex (8, out surrogate, out error); + } else { + ch = getHex (4, out surrogate, out error); + } + + if (error) + Report.Error (1009, Location, "Unrecognized escape sequence"); + + return ch; + } + + int get_char () + { + int x; + if (putback_char != -1) { + x = putback_char; + putback_char = -1; + } else { + x = reader.Read (); + } + + if (x == '\r') { + if (peek_char () == '\n') { + putback_char = -1; + } + + x = '\n'; + advance_line (); + } else if (x == '\n') { + advance_line (); + } else { + col++; + } + return x; + } + + void advance_line () + { + line++; + ref_line++; + previous_col = col; + col = 0; + startsLine = true; + } + + int peek_char () + { + if (putback_char == -1) + putback_char = reader.Read (); + return putback_char; + } + + int peek_char2 () + { + if (putback_char != -1) + return putback_char; + return reader.Peek (); + } + + void putback (int c) + { + if (putback_char != -1){ + Console.WriteLine ("Col: " + col); + Console.WriteLine ("Row: " + line); + Console.WriteLine ("Name: " + ref_name.Name); + Console.WriteLine ("Current [{0}] putting back [{1}] ", putback_char, c); + throw new Exception ("This should not happen putback on putback"); + } + if (c == '\n' || col == 0) { + // It won't happen though. + line--; + ref_line--; + col = previous_col; + } + else + col--; + putback_char = c; + } + + public bool advance () + { + return peek_char () != -1 || CompleteOnEOF; + } + + public Object Value { + get { + return val; + } + } + + public Object value () + { + return val; + } + + public int token () + { + current_token = xtoken (); + return current_token; + } + + int TokenizePreprocessorIdentifier (out int c) + { + int endLine, endCol; + return TokenizePreprocessorIdentifier (out c, out endLine, out endCol); + } + + int TokenizePreprocessorIdentifier (out int c, out int endLine, out int endCol) + { + // skip over white space + do { + c = get_char (); + } while (c == ' ' || c == '\t'); + + endLine = line; + endCol = col; + int pos = 0; + while (c != -1 && c >= 'a' && c <= 'z') { + id_builder[pos++] = (char) c; + endCol = col + 1; + c = get_char (); + if (c == '\\') { + int peek = peek_char (); + if (peek == 'U' || peek == 'u') { + int surrogate; + c = EscapeUnicode (c, out surrogate); + if (surrogate != 0) { + if (is_identifier_part_character ((char) c)) { + id_builder[pos++] = (char) c; + } + c = surrogate; + } + } + } + } + + return pos; + } + + PreprocessorDirective get_cmd_arg (out string arg) + { + int c; + int startLine = line, startCol = col; + + tokens_seen = false; + arg = ""; + + int endLine, endCol; + var cmd = GetPreprocessorDirective (id_builder, TokenizePreprocessorIdentifier (out c, out endLine, out endCol)); + + if ((cmd & PreprocessorDirective.CustomArgumentsParsing) != 0) { + sbag.AddPreProcessorDirective (startLine, startCol, line, col, cmd, null); + return cmd; + } + + + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + + int has_identifier_argument = (int)(cmd & PreprocessorDirective.RequiresArgument); + + int pos = 0; + + while (c != -1 && c != '\n' && c != '\r') { + if (c == '\\' && has_identifier_argument >= 0) { + if (has_identifier_argument != 0) { + has_identifier_argument = 1; + + int peek = peek_char (); + if (peek == 'U' || peek == 'u') { + int surrogate; + c = EscapeUnicode (c, out surrogate); + if (surrogate != 0) { + if (is_identifier_part_character ((char)c)) { + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder [pos++] = (char)c; + } + c = surrogate; + } + } + } else { + has_identifier_argument = -1; + } + } else if (c == '/' && peek_char () == '/') { + // + // Eat single-line comments + // + get_char (); + do { + c = get_char (); + } while (c != -1 && c != '\n'); + + break; + } + + endLine = line; + endCol = col; + + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + c = get_char (); + } + + if (pos != 0) { + if (pos > max_id_size) + arg = new string (value_builder, 0, pos); + else + arg = InternIdentifier (value_builder, pos); + + // Eat any trailing whitespaces + arg = arg.Trim (simple_whitespaces); + } + sbag.AddPreProcessorDirective (startLine, startCol, endLine, endCol, cmd, arg); + + return cmd; + } + + // + // Handles the #line directive + // + bool PreProcessLine (string arg) + { + if (arg.Length == 0) + return false; + + if (arg == "default"){ + ref_line = line; + ref_name = file_name; + hidden = false; + Location.Push (file_name, ref_name); + return true; + } else if (arg == "hidden"){ + hidden = true; + return true; + } + + try { + int pos; + + if ((pos = arg.IndexOf (' ')) != -1 && pos != 0){ + ref_line = System.Int32.Parse (arg.Substring (0, pos)); + pos++; + + char [] quotes = { '\"' }; + + string name = arg.Substring (pos). Trim (quotes); + ref_name = context.LookupFile (file_name, name); + file_name.AddIncludeFile (ref_name); + hidden = false; + Location.Push (file_name, ref_name); + } else { + ref_line = System.Int32.Parse (arg); + hidden = false; + } + } catch { + return false; + } + + return true; + } + + // + // Handles #define and #undef + // + void PreProcessDefinition (bool is_define, string ident, bool caller_is_taking) + { + if (ident.Length == 0 || ident == "true" || ident == "false"){ + Report.Error (1001, Location, "Missing identifier to pre-processor directive"); + return; + } + + if (ident.IndexOfAny (simple_whitespaces) != -1){ + Error_EndLineExpected (); + return; + } + + if (!is_identifier_start_character (ident [0])) + Report.Error (1001, Location, "Identifier expected: {0}", ident); + + foreach (char c in ident.Substring (1)){ + if (!is_identifier_part_character (c)){ + Report.Error (1001, Location, "Identifier expected: {0}", ident); + return; + } + } + + if (!caller_is_taking) + return; + + if (is_define) { + // + // #define ident + // + if (context.Settings.IsConditionalSymbolDefined (ident)) + return; + + file_name.AddDefine (ident); + } else { + // + // #undef ident + // + file_name.AddUndefine (ident); + } + } + + byte read_hex (out bool error) + { + int total; + int c = get_char (); + + if ((c >= '0') && (c <= '9')) + total = (int) c - (int) '0'; + else if ((c >= 'A') && (c <= 'F')) + total = (int) c - (int) 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + total = (int) c - (int) 'a' + 10; + else { + error = true; + return 0; + } + + total *= 16; + c = get_char (); + + if ((c >= '0') && (c <= '9')) + total += (int) c - (int) '0'; + else if ((c >= 'A') && (c <= 'F')) + total += (int) c - (int) 'A' + 10; + else if ((c >= 'a') && (c <= 'f')) + total += (int) c - (int) 'a' + 10; + else { + error = true; + return 0; + } + + error = false; + return (byte) total; + } + + // + // Parses #pragma checksum + // + bool ParsePragmaChecksum () + { + // + // The syntax is ` "foo.txt" "{guid}" "hash"' + // + int c = get_char (); + + if (c != '"') + return false; + + string_builder.Length = 0; + while (c != -1 && c != '\n') { + c = get_char (); + if (c == '"') { + c = get_char (); + break; + } + + string_builder.Append ((char) c); + } + + if (string_builder.Length == 0) { + Report.Warning (1709, 1, Location, "Filename specified for preprocessor directive is empty"); + } + + // TODO: Any white-spaces count + if (c != ' ') + return false; + + SourceFile file = context.LookupFile (file_name, string_builder.ToString ()); + + if (get_char () != '"' || get_char () != '{') + return false; + + bool error; + byte[] guid_bytes = new byte [16]; + int i = 0; + + for (; i < 4; i++) { + guid_bytes [i] = read_hex (out error); + if (error) + return false; + } + + if (get_char () != '-') + return false; + + for (; i < 10; i++) { + guid_bytes [i] = read_hex (out error); + if (error) + return false; + + guid_bytes [i++] = read_hex (out error); + if (error) + return false; + + if (get_char () != '-') + return false; + } + + for (; i < 16; i++) { + guid_bytes [i] = read_hex (out error); + if (error) + return false; + } + + if (get_char () != '}' || get_char () != '"') + return false; + + // TODO: Any white-spaces count + c = get_char (); + if (c != ' ') + return false; + + if (get_char () != '"') + return false; + + // Any length of checksum + List checksum_bytes = new List (16); + + c = peek_char (); + while (c != '"' && c != -1) { + checksum_bytes.Add (read_hex (out error)); + if (error) + return false; + + c = peek_char (); + } + + if (c == '/') { + ReadSingleLineComment (); + } else if (get_char () != '"') { + return false; + } + + file.SetChecksum (guid_bytes, checksum_bytes.ToArray ()); + ref_name.AutoGenerated = true; + return true; + } + + bool IsTokenIdentifierEqual (char[] identifier) + { + for (int i = 0; i < identifier.Length; ++i) { + if (identifier[i] != id_builder[i]) + return false; + } + + return true; + } + + int TokenizePragmaNumber (ref int c) + { + number_pos = 0; + + int number; + + if (c >= '0' && c <= '9') { + decimal_digits (c); + uint ui = (uint) (number_builder[0] - '0'); + + try { + for (int i = 1; i < number_pos; i++) { + ui = checked ((ui * 10) + ((uint) (number_builder[i] - '0'))); + } + + number = (int) ui; + } catch (OverflowException) { + Error_NumericConstantTooLong (); + number = -1; + } + + + c = get_char (); + + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + + if (c == ',') { + c = get_char (); + } + + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + } else { + number = -1; + if (c == '/') { + ReadSingleLineComment (); + } else { + Report.Warning (1692, 1, Location, "Invalid number"); + + // Read everything till the end of the line or file + do { + c = get_char (); + } while (c != -1 && c != '\n'); + } + } + + return number; + } + + + void ReadSingleLineComment () + { + if (peek_char () != '/') + Report.Warning (1696, 1, Location, "Single-line comment or end-of-line expected"); + sbag.StartComment (SpecialsBag.CommentType.Single, startsLine, line, col - 1); + // Read everything till the end of the line or file + int c; + do { + c = get_char (); + sbag.PushCommentChar (c); + var pc = peek_char (); + if (pc == '\n' || pc == -1) + sbag.EndComment (line, col + 1); + } while (c != -1 && c != '\n'); + } + + /// + /// Handles #pragma directive + /// + void ParsePragmaDirective (string arg) + { + int c; + int length = TokenizePreprocessorIdentifier (out c); + if (length == pragma_warning.Length && IsTokenIdentifierEqual (pragma_warning)) { + length = TokenizePreprocessorIdentifier (out c); + + // + // #pragma warning disable + // #pragma warning restore + // + if (length == pragma_warning_disable.Length) { + bool disable = IsTokenIdentifierEqual (pragma_warning_disable); + if (disable || IsTokenIdentifierEqual (pragma_warning_restore)) { + // skip over white space + while (c == ' ' || c == '\t') + c = get_char (); + + var loc = Location; + + if (c == '\n' || c == '/') { + if (c == '/') + ReadSingleLineComment (); + + // + // Disable/Restore all warnings + // + if (disable) { + Report.RegisterWarningRegion (loc).WarningDisable (loc.Row); + } else { + Report.RegisterWarningRegion (loc).WarningEnable (loc.Row); + } + } else { + // + // Disable/Restore a warning or group of warnings + // + int code; + do { + code = TokenizePragmaNumber (ref c); + if (code > 0) { + if (disable) { + Report.RegisterWarningRegion (loc).WarningDisable (loc, code, Report); + } else { + Report.RegisterWarningRegion (loc).WarningEnable (loc, code, Report); + } + } + } while (code >= 0 && c != '\n' && c != -1); + } + + return; + } + } + + Report.Warning (1634, 1, Location, "Expected disable or restore"); + return; + } + + // + // #pragma checksum + // + if (length == pragma_checksum.Length && IsTokenIdentifierEqual (pragma_checksum)) { + if (c != ' ' || !ParsePragmaChecksum ()) { + Report.Warning (1695, 1, Location, + "Invalid #pragma checksum syntax. Expected \"filename\" \"{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}\" \"XXXX...\""); + } + + return; + } + + Report.Warning (1633, 1, Location, "Unrecognized #pragma directive"); + } + + bool eval_val (string s) + { + if (s == "true") + return true; + if (s == "false") + return false; + + return file_name.IsConditionalDefined (context, s); + } + + bool pp_primary (ref string s) + { + s = s.Trim (); + int len = s.Length; + + if (len > 0){ + char c = s [0]; + + if (c == '('){ + s = s.Substring (1); + bool val = pp_expr (ref s, false); + if (s.Length > 0 && s [0] == ')'){ + s = s.Substring (1); + return val; + } + Error_InvalidDirective (); + return false; + } + + if (is_identifier_start_character (c)){ + int j = 1; + + while (j < len){ + c = s [j]; + + if (is_identifier_part_character (c)){ + j++; + continue; + } + bool v = eval_val (s.Substring (0, j)); + s = s.Substring (j); + return v; + } + bool vv = eval_val (s); + s = ""; + return vv; + } + } + Error_InvalidDirective (); + return false; + } + + bool pp_unary (ref string s) + { + s = s.Trim (); + int len = s.Length; + + if (len > 0){ + if (s [0] == '!'){ + if (len > 1 && s [1] == '='){ + Error_InvalidDirective (); + return false; + } + s = s.Substring (1); + return ! pp_primary (ref s); + } else + return pp_primary (ref s); + } else { + Error_InvalidDirective (); + return false; + } + } + + bool pp_eq (ref string s) + { + bool va = pp_unary (ref s); + + s = s.Trim (); + int len = s.Length; + if (len > 0){ + if (s [0] == '='){ + if (len > 2 && s [1] == '='){ + s = s.Substring (2); + return va == pp_unary (ref s); + } else { + Error_InvalidDirective (); + return false; + } + } else if (s [0] == '!' && len > 1 && s [1] == '='){ + s = s.Substring (2); + + return va != pp_unary (ref s); + + } + } + + return va; + + } + + bool pp_and (ref string s) + { + bool va = pp_eq (ref s); + + s = s.Trim (); + int len = s.Length; + if (len > 0){ + if (s [0] == '&'){ + if (len > 2 && s [1] == '&'){ + s = s.Substring (2); + return (va & pp_and (ref s)); + } else { + Error_InvalidDirective (); + return false; + } + } + } + return va; + } + + // + // Evaluates an expression for `#if' or `#elif' + // + bool pp_expr (ref string s, bool isTerm) + { + bool va = pp_and (ref s); + s = s.Trim (); + int len = s.Length; + if (len > 0){ + char c = s [0]; + + if (c == '|'){ + if (len > 2 && s [1] == '|'){ + s = s.Substring (2); + return va | pp_expr (ref s, isTerm); + } else { + Error_InvalidDirective (); + return false; + } + } + if (isTerm) { + Error_EndLineExpected (); + return false; + } + } + + return va; + } + + bool eval (string s) + { + bool v = pp_expr (ref s, true); + s = s.Trim (); + if (s.Length != 0){ + return false; + } + + return v; + } + + void Error_NumericConstantTooLong () + { + Report.Error (1021, Location, "Integral constant is too large"); + } + + void Error_InvalidDirective () + { + Report.Error (1517, Location, "Invalid preprocessor directive"); + } + + void Error_UnexpectedDirective (string extra) + { + Report.Error ( + 1028, Location, + "Unexpected processor directive ({0})", extra); + } + + void Error_TokensSeen () + { + Report.Error (1032, Location, + "Cannot define or undefine preprocessor symbols after first token in file"); + } + + void Eror_WrongPreprocessorLocation () + { + Report.Error (1040, Location, + "Preprocessor directives must appear as the first non-whitespace character on a line"); + } + + void Error_EndLineExpected () + { + Report.Error (1025, Location, "Single-line comment or end-of-line expected"); + } + + // + // Raises a warning when tokenizer found documentation comment + // on unexpected place + // + void WarningMisplacedComment (Location loc) + { + if (doc_state != XmlCommentState.Error) { + doc_state = XmlCommentState.Error; + Report.Warning (1587, 2, loc, "XML comment is not placed on a valid language element"); + } + } + + // + // if true, then the code continues processing the code + // if false, the code stays in a loop until another directive is + // reached. + // When caller_is_taking is false we ignore all directives except the ones + // which can help us to identify where the #if block ends + bool ParsePreprocessingDirective (bool caller_is_taking) + { + string arg; + bool region_directive = false; + + var directive = get_cmd_arg (out arg); + + // + // The first group of pre-processing instructions is always processed + // + switch (directive) { + case PreprocessorDirective.Region: + region_directive = true; + arg = "true"; + goto case PreprocessorDirective.If; + + case PreprocessorDirective.Endregion: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #region for this #endregion"); + return true; + } + int pop = ifstack.Pop (); + + if ((pop & REGION) == 0) + Report.Error (1027, Location, "Expected `#endif' directive"); + + return caller_is_taking; + + case PreprocessorDirective.If: + if (ifstack == null) + ifstack = new Stack (2); + + int flags = region_directive ? REGION : 0; + if (ifstack.Count == 0){ + flags |= PARENT_TAKING; + } else { + int state = ifstack.Peek (); + if ((state & TAKING) != 0) { + flags |= PARENT_TAKING; + } + } + + if (eval (arg) && caller_is_taking) { + ifstack.Push (flags | TAKING); + return true; + } + ifstack.Push (flags); + return false; + + case PreprocessorDirective.Endif: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #if for this #endif"); + return true; + } else { + pop = ifstack.Pop (); + + if ((pop & REGION) != 0) + Report.Error (1038, Location, "#endregion directive expected"); + + if (arg.Length != 0) { + Error_EndLineExpected (); + } + + if (ifstack.Count == 0) + return true; + + int state = ifstack.Peek (); + return (state & TAKING) != 0; + } + + case PreprocessorDirective.Elif: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #if for this #elif"); + return true; + } else { + int state = ifstack.Pop (); + + if ((state & REGION) != 0) { + Report.Error (1038, Location, "#endregion directive expected"); + return true; + } + + if ((state & ELSE_SEEN) != 0){ + Error_UnexpectedDirective ("#elif not valid after #else"); + return true; + } + + if ((state & TAKING) != 0) { + ifstack.Push (0); + return false; + } + + if (eval (arg) && ((state & PARENT_TAKING) != 0)){ + ifstack.Push (state | TAKING); + return true; + } + + ifstack.Push (state); + return false; + } + + case PreprocessorDirective.Else: + if (ifstack == null || ifstack.Count == 0){ + Error_UnexpectedDirective ("no #if for this #else"); + return true; + } else { + int state = ifstack.Peek (); + + if ((state & REGION) != 0) { + Report.Error (1038, Location, "#endregion directive expected"); + return true; + } + + if ((state & ELSE_SEEN) != 0){ + Error_UnexpectedDirective ("#else within #else"); + return true; + } + + ifstack.Pop (); + + if (arg.Length != 0) { + Error_EndLineExpected (); + return true; + } + + bool ret = false; + if ((state & PARENT_TAKING) != 0) { + ret = (state & TAKING) == 0; + + if (ret) + state |= TAKING; + else + state &= ~TAKING; + } + + ifstack.Push (state | ELSE_SEEN); + + return ret; + } + case PreprocessorDirective.Define: + if (any_token_seen){ + Error_TokensSeen (); + return caller_is_taking; + } + PreProcessDefinition (true, arg, caller_is_taking); + return caller_is_taking; + + case PreprocessorDirective.Undef: + if (any_token_seen){ + Error_TokensSeen (); + return caller_is_taking; + } + PreProcessDefinition (false, arg, caller_is_taking); + return caller_is_taking; + + case PreprocessorDirective.Invalid: + Report.Error (1024, Location, "Wrong preprocessor directive"); + return true; + } + + // + // These are only processed if we are in a `taking' block + // + if (!caller_is_taking) + return false; + + switch (directive){ + case PreprocessorDirective.Error: + Report.Error (1029, Location, "#error: '{0}'", arg); + return true; + + case PreprocessorDirective.Warning: + Report.Warning (1030, 1, Location, "#warning: `{0}'", arg); + return true; + + case PreprocessorDirective.Pragma: + if (context.Settings.Version == LanguageVersion.ISO_1) { + Report.FeatureIsNotAvailable (context, Location, "#pragma"); + } + + ParsePragmaDirective (arg); + return true; + + case PreprocessorDirective.Line: + if (!PreProcessLine (arg)) + Report.Error ( + 1576, Location, + "The line number specified for #line directive is missing or invalid"); + return caller_is_taking; + } + + throw new NotImplementedException (directive.ToString ()); + } + + private int consume_string (bool quoted) + { + int c; + int pos = 0; + Location start_location = Location; + if (quoted) + start_location = start_location - 1; + +#if FULL_AST + int reader_pos = reader.Position; +#endif + + while (true){ + c = get_char (); + if (c == '"') { + if (quoted && peek_char () == '"') { + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + get_char (); + continue; + } + + string s; + if (pos == 0) + s = string.Empty; + else if (pos <= 4) + s = InternIdentifier (value_builder, pos); + else + s = new string (value_builder, 0, pos); + + ILiteralConstant res = new StringLiteral (context.BuiltinTypes, s, start_location); + val = res; +#if FULL_AST + 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) { + 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); + if (c == -1) + return Token.ERROR; + if (surrogate != 0) { + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + c = surrogate; + } + } else if (c == -1) { + Report.Error (1039, Location, "Unterminated string literal"); + return Token.EOF; + } + + if (pos == value_builder.Length) + Array.Resize (ref value_builder, pos * 2); + + value_builder[pos++] = (char) c; + } + } + + private int consume_identifier (int s) + { + int res = consume_identifier (s, false); + + if (doc_state == XmlCommentState.Allowed) + doc_state = XmlCommentState.NotAllowed; + startsLine = false; + return res; + } + + int consume_identifier (int c, bool quoted) + { + // + // This method is very performance sensitive. It accounts + // for approximately 25% of all parser time + // + + int pos = 0; + int column = col; + if (quoted) + --column; + + if (c == '\\') { + int surrogate; + c = escape (c, out surrogate); + if (surrogate != 0) { + id_builder [pos++] = (char) c; + c = surrogate; + } + } + + id_builder [pos++] = (char) c; + + try { + while (true) { + c = reader.Read (); + + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9')) { + id_builder [pos++] = (char) c; + continue; + } + + if (c < 0x80) { + if (c == '\\') { + int surrogate; + c = escape (c, out surrogate); + if (is_identifier_part_character ((char) c)) + id_builder[pos++] = (char) c; + + if (surrogate != 0) { + c = surrogate; + } + + continue; + } + } else if (Char.IsLetter ((char) c) || Char.GetUnicodeCategory ((char) c) == UnicodeCategory.ConnectorPunctuation) { + id_builder [pos++] = (char) c; + continue; + } + + putback_char = c; + break; + } + } catch (IndexOutOfRangeException) { + Report.Error (645, Location, "Identifier too long (limit is 512 chars)"); + --pos; + col += pos; + } + + col += pos - 1; + + // + // Optimization: avoids doing the keyword lookup + // on uppercase letters + // + if (id_builder [0] >= '_' && !quoted) { + int keyword = GetKeyword (id_builder, pos); + if (keyword != -1) { + val = LocatedToken.Create (null, ref_line, column); + return keyword; + } + } + + string s = InternIdentifier (id_builder, pos); +#if FULL_AST + if (quoted) { + val = LocatedToken.Create ("@" + s, ref_line, column - 1); + } else { + val = LocatedToken.Create (s, ref_line, column); + } +#else + val = LocatedToken.Create (s, ref_line, column); +#endif + if (quoted && parsing_attribute_section) + AddEscapedIdentifier (((LocatedToken) val).Location); + + return Token.IDENTIFIER; + } + + static string InternIdentifier (char[] charBuffer, int length) + { + // + // Keep identifiers in an array of hashtables to avoid needless + // allocations + // + var identifiers_group = identifiers [length]; + string s; + if (identifiers_group != null) { + if (identifiers_group.TryGetValue (charBuffer, out s)) { + return s; + } + } else { + // TODO: this should be number of files dependant + // corlib compilation peaks at 1000 and System.Core at 150 + int capacity = length > 20 ? 10 : 100; + identifiers_group = new Dictionary (capacity, new IdentifiersComparer (length)); + identifiers [length] = identifiers_group; + } + + char[] chars = new char[length]; + Array.Copy (charBuffer, chars, length); + + s = new string (charBuffer, 0, length); + identifiers_group.Add (chars, s); + + return s; + } + + public int xtoken () + { + int d, c; + + // Whether we have seen comments on the current line + bool comments_seen = false; + while ((c = get_char ()) != -1) { + switch (c) { + case '\t': + col = ((col - 1 + tab_size) / tab_size) * tab_size; + continue; + + case ' ': + case '\f': + case '\v': + case 0xa0: + case 0: + case 0xFEFF: // Ignore BOM anywhere in the file + continue; + +/* This is required for compatibility with .NET + case 0xEF: + if (peek_char () == 0xBB) { + PushPosition (); + get_char (); + if (get_char () == 0xBF) + continue; + PopPosition (); + } + break; +*/ + case '\\': + tokens_seen = true; + return consume_identifier (c); + + case '{': + val = LocatedToken.Create (ref_line, col); + return Token.OPEN_BRACE; + case '}': + val = LocatedToken.Create (ref_line, col); + return Token.CLOSE_BRACE; + case '[': + // To block doccomment inside attribute declaration. + if (doc_state == XmlCommentState.Allowed) + doc_state = XmlCommentState.NotAllowed; + + val = LocatedToken.Create (ref_line, col); + + if (parsing_block == 0 || lambda_arguments_parsing) + return Token.OPEN_BRACKET; + + int next = peek_char (); + switch (next) { + case ']': + case ',': + return Token.OPEN_BRACKET; + + case ' ': + case '\f': + case '\v': + case '\r': + case '\n': + case '/': + next = peek_token (); + if (next == Token.COMMA || next == Token.CLOSE_BRACKET) + return Token.OPEN_BRACKET; + + return Token.OPEN_BRACKET_EXPR; + default: + return Token.OPEN_BRACKET_EXPR; + } + case ']': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.CLOSE_BRACKET; + case '(': + val = LocatedToken.Create (ref_line, col); + // + // An expression versions of parens can appear in block context only + // + if (parsing_block != 0 && !lambda_arguments_parsing) { + + // + // Optmize most common case where we know that parens + // is not special + // + switch (current_token) { + case Token.IDENTIFIER: + case Token.IF: + case Token.FOR: + case Token.FOREACH: + case Token.TYPEOF: + case Token.WHILE: + case Token.USING: + case Token.DEFAULT: + case Token.DELEGATE: + case Token.OP_GENERICS_GT: + return Token.OPEN_PARENS; + } + + // Optimize using peek + int xx = peek_char (); + switch (xx) { + case '(': + case '\'': + case '"': + case '0': + case '1': + return Token.OPEN_PARENS; + } + + lambda_arguments_parsing = true; + PushPosition (); + d = TokenizeOpenParens (); + PopPosition (); + lambda_arguments_parsing = false; + return d; + } + + return Token.OPEN_PARENS; + case ')': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.CLOSE_PARENS; + case ',': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.COMMA; + case ';': + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.SEMICOLON; + case '~': + val = LocatedToken.Create (ref_line, col); + return Token.TILDE; + case '?': + val = LocatedToken.Create (ref_line, col); + return TokenizePossibleNullableType (); + case '<': + val = LocatedToken.Create (ref_line, col); + if (parsing_generic_less_than++ > 0) + return Token.OP_GENERICS_LT; + + return TokenizeLessThan (); + + case '>': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + + if (d == '=') { + get_char (); + return Token.OP_GE; + } + + if (parsing_generic_less_than > 1 || (parsing_generic_less_than == 1 && d != '>')) { + parsing_generic_less_than--; + return Token.OP_GENERICS_GT; + } + + if (d == '>') { + get_char (); + d = peek_char (); + + if (d == '=') { + get_char (); + return Token.OP_SHIFT_RIGHT_ASSIGN; + } + return Token.OP_SHIFT_RIGHT; + } + + return Token.OP_GT; + + case '+': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '+') { + d = Token.OP_INC; + } else if (d == '=') { + d = Token.OP_ADD_ASSIGN; + } else { + return Token.PLUS; + } + get_char (); + return d; + + case '-': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '-') { + d = Token.OP_DEC; + } else if (d == '=') + d = Token.OP_SUB_ASSIGN; + else if (d == '>') + d = Token.OP_PTR; + else { + return Token.MINUS; + } + get_char (); + return d; + + case '!': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '=') { + get_char (); + return Token.OP_NE; + } + return Token.BANG; + + case '=': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '=') { + get_char (); + return Token.OP_EQ; + } + if (d == '>') { + get_char (); + return Token.ARROW; + } + + return Token.ASSIGN; + + case '&': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '&') { + get_char (); + return Token.OP_AND; + } + if (d == '=') { + get_char (); + return Token.OP_AND_ASSIGN; + } + return Token.BITWISE_AND; + + case '|': + val = LocatedToken.Create (ref_line, col); + d = peek_char (); + if (d == '|') { + get_char (); + return Token.OP_OR; + } + if (d == '=') { + get_char (); + return Token.OP_OR_ASSIGN; + } + return Token.BITWISE_OR; + + case '*': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '=') { + get_char (); + return Token.OP_MULT_ASSIGN; + } + return Token.STAR; + + case '/': + d = peek_char (); + if (d == '=') { + val = LocatedToken.Create (ref_line, col); + get_char (); + return Token.OP_DIV_ASSIGN; + } + + // Handle double-slash comments. + if (d == '/') { + get_char (); + if (doc_processing) { + if (peek_char () == '/') { + sbag.StartComment (SpecialsBag.CommentType.Documentation, startsLine, line, col - 1); + get_char (); + // Don't allow ////. + if ((d = peek_char ()) != '/') { + sbag.PushCommentChar (d); + if (doc_state == XmlCommentState.Allowed) + handle_one_line_xml_comment (); + else if (doc_state == XmlCommentState.NotAllowed) + WarningMisplacedComment (Location - 3); + } + } else { + if (xml_comment_buffer.Length > 0) + doc_state = XmlCommentState.NotAllowed; + } + } else { + bool isDoc = peek_char () == '/'; + sbag.StartComment (isDoc ? SpecialsBag.CommentType.Documentation : SpecialsBag.CommentType.Single, startsLine, line, col - 1); + if (isDoc) + get_char (); + } + + d = peek_char (); + if (d == '\n' || d == '\r') + sbag.EndComment (line, col + 1); + + while ((d = get_char ()) != -1 && (d != '\n') && d != '\r') { + sbag.PushCommentChar (d); + var pc = peek_char (); + if (pc == -1 || pc == '\n' || pc == '\r') { + sbag.EndComment (line, col + 1); + } + } + + any_token_seen |= tokens_seen; + tokens_seen = false; + comments_seen = false; + continue; + } else if (d == '*'){ + sbag.StartComment (SpecialsBag.CommentType.Multi, startsLine, line, col); + get_char (); + bool docAppend = false; + if (doc_processing && peek_char () == '*') { + int ch = get_char (); + sbag.PushCommentChar (ch); + // But when it is /**/, just do nothing. + if (peek_char () == '/') { + ch = get_char (); + sbag.PushCommentChar (ch); + sbag.EndComment (line, col + 1); + continue; + } + if (doc_state == XmlCommentState.Allowed) + docAppend = true; + else if (doc_state == XmlCommentState.NotAllowed) { + WarningMisplacedComment (Location - 2); + } + } + + int current_comment_start = 0; + if (docAppend) { + current_comment_start = xml_comment_buffer.Length; + xml_comment_buffer.Append (Environment.NewLine); + } + + while ((d = get_char ()) != -1){ + sbag.PushCommentChar (d); + if (d == '*' && peek_char () == '/'){ + sbag.PushCommentChar ('/'); + get_char (); + sbag.EndComment (line, col + 1); + comments_seen = true; + break; + } + if (docAppend) + xml_comment_buffer.Append ((char) d); + + if (d == '\n'){ + any_token_seen |= tokens_seen; + tokens_seen = false; + // + // Reset 'comments_seen' just to be consistent. + // It doesn't matter either way, here. + // + comments_seen = false; + } + } + + if (!comments_seen) + Report.Error (1035, Location, "End-of-file found, '*/' expected"); + + if (docAppend) + update_formatted_doc_comment (current_comment_start); + continue; + } + val = LocatedToken.Create (ref_line, col); + return Token.DIV; + + case '%': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '='){ + get_char (); + return Token.OP_MOD_ASSIGN; + } + return Token.PERCENT; + + case '^': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == '='){ + get_char (); + return Token.OP_XOR_ASSIGN; + } + return Token.CARRET; + + case ':': + val = LocatedToken.Create (ref_line, col); + if (peek_char () == ':') { + get_char (); + return Token.DOUBLE_COLON; + } + return Token.COLON; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + tokens_seen = true; + return is_number (c); + + case '\n': // white space + any_token_seen |= tokens_seen; + tokens_seen = false; + comments_seen = false; + continue; + + case '.': + tokens_seen = true; + d = peek_char (); + if (d >= '0' && d <= '9') + return is_number (c); + + LocatedToken.CreateOptional (ref_line, col, ref val); + return Token.DOT; + + case '#': + if (tokens_seen || comments_seen) { + Eror_WrongPreprocessorLocation (); + return Token.ERROR; + } + + if (ParsePreprocessingDirective (true)) + continue; + + bool directive_expected = false; + while ((c = get_char ()) != -1) { + if (col == 1) { + directive_expected = true; + } else if (!directive_expected) { + // TODO: Implement comment support for disabled code and uncomment this code +// if (c == '#') { +// Eror_WrongPreprocessorLocation (); +// return Token.ERROR; +// } + continue; + } + + if (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' ) + continue; + + if (c == '#') { + if (ParsePreprocessingDirective (false)) + break; + } + directive_expected = false; + } + + if (c != -1) { + tokens_seen = false; + continue; + } + + return Token.EOF; + + case '"': + return consume_string (false); + + case '\'': + return TokenizeBackslash (); + + case '@': + c = get_char (); + if (c == '"') { + tokens_seen = true; + return consume_string (true); + } + + if (is_identifier_start_character (c)){ + return consume_identifier (c, true); + } + + Report.Error (1646, Location, "Keyword, identifier, or string expected after verbatim specifier: @"); + return Token.ERROR; + + case EvalStatementParserCharacter: + return Token.EVAL_STATEMENT_PARSER; + case EvalCompilationUnitParserCharacter: + return Token.EVAL_COMPILATION_UNIT_PARSER; + case EvalUsingDeclarationsParserCharacter: + return Token.EVAL_USING_DECLARATIONS_UNIT_PARSER; + case DocumentationXref: + return Token.DOC_SEE; + } + + if (is_identifier_start_character (c)) { + tokens_seen = true; + return consume_identifier (c); + } + + if (char.IsWhiteSpace ((char) c)) + continue; + + Report.Error (1056, Location, "Unexpected character `{0}'", ((char) c).ToString ()); + } + + if (CompleteOnEOF){ + if (generated) + return Token.COMPLETE_COMPLETION; + + generated = true; + return Token.GENERATE_COMPLETION; + } + + + return Token.EOF; + } + + int TokenizeBackslash () + { + int c = get_char (); + tokens_seen = true; + if (c == '\'') { + val = new CharLiteral (context.BuiltinTypes, (char) c, Location); + Report.Error (1011, Location, "Empty character literal"); + return Token.LITERAL; + } + + if (c == '\n') { + Report.Error (1010, Location, "Newline in constant"); + return Token.ERROR; + } + + int d; + c = escape (c, out d); + if (c == -1) + return Token.ERROR; + if (d != 0) + throw new NotImplementedException (); + + val = new CharLiteral (context.BuiltinTypes, (char) c, Location); + c = get_char (); + + if (c != '\'') { + Report.Error (1012, Location, "Too many characters in character literal"); + + // Try to recover, read until newline or next "'" + while ((c = get_char ()) != -1) { + if (c == '\n' || c == '\'') + break; + } + } + + return Token.LITERAL; + } + + int TokenizeLessThan () + { + int d; + if (handle_typeof) { + PushPosition (); + if (parse_generic_dimension (out d)) { + val = d; + DiscardPosition (); + return Token.GENERIC_DIMENSION; + } + PopPosition (); + } + + // Save current position and parse next token. + PushPosition (); + if (parse_less_than ()) { + if (parsing_generic_declaration && (parsing_generic_declaration_doc || token () != Token.DOT)) { + d = Token.OP_GENERICS_LT_DECL; + } else { + d = Token.OP_GENERICS_LT; + } + PopPosition (); + return d; + } + + PopPosition (); + parsing_generic_less_than = 0; + + d = peek_char (); + if (d == '<') { + get_char (); + d = peek_char (); + + if (d == '=') { + get_char (); + return Token.OP_SHIFT_LEFT_ASSIGN; + } + return Token.OP_SHIFT_LEFT; + } + + if (d == '=') { + get_char (); + return Token.OP_LE; + } + return Token.OP_LT; + } + + // + // Handles one line xml comment + // + private void handle_one_line_xml_comment () + { + int c; + while ((c = peek_char ()) == ' ') { + sbag.PushCommentChar (c); + get_char (); // skip heading whitespaces. + } + while ((c = peek_char ()) != -1 && c != '\n' && c != '\r') { + sbag.PushCommentChar (c); + xml_comment_buffer.Append ((char) get_char ()); + } + if (c == '\r' || c == '\n') + xml_comment_buffer.Append (Environment.NewLine); + } + + // + // Remove heading "*" in Javadoc-like xml documentation. + // + private void update_formatted_doc_comment (int current_comment_start) + { + int length = xml_comment_buffer.Length - current_comment_start; + string [] lines = xml_comment_buffer.ToString ( + current_comment_start, + length).Replace ("\r", "").Split ('\n'); + + // The first line starts with /**, thus it is not target + // for the format check. + for (int i = 1; i < lines.Length; i++) { + string s = lines [i]; + int idx = s.IndexOf ('*'); + string head = null; + if (idx < 0) { + if (i < lines.Length - 1) + return; + head = s; + } else + head = s.Substring (0, idx); + foreach (char c in head) + if (c != ' ') + return; + lines [i] = s.Substring (idx + 1); + } + xml_comment_buffer.Remove (current_comment_start, length); + xml_comment_buffer.Insert (current_comment_start, String.Join (Environment.NewLine, lines)); + } + + // + // Checks if there was incorrect doc comments and raise + // warnings. + // + public void check_incorrect_doc_comment () + { + if (xml_comment_buffer.Length > 0) + WarningMisplacedComment (Location); + } + + // + // Consumes the saved xml comment lines (if any) + // as for current target member or type. + // + public string consume_doc_comment () + { + if (xml_comment_buffer.Length > 0) { + string ret = xml_comment_buffer.ToString (); + reset_doc_comment (); + return ret; + } + return null; + } + + Report Report { + get { return context.Report; } + } + + void reset_doc_comment () + { + xml_comment_buffer.Length = 0; + } + + public void cleanup () + { + if (ifstack != null && ifstack.Count >= 1) { + int state = ifstack.Pop (); + if ((state & REGION) != 0) + Report.Error (1038, Location, "#endregion directive expected"); + else + Report.Error (1027, Location, "Expected `#endif' directive"); + } + } + } + + // + // Indicates whether it accepts XML documentation or not. + // + public enum XmlCommentState { + // comment is allowed in this state. + Allowed, + // comment is not allowed in this state. + NotAllowed, + // once comments appeared when it is NotAllowed, then the + // state is changed to it, until the state is changed to + // .Allowed. + Error + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs new file mode 100644 index 0000000000..0329cf6a50 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs @@ -0,0 +1,1557 @@ +// +// decl.cs: Declaration base class for structs, classes, enums and interfaces. +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc +// +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +#if NET_2_1 +using XmlElement = System.Object; +#else +using System.Xml; +#endif + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +using Mono.Collections.Generic; +#endif + +namespace Mono.CSharp { + + // + // Better name would be DottenName + // + [DebuggerDisplay ("{GetSignatureForError()}")] + public class MemberName { + public readonly string Name; + public TypeArguments TypeArguments; + + public readonly MemberName Left; + public readonly Location Location; + + public static readonly MemberName Null = new MemberName (""); + + bool is_double_colon; + + public bool IsDoubleColon { get { return is_double_colon; } } + + private MemberName (MemberName left, string name, bool is_double_colon, + Location loc) + { + this.Name = name; + this.Location = loc; + this.is_double_colon = is_double_colon; + this.Left = left; + } + + private MemberName (MemberName left, string name, bool is_double_colon, + TypeArguments args, Location loc) + : this (left, name, is_double_colon, loc) + { + if (args != null && args.Count > 0) + this.TypeArguments = args; + } + + public MemberName (string name) + : this (name, Location.Null) + { } + + public MemberName (string name, Location loc) + : this (null, name, false, loc) + { } + + public MemberName (string name, TypeArguments args, Location loc) + : this (null, name, false, args, loc) + { } + + public MemberName (MemberName left, string name) + : this (left, name, left != null ? left.Location : Location.Null) + { } + + public MemberName (MemberName left, string name, Location loc) + : this (left, name, false, loc) + { } + + public MemberName (MemberName left, string name, TypeArguments args, Location loc) + : this (left, name, false, args, loc) + { } + + public MemberName (string alias, string name, TypeArguments args, Location loc) + : this (new MemberName (alias, loc), name, true, args, loc) + { } + + public MemberName (MemberName left, MemberName right) + : this (left, right, right.Location) + { } + + public MemberName (MemberName left, MemberName right, Location loc) + : this (null, right.Name, false, right.TypeArguments, loc) + { + if (right.is_double_colon) + throw new InternalErrorException ("Cannot append double_colon member name"); + this.Left = (right.Left == null) ? left : new MemberName (left, right.Left); + } + + // TODO: Remove + public string GetName () + { + return GetName (false); + } + + public int Arity { + get { + return TypeArguments == null ? 0 : TypeArguments.Count; + } + } + + public bool IsGeneric { + get { + if (TypeArguments != null) + return true; + else if (Left != null) + return Left.IsGeneric; + else + return false; + } + } + + public string GetName (bool is_generic) + { + string name = is_generic ? Basename : Name; + if (Left != null) + return Left.GetName (is_generic) + (is_double_colon ? "::" : ".") + name; + + return name; + } + + public ATypeNameExpression GetTypeExpression () + { + if (Left == null) { + if (TypeArguments != null) + return new SimpleName (Name, TypeArguments, Location); + + return new SimpleName (Name, Location); + } + + if (is_double_colon) { + if (Left.Left != null) + throw new InternalErrorException ("The left side of a :: should be an identifier"); + return new QualifiedAliasMember (Left.Name, Name, TypeArguments, Location); + } + + Expression lexpr = Left.GetTypeExpression (); + return new MemberAccess (lexpr, Name, TypeArguments, Location); + } + + public MemberName Clone () + { + MemberName left_clone = Left == null ? null : Left.Clone (); + return new MemberName (left_clone, Name, is_double_colon, TypeArguments, Location); + } + + public string Basename { + get { + if (TypeArguments != null) + return MakeName (Name, TypeArguments); + return Name; + } + } + + public string GetSignatureForError () + { + string append = TypeArguments == null ? "" : "<" + TypeArguments.GetSignatureForError () + ">"; + if (Left == null) + return Name + append; + string connect = is_double_colon ? "::" : "."; + return Left.GetSignatureForError () + connect + Name + append; + } + + public override bool Equals (object other) + { + return Equals (other as MemberName); + } + + public bool Equals (MemberName other) + { + if (this == other) + return true; + if (other == null || Name != other.Name) + return false; + if (is_double_colon != other.is_double_colon) + return false; + + if ((TypeArguments != null) && + (other.TypeArguments == null || TypeArguments.Count != other.TypeArguments.Count)) + return false; + + if ((TypeArguments == null) && (other.TypeArguments != null)) + return false; + + if (Left == null) + return other.Left == null; + + return Left.Equals (other.Left); + } + + public override int GetHashCode () + { + int hash = Name.GetHashCode (); + for (MemberName n = Left; n != null; n = n.Left) + hash ^= n.Name.GetHashCode (); + if (is_double_colon) + hash ^= 0xbadc01d; + + if (TypeArguments != null) + hash ^= TypeArguments.Count << 5; + + return hash & 0x7FFFFFFF; + } + + public int CountTypeArguments { + get { + if (TypeArguments != null) + return TypeArguments.Count; + else if (Left != null) + return Left.CountTypeArguments; + else + return 0; + } + } + + public static string MakeName (string name, TypeArguments args) + { + if (args == null) + return name; + + return name + "`" + args.Count; + } + + public static string MakeName (string name, int count) + { + return name + "`" + count; + } + } + + public class SimpleMemberName + { + public string Value; + public Location Location; + + public SimpleMemberName (string name, Location loc) + { + this.Value = name; + this.Location = loc; + } + } + + /// + /// Base representation for members. This is used to keep track + /// of Name, Location and Modifier flags, and handling Attributes. + /// + [System.Diagnostics.DebuggerDisplay ("{GetSignatureForError()}")] + public abstract class MemberCore : Attributable, IMemberContext, IMemberDefinition + { + /// + /// Public name + /// + + protected string cached_name; + // TODO: Remove in favor of MemberName + public string Name { + get { + if (cached_name == null) + cached_name = MemberName.GetName (!(this is GenericMethod) && !(this is Method)); + return cached_name; + } + } + + string IMemberDefinition.Name { + get { + return member_name.Name; + } + } + + // Is not readonly because of IndexerName attribute + private MemberName member_name; + public MemberName MemberName { + get { return member_name; } + } + + /// + /// Modifier flags that the user specified in the source code + /// + private Modifiers mod_flags; + public Modifiers ModFlags { + set { + mod_flags = value; + if ((value & Modifiers.COMPILER_GENERATED) != 0) + caching_flags = Flags.IsUsed | Flags.IsAssigned; + } + get { + return mod_flags; + } + } + + public virtual ModuleContainer Module { + get { + return Parent.Module; + } + } + + public /*readonly*/ TypeContainer Parent; + + /// + /// Location where this declaration happens + /// + public Location Location { + get { return member_name.Location; } + } + + /// + /// XML documentation comment + /// + protected string comment; + + /// + /// Represents header string for documentation comment + /// for each member types. + /// + public abstract string DocCommentHeader { get; } + + [Flags] + public enum Flags { + Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet + Obsolete = 1 << 1, // Type has obsolete attribute + ClsCompliance_Undetected = 1 << 2, // CLS Compliance has not been detected yet + ClsCompliant = 1 << 3, // Type is CLS Compliant + CloseTypeCreated = 1 << 4, // Tracks whether we have Closed the type + HasCompliantAttribute_Undetected = 1 << 5, // Presence of CLSCompliantAttribute has not been detected + HasClsCompliantAttribute = 1 << 6, // Type has CLSCompliantAttribute + ClsCompliantAttributeFalse = 1 << 7, // Member has CLSCompliant(false) + Excluded_Undetected = 1 << 8, // Conditional attribute has not been detected yet + Excluded = 1 << 9, // Method is conditional + MethodOverloadsExist = 1 << 10, // Test for duplication must be performed + IsUsed = 1 << 11, + IsAssigned = 1 << 12, // Field is assigned + HasExplicitLayout = 1 << 13, + PartialDefinitionExists = 1 << 14, // Set when corresponding partial method definition exists + HasStructLayout = 1 << 15 // Has StructLayoutAttribute + } + + /// + /// MemberCore flags at first detected then cached + /// + internal Flags caching_flags; + + public MemberCore (DeclSpace parent, MemberName name, Attributes attrs) + { + this.Parent = parent as TypeContainer; + member_name = name; + caching_flags = Flags.Obsolete_Undetected | Flags.ClsCompliance_Undetected | Flags.HasCompliantAttribute_Undetected | Flags.Excluded_Undetected; + AddAttributes (attrs, this); + } + + protected virtual void SetMemberName (MemberName new_name) + { + member_name = new_name; + cached_name = null; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + protected bool CheckAbstractAndExtern (bool has_block) + { + if (Parent.PartialContainer.Kind == MemberKind.Interface) + return true; + + if (has_block) { + if ((ModFlags & Modifiers.EXTERN) != 0) { + Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern", + GetSignatureForError ()); + return false; + } + + if ((ModFlags & Modifiers.ABSTRACT) != 0) { + Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract", + GetSignatureForError ()); + return false; + } + } else { + if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN | Modifiers.PARTIAL)) == 0 && !(Parent is Delegate)) { + if (Compiler.Settings.Version >= LanguageVersion.V_3) { + Property.PropertyMethod pm = this as Property.PropertyMethod; + if (pm is Indexer.GetIndexerMethod || pm is Indexer.SetIndexerMethod) + pm = null; + + if (pm != null && pm.Property.AccessorSecond == null) { + Report.Error (840, Location, + "`{0}' must have a body because it is not marked abstract or extern. The property can be automatically implemented when you define both accessors", + GetSignatureForError ()); + return false; + } + } + + Report.Error (501, Location, "`{0}' must have a body because it is not marked abstract, extern, or partial", + GetSignatureForError ()); + return false; + } + } + + return true; + } + + protected void CheckProtectedModifier () + { + if ((ModFlags & Modifiers.PROTECTED) == 0) + return; + + if (Parent.PartialContainer.Kind == MemberKind.Struct) { + Report.Error (666, Location, "`{0}': Structs cannot contain protected members", + GetSignatureForError ()); + return; + } + + if ((Parent.ModFlags & Modifiers.STATIC) != 0) { + Report.Error (1057, Location, "`{0}': Static classes cannot contain protected members", + GetSignatureForError ()); + return; + } + + if ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.OVERRIDE) == 0 && + !(this is Destructor)) { + Report.Warning (628, 4, Location, "`{0}': new protected member declared in sealed class", + GetSignatureForError ()); + return; + } + } + + public abstract bool Define (); + + public virtual string DocComment { + get { + return comment; + } + set { + comment = value; + } + } + + // + // Returns full member name for error message + // + public virtual string GetSignatureForError () + { + if (Parent == null || Parent.Parent == null) + return member_name.GetSignatureForError (); + + return Parent.GetSignatureForError () + "." + member_name.GetSignatureForError (); + } + + /// + /// Base Emit method. This is also entry point for CLS-Compliant verification. + /// + public virtual void Emit () + { + if (!Compiler.Settings.VerifyClsCompliance) + return; + + VerifyClsCompliance (); + } + + public bool IsCompilerGenerated { + get { + if ((mod_flags & Modifiers.COMPILER_GENERATED) != 0) + return true; + + return Parent == null ? false : Parent.IsCompilerGenerated; + } + } + + public bool IsImported { + get { + return false; + } + } + + public virtual bool IsUsed { + get { + return (caching_flags & Flags.IsUsed) != 0; + } + } + + protected Report Report { + get { + return Compiler.Report; + } + } + + public void SetIsUsed () + { + caching_flags |= Flags.IsUsed; + } + + public void SetIsAssigned () + { + caching_flags |= Flags.IsAssigned; + } + + /// + /// Returns instance of ObsoleteAttribute for this MemberCore + /// + public virtual ObsoleteAttribute GetAttributeObsolete () + { + if ((caching_flags & (Flags.Obsolete_Undetected | Flags.Obsolete)) == 0) + return null; + + caching_flags &= ~Flags.Obsolete_Undetected; + + if (OptAttributes == null) + return null; + + Attribute obsolete_attr = OptAttributes.Search (Module.PredefinedAttributes.Obsolete); + if (obsolete_attr == null) + return null; + + caching_flags |= Flags.Obsolete; + + ObsoleteAttribute obsolete = obsolete_attr.GetObsoleteAttribute (); + if (obsolete == null) + return null; + + return obsolete; + } + + /// + /// Checks for ObsoleteAttribute presence. It's used for testing of all non-types elements + /// + public virtual void CheckObsoleteness (Location loc) + { + ObsoleteAttribute oa = GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, Report); + } + + // + // Checks whether the type P is as accessible as this member + // + public bool IsAccessibleAs (TypeSpec p) + { + // + // if M is private, its accessibility is the same as this declspace. + // we already know that P is accessible to T before this method, so we + // may return true. + // + if ((mod_flags & Modifiers.PRIVATE) != 0) + return true; + + while (TypeManager.HasElementType (p)) + p = TypeManager.GetElementType (p); + + if (p.IsGenericParameter) + return true; + + for (TypeSpec p_parent; p != null; p = p_parent) { + p_parent = p.DeclaringType; + + if (p.IsGeneric) { + foreach (TypeSpec t in p.TypeArguments) { + if (!IsAccessibleAs (t)) + return false; + } + } + + var pAccess = p.Modifiers & Modifiers.AccessibilityMask; + if (pAccess == Modifiers.PUBLIC) + continue; + + bool same_access_restrictions = false; + for (MemberCore mc = this; !same_access_restrictions && mc != null && mc.Parent != null; mc = mc.Parent) { + var al = mc.ModFlags & Modifiers.AccessibilityMask; + switch (pAccess) { + case Modifiers.INTERNAL: + if (al == Modifiers.PRIVATE || al == Modifiers.INTERNAL) + same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); + + break; + + case Modifiers.PROTECTED: + if (al == Modifiers.PROTECTED) { + same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent); + break; + } + + if (al == Modifiers.PRIVATE) { + // + // When type is private and any of its parents derives from + // protected type then the type is accessible + // + while (mc.Parent != null) { + if (mc.Parent.IsBaseTypeDefinition (p_parent)) + same_access_restrictions = true; + mc = mc.Parent; + } + } + + break; + + case Modifiers.PROTECTED | Modifiers.INTERNAL: + if (al == Modifiers.INTERNAL) + same_access_restrictions = p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); + else if (al == (Modifiers.PROTECTED | Modifiers.INTERNAL)) + same_access_restrictions = mc.Parent.IsBaseTypeDefinition (p_parent) && p.MemberDefinition.IsInternalAsPublic (mc.Module.DeclaringAssembly); + else + goto case Modifiers.PROTECTED; + + break; + + case Modifiers.PRIVATE: + // + // Both are private and share same parent + // + if (al == Modifiers.PRIVATE) { + var decl = mc.Parent; + do { + same_access_restrictions = decl.CurrentType == p_parent; + } while (!same_access_restrictions && !decl.IsTopLevel && (decl = decl.Parent) != null); + } + + break; + + default: + throw new InternalErrorException (al.ToString ()); + } + } + + if (!same_access_restrictions) + return false; + } + + return true; + } + + /// + /// Analyze whether CLS-Compliant verification must be execute for this MemberCore. + /// + public override bool IsClsComplianceRequired () + { + if ((caching_flags & Flags.ClsCompliance_Undetected) == 0) + return (caching_flags & Flags.ClsCompliant) != 0; + + caching_flags &= ~Flags.ClsCompliance_Undetected; + + if (HasClsCompliantAttribute) { + if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) + return false; + + caching_flags |= Flags.ClsCompliant; + return true; + } + + if (Parent.PartialContainer.IsClsComplianceRequired ()) { + caching_flags |= Flags.ClsCompliant; + return true; + } + + return false; + } + + public virtual string[] ConditionalConditions () + { + return null; + } + + /// + /// Returns true when MemberCore is exposed from assembly. + /// + public bool IsExposedFromAssembly () + { + if ((ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) + return false; + + DeclSpace parentContainer = Parent.PartialContainer; + while (parentContainer != null && parentContainer.ModFlags != 0) { + if ((parentContainer.ModFlags & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) + return false; + parentContainer = parentContainer.Parent; + } + return true; + } + + public virtual IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return Parent.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + public virtual FullNamedExpression LookupNamespaceAlias (string name) + { + return Parent.NamespaceEntry.LookupNamespaceAlias (name); + } + + public virtual FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + return Parent.LookupNamespaceOrType (name, arity, mode, loc); + } + + /// + /// Goes through class hierarchy and gets value of first found CLSCompliantAttribute. + /// If no is attribute exists then assembly CLSCompliantAttribute is returned. + /// + public bool? CLSAttributeValue { + get { + if ((caching_flags & Flags.HasCompliantAttribute_Undetected) == 0) { + if ((caching_flags & Flags.HasClsCompliantAttribute) == 0) + return null; + + return (caching_flags & Flags.ClsCompliantAttributeFalse) == 0; + } + + caching_flags &= ~Flags.HasCompliantAttribute_Undetected; + + if (OptAttributes != null) { + Attribute cls_attribute = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + if (cls_attribute != null) { + caching_flags |= Flags.HasClsCompliantAttribute; + if (cls_attribute.GetClsCompliantAttributeValue ()) + return true; + + caching_flags |= Flags.ClsCompliantAttributeFalse; + return false; + } + } + + return null; + } + } + + /// + /// Returns true if MemberCore is explicitly marked with CLSCompliantAttribute + /// + protected bool HasClsCompliantAttribute { + get { + return CLSAttributeValue.HasValue; + } + } + + /// + /// Returns true when a member supports multiple overloads (methods, indexers, etc) + /// + public virtual bool EnableOverloadChecks (MemberCore overload) + { + return false; + } + + /// + /// The main virtual method for CLS-Compliant verifications. + /// The method returns true if member is CLS-Compliant and false if member is not + /// CLS-Compliant which means that CLS-Compliant tests are not necessary. A descendants override it + /// and add their extra verifications. + /// + protected virtual bool VerifyClsCompliance () + { + if (HasClsCompliantAttribute) { + if (!Module.DeclaringAssembly.HasCLSCompliantAttribute) { + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) { + Report.Warning (3021, 2, a.Location, + "`{0}' does not need a CLSCompliant attribute because the assembly is not marked as CLS-compliant", + GetSignatureForError ()); + } else { + Report.Warning (3014, 1, a.Location, + "`{0}' cannot be marked as CLS-compliant because the assembly is not marked as CLS-compliant", + GetSignatureForError ()); + } + return false; + } + + if (!IsExposedFromAssembly ()) { + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + Report.Warning (3019, 2, a.Location, "CLS compliance checking will not be performed on `{0}' because it is not visible from outside this assembly", GetSignatureForError ()); + return false; + } + + if ((caching_flags & Flags.ClsCompliantAttributeFalse) != 0) { + if (Parent.Kind == MemberKind.Interface && Parent.IsClsComplianceRequired ()) { + Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ()); + } else if (Parent.Kind == MemberKind.Class && (ModFlags & Modifiers.ABSTRACT) != 0 && Parent.IsClsComplianceRequired ()) { + Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ()); + } + + return false; + } + + if (Parent.Parent != null && !Parent.IsClsComplianceRequired ()) { + Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CLSCompliant); + Report.Warning (3018, 1, a.Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'", + GetSignatureForError (), Parent.GetSignatureForError ()); + return false; + } + } else { + if (!IsExposedFromAssembly ()) + return false; + + if (!Parent.PartialContainer.IsClsComplianceRequired ()) + return false; + } + + if (member_name.Name [0] == '_') { + Report.Warning (3008, 1, Location, "Identifier `{0}' is not CLS-compliant", GetSignatureForError () ); + } + + return true; + } + + // + // Returns a string that represents the signature for this + // member which should be used in XML documentation. + // + public abstract string GetSignatureForDocumentation (); + + // + // Generates xml doc comments (if any), and if required, + // handle warning report. + // + internal virtual void GenerateDocComment (DocumentationBuilder builder) + { + if (DocComment == null) { + if (IsExposedFromAssembly ()) { + Constructor c = this as Constructor; + if (c == null || !c.IsDefault ()) + Report.Warning (1591, 4, Location, + "Missing XML comment for publicly visible type or member `{0}'", GetSignatureForError ()); + } + + return; + } + + try { + builder.GenerateDocumentationForMember (this); + } catch (Exception e) { + throw new InternalErrorException (this, e); + } + } + + #region IMemberContext Members + + public virtual CompilerContext Compiler { + get { return Parent.Compiler; } + } + + public virtual TypeSpec CurrentType { + get { return Parent.CurrentType; } + } + + public MemberCore CurrentMemberDefinition { + get { return this; } + } + + public virtual TypeParameter[] CurrentTypeParameters { + get { return null; } + } + + public bool IsObsolete { + get { + if (GetAttributeObsolete () != null) + return true; + + return Parent == null ? false : Parent.IsObsolete; + } + } + + public bool IsUnsafe { + get { + if ((ModFlags & Modifiers.UNSAFE) != 0) + return true; + + return Parent == null ? false : Parent.IsUnsafe; + } + } + + public bool IsStatic { + get { + return (ModFlags & Modifiers.STATIC) != 0; + } + } + + #endregion + } + + // + // Base member specification. A member specification contains + // member details which can alter in the context (e.g. generic instances) + // + public abstract class MemberSpec + { + [Flags] + public enum StateFlags + { + Obsolete_Undetected = 1, // Obsolete attribute has not been detected yet + Obsolete = 1 << 1, // Member has obsolete attribute + CLSCompliant_Undetected = 1 << 2, // CLSCompliant attribute has not been detected yet + CLSCompliant = 1 << 3, // Member is CLS Compliant + MissingDependency_Undetected = 1 << 4, + MissingDependency = 1 << 5, + HasDynamicElement = 1 << 6, + ConstraintsChecked = 1 << 7, + + IsAccessor = 1 << 9, // Method is an accessor + IsGeneric = 1 << 10, // Member contains type arguments + + PendingMetaInflate = 1 << 12, + PendingMakeMethod = 1 << 13, + PendingMemberCacheMembers = 1 << 14, + PendingBaseTypeInflate = 1 << 15, + InterfacesExpanded = 1 << 16, + IsNotCSharpCompatible = 1 << 17, + SpecialRuntimeType = 1 << 18, + InflatedExpressionType = 1 << 19, + InflatedNullableType = 1 << 20, + GenericIterateInterface = 1 << 21, + GenericTask = 1 << 22 + } + + protected Modifiers modifiers; + public StateFlags state; + protected IMemberDefinition definition; + public readonly MemberKind Kind; + protected TypeSpec declaringType; + +#if DEBUG + static int counter; + public int ID = counter++; +#endif + + protected MemberSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, Modifiers modifiers) + { + this.Kind = kind; + this.declaringType = declaringType; + this.definition = definition; + this.modifiers = modifiers; + + state = StateFlags.Obsolete_Undetected | StateFlags.CLSCompliant_Undetected | StateFlags.MissingDependency_Undetected; + } + + #region Properties + + public virtual int Arity { + get { + return 0; + } + } + + public TypeSpec DeclaringType { + get { + return declaringType; + } + set { + declaringType = value; + } + } + + public IMemberDefinition MemberDefinition { + get { + return definition; + } + } + + public Modifiers Modifiers { + get { + return modifiers; + } + set { + modifiers = value; + } + } + + public virtual string Name { + get { + return definition.Name; + } + } + + public bool IsAbstract { + get { return (modifiers & Modifiers.ABSTRACT) != 0; } + } + + public bool IsAccessor { + get { + return (state & StateFlags.IsAccessor) != 0; + } + set { + state = value ? state | StateFlags.IsAccessor : state & ~StateFlags.IsAccessor; + } + } + + // + // Return true when this member is a generic in C# terms + // A nested non-generic type of generic type will return false + // + public bool IsGeneric { + get { + return (state & StateFlags.IsGeneric) != 0; + } + set { + state = value ? state | StateFlags.IsGeneric : state & ~StateFlags.IsGeneric; + } + } + + // + // Returns true for imported members which are not compatible with C# language + // + public bool IsNotCSharpCompatible { + get { + return (state & StateFlags.IsNotCSharpCompatible) != 0; + } + set { + state = value ? state | StateFlags.IsNotCSharpCompatible : state & ~StateFlags.IsNotCSharpCompatible; + } + } + + public bool IsPrivate { + get { return (modifiers & Modifiers.PRIVATE) != 0; } + } + + public bool IsPublic { + get { return (modifiers & Modifiers.PUBLIC) != 0; } + } + + public bool IsStatic { + get { + return (modifiers & Modifiers.STATIC) != 0; + } + } + + #endregion + + public virtual ObsoleteAttribute GetAttributeObsolete () + { + if ((state & (StateFlags.Obsolete | StateFlags.Obsolete_Undetected)) == 0) + return null; + + state &= ~StateFlags.Obsolete_Undetected; + + var oa = definition.GetAttributeObsolete (); + if (oa != null) + state |= StateFlags.Obsolete; + + return oa; + } + + // + // Returns a list of missing dependencies of this member. The list + // will contain types only but it can have numerous values for members + // like methods where both return type and all parameters are checked + // + public List GetMissingDependencies () + { + if ((state & (StateFlags.MissingDependency | StateFlags.MissingDependency_Undetected)) == 0) + return null; + + state &= ~StateFlags.MissingDependency_Undetected; + + var imported = definition as ImportedDefinition; + List missing; + if (imported != null) { + missing = ResolveMissingDependencies (); + } else if (this is ElementTypeSpec) { + missing = ((ElementTypeSpec) this).Element.GetMissingDependencies (); + } else { + missing = null; + } + + if (missing != null) { + state |= StateFlags.MissingDependency; + } + + return missing; + } + + public abstract List ResolveMissingDependencies (); + + protected virtual bool IsNotCLSCompliant (out bool attrValue) + { + var cls = MemberDefinition.CLSAttributeValue; + attrValue = cls ?? false; + return cls == false; + } + + public virtual string GetSignatureForDocumentation () + { + return DeclaringType.GetSignatureForDocumentation () + "." + Name; + } + + public virtual string GetSignatureForError () + { + var bf = MemberDefinition as Property.BackingField; + var name = bf == null ? Name : bf.OriginalName; + return DeclaringType.GetSignatureForError () + "." + name; + } + + public virtual MemberSpec InflateMember (TypeParameterInflator inflator) + { + var inflated = (MemberSpec) MemberwiseClone (); + inflated.declaringType = inflator.TypeInstance; + if (DeclaringType.IsGenericOrParentIsGeneric) + inflated.state |= StateFlags.PendingMetaInflate; +#if DEBUG + inflated.ID += 1000000; +#endif + return inflated; + } + + // + // Is this member accessible from invocation context + // + public bool IsAccessible (IMemberContext ctx) + { + var ma = Modifiers & Modifiers.AccessibilityMask; + if (ma == Modifiers.PUBLIC) + return true; + + var parentType = /* this as TypeSpec ?? */ DeclaringType; + var ctype = ctx.CurrentType; + + if (ma == Modifiers.PRIVATE) { + if (ctype == null) + return false; + // + // It's only accessible to the current class or children + // + if (parentType.MemberDefinition == ctype.MemberDefinition) + return true; + + return TypeManager.IsNestedChildOf (ctype, parentType.MemberDefinition); + } + + if ((ma & Modifiers.INTERNAL) != 0) { + bool b; + var assembly = ctype == null ? ctx.Module.DeclaringAssembly : ctype.MemberDefinition.DeclaringAssembly; + + if (parentType == null) { + b = ((ITypeDefinition) MemberDefinition).IsInternalAsPublic (assembly); + } else { + b = DeclaringType.MemberDefinition.IsInternalAsPublic (assembly); + } + + if (b || ma == Modifiers.INTERNAL) + return b; + } + + // + // Checks whether `ctype' is a subclass or nested child of `parentType'. + // + while (ctype != null) { + if (TypeManager.IsFamilyAccessible (ctype, parentType)) + return true; + + // Handle nested types. + ctype = ctype.DeclaringType; // TODO: Untested ??? + } + + return false; + } + + // + // Returns member CLS compliance based on full member hierarchy + // + public bool IsCLSCompliant () + { + if ((state & StateFlags.CLSCompliant_Undetected) != 0) { + state &= ~StateFlags.CLSCompliant_Undetected; + + bool compliant; + if (IsNotCLSCompliant (out compliant)) + return false; + + if (!compliant) { + if (DeclaringType != null) { + compliant = DeclaringType.IsCLSCompliant (); + } else { + compliant = ((ITypeDefinition) MemberDefinition).DeclaringAssembly.IsCLSCompliant; + } + } + + if (compliant) + state |= StateFlags.CLSCompliant; + } + + return (state & StateFlags.CLSCompliant) != 0; + } + + public bool IsConditionallyExcluded (CompilerContext ctx, Location loc) + { + if ((Kind & (MemberKind.Class | MemberKind.Method)) == 0) + return false; + + var conditions = MemberDefinition.ConditionalConditions (); + if (conditions == null) + return false; + + foreach (var condition in conditions) { + if (loc.CompilationUnit.IsConditionalDefined (ctx, condition)) + return false; + } + + return true; + } + + public override string ToString () + { + return GetSignatureForError (); + } + } + + // + // Member details which are same between all member + // specifications + // + public interface IMemberDefinition + { + bool? CLSAttributeValue { get; } + string Name { get; } + bool IsImported { get; } + + string[] ConditionalConditions (); + ObsoleteAttribute GetAttributeObsolete (); + void SetIsAssigned (); + void SetIsUsed (); + } + + public interface IParametersMember : IInterfaceMemberSpec + { + AParametersCollection Parameters { get; } + } + + public interface IInterfaceMemberSpec + { + TypeSpec MemberType { get; } + } + + // + // Base type container declaration. It exists to handle partial types + // which share same definition (PartialContainer) but have different + // resolve scopes + // + public abstract class DeclSpace : MemberCore { + /// + /// This points to the actual definition that is being + /// created with System.Reflection.Emit + /// + public TypeBuilder TypeBuilder; + + // + // This is the namespace in which this typecontainer + // was declared. We use this to resolve names. + // + public NamespaceContainer NamespaceEntry; + + public readonly string Basename; + + protected Dictionary defined_names; + + public TypeContainer PartialContainer; + + protected readonly bool is_generic; + readonly int count_type_params; + protected TypeParameter[] type_params; + TypeParameter[] type_param_list; + + // + // Whether we are Generic + // + public bool IsGeneric { + get { + if (is_generic) + return true; + else if (Parent != null) + return Parent.IsGeneric; + else + return false; + } + } + + static readonly string[] attribute_targets = new string [] { "type" }; + + public DeclSpace (NamespaceContainer ns, DeclSpace parent, MemberName name, + Attributes attrs) + : base (parent, name, attrs) + { + NamespaceEntry = ns; + Basename = name.Basename; + defined_names = new Dictionary (); + PartialContainer = null; + if (name.TypeArguments != null) { + is_generic = true; + count_type_params = name.TypeArguments.Count; + } + if (parent != null) + count_type_params += parent.count_type_params; + } + + /// + /// Adds the member to defined_names table. It tests for duplications and enclosing name conflicts + /// + protected virtual bool AddToContainer (MemberCore symbol, string name) + { + MemberCore mc; + if (!defined_names.TryGetValue (name, out mc)) { + defined_names.Add (name, symbol); + return true; + } + + if (((mc.ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0) + return true; + + if (symbol.EnableOverloadChecks (mc)) + return true; + + InterfaceMemberBase im = mc as InterfaceMemberBase; + if (im != null && im.IsExplicitImpl) + return true; + + Report.SymbolRelatedToPreviousError (mc); + if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) { + Error_MissingPartialModifier (symbol); + return false; + } + + if (symbol is TypeParameter) { + Report.Error (692, symbol.Location, + "Duplicate type parameter `{0}'", symbol.GetSignatureForError ()); + } else { + Report.Error (102, symbol.Location, + "The type `{0}' already contains a definition for `{1}'", + GetSignatureForError (), symbol.MemberName.Name); + } + + return false; + } + + protected void RemoveFromContainer (string name) + { + defined_names.Remove (name); + } + + /// + /// Returns the MemberCore associated with a given name in the declaration + /// space. It doesn't return method based symbols !! + /// + /// + public MemberCore GetDefinition (string name) + { + MemberCore mc = null; + defined_names.TryGetValue (name, out mc); + return mc; + } + + // + // root_types contains all the types. All TopLevel types + // hence have a parent that points to `root_types', that is + // why there is a non-obvious test down here. + // + public bool IsTopLevel { + get { return (Parent != null && Parent.Parent == null); } + } + + public virtual bool IsUnmanagedType () + { + return false; + } + + protected abstract TypeAttributes TypeAttr { get; } + + /// + /// Should be overriten by the appropriate declaration space + /// + public abstract void DefineType (); + + protected void Error_MissingPartialModifier (MemberCore type) + { + Report.Error (260, type.Location, + "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists", + type.GetSignatureForError ()); + } + + public override string GetSignatureForDocumentation () + { + return Name; + } + + public override string GetSignatureForError () + { + return MemberName.GetSignatureForError (); + } + + TypeParameter[] initialize_type_params () + { + if (type_param_list != null) + return type_param_list; + + DeclSpace the_parent = Parent; + if (this is GenericMethod) + the_parent = null; + + var list = new List (); + if (the_parent != null && the_parent.IsGeneric) { + // FIXME: move generics info out of DeclSpace + TypeParameter[] parent_params = the_parent.TypeParameters; + list.AddRange (parent_params); + } + + int count = type_params != null ? type_params.Length : 0; + for (int i = 0; i < count; i++) { + TypeParameter param = type_params [i]; + list.Add (param); + if (Parent.CurrentTypeParameters != null) { + foreach (TypeParameter tp in Parent.CurrentTypeParameters) { + if (tp.Name != param.Name) + continue; + + Report.SymbolRelatedToPreviousError (tp.Location, null); + Report.Warning (693, 3, param.Location, + "Type parameter `{0}' has the same name as the type parameter from outer type `{1}'", + param.Name, Parent.GetSignatureForError ()); + } + } + } + + type_param_list = new TypeParameter [list.Count]; + list.CopyTo (type_param_list, 0); + return type_param_list; + } + +#if FULL_AST + public List PlainConstraints { + get; + private set; + } +#endif + + public List Constraints { + get; + private set; + } + + public virtual void SetParameterInfo (List constraints_list) + { +#if FULL_AST + if (constraints_list != null) { + this.PlainConstraints = constraints_list; + constraints_list = this.Constraints = new List (constraints_list); + } +#else + this.Constraints = constraints_list; +#endif + if (!is_generic) { + if (constraints_list != null) { + Report.Error ( + 80, Location, "Constraints are not allowed " + + "on non-generic declarations"); + } + + return; + } + + TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations (); + type_params = new TypeParameter [names.Length]; + + // + // Register all the names + // + for (int i = 0; i < type_params.Length; i++) { + TypeParameterName name = names [i]; + + Constraints constraints = null; + if (constraints_list != null) { + int total = constraints_list.Count; + for (int ii = 0; ii < total; ++ii) { + Constraints constraints_at = (Constraints)constraints_list[ii]; + // TODO: it is used by iterators only + if (constraints_at == null) { + constraints_list.RemoveAt (ii); + --total; + continue; + } + if (constraints_at.TypeParameter.Value == name.Name) { + constraints = constraints_at; + constraints_list.RemoveAt(ii); + break; + } + } + } + + Variance variance = name.Variance; + if (name.Variance != Variance.None && !(this is Delegate || this is Interface)) { + Report.Error (1960, name.Location, "Variant type parameters can only be used with interfaces and delegates"); + variance = Variance.None; + } + + type_params [i] = new TypeParameter ( + Parent, i, new MemberName (name.Name, Location), constraints, name.OptAttributes, variance); + + AddToContainer (type_params [i], name.Name); + } + + if (constraints_list != null && constraints_list.Count > 0) { + foreach (Constraints constraint in constraints_list) { + Report.Error(699, constraint.Location, "`{0}': A constraint references nonexistent type parameter `{1}'", + GetSignatureForError (), constraint.TypeParameter.Value); + } + } + } + + protected TypeParameter[] TypeParameters { + get { + if (!IsGeneric) + throw new InvalidOperationException (); + if ((PartialContainer != null) && (PartialContainer != this)) + return PartialContainer.TypeParameters; + if (type_param_list == null) + initialize_type_params (); + + return type_param_list; + } + } + + public int CountTypeParameters { + get { + return count_type_params; + } + } + + public override string[] ValidAttributeTargets { + get { return attribute_targets; } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) { + return false; + } + + if (type_params != null) { + foreach (TypeParameter tp in type_params) { + tp.VerifyClsCompliance (); + } + } + + return true; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs new file mode 100644 index 0000000000..8752aebc19 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs @@ -0,0 +1,774 @@ +// +// delegate.cs: Delegate Handler +// +// Authors: +// Ravi Pratap (ravi@ximian.com) +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2009 Novell, Inc (http://www.novell.com) +// + +using System; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + // + // Delegate container implementation + // + public class Delegate : TypeContainer, IParametersMember + { + public FullNamedExpression ReturnType; + readonly ParametersCompiled parameters; + + Constructor Constructor; + Method InvokeBuilder; + Method BeginInvokeBuilder; + Method EndInvokeBuilder; + + static readonly string[] attribute_targets = new string [] { "type", "return" }; + + public static readonly string InvokeMethodName = "Invoke"; + + Expression instance_expr; + ReturnParameter return_attributes; + + const Modifiers MethodModifiers = Modifiers.PUBLIC | Modifiers.VIRTUAL; + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.UNSAFE | + Modifiers.PRIVATE; + + public Delegate (NamespaceContainer ns, DeclSpace parent, FullNamedExpression type, + Modifiers mod_flags, MemberName name, ParametersCompiled param_list, + Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Delegate) + + { + this.ReturnType = type; + ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, + IsTopLevel ? Modifiers.INTERNAL : + Modifiers.PRIVATE, name.Location, Report); + parameters = param_list; + spec = new TypeSpec (Kind, null, this, null, ModFlags | Modifiers.SEALED); + } + + #region Properties + public TypeSpec MemberType { + get { + return ReturnType.Type; + } + } + + public AParametersCollection Parameters { + get { + return parameters; + } + } + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.ReturnValue) { + if (return_attributes == null) + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Delegate; + } + } + + protected override bool DoDefineMembers () + { + var builtin_types = Compiler.BuiltinTypes; + + var ctor_parameters = ParametersCompiled.CreateFullyResolved ( + new [] { + new Parameter (new TypeExpression (builtin_types.Object, Location), "object", Parameter.Modifier.NONE, null, Location), + new Parameter (new TypeExpression (builtin_types.IntPtr, Location), "method", Parameter.Modifier.NONE, null, Location) + }, + new [] { + builtin_types.Object, + builtin_types.IntPtr + } + ); + + Constructor = new Constructor (this, Constructor.ConstructorName, + Modifiers.PUBLIC, null, ctor_parameters, null, Location); + Constructor.Define (); + + // + // Here the various methods like Invoke, BeginInvoke etc are defined + // + // First, call the `out of band' special method for + // defining recursively any types we need: + // + var p = parameters; + + if (!p.Resolve (this)) + return false; + + // + // Invoke method + // + + // Check accessibility + foreach (var partype in p.Types) { + if (!IsAccessibleAs (partype)) { + Report.SymbolRelatedToPreviousError (partype); + Report.Error (59, Location, + "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'", + TypeManager.CSharpName (partype), GetSignatureForError ()); + } + } + + var ret_type = ReturnType.ResolveAsType (this); + if (ret_type == null) + return false; + + // + // We don't have to check any others because they are all + // guaranteed to be accessible - they are standard types. + // + if (!IsAccessibleAs (ret_type)) { + Report.SymbolRelatedToPreviousError (ret_type); + Report.Error (58, Location, + "Inconsistent accessibility: return type `" + + TypeManager.CSharpName (ret_type) + "' is less " + + "accessible than delegate `" + GetSignatureForError () + "'"); + return false; + } + + CheckProtectedModifier (); + + if (Compiler.Settings.StdLib && ret_type.IsSpecialRuntimeType) { + Method.Error1599 (Location, ret_type, Report); + return false; + } + + TypeManager.CheckTypeVariance (ret_type, Variance.Covariant, this); + + InvokeBuilder = new Method (this, null, ReturnType, 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); + } + + return true; + } + + void DefineAsyncMethods (CallingConventions cc) + { + var iasync_result = Module.PredefinedTypes.IAsyncResult; + var async_callback = Module.PredefinedTypes.AsyncCallback; + + // + // It's ok when async types don't exist, the delegate will have Invoke method only + // + if (!iasync_result.Define () || !async_callback.Define ()) + return; + + // + // BeginInvoke + // + ParametersCompiled async_parameters; + if (Parameters.Count == 0) { + async_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } else { + var compiled = new Parameter[Parameters.Count]; + for (int i = 0; i < compiled.Length; ++i) { + var p = parameters[i]; + compiled[i] = new Parameter (new TypeExpression (parameters.Types[i], Location), + p.Name, + p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); + } + + async_parameters = new ParametersCompiled (compiled); + } + + async_parameters = ParametersCompiled.MergeGenerated (Compiler, async_parameters, false, + new Parameter[] { + new Parameter (new TypeExpression (async_callback.TypeSpec, Location), "callback", Parameter.Modifier.NONE, null, Location), + new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, Location), "object", Parameter.Modifier.NONE, null, Location) + }, + new [] { + async_callback.TypeSpec, + Compiler.BuiltinTypes.Object + } + ); + + BeginInvokeBuilder = new Method (this, null, + new TypeExpression (iasync_result.TypeSpec, Location), MethodModifiers, + new MemberName ("BeginInvoke"), async_parameters, null); + BeginInvokeBuilder.Define (); + + // + // EndInvoke is a bit more interesting, all the parameters labeled as + // out or ref have to be duplicated here. + // + + // + // Define parameters, and count out/ref parameters + // + ParametersCompiled end_parameters; + int out_params = 0; + + foreach (Parameter p in Parameters.FixedParameters) { + if ((p.ModFlags & Parameter.Modifier.ISBYREF) != 0) + ++out_params; + } + + if (out_params > 0) { + Parameter[] end_params = new Parameter[out_params]; + + int param = 0; + for (int i = 0; i < Parameters.FixedParameters.Length; ++i) { + Parameter p = parameters [i]; + if ((p.ModFlags & Parameter.Modifier.ISBYREF) == 0) + continue; + + end_params [param++] = new Parameter (new TypeExpression (p.Type, Location), + p.Name, + p.ModFlags & (Parameter.Modifier.REF | Parameter.Modifier.OUT), + p.OptAttributes == null ? null : p.OptAttributes.Clone (), Location); + } + + end_parameters = new ParametersCompiled (end_params); + } else { + end_parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + + end_parameters = ParametersCompiled.MergeGenerated (Compiler, end_parameters, false, + new Parameter ( + new TypeExpression (iasync_result.TypeSpec, Location), + "result", Parameter.Modifier.NONE, null, Location), + iasync_result.TypeSpec); + + // + // Create method, define parameters, register parameters with type system + // + EndInvokeBuilder = new Method (this, null, ReturnType, MethodModifiers, new MemberName ("EndInvoke"), end_parameters, null); + EndInvokeBuilder.Define (); + } + + public override void DefineConstants () + { + if (!Parameters.IsEmpty) { + parameters.ResolveDefaultValues (this); + } + } + + public override void EmitType () + { + if (ReturnType.Type != null) { + if (ReturnType.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.Type.HasDynamicElement) { + return_attributes = new ReturnParameter (this, InvokeBuilder.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType.Type, Location); + } + + ConstraintChecker.Check (this, ReturnType.Type, ReturnType.Location); + } + + Constructor.ParameterInfo.ApplyAttributes (this, Constructor.ConstructorBuilder); + Constructor.ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + + parameters.CheckConstraints (this); + parameters.ApplyAttributes (this, InvokeBuilder.MethodBuilder); + InvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + + if (BeginInvokeBuilder != null) { + BeginInvokeBuilder.ParameterInfo.ApplyAttributes (this, BeginInvokeBuilder.MethodBuilder); + EndInvokeBuilder.ParameterInfo.ApplyAttributes (this, EndInvokeBuilder.MethodBuilder); + + BeginInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + EndInvokeBuilder.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Runtime); + } + + if (OptAttributes != null) { + OptAttributes.Emit (); + } + + base.Emit (); + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + base_type = Compiler.BuiltinTypes.MulticastDelegate; + base_class = null; + return null; + } + + protected override TypeAttributes TypeAttr { + get { + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | + TypeAttributes.Class | TypeAttributes.Sealed | + base.TypeAttr; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + //TODO: duplicate + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) { + return false; + } + + parameters.VerifyClsCompliance (this); + + if (!InvokeBuilder.MemberType.IsCLSCompliant ()) { + Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + return true; + } + + + public static MethodSpec GetConstructor (TypeSpec delType) + { + var ctor = MemberCache.FindMember (delType, MemberFilter.Constructor (null), BindingRestriction.DeclaredOnly); + return (MethodSpec) ctor; + } + + // + // Returns the "Invoke" from a delegate type + // + public static MethodSpec GetInvokeMethod (TypeSpec delType) + { + var invoke = MemberCache.FindMember (delType, + MemberFilter.Method (InvokeMethodName, 0, null, null), + BindingRestriction.DeclaredOnly); + + return (MethodSpec) invoke; + } + + public static AParametersCollection GetParameters (TypeSpec delType) + { + var invoke_mb = GetInvokeMethod (delType); + return invoke_mb.Parameters; + } + + // + // 15.2 Delegate compatibility + // + public static bool IsTypeCovariant (ResolveContext rc, TypeSpec a, TypeSpec b) + { + // + // For each value parameter (a parameter with no ref or out modifier), an + // identity conversion or implicit reference conversion exists from the + // parameter type in D to the corresponding parameter type in M + // + if (a == b) + return true; + + if (rc.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) + return false; + + if (a.IsGenericParameter && b.IsGenericParameter) + return a == b; + + return Convert.ImplicitReferenceConversionExists (a, b); + } + + public static string FullDelegateDesc (MethodSpec invoke_method) + { + return TypeManager.GetFullNameSignature (invoke_method).Replace (".Invoke", ""); + } + + public Expression InstanceExpression { + get { + return instance_expr; + } + set { + instance_expr = value; + } + } + } + + // + // Base class for `NewDelegate' and `ImplicitDelegateCreation' + // + public abstract class DelegateCreation : Expression, OverloadResolver.IErrorHandler + { + protected MethodSpec constructor_method; + protected MethodGroupExpr method_group; + + public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc) + { + Arguments delegate_arguments = new Arguments (pd.Count); + for (int i = 0; i < pd.Count; ++i) { + Argument.AType atype_modifier; + switch (pd.FixedParameters [i].ModFlags) { + case Parameter.Modifier.REF: + atype_modifier = Argument.AType.Ref; + break; + case Parameter.Modifier.OUT: + atype_modifier = Argument.AType.Out; + break; + default: + atype_modifier = 0; + break; + } + + delegate_arguments.Add (new Argument (new TypeExpression (types [i], loc), atype_modifier)); + } + + return delegate_arguments; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + MemberAccess ma = new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Delegate", loc), "CreateDelegate", loc); + + Arguments args = new Arguments (3); + args.Add (new Argument (new TypeOf (type, loc))); + + if (method_group.InstanceExpression == null) + args.Add (new Argument (new NullLiteral (loc))); + else + args.Add (new Argument (method_group.InstanceExpression)); + + args.Add (new Argument (method_group.CreateExpressionTree (ec))); + Expression e = new Invocation (ma, args).Resolve (ec); + if (e == null) + return null; + + e = Convert.ExplicitConversion (ec, e, type, loc); + if (e == null) + return null; + + return e.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + constructor_method = Delegate.GetConstructor (type); + + var invoke_method = Delegate.GetInvokeMethod (type); + + Arguments arguments = CreateDelegateMethodArguments (invoke_method.Parameters, invoke_method.Parameters.Types, loc); + method_group = method_group.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.CovariantDelegate); + if (method_group == null) + return null; + + var delegate_method = method_group.BestCandidate; + + if (delegate_method.DeclaringType.IsNullableType) { + ec.Report.Error (1728, loc, "Cannot create delegate from method `{0}' because it is a member of System.Nullable type", + delegate_method.GetSignatureForError ()); + return null; + } + + Invocation.IsSpecialMethodInvocation (ec, delegate_method, loc); + + ExtensionMethodGroupExpr emg = method_group as ExtensionMethodGroupExpr; + if (emg != null) { + method_group.InstanceExpression = emg.ExtensionExpression; + TypeSpec e_type = emg.ExtensionExpression.Type; + if (TypeSpec.IsValueType (e_type)) { + ec.Report.Error (1113, loc, "Extension method `{0}' of value type `{1}' cannot be used to create delegates", + delegate_method.GetSignatureForError (), TypeManager.CSharpName (e_type)); + } + } + + TypeSpec rt = delegate_method.ReturnType; + if (!Delegate.IsTypeCovariant (ec, rt, invoke_method.ReturnType)) { + Expression ret_expr = new TypeExpression (rt, loc); + Error_ConversionFailed (ec, delegate_method, ret_expr); + } + + if (delegate_method.IsConditionallyExcluded (ec.Module.Compiler, loc)) { + ec.Report.SymbolRelatedToPreviousError (delegate_method); + MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator; + if (m != null && m.IsPartialDefinition) { + ec.Report.Error (762, loc, "Cannot create delegate from partial method declaration `{0}'", + delegate_method.GetSignatureForError ()); + } else { + ec.Report.Error (1618, loc, "Cannot create delegate with `{0}' because it has a Conditional attribute", + TypeManager.CSharpSignature (delegate_method)); + } + } + + var expr = method_group.InstanceExpression; + if (expr != null && (expr.Type.IsGenericParameter || !TypeSpec.IsReferenceType (expr.Type))) + method_group.InstanceExpression = new BoxedCast (expr, ec.BuiltinTypes.Object); + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + if (method_group.InstanceExpression == null) + ec.Emit (OpCodes.Ldnull); + else + method_group.InstanceExpression.Emit (ec); + + var delegate_method = method_group.BestCandidate; + + // Any delegate must be sealed + if (!delegate_method.DeclaringType.IsDelegate && delegate_method.IsVirtual && !method_group.IsBase) { + ec.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Ldvirtftn, delegate_method); + } else { + ec.Emit (OpCodes.Ldftn, delegate_method); + } + + ec.Emit (OpCodes.Newobj, constructor_method); + } + + void Error_ConversionFailed (ResolveContext ec, MethodSpec method, Expression return_type) + { + var invoke_method = Delegate.GetInvokeMethod (type); + string member_name = method_group.InstanceExpression != null ? + Delegate.FullDelegateDesc (method) : + TypeManager.GetFullNameSignature (method); + + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.SymbolRelatedToPreviousError (method); + if (ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) { + ec.Report.Error (410, loc, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type", + TypeManager.CSharpName (method.ReturnType), member_name, + TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); + return; + } + + if (return_type == null) { + ec.Report.Error (123, loc, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters", + member_name, Delegate.FullDelegateDesc (invoke_method)); + return; + } + + ec.Report.Error (407, loc, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type", + return_type.GetSignatureForError (), member_name, + TypeManager.CSharpName (invoke_method.ReturnType), Delegate.FullDelegateDesc (invoke_method)); + } + + public static bool ImplicitStandardConversionExists (ResolveContext ec, MethodGroupExpr mg, TypeSpec target_type) + { +// if (target_type == TypeManager.delegate_type || target_type == TypeManager.multicast_delegate_type) +// return false; + + var invoke = Delegate.GetInvokeMethod (target_type); + + Arguments arguments = CreateDelegateMethodArguments (invoke.Parameters, invoke.Parameters.Types, mg.Location); + return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly) != null; + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) + { + return false; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + Error_ConversionFailed (rc, best as MethodSpec, null); + return true; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + Error_ConversionFailed (rc, best as MethodSpec, null); + return true; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + return false; + } + + #endregion + } + + // + // Created from the conversion code + // + public class ImplicitDelegateCreation : DelegateCreation + { + ImplicitDelegateCreation (TypeSpec t, MethodGroupExpr mg, Location l) + { + type = t; + this.method_group = mg; + loc = l; + } + + static public Expression Create (ResolveContext ec, MethodGroupExpr mge, + TypeSpec target_type, Location loc) + { + ImplicitDelegateCreation d = new ImplicitDelegateCreation (target_type, mge, loc); + return d.DoResolve (ec); + } + } + + // + // A delegate-creation-expression, invoked from the `New' class + // + public class NewDelegate : DelegateCreation + { + public Arguments Arguments; + + // + // This constructor is invoked from the `New' expression + // + public NewDelegate (TypeSpec type, Arguments Arguments, Location loc) + { + this.type = type; + this.Arguments = Arguments; + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (Arguments == null || Arguments.Count != 1) { + ec.Report.Error (149, loc, "Method name expected"); + return null; + } + + Argument a = Arguments [0]; + if (!a.ResolveMethodGroup (ec)) + return null; + + Expression e = a.Expr; + + AnonymousMethodExpression ame = e as AnonymousMethodExpression; + if (ame != null && ec.Module.Compiler.Settings.Version != LanguageVersion.ISO_1) { + e = ame.Compatible (ec, type); + if (e == null) + return null; + + return e.Resolve (ec); + } + + method_group = e as MethodGroupExpr; + if (method_group == null) { + if (e.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + e = Convert.ImplicitConversionRequired (ec, e, type, loc); + } else if (!e.Type.IsDelegate) { + e.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup | ResolveFlags.Type, loc); + return null; + } + + // + // An argument is not a method but another delegate + // + method_group = new MethodGroupExpr (Delegate.GetInvokeMethod (e.Type), e.Type, loc); + method_group.InstanceExpression = e; + } + + return base.DoResolve (ec); + } + } + + // + // Invocation converted to delegate Invoke call + // + class DelegateInvocation : ExpressionStatement + { + readonly Expression InstanceExpr; + Arguments arguments; + MethodSpec method; + + public DelegateInvocation (Expression instance_expr, Arguments args, Location loc) + { + this.InstanceExpr = instance_expr; + this.arguments = args; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, this.arguments, + InstanceExpr.CreateExpressionTree (ec)); + + return CreateExpressionFactoryCall (ec, "Invoke", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + TypeSpec del_type = InstanceExpr.Type; + if (del_type == null) + return null; + + // + // Do only core overload resolution the rest of the checks has been + // done on primary expression + // + method = Delegate.GetInvokeMethod (del_type); + var res = new OverloadResolver (new MemberSpec[] { method }, OverloadResolver.Restrictions.DelegateInvoke, loc); + var valid = res.ResolveMember (ec, ref arguments); + if (valid == null && !res.BestCandidateIsDynamic) + return null; + + type = method.ReturnType; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + // + // Invocation on delegates call the virtual Invoke member + // so we are always `instance' calls + // + Invocation.EmitCall (ec, InstanceExpr, method, arguments, loc); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec); + // + // Pop the return value if there is one + // + if (type.Kind != MemberKind.Void) + ec.Emit (OpCodes.Pop); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + return Invocation.MakeExpression (ctx, InstanceExpr, method, arguments); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj new file mode 100644 index 0000000000..154cad4949 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj @@ -0,0 +1,154 @@ + + + + Debug + AnyCPU + 10.0.20506 + 2.0 + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56} + Exe + Properties + dmcs + dmcs + v4.0 + 512 + x86 + + + true + full + false + .\ + TRACE;DEBUG;NET_4_0;MS_COMPATIBLE + prompt + 4 + true + + + pdbonly + true + TRACE;NET_2_0;MS_COMPATIBLE;GMCS_SOURCE + prompt + prompt + 4 + .\ + + + + + + + + + + CryptoConvert.cs + + + MonoSymbolFile.cs + + + MonoSymbolTable.cs + + + MonoSymbolWriter.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + outline.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config new file mode 100644 index 0000000000..cab6cf8fa5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources new file mode 100644 index 0000000000..71a658ad1f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources @@ -0,0 +1,55 @@ +AssemblyInfo.cs +anonymous.cs +argument.cs +assign.cs +attribute.cs +cs-tokenizer.cs +cfold.cs +class.cs +codegen.cs +complete.cs +const.cs +constant.cs +convert.cs +context.cs +decl.cs +delegate.cs +doc.cs +driver.cs +dynamic.cs +ecore.cs +enum.cs +eval.cs +expression.cs +field.cs +flowanalysis.cs +generic.cs +import.cs +iterators.cs +lambda.cs +linq.cs +literal.cs +location.cs +membercache.cs +method.cs +modifiers.cs +namespace.cs +nullable.cs +parameter.cs +pending.cs +property.cs +report.cs +rootcontext.cs +roottypes.cs +statement.cs +support.cs +typemanager.cs +typespec.cs +visit.cs +symbolwriter.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs +../build/common/Consts.cs +../tools/monop/outline.cs diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln new file mode 100644 index 0000000000..2ea4ed44aa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dmcs", "dmcs.csproj", "{D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs new file mode 100644 index 0000000000..f81f7e86aa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs @@ -0,0 +1,59 @@ +// +// doc-bootstrap.cs: Stub support for XML documentation. +// +// Author: +// Raja R Harinath +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2004 Novell, Inc. +// +// + +#if BOOTSTRAP_WITH_OLDLIB || NET_2_1 + +using XmlElement = System.Object; + +namespace Mono.CSharp { + public class DocUtil + { + internal static void GenerateTypeDocComment (TypeContainer t, DeclSpace ds, Report r) + { + } + + internal static void GenerateDocComment (MemberCore mc, DeclSpace ds, Report r) + { + } + + public static string GetMethodDocCommentName (MemberCore mc, ParametersCompiled p, DeclSpace ds) + { + return ""; + } + + internal static void OnMethodGenerateDocComment (MethodCore mc, XmlElement el, Report r) + { + } + + public static void GenerateEnumDocComment (Enum e, DeclSpace ds) + { + } + } + + public class Documentation + { + public Documentation (string xml_output_filename) + { + } + + public bool OutputDocComment (string asmfilename, Report r) + { + return true; + } + + public void GenerateDocComment () + { + } + } +} + +#endif diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs new file mode 100644 index 0000000000..769154d691 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs @@ -0,0 +1,645 @@ +// +// doc.cs: Support for XML documentation comment. +// +// Authors: +// Atsushi Enomoto +// Marek Safar (marek.safar@gmail.com> +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2004 Novell, Inc. +// +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Xml; +using System.Linq; + +namespace Mono.CSharp +{ + // + // Implements XML documentation generation. + // + class DocumentationBuilder + { + // + // Used to create element which helps well-formedness checking. + // + readonly XmlDocument XmlDocumentation; + + readonly ModuleContainer module; + + // + // The output for XML documentation. + // + XmlWriter XmlCommentOutput; + + static readonly string line_head = Environment.NewLine + " "; + + // + // Stores XmlDocuments that are included in XML documentation. + // Keys are included filenames, values are XmlDocuments. + // + Dictionary StoredDocuments = new Dictionary (); + + public DocumentationBuilder (ModuleContainer module) + { + this.module = module; + XmlDocumentation = new XmlDocument (); + XmlDocumentation.PreserveWhitespace = false; + } + + Report Report { + get { + return module.Compiler.Report; + } + } + + public MemberName ParsedName { + get; set; + } + + public List ParsedParameters { + get; set; + } + + public TypeExpression ParsedBuiltinType { + get; set; + } + + public Operator.OpType? ParsedOperator { + get; set; + } + + XmlNode GetDocCommentNode (MemberCore mc, string name) + { + // FIXME: It could be even optimizable as not + // to use XmlDocument. But anyways the nodes + // are not kept in memory. + XmlDocument doc = XmlDocumentation; + try { + XmlElement el = doc.CreateElement ("member"); + el.SetAttribute ("name", name); + string normalized = mc.DocComment; + el.InnerXml = normalized; + // csc keeps lines as written in the sources + // and inserts formatting indentation (which + // is different from XmlTextWriter.Formatting + // one), but when a start tag contains an + // endline, it joins the next line. We don't + // have to follow such a hacky behavior. + string [] split = + normalized.Split ('\n'); + int j = 0; + for (int i = 0; i < split.Length; i++) { + string s = split [i].TrimEnd (); + if (s.Length > 0) + split [j++] = s; + } + el.InnerXml = line_head + String.Join ( + line_head, split, 0, j); + return el; + } catch (Exception ex) { + Report.Warning (1570, 1, mc.Location, "XML documentation comment on `{0}' is not well-formed XML markup ({1})", + mc.GetSignatureForError (), ex.Message); + + return doc.CreateComment (String.Format ("FIXME: Invalid documentation markup was found for member {0}", name)); + } + } + + // + // Generates xml doc comments (if any), and if required, + // handle warning report. + // + internal void GenerateDocumentationForMember (MemberCore mc) + { + string name = mc.DocCommentHeader + mc.GetSignatureForDocumentation (); + + XmlNode n = GetDocCommentNode (mc, name); + + XmlElement el = n as XmlElement; + if (el != null) { + var pm = mc as IParametersMember; + if (pm != null) { + CheckParametersComments (mc, pm, el); + } + + // FIXME: it could be done with XmlReader + XmlNodeList nl = n.SelectNodes (".//include"); + if (nl.Count > 0) { + // It could result in current node removal, so prepare another list to iterate. + var al = new List (nl.Count); + foreach (XmlNode inc in nl) + al.Add (inc); + foreach (XmlElement inc in al) + if (!HandleInclude (mc, inc)) + inc.ParentNode.RemoveChild (inc); + } + + // FIXME: it could be done with XmlReader + DeclSpace ds_target = mc as DeclSpace; + if (ds_target == null) + ds_target = mc.Parent; + + foreach (XmlElement see in n.SelectNodes (".//see")) + HandleSee (mc, ds_target, see); + foreach (XmlElement seealso in n.SelectNodes (".//seealso")) + 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); + } + + // + // Processes "include" element. Check included file and + // embed the document content inside this documentation node. + // + bool HandleInclude (MemberCore mc, XmlElement el) + { + bool keep_include_node = false; + string file = el.GetAttribute ("file"); + string path = el.GetAttribute ("path"); + if (file == "") { + Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `file' attribute"); + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el); + keep_include_node = true; + } + else if (path.Length == 0) { + Report.Warning (1590, 1, mc.Location, "Invalid XML `include' element. Missing `path' attribute"); + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Include tag is invalid "), el); + keep_include_node = true; + } + else { + XmlDocument doc; + if (!StoredDocuments.TryGetValue (file, out doc)) { + try { + doc = new XmlDocument (); + doc.Load (file); + StoredDocuments.Add (file, doc); + } catch (Exception) { + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (String.Format (" Badly formed XML in at comment file `{0}': cannot be included ", file)), el); + Report.Warning (1592, 1, mc.Location, "Badly formed XML in included comments file -- `{0}'", file); + } + } + if (doc != null) { + try { + XmlNodeList nl = doc.SelectNodes (path); + if (nl.Count == 0) { + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" No matching elements were found for the include tag embedded here. "), el); + + keep_include_node = true; + } + foreach (XmlNode n in nl) + el.ParentNode.InsertBefore (el.OwnerDocument.ImportNode (n, true), el); + } catch (Exception ex) { + el.ParentNode.InsertBefore (el.OwnerDocument.CreateComment (" Failed to insert some or all of included XML "), el); + Report.Warning (1589, 1, mc.Location, "Unable to include XML fragment `{0}' of file `{1}' ({2})", path, file, ex.Message); + } + } + } + return keep_include_node; + } + + // + // Handles elements. + // + void HandleSee (MemberCore mc, DeclSpace ds, XmlElement see) + { + HandleXrefCommon (mc, ds, see); + } + + // + // Handles elements. + // + void HandleSeeAlso (MemberCore mc, DeclSpace ds, XmlElement seealso) + { + HandleXrefCommon (mc, ds, seealso); + } + + // + // Handles elements. + // + void HandleException (MemberCore mc, DeclSpace ds, XmlElement seealso) + { + HandleXrefCommon (mc, ds, seealso); + } + + // + // Handles 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 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) + return context.LookupNamespaceOrType (mn.Name, mn.Arity, LookupMode.Probing, Location.Null); + + var left = ResolveMemberName (context, mn.Left); + var ns = left as Namespace; + if (ns != null) + return ns.LookupTypeOrNamespace (context, mn.Name, mn.Arity, LookupMode.Probing, Location.Null); + + TypeExpr texpr = left as TypeExpr; + if (texpr != null) { + var found = MemberCache.FindNestedType (texpr.Type, ParsedName.Name, ParsedName.Arity); + if (found != null) + return new TypeExpression (found, Location.Null); + + return null; + } + + return left; + } + + // + // Processes "see" or "seealso" elements from cref attribute. + // + void HandleXrefCommon (MemberCore mc, DeclSpace ds, XmlElement xref) + { + string cref = xref.GetAttribute ("cref"); + // when, XmlReader, "if (cref == null)" + if (!xref.HasAttribute ("cref")) + return; + + // Nothing to be resolved the reference is marked explicitly + if (cref.Length > 2 && cref [1] == ':') + return; + + // Additional symbols for < and > are allowed for easier XML typing + cref = cref.Replace ('{', '<').Replace ('}', '>'); + + var encoding = module.Compiler.Settings.Encoding; + var s = new MemoryStream (encoding.GetBytes (cref)); + SeekableStreamReader seekable = new SeekableStreamReader (s, encoding); + + var source_file = new CompilationSourceFile ("{documentation}", "", 1); + var doc_module = new ModuleContainer (module.Compiler); + doc_module.DocumentationBuilder = this; + source_file.NamespaceContainer = new NamespaceContainer (null, doc_module, null, source_file); + + Report parse_report = new Report (new NullReportPrinter ()); + var parser = new CSharpParser (seekable, source_file, parse_report); + ParsedParameters = null; + ParsedName = null; + ParsedBuiltinType = null; + ParsedOperator = null; + parser.Lexer.putback_char = Tokenizer.DocumentationXref; + parser.Lexer.parsing_generic_declaration_doc = true; + parser.parse (); + if (parse_report.Errors > 0) { + Report.Warning (1584, 1, mc.Location, "XML comment on `{0}' has syntactically incorrect cref attribute `{1}'", + mc.GetSignatureForError (), cref); + + xref.SetAttribute ("cref", "!:" + cref); + return; + } + + MemberSpec member; + string prefix = null; + FullNamedExpression fne = null; + + // + // Try built-in type first because we are using ParsedName as identifier of + // member names on built-in types + // + if (ParsedBuiltinType != null && (ParsedParameters == null || ParsedName != null)) { + member = ParsedBuiltinType.Type; + } else { + member = null; + } + + if (ParsedName != null || ParsedOperator.HasValue) { + TypeSpec type = null; + string member_name = null; + + if (member == null) { + if (ParsedOperator.HasValue) { + type = mc.CurrentType; + } else if (ParsedName.Left != null) { + fne = ResolveMemberName (mc, ParsedName.Left); + if (fne != null) { + var ns = fne as Namespace; + if (ns != null) { + fne = ns.LookupTypeOrNamespace (mc, ParsedName.Name, ParsedName.Arity, LookupMode.Probing, Location.Null); + if (fne != null) { + member = fne.Type; + } + } else { + type = fne.Type; + } + } + } else { + fne = ResolveMemberName (mc, ParsedName); + if (fne == null) { + type = mc.CurrentType; + } else if (ParsedParameters == null) { + member = fne.Type; + } else if (fne.Type.MemberDefinition == mc.CurrentType.MemberDefinition) { + member_name = Constructor.ConstructorName; + type = fne.Type; + } + } + } else { + type = (TypeSpec) member; + member = null; + } + + if (ParsedParameters != null) { + var old_printer = mc.Module.Compiler.Report.SetPrinter (new NullReportPrinter ()); + foreach (var pp in ParsedParameters) { + pp.Resolve (mc); + } + mc.Module.Compiler.Report.SetPrinter (old_printer); + } + + if (type != null) { + if (member_name == null) + member_name = ParsedOperator.HasValue ? + Operator.GetMetadataName (ParsedOperator.Value) : ParsedName.Name; + + int parsed_param_count; + if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) { + parsed_param_count = ParsedParameters.Count - 1; + } else if (ParsedParameters != null) { + parsed_param_count = ParsedParameters.Count; + } else { + parsed_param_count = 0; + } + + int parameters_match = -1; + do { + var members = MemberCache.FindMembers (type, member_name, true); + if (members != null) { + foreach (var m in members) { + if (ParsedName != null && m.Arity != ParsedName.Arity) + continue; + + if (ParsedParameters != null) { + IParametersMember pm = m as IParametersMember; + if (pm == null) + continue; + + if (m.Kind == MemberKind.Operator && !ParsedOperator.HasValue) + continue; + + int i; + for (i = 0; i < parsed_param_count; ++i) { + var pparam = ParsedParameters[i]; + + if (i >= pm.Parameters.Count || pparam == null || + pparam.TypeSpec != pm.Parameters.Types[i] || + (pparam.Modifier & Parameter.Modifier.SignatureMask) != (pm.Parameters.FixedParameters[i].ModFlags & Parameter.Modifier.SignatureMask)) { + + if (i > parameters_match) { + parameters_match = i; + } + + i = -1; + break; + } + } + + if (i < 0) + continue; + + if (ParsedOperator == Operator.OpType.Explicit || ParsedOperator == Operator.OpType.Implicit) { + if (pm.MemberType != ParsedParameters[parsed_param_count].TypeSpec) { + parameters_match = parsed_param_count + 1; + continue; + } + } else { + if (parsed_param_count != pm.Parameters.Count) + continue; + } + } + + if (member != null) { + Report.Warning (419, 3, mc.Location, + "Ambiguous reference in cref attribute `{0}'. Assuming `{1}' but other overloads including `{2}' have also matched", + cref, member.GetSignatureForError (), m.GetSignatureForError ()); + + break; + } + + member = m; + } + } + + // Continue with parent type for nested types + if (member == null) { + type = type.DeclaringType; + } else { + type = null; + } + } while (type != null); + + if (member == null && parameters_match >= 0) { + for (int i = parameters_match; i < parsed_param_count; ++i) { + Report.Warning (1580, 1, mc.Location, "Invalid type for parameter `{0}' in XML comment cref attribute `{1}'", + (i + 1).ToString (), cref); + } + + if (parameters_match == parsed_param_count + 1) { + Report.Warning (1581, 1, mc.Location, "Invalid return type in XML comment cref attribute `{0}'", cref); + } + } + } + } + + if (member == null) { + Report.Warning (1574, 1, mc.Location, "XML comment on `{0}' has cref attribute `{1}' that could not be resolved", + mc.GetSignatureForError (), cref); + cref = "!:" + cref; + } else if (member == InternalType.Namespace) { + cref = "N:" + fne.GetSignatureForError (); + } else { + prefix = GetMemberDocHead (member); + cref = prefix + member.GetSignatureForDocumentation (); + } + + xref.SetAttribute ("cref", cref); + } + + // + // Get a prefix from member type for XML documentation (used + // to formalize cref target name). + // + static string GetMemberDocHead (MemberSpec type) + { + if (type is FieldSpec) + return "F:"; + if (type is MethodSpec) + return "M:"; + if (type is EventSpec) + return "E:"; + if (type is PropertySpec) + return "P:"; + if (type is TypeSpec) + return "T:"; + + throw new NotImplementedException (type.GetType ().ToString ()); + } + + // + // Raised (and passed an XmlElement that contains the comment) + // when GenerateDocComment is writing documentation expectedly. + // + // FIXME: with a few effort, it could be done with XmlReader, + // that means removal of DOM use. + // + void CheckParametersComments (MemberCore member, IParametersMember paramMember, XmlElement el) + { + HashSet found_tags = null; + foreach (XmlElement pelem in el.SelectNodes ("param")) { + string xname = pelem.GetAttribute ("name"); + if (xname.Length == 0) + continue; // really? but MS looks doing so + + if (found_tags == null) { + found_tags = new HashSet (); + } + + if (xname != "" && paramMember.Parameters.GetParameterIndexByName (xname) < 0) { + Report.Warning (1572, 2, member.Location, + "XML comment on `{0}' has a param tag for `{1}', but there is no parameter by that name", + member.GetSignatureForError (), xname); + continue; + } + + if (found_tags.Contains (xname)) { + Report.Warning (1571, 2, member.Location, + "XML comment on `{0}' has a duplicate param tag for `{1}'", + member.GetSignatureForError (), xname); + continue; + } + + found_tags.Add (xname); + } + + if (found_tags != null) { + foreach (Parameter p in paramMember.Parameters.FixedParameters) { + if (!found_tags.Contains (p.Name) && !(p is ArglistParameter)) + Report.Warning (1573, 4, member.Location, + "Parameter `{0}' has no matching param tag in the XML comment for `{1}'", + p.Name, member.GetSignatureForError ()); + } + } + } + + // + // Outputs XML documentation comment from tokenized comments. + // + public bool OutputDocComment (string asmfilename, string xmlFileName) + { + XmlTextWriter w = null; + try { + w = new XmlTextWriter (xmlFileName, null); + w.Indentation = 4; + w.Formatting = Formatting.Indented; + w.WriteStartDocument (); + w.WriteStartElement ("doc"); + w.WriteStartElement ("assembly"); + w.WriteStartElement ("name"); + w.WriteString (Path.GetFileNameWithoutExtension (asmfilename)); + w.WriteEndElement (); // name + w.WriteEndElement (); // assembly + w.WriteStartElement ("members"); + XmlCommentOutput = w; + module.GenerateDocComment (this); + w.WriteFullEndElement (); // members + w.WriteEndElement (); + w.WriteWhitespace (Environment.NewLine); + w.WriteEndDocument (); + return true; + } catch (Exception ex) { + Report.Error (1569, "Error generating XML documentation file `{0}' (`{1}')", xmlFileName, ex.Message); + return false; + } finally { + if (w != null) + w.Close (); + } + } + } + + class DocumentationParameter + { + public readonly Parameter.Modifier Modifier; + public FullNamedExpression Type; + TypeSpec type; + + public DocumentationParameter (Parameter.Modifier modifier, FullNamedExpression type) + : this (type) + { + this.Modifier = modifier; + } + + public DocumentationParameter (FullNamedExpression type) + { + this.Type = type; + } + + public TypeSpec TypeSpec { + get { + return type; + } + } + + public void Resolve (IMemberContext context) + { + type = Type.ResolveAsType (context); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs new file mode 100644 index 0000000000..de220c3e79 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs @@ -0,0 +1,472 @@ +// +// driver.cs: The compiler command line driver. +// +// Authors: +// Miguel de Icaza (miguel@gnu.org) +// 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, 2005, 2006, 2007, 2008 Novell, Inc +// + +using System; +using System.Reflection; +using System.Reflection.Emit; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Globalization; +using System.Diagnostics; + +namespace Mono.CSharp +{ + /// + /// The compiler driver. + /// + class Driver + { + readonly CompilerContext ctx; + + public Driver (CompilerContext ctx) + { + this.ctx = ctx; + } + + Report Report { + get { + return ctx.Report; + } + } + + void tokenize_file (CompilationSourceFile file) + { + Stream input; + + try { + input = File.OpenRead (file.Name); + } catch { + Report.Error (2001, "Source file `" + file.Name + "' could not be found"); + return; + } + + using (input){ + SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding); + Tokenizer lexer = new Tokenizer (reader, file, ctx); + int token, tokens = 0, errors = 0; + + while ((token = lexer.token ()) != Token.EOF){ + tokens++; + if (token == Token.ERROR) + errors++; + } + Console.WriteLine ("Tokenized: " + tokens + " found " + errors + " errors"); + } + + return; + } + + void Parse (ModuleContainer module) + { + Location.Initialize (module.Compiler.SourceFiles); + + bool tokenize_only = module.Compiler.Settings.TokenizeOnly; + var sources = module.Compiler.SourceFiles; + for (int i = 0; i < sources.Count; ++i) { + if (tokenize_only) { + tokenize_file (sources[i]); + } else { + Parse (sources[i], module); + } + } + } + + public void Parse (CompilationSourceFile file, ModuleContainer module) + { + Stream input; + + try { + input = File.OpenRead (file.Name); + } catch { + Report.Error (2001, "Source file `{0}' could not be found", file.Name); + return; + } + + // Check 'MZ' header + if (input.ReadByte () == 77 && input.ReadByte () == 90) { + Report.Error (2015, "Source file `{0}' is a binary file and not a text file", file.Name); + input.Close (); + return; + } + + input.Position = 0; + SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding); + + Parse (reader, file, module); + reader.Dispose (); + input.Close (); + } + + public void Parse (SeekableStreamReader reader, CompilationSourceFile file, ModuleContainer module) + { + file.NamespaceContainer = new NamespaceContainer (null, module, null, file); + + CSharpParser parser = new CSharpParser (reader, file); + parser.parse (); + } + + public static int Main (string[] args) + { + Location.InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t"; + + var r = new Report (new ConsoleReportPrinter ()); + CommandLineParser cmd = new CommandLineParser (r); + var settings = cmd.ParseArguments (args); + if (settings == null || r.Errors > 0) + return 1; + + if (cmd.HasBeenStopped) + return 0; + + Driver d = new Driver (new CompilerContext (settings, r)); + + if (d.Compile () && d.Report.Errors == 0) { + if (d.Report.Warnings > 0) { + Console.WriteLine ("Compilation succeeded - {0} warning(s)", d.Report.Warnings); + } + Environment.Exit (0); + return 0; + } + + + Console.WriteLine("Compilation failed: {0} error(s), {1} warnings", + d.Report.Errors, d.Report.Warnings); + Environment.Exit (1); + return 1; + } + + public static string GetPackageFlags (string packages, Report report) + { + ProcessStartInfo pi = new ProcessStartInfo (); + pi.FileName = "pkg-config"; + pi.RedirectStandardOutput = true; + pi.UseShellExecute = false; + pi.Arguments = "--libs " + packages; + Process p = null; + try { + p = Process.Start (pi); + } catch (Exception e) { + if (report == null) + throw; + + report.Error (-27, "Couldn't run pkg-config: " + e.Message); + return null; + } + + if (p.StandardOutput == null) { + if (report == null) + throw new ApplicationException ("Specified package did not return any information"); + + report.Warning (-27, 1, "Specified package did not return any information"); + p.Close (); + return null; + } + + string pkgout = p.StandardOutput.ReadToEnd (); + p.WaitForExit (); + if (p.ExitCode != 0) { + if (report == null) + throw new ApplicationException (pkgout); + + report.Error (-27, "Error running pkg-config. Check the above output."); + p.Close (); + return null; + } + + p.Close (); + return pkgout; + } + + // + // Main compilation method + // + public bool Compile () + { + var settings = ctx.Settings; + + // + // If we are an exe, require a source file for the entry point or + // if there is nothing to put in the assembly, and we are not a library + // + if (settings.FirstSourceFile == null && + ((settings.Target == Target.Exe || settings.Target == Target.WinExe || settings.Target == Target.Module) || + settings.Resources == null)) { + Report.Error (2008, "No files to compile were specified"); + return false; + } + + TimeReporter tr = new TimeReporter (settings.Timestamps); + ctx.TimeReporter = tr; + tr.StartTotal (); + + var module = new ModuleContainer (ctx); + RootContext.ToplevelTypes = module; + + tr.Start (TimeReporter.TimerType.ParseTotal); + Parse (module); + tr.Stop (TimeReporter.TimerType.ParseTotal); + + if (Report.Errors > 0) + return false; + + if (settings.TokenizeOnly || settings.ParseOnly) { + tr.StopTotal (); + tr.ShowStats (); + return true; + } + + var output_file = settings.OutputFile; + string output_file_name; + if (output_file == null) { + var source_file = settings.FirstSourceFile; + + if (source_file == null) { + Report.Error (1562, "If no source files are specified you must specify the output file with -out:"); + return false; + } + + output_file_name = source_file.Name; + int pos = output_file_name.LastIndexOf ('.'); + + if (pos > 0) + output_file_name = output_file_name.Substring (0, pos); + + output_file_name += settings.TargetExt; + output_file = output_file_name; + } else { + output_file_name = Path.GetFileName (output_file); + } + +#if STATIC + var importer = new StaticImporter (module); + var references_loader = new StaticLoader (importer, ctx); + + tr.Start (TimeReporter.TimerType.AssemblyBuilderSetup); + var assembly = new AssemblyDefinitionStatic (module, references_loader, output_file_name, output_file); + assembly.Create (references_loader.Domain); + tr.Stop (TimeReporter.TimerType.AssemblyBuilderSetup); + + // Create compiler types first even before any referenced + // assembly is loaded to allow forward referenced types from + // loaded assembly into compiled builder to be resolved + // correctly + tr.Start (TimeReporter.TimerType.CreateTypeTotal); + module.CreateType (); + importer.AddCompiledAssembly (assembly); + tr.Stop (TimeReporter.TimerType.CreateTypeTotal); + + references_loader.LoadReferences (module); + + tr.Start (TimeReporter.TimerType.PredefinedTypesInit); + if (!ctx.BuiltinTypes.CheckDefinitions (module)) + return false; + + tr.Stop (TimeReporter.TimerType.PredefinedTypesInit); + + references_loader.LoadModules (assembly, module.GlobalRootNamespace); +#else + var assembly = new AssemblyDefinitionDynamic (module, output_file_name, output_file); + module.SetDeclaringAssembly (assembly); + + var importer = new ReflectionImporter (module, ctx.BuiltinTypes); + assembly.Importer = importer; + + var loader = new DynamicLoader (importer, ctx); + loader.LoadReferences (module); + + if (!ctx.BuiltinTypes.CheckDefinitions (module)) + return false; + + if (!assembly.Create (AppDomain.CurrentDomain, AssemblyBuilderAccess.Save)) + return false; + + module.CreateType (); + + loader.LoadModules (assembly, module.GlobalRootNamespace); +#endif + module.InitializePredefinedTypes (); + + tr.Start (TimeReporter.TimerType.UsingResolve); + foreach (var source_file in ctx.SourceFiles) { + source_file.NamespaceContainer.Resolve (); + } + tr.Stop (TimeReporter.TimerType.UsingResolve); + + tr.Start (TimeReporter.TimerType.ModuleDefinitionTotal); + module.Define (); + tr.Stop (TimeReporter.TimerType.ModuleDefinitionTotal); + + if (Report.Errors > 0) + return false; + + if (settings.DocumentationFile != null) { + var doc = new DocumentationBuilder (module); + doc.OutputDocComment (output_file, settings.DocumentationFile); + } + + assembly.Resolve (); + + if (Report.Errors > 0) + return false; + + + tr.Start (TimeReporter.TimerType.EmitTotal); + assembly.Emit (); + tr.Stop (TimeReporter.TimerType.EmitTotal); + + if (Report.Errors > 0){ + return false; + } + + tr.Start (TimeReporter.TimerType.CloseTypes); + module.CloseType (); + tr.Stop (TimeReporter.TimerType.CloseTypes); + + tr.Start (TimeReporter.TimerType.Resouces); + assembly.EmbedResources (); + tr.Stop (TimeReporter.TimerType.Resouces); + + if (Report.Errors > 0) + return false; + + assembly.Save (); + +#if STATIC + references_loader.Dispose (); +#endif + tr.StopTotal (); + tr.ShowStats (); + + return Report.Errors == 0; + } + } + + public class CompilerCompilationUnit { + public ModuleContainer ModuleCompiled { get; set; } + public LocationsBag LocationsBag { get; set; } + public UsingsBag UsingsBag { get; set; } + public SpecialsBag SpecialsBag { get; set; } + public object LastYYValue { get; set; } + } + + // + // This is the only public entry point + // + public class CompilerCallableEntryPoint : MarshalByRefObject { + + public static bool InvokeCompiler (string [] args, TextWriter error) + { + try { + var r = new Report (new StreamReportPrinter (error)); + CommandLineParser cmd = new CommandLineParser (r, error); + var setting = cmd.ParseArguments (args); + if (setting == null || r.Errors > 0) + return false; + + var d = new Driver (new CompilerContext (setting, r)); + return d.Compile (); + } finally { + Reset (); + } + } + + public static int[] AllWarningNumbers { + get { + return Report.AllWarnings; + } + } + + public static void Reset () + { + Reset (true); + } + + public static void PartialReset () + { + Reset (false); + } + + public static void Reset (bool full_flag) + { + CSharpParser.yacc_verbose_flag = 0; + Location.Reset (); + + if (!full_flag) + return; + + AnonymousTypeClass.Reset (); + AnonymousMethodBody.Reset (); + AnonymousMethodStorey.Reset (); + SymbolWriter.Reset (); + Switch.Reset (); + Linq.QueryBlock.TransparentParameter.Reset (); + TypeInfo.Reset (); + } + + public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, TextWriter reportStream) + { + return ParseFile (args, input, inputFile, new StreamReportPrinter (reportStream)); + } + + internal static object parseLock = new object (); + + public static CompilerCompilationUnit ParseFile (string[] args, Stream input, string inputFile, ReportPrinter reportPrinter) + { + lock (parseLock) { + try { + // Driver d = Driver.Create (args, false, null, reportPrinter); + // if (d == null) + // return null; + + var r = new Report (reportPrinter); + CommandLineParser cmd = new CommandLineParser (r, Console.Out); + var setting = cmd.ParseArguments (args); + if (setting == null || r.Errors > 0) + return null; + + CompilerContext ctx = new CompilerContext (setting, r); + + var files = new List (); + var unit = new CompilationSourceFile (inputFile, inputFile, 0); + var module = new ModuleContainer (ctx); + unit.NamespaceContainer = new NamespaceContainer (null, module, null, unit); + files.Add (unit); + Location.Initialize (files); + + // TODO: encoding from driver + SeekableStreamReader reader = new SeekableStreamReader (input, Encoding.Default); + + RootContext.ToplevelTypes = module; + + CSharpParser parser = new CSharpParser (reader, unit); + parser.Lexer.TabSize = 1; + parser.Lexer.sbag = new SpecialsBag (); + 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, + LastYYValue = parser.LastYYVal + }; + } finally { + Reset (); + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs new file mode 100644 index 0000000000..c7df9f7c85 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs @@ -0,0 +1,965 @@ +// +// dynamic.cs: support for dynamic expressions +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2009 Novell, Inc +// + +using System; +using System.Linq; +using SLE = System.Linq.Expressions; + +#if NET_4_0 +using System.Dynamic; +#endif + +namespace Mono.CSharp +{ + // + // A copy of Microsoft.CSharp/Microsoft.CSharp.RuntimeBinder/CSharpBinderFlags.cs + // has to be kept in sync + // + [Flags] + public enum CSharpBinderFlags + { + None = 0, + CheckedContext = 1, + InvokeSimpleName = 1 << 1, + InvokeSpecialName = 1 << 2, + BinaryOperationLogical = 1 << 3, + ConvertExplicit = 1 << 4, + ConvertArrayIndex = 1 << 5, + ResultIndexed = 1 << 6, + ValueFromCompoundAssignment = 1 << 7, + ResultDiscarded = 1 << 8 + } + + // + // Type expression with internal dynamic type symbol + // + class DynamicTypeExpr : TypeExpr + { + public DynamicTypeExpr (Location loc) + { + this.loc = loc; + } + + public override TypeSpec ResolveAsType (IMemberContext ec) + { + eclass = ExprClass.Type; + type = ec.Module.Compiler.BuiltinTypes.Dynamic; + return type; + } + } + + #region Dynamic runtime binder expressions + + // + // Expression created from runtime dynamic object value by dynamic binder + // + public class RuntimeValueExpression : Expression, IDynamicAssign, IMemoryLocation + { +#if !NET_4_0 + public class DynamicMetaObject + { + public TypeSpec RuntimeType; + public TypeSpec LimitType; + public SLE.Expression Expression; + } +#endif + + readonly DynamicMetaObject obj; + + public RuntimeValueExpression (DynamicMetaObject obj, TypeSpec type) + { + this.obj = obj; + this.type = type; + this.eclass = ExprClass.Variable; + } + + #region Properties + + public bool IsSuggestionOnly { get; set; } + + public DynamicMetaObject MetaObject { + get { return obj; } + } + + #endregion + + public void AddressOf (EmitContext ec, AddressOp mode) + { + throw new NotImplementedException (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotImplementedException (); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + throw new NotImplementedException (); + } + + #endregion + + public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { + return obj.Expression; + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + + #if NET_4_0 + if (type.IsStruct && !obj.Expression.Type.IsValueType) + return SLE.Expression.Unbox (obj.Expression, type.GetMetaInfo ()); + + if (obj.Expression.NodeType == SLE.ExpressionType.Parameter) { + if (((SLE.ParameterExpression) obj.Expression).IsByRef) + return obj.Expression; + } + #endif + + return SLE.Expression.Convert (obj.Expression, type.GetMetaInfo ()); +#endif + } + } + + // + // Wraps runtime dynamic expression into expected type. Needed + // to satify expected type check by dynamic binder and no conversion + // is required (ResultDiscarded). + // + public class DynamicResultCast : ShimExpression + { + public DynamicResultCast (TypeSpec type, Expression expr) + : base (expr) + { + this.type = type; + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + eclass = ExprClass.Value; + return this; + } + +#if NET_4_0 + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Block (expr.MakeExpression (ctx), SLE.Expression.Default (type.GetMetaInfo ())); +#endif + } +#endif + } + + #endregion + + // + // Creates dynamic binder expression + // + interface IDynamicBinder + { + Expression CreateCallSiteBinder (ResolveContext ec, Arguments args); + } + + // + // Extends standard assignment interface for expressions + // supported by dynamic resolver + // + interface IDynamicAssign : IAssignMethod + { + SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source); + } + + // + // Base dynamic expression statement creator + // + class DynamicExpressionStatement : ExpressionStatement + { + // + // Binder flag dynamic constant, the value is combination of + // flags known at resolve stage and flags known only at emit + // stage + // + protected class BinderFlags : EnumConstant + { + DynamicExpressionStatement statement; + CSharpBinderFlags flags; + + public BinderFlags (CSharpBinderFlags flags, DynamicExpressionStatement statement) + : base (statement.loc) + { + this.flags = flags; + this.statement = statement; + eclass = 0; + } + + protected override Expression DoResolve (ResolveContext ec) + { + Child = new IntConstant (ec.BuiltinTypes, (int) (flags | statement.flags), statement.loc); + + type = ec.Module.PredefinedTypes.BinderFlags.Resolve (); + eclass = Child.eclass; + return this; + } + } + + readonly Arguments arguments; + protected IDynamicBinder binder; + protected Expression binder_expr; + + // Used by BinderFlags + protected CSharpBinderFlags flags; + + TypeSpec binder_type; + TypeParameter[] context_mvars; + + public DynamicExpressionStatement (IDynamicBinder binder, Arguments args, Location loc) + { + this.binder = binder; + this.arguments = args; + this.loc = loc; + } + + public Arguments Arguments { + get { + return arguments; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1963, loc, "An expression tree cannot contain a dynamic operation"); + return null; + } + + protected override Expression DoResolve (ResolveContext rc) + { + if (DoResolveCore (rc)) + binder_expr = binder.CreateCallSiteBinder (rc, arguments); + + return this; + } + + protected bool DoResolveCore (ResolveContext rc) + { + if (rc.CurrentTypeParameters != null && rc.CurrentTypeParameters[0].IsMethodTypeParameter) + context_mvars = rc.CurrentTypeParameters; + + int errors = rc.Report.Errors; + var pt = rc.Module.PredefinedTypes; + + binder_type = pt.Binder.Resolve (); + pt.CallSite.Resolve (); + pt.CallSiteGeneric.Resolve (); + + eclass = ExprClass.Value; + + if (type == null) + type = rc.BuiltinTypes.Dynamic; + + if (rc.Report.Errors == errors) + return true; + + rc.Report.Error (1969, loc, + "Dynamic operation cannot be compiled without `Microsoft.CSharp.dll' assembly reference"); + return false; + } + + public override void Emit (EmitContext ec) + { + EmitCall (ec, binder_expr, arguments, false); + } + + public override void EmitStatement (EmitContext ec) + { + EmitCall (ec, binder_expr, arguments, true); + } + + protected void EmitCall (EmitContext ec, Expression binder, Arguments arguments, bool isStatement) + { + // + // This method generates all internal infrastructure for a dynamic call. The + // reason why it's quite complicated is the mixture of dynamic and anonymous + // methods. Dynamic itself requires a temporary class (ContainerX) and anonymous + // methods can generate temporary storey as well (AnonStorey). Handling MVAR + // type parameters rewrite is non-trivial in such case as there are various + // combinations possible therefore the mutator is not straightforward. Secondly + // we need to keep both MVAR(possibly VAR for anon storey) and type VAR to emit + // correct Site field type and its access from EmitContext. + // + + int dyn_args_count = arguments == null ? 0 : arguments.Count; + int default_args = isStatement ? 1 : 2; + var module = ec.Module; + + bool has_ref_out_argument = false; + var targs = new TypeExpression[dyn_args_count + default_args]; + targs[0] = new TypeExpression (module.PredefinedTypes.CallSite.TypeSpec, loc); + + TypeExpression[] targs_for_instance = null; + TypeParameterMutator mutator; + + var site_container = ec.CreateDynamicSite (); + + if (context_mvars != null) { + TypeParameter[] tparam; + TypeContainer sc = site_container; + do { + tparam = sc.CurrentTypeParameters; + sc = sc.Parent; + } while (tparam == null); + + mutator = new TypeParameterMutator (context_mvars, tparam); + + if (!ec.IsAnonymousStoreyMutateRequired) { + targs_for_instance = new TypeExpression[targs.Length]; + targs_for_instance[0] = targs[0]; + } + } else { + mutator = null; + } + + for (int i = 0; i < dyn_args_count; ++i) { + Argument a = arguments[i]; + if (a.ArgType == Argument.AType.Out || a.ArgType == Argument.AType.Ref) + has_ref_out_argument = true; + + var t = a.Type; + + // Convert any internal type like dynamic or null to object + if (t.Kind == MemberKind.InternalCompilerType) + t = ec.BuiltinTypes.Object; + + if (targs_for_instance != null) + targs_for_instance[i + 1] = new TypeExpression (t, loc); + + if (mutator != null) + t = t.Mutate (mutator); + + targs[i + 1] = new TypeExpression (t, loc); + } + + TypeExpr del_type = null; + TypeExpr del_type_instance_access = null; + if (!has_ref_out_argument) { + string d_name = isStatement ? "Action" : "Func"; + + TypeExpr te = null; + Namespace type_ns = module.GlobalRootNamespace.GetNamespace ("System", true); + if (type_ns != null) { + te = type_ns.LookupType (module, d_name, dyn_args_count + default_args, LookupMode.Normal, loc); + } + + if (te != null) { + if (!isStatement) { + var t = type; + if (t.Kind == MemberKind.InternalCompilerType) + t = ec.BuiltinTypes.Object; + + if (targs_for_instance != null) + targs_for_instance[targs_for_instance.Length - 1] = new TypeExpression (t, loc); + + if (mutator != null) + t = t.Mutate (mutator); + + targs[targs.Length - 1] = new TypeExpression (t, loc); + } + + del_type = new GenericTypeExpr (te.Type, new TypeArguments (targs), loc); + if (targs_for_instance != null) + del_type_instance_access = new GenericTypeExpr (te.Type, new TypeArguments (targs_for_instance), loc); + else + del_type_instance_access = del_type; + } + } + + // + // Create custom delegate when no appropriate predefined delegate has been found + // + Delegate d; + if (del_type == null) { + TypeSpec rt = isStatement ? ec.BuiltinTypes.Void : type; + Parameter[] p = new Parameter[dyn_args_count + 1]; + p[0] = new Parameter (targs[0], "p0", Parameter.Modifier.NONE, null, loc); + + var site = ec.CreateDynamicSite (); + int index = site.Types == null ? 0 : site.Types.Count; + + if (mutator != null) + rt = mutator.Mutate (rt); + + for (int i = 1; i < dyn_args_count + 1; ++i) { + p[i] = new Parameter (targs[i], "p" + i.ToString ("X"), arguments[i - 1].Modifier, null, loc); + } + + d = new Delegate (site.NamespaceEntry, site, new TypeExpression (rt, loc), + Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED, + new MemberName ("Container" + index.ToString ("X")), + new ParametersCompiled (p), null); + + d.CreateType (); + d.DefineType (); + d.Define (); + d.Emit (); + + site.AddDelegate (d); + del_type = new TypeExpression (d.CurrentType, loc); + if (targs_for_instance != null) { + del_type_instance_access = null; + } else { + del_type_instance_access = del_type; + } + } else { + d = null; + } + + var site_type_decl = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, new TypeArguments (del_type), loc); + var field = site_container.CreateCallSiteField (site_type_decl, loc); + if (field == null) + return; + + if (del_type_instance_access == null) { + var dt = d.CurrentType.DeclaringType.MakeGenericType (module, context_mvars.Select (l => l.Type).ToArray ()); + del_type_instance_access = new TypeExpression (MemberCache.GetMember (dt, d.CurrentType), loc); + } + + var instanceAccessExprType = new GenericTypeExpr (module.PredefinedTypes.CallSiteGeneric.TypeSpec, + new TypeArguments (del_type_instance_access), loc); + + if (instanceAccessExprType.ResolveAsType (ec.MemberContext) == null) + return; + + bool inflate_using_mvar = context_mvars != null && ec.IsAnonymousStoreyMutateRequired; + + TypeSpec gt; + if (inflate_using_mvar || context_mvars == null) { + gt = site_container.CurrentType; + } else { + gt = site_container.CurrentType.MakeGenericType (module, context_mvars.Select (l => l.Type).ToArray ()); + } + + // When site container already exists the inflated version has to be + // updated manually to contain newly created field + if (gt is InflatedTypeSpec && site_container.Fields.Count > 1) { + var tparams = gt.MemberDefinition.TypeParametersCount > 0 ? gt.MemberDefinition.TypeParameters : TypeParameterSpec.EmptyTypes; + var inflator = new TypeParameterInflator (module, gt, tparams, gt.TypeArguments); + gt.MemberCache.AddMember (field.InflateMember (inflator)); + } + + FieldExpr site_field_expr = new FieldExpr (MemberCache.GetMember (gt, field), loc); + + BlockContext bc = new BlockContext (ec.MemberContext, null, ec.BuiltinTypes.Void); + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + Arguments args = new Arguments (1); + args.Add (new Argument (binder)); + StatementExpression s = new StatementExpression (new SimpleAssign (site_field_expr, new Invocation (new MemberAccess (instanceAccessExprType, "Create"), args))); + + if (s.Resolve (bc)) { + Statement init = new If (new Binary (Binary.Operator.Equality, site_field_expr, new NullLiteral (loc), loc), s, loc); + init.Emit (ec); + } + + args = new Arguments (1 + dyn_args_count); + args.Add (new Argument (site_field_expr)); + if (arguments != null) { + int arg_pos = 1; + foreach (Argument a in arguments) { + if (a is NamedArgument) { + // Name is not valid in this context + args.Add (new Argument (a.Expr, a.ArgType)); + } else { + args.Add (a); + } + + if (inflate_using_mvar && a.Type != targs[arg_pos].Type) + a.Expr.Type = targs[arg_pos].Type; + + ++arg_pos; + } + } + + Expression target = new DelegateInvocation (new MemberAccess (site_field_expr, "Target", loc).Resolve (bc), args, loc).Resolve (bc); + if (target != null) + target.Emit (ec); + + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + public static MemberAccess GetBinderNamespace (Location loc) + { + return new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "Microsoft", loc), "CSharp", loc), "RuntimeBinder", loc); + } + + protected MemberAccess GetBinder (string name, Location loc) + { + return new MemberAccess (new TypeExpression (binder_type, loc), name, loc); + } + } + + // + // Dynamic member access compound assignment for events + // + class DynamicEventCompoundAssign : ExpressionStatement + { + class IsEvent : DynamicExpressionStatement, IDynamicBinder + { + string name; + + public IsEvent (string name, Arguments args, Location loc) + : base (null, args, loc) + { + this.name = name; + binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + type = ec.BuiltinTypes.Bool; + + Arguments binder_args = new Arguments (3); + + binder_args.Add (new Argument (new BinderFlags (0, this))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + + return new Invocation (GetBinder ("IsEvent", loc), binder_args); + } + } + + Expression condition; + ExpressionStatement invoke, assign; + + public DynamicEventCompoundAssign (string name, Arguments args, ExpressionStatement assignment, ExpressionStatement invoke, Location loc) + { + condition = new IsEvent (name, args, loc); + this.invoke = invoke; + this.assign = assignment; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return condition.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext rc) + { + type = rc.BuiltinTypes.Dynamic; + eclass = ExprClass.Value; + condition = condition.Resolve (rc); + return this; + } + + public override void Emit (EmitContext ec) + { + var rc = new ResolveContext (ec.MemberContext); + var expr = new Conditional (new BooleanExpression (condition), invoke, assign, loc).Resolve (rc); + expr.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + var stmt = new If (condition, new StatementExpression (invoke), new StatementExpression (assign), loc); + stmt.Emit (ec); + } + } + + class DynamicConversion : DynamicExpressionStatement, IDynamicBinder + { + public DynamicConversion (TypeSpec targetType, CSharpBinderFlags flags, Arguments args, Location loc) + : base (null, args, loc) + { + type = targetType; + base.flags = flags; + base.binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (3); + + flags |= ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new TypeOf (type, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + return new Invocation (GetBinder ("Convert", loc), binder_args); + } + } + + class DynamicConstructorBinder : DynamicExpressionStatement, IDynamicBinder + { + public DynamicConstructorBinder (TypeSpec type, Arguments args, Location loc) + : base (null, args, loc) + { + this.type = type; + base.binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (3); + + binder_args.Add (new Argument (new BinderFlags (0, this))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + return new Invocation (GetBinder ("InvokeConstructor", loc), binder_args); + } + } + + class DynamicIndexBinder : DynamicMemberAssignable + { + bool can_be_mutator; + + public DynamicIndexBinder (Arguments args, Location loc) + : base (args, loc) + { + } + + public DynamicIndexBinder (CSharpBinderFlags flags, Arguments args, Location loc) + : this (args, loc) + { + base.flags = flags; + } + + protected override Expression DoResolve (ResolveContext ec) + { + can_be_mutator = true; + return base.DoResolve (ec); + } + + protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) + { + Arguments binder_args = new Arguments (3); + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; + return new Invocation (GetBinder (isSet ? "SetIndex" : "GetIndex", loc), binder_args); + } + + protected override Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) + { + // + // Indexer has arguments which complicates things as the setter and getter + // are called in two steps when unary mutator is used. We have to make a + // copy of all variable arguments to not duplicate any side effect. + // + // ++d[++arg, Foo ()] + // + + if (!can_be_mutator) + return base.CreateSetterArguments (rc, rhs); + + var setter_args = new Arguments (Arguments.Count + 1); + for (int i = 0; i < Arguments.Count; ++i) { + var expr = Arguments[i].Expr; + + if (expr is Constant || expr is VariableReference || expr is This) { + setter_args.Add (Arguments [i]); + continue; + } + + LocalVariable temp = LocalVariable.CreateCompilerGenerated (expr.Type, rc.CurrentBlock, loc); + expr = new SimpleAssign (temp.CreateReferenceExpression (rc, expr.Location), expr).Resolve (rc); + Arguments[i].Expr = temp.CreateReferenceExpression (rc, expr.Location).Resolve (rc); + setter_args.Add (Arguments [i].Clone (expr)); + } + + setter_args.Add (new Argument (rhs)); + return setter_args; + } + } + + class DynamicInvocation : DynamicExpressionStatement, IDynamicBinder + { + ATypeNameExpression member; + + public DynamicInvocation (ATypeNameExpression member, Arguments args, Location loc) + : base (null, args, loc) + { + base.binder = this; + this.member = member; + } + + // + // When a return type is known not to be dynamic + // + public DynamicInvocation (ATypeNameExpression member, Arguments args, TypeSpec type, Location loc) + : this (member, args, loc) + { + this.type = type; + } + + public static DynamicInvocation CreateSpecialNameInvoke (ATypeNameExpression member, Arguments args, Location loc) + { + return new DynamicInvocation (member, args, loc) { + flags = CSharpBinderFlags.InvokeSpecialName + }; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (member != null ? 5 : 3); + bool is_member_access = member is MemberAccess; + + CSharpBinderFlags call_flags; + if (!is_member_access && member is SimpleName) { + call_flags = CSharpBinderFlags.InvokeSimpleName; + is_member_access = true; + } else { + call_flags = 0; + } + + binder_args.Add (new Argument (new BinderFlags (call_flags, this))); + + if (is_member_access) + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, member.Name, member.Location))); + + if (member != null && member.HasTypeArguments) { + TypeArguments ta = member.TypeArguments; + if (ta.Resolve (ec)) { + var targs = new ArrayInitializer (ta.Count, loc); + foreach (TypeSpec t in ta.Arguments) + targs.Add (new TypeOf (t, loc)); + + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (targs, loc))); + } + } else if (is_member_access) { + binder_args.Add (new Argument (new NullLiteral (loc))); + } + + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + + Expression real_args; + if (args == null) { + // Cannot be null because .NET trips over + real_args = new ArrayCreation ( + new MemberAccess (GetBinderNamespace (loc), "CSharpArgumentInfo", loc), + new ArrayInitializer (0, loc), loc); + } else { + real_args = new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc); + } + + binder_args.Add (new Argument (real_args)); + + return new Invocation (GetBinder (is_member_access ? "InvokeMember" : "Invoke", loc), binder_args); + } + + public override void EmitStatement (EmitContext ec) + { + flags |= CSharpBinderFlags.ResultDiscarded; + base.EmitStatement (ec); + } + } + + class DynamicMemberBinder : DynamicMemberAssignable + { + readonly string name; + + public DynamicMemberBinder (string name, Arguments args, Location loc) + : base (args, loc) + { + this.name = name; + } + + public DynamicMemberBinder (string name, CSharpBinderFlags flags, Arguments args, Location loc) + : this (name, args, loc) + { + base.flags = flags; + } + + protected override Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet) + { + Arguments binder_args = new Arguments (4); + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new StringLiteral (ec.BuiltinTypes, name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + isSet |= (flags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0; + return new Invocation (GetBinder (isSet ? "SetMember" : "GetMember", loc), binder_args); + } + } + + // + // Any member binder which can be source and target of assignment + // + abstract class DynamicMemberAssignable : DynamicExpressionStatement, IDynamicBinder, IAssignMethod + { + Expression setter; + Arguments setter_args; + + protected DynamicMemberAssignable (Arguments args, Location loc) + : base (null, args, loc) + { + base.binder = this; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + // + // DoResolve always uses getter + // + return CreateCallSiteBinder (ec, args, false); + } + + protected abstract Expression CreateCallSiteBinder (ResolveContext ec, Arguments args, bool isSet); + + protected virtual Arguments CreateSetterArguments (ResolveContext rc, Expression rhs) + { + var setter_args = new Arguments (Arguments.Count + 1); + setter_args.AddRange (Arguments); + setter_args.Add (new Argument (rhs)); + return setter_args; + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + if (right_side == EmptyExpression.OutAccess) { + right_side.DoResolveLValue (rc, this); + return null; + } + + if (DoResolveCore (rc)) { + setter_args = CreateSetterArguments (rc, right_side); + setter = CreateCallSiteBinder (rc, setter_args, true); + } + + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + // It's null for ResolveLValue used without assignment + if (binder_expr == null) + EmitCall (ec, setter, Arguments, false); + else + base.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + // It's null for ResolveLValue used without assignment + if (binder_expr == null) + EmitCall (ec, setter, Arguments, true); + else + base.EmitStatement (ec); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + EmitCall (ec, setter, setter_args, !leave_copy); + } + + #endregion + } + + class DynamicUnaryConversion : DynamicExpressionStatement, IDynamicBinder + { + readonly string name; + + public DynamicUnaryConversion (string name, Arguments args, Location loc) + : base (null, args, loc) + { + this.name = name; + base.binder = this; + } + + public static DynamicUnaryConversion CreateIsTrue (ResolveContext rc, Arguments args, Location loc) + { + return new DynamicUnaryConversion ("IsTrue", args, loc) { type = rc.BuiltinTypes.Bool }; + } + + public static DynamicUnaryConversion CreateIsFalse (ResolveContext rc, Arguments args, Location loc) + { + return new DynamicUnaryConversion ("IsFalse", args, loc) { type = rc.BuiltinTypes.Bool }; + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (4); + + MemberAccess sle = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); + + var flags = ec.HasSet (ResolveContext.Options.CheckedScope) ? CSharpBinderFlags.CheckedContext : 0; + + binder_args.Add (new Argument (new BinderFlags (flags, this))); + binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), name, loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + return new Invocation (GetBinder ("UnaryOperation", loc), binder_args); + } + } + + sealed class DynamicSiteClass : HoistedStoreyClass + { + public DynamicSiteClass (TypeContainer parent, MemberBase host, TypeParameter[] tparams) + : base (parent, MakeMemberName (host, "DynamicSite", parent.DynamicSitesCounter, tparams, Location.Null), tparams, Modifiers.STATIC) + { + parent.DynamicSitesCounter++; + } + + public FieldSpec CreateCallSiteField (FullNamedExpression type, Location loc) + { + int index = fields == null ? 0 : fields.Count; + Field f = new HoistedField (this, type, Modifiers.PUBLIC | Modifiers.STATIC, "Site" + index.ToString ("X"), null, loc); + f.Define (); + + AddField (f); + return f.Spec; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs new file mode 100644 index 0000000000..3be2ce0cda --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs @@ -0,0 +1,5920 @@ +// +// ecore.cs: Core of the Expression representation for the intermediate tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// +// + +using System; +using System.Collections.Generic; +using System.Text; +using SLE = System.Linq.Expressions; +using System.Linq; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// The ExprClass class contains the is used to pass the + /// classification of an expression (value, variable, namespace, + /// type, method group, property access, event access, indexer access, + /// nothing). + /// + public enum ExprClass : byte { + Unresolved = 0, + + Value, + Variable, + Namespace, + Type, + TypeParameter, + MethodGroup, + PropertyAccess, + EventAccess, + IndexerAccess, + Nothing, + } + + /// + /// This is used to tell Resolve in which types of expressions we're + /// interested. + /// + [Flags] + public enum ResolveFlags { + // Returns Value, Variable, PropertyAccess, EventAccess or IndexerAccess. + VariableOrValue = 1, + + // Returns a type expression. + Type = 1 << 1, + + // Returns a method group. + MethodGroup = 1 << 2, + + TypeParameter = 1 << 3, + + // Mask of all the expression class flags. + MaskExprClass = VariableOrValue | Type | MethodGroup | TypeParameter, + } + + // + // This is just as a hint to AddressOf of what will be done with the + // address. + [Flags] + public enum AddressOp { + Store = 1, + Load = 2, + LoadStore = 3 + }; + + /// + /// This interface is implemented by variables + /// + public interface IMemoryLocation { + /// + /// The AddressOf method should generate code that loads + /// the address of the object and leaves it on the stack. + /// + /// The `mode' argument is used to notify the expression + /// of whether this will be used to read from the address or + /// write to the address. + /// + /// This is just a hint that can be used to provide good error + /// reporting, and should have no other side effects. + /// + void AddressOf (EmitContext ec, AddressOp mode); + } + + // + // An expressions resolved as a direct variable reference + // + public interface IVariableReference : IFixedExpression + { + bool IsHoisted { get; } + string Name { get; } + VariableInfo VariableInfo { get; } + + void SetHasAddressTaken (); + } + + // + // Implemented by an expression which could be or is always + // fixed + // + public interface IFixedExpression + { + bool IsFixed { get; } + } + + /// + /// Base class for expressions + /// + public abstract class Expression { + public ExprClass eclass; + protected TypeSpec type; + protected Location loc; + + public TypeSpec Type { + get { return type; } + set { type = value; } + } + + public Location Location { + get { return loc; } + } + + public virtual string GetSignatureForError () + { + if (type == null) + return ""; + TypeSpec typeSpec = type.GetDefinition (); + return typeSpec != null ? typeSpec.GetSignatureForError () : ""; + } + + public virtual bool IsNull { + get { + return false; + } + } + + /// + /// Performs semantic analysis on the Expression + /// + /// + /// + /// The Resolve method is invoked to perform the semantic analysis + /// on the node. + /// + /// The return value is an expression (it can be the + /// same expression in some cases) or a new + /// expression that better represents this node. + /// + /// For example, optimizations of Unary (LiteralInt) + /// would return a new LiteralInt with a negated + /// value. + /// + /// If there is an error during semantic analysis, + /// then an error should be reported (using Report) + /// and a null value should be returned. + /// + /// There are two side effects expected from calling + /// Resolve(): the the field variable "eclass" should + /// be set to any value of the enumeration + /// `ExprClass' and the type variable should be set + /// to a valid type (this is the type of the + /// expression). + /// + protected abstract Expression DoResolve (ResolveContext rc); + + public virtual Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + return null; + } + + // + // This is used if the expression should be resolved as a type or namespace name. + // the default implementation fails. + // + public virtual TypeSpec ResolveAsType (IMemberContext mc) + { + ResolveContext ec = new ResolveContext (mc); + Expression e = Resolve (ec); + if (e != null) + e.Error_UnexpectedKind (ec, ResolveFlags.Type, loc); + + return null; + } + + public static void ErrorIsInaccesible (IMemberContext rc, string member, Location loc) + { + rc.Module.Compiler.Report.Error (122, loc, "`{0}' is inaccessible due to its protection level", member); + } + + public void Error_ExpressionMustBeConstant (ResolveContext rc, Location loc, string e_name) + { + rc.Report.Error (133, loc, "The expression being assigned to `{0}' must be constant", e_name); + } + + public void Error_ConstantCanBeInitializedWithNullOnly (ResolveContext rc, TypeSpec type, Location loc, string name) + { + rc.Report.Error (134, loc, "A constant `{0}' of reference type `{1}' can only be initialized with null", + name, TypeManager.CSharpName (type)); + } + + public static void Error_InvalidExpressionStatement (Report Report, Location loc) + { + Report.Error (201, loc, "Only assignment, call, increment, decrement, and new object " + + "expressions can be used as a statement"); + } + + public void Error_InvalidExpressionStatement (BlockContext ec) + { + Error_InvalidExpressionStatement (ec.Report, loc); + } + + public static void Error_VoidInvalidInTheContext (Location loc, Report Report) + { + Report.Error (1547, loc, "Keyword `void' cannot be used in this context"); + } + + public virtual void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + Error_ValueCannotBeConvertedCore (ec, loc, target, expl); + } + + protected void Error_ValueCannotBeConvertedCore (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + // The error was already reported as CS1660 + if (type == InternalType.AnonymousMethod) + return; + + string from_type = type.GetSignatureForError (); + string to_type = target.GetSignatureForError (); + if (from_type == to_type) { + from_type = type.GetSignatureForErrorIncludingAssemblyName (); + to_type = target.GetSignatureForErrorIncludingAssemblyName (); + } + + if (expl) { + ec.Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'", + from_type, to_type); + return; + } + + ec.Report.DisableReporting (); + bool expl_exists = Convert.ExplicitConversion (ec, this, target, Location.Null) != null; + ec.Report.EnableReporting (); + + if (expl_exists) { + ec.Report.Error (266, loc, + "Cannot implicitly convert type `{0}' to `{1}'. An explicit conversion exists (are you missing a cast?)", + from_type, to_type); + } else { + ec.Report.Error (29, loc, "Cannot implicitly convert type `{0}' to `{1}'", + from_type, to_type); + } + } + + public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, MemberSpec member, int arity, Location loc) + { + // Better message for possible generic expressions + if (member != null && (member.Kind & MemberKind.GenericMask) != 0) { + var report = context.Module.Compiler.Report; + report.SymbolRelatedToPreviousError (member); + if (member is TypeSpec) + member = ((TypeSpec) member).GetDefinition (); + else + member = ((MethodSpec) member).GetGenericMethodDefinition (); + + string name = member.Kind == MemberKind.Method ? "method" : "type"; + if (member.IsGeneric) { + report.Error (305, loc, "Using the generic {0} `{1}' requires `{2}' type argument(s)", + name, member.GetSignatureForError (), member.Arity.ToString ()); + } else { + report.Error (308, loc, "The non-generic {0} `{1}' cannot be used with the type arguments", + name, member.GetSignatureForError ()); + } + } else { + Error_TypeArgumentsCannotBeUsed (context, ExprClassName, GetSignatureForError (), loc); + } + } + + public void Error_TypeArgumentsCannotBeUsed (IMemberContext context, string exprType, string name, Location loc) + { + context.Module.Compiler.Report.Error (307, loc, "The {0} `{1}' cannot be used with type arguments", + exprType, name); + } + + protected virtual void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + Error_TypeDoesNotContainDefinition (ec, loc, type, name); + } + + public static void Error_TypeDoesNotContainDefinition (ResolveContext ec, Location loc, TypeSpec type, string name) + { + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (117, loc, "`{0}' does not contain a definition for `{1}'", + TypeManager.CSharpName (type), name); + } + + protected static void Error_ValueAssignment (ResolveContext ec, Location loc) + { + ec.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) + { + rc.Report.Error (242, loc, "The operation in question is undefined on void pointers"); + } + + public ResolveFlags ExprClassToResolveFlags { + get { + switch (eclass) { + case ExprClass.Type: + case ExprClass.Namespace: + return ResolveFlags.Type; + + case ExprClass.MethodGroup: + return ResolveFlags.MethodGroup; + + case ExprClass.TypeParameter: + return ResolveFlags.TypeParameter; + + case ExprClass.Value: + case ExprClass.Variable: + case ExprClass.PropertyAccess: + case ExprClass.EventAccess: + case ExprClass.IndexerAccess: + return ResolveFlags.VariableOrValue; + + default: + throw new InternalErrorException (loc.ToString () + " " + GetType () + " ExprClass is Invalid after resolve"); + } + } + } + + /// + /// Resolves an expression and performs semantic analysis on it. + /// + /// + /// + /// Currently Resolve wraps DoResolve to perform sanity + /// checking and assertion checking on what we expect from Resolve. + /// + public Expression Resolve (ResolveContext ec, ResolveFlags flags) + { + if (eclass != ExprClass.Unresolved) + return this; + + Expression e; + try { + e = DoResolve (ec); + + if (e == null) + return null; + + if ((flags & e.ExprClassToResolveFlags) == 0) { + e.Error_UnexpectedKind (ec, flags, loc); + return null; + } + + if (e.type == null) + throw new InternalErrorException ("Expression `{0}' didn't set its type in DoResolve", e.GetType ()); + + return e; + } catch (Exception ex) { + if (loc.IsNull || ec.Module.Compiler.Settings.DebugFlags > 0 || ex is CompletionResult || ec.Report.IsDisabled) + throw; + + ec.Report.Error (584, loc, "Internal compiler error: {0}", ex.Message); + return EmptyExpression.Null; // TODO: Add location + } + } + + /// + /// Resolves an expression and performs semantic analysis on it. + /// + public Expression Resolve (ResolveContext rc) + { + return Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + } + + /// + /// Resolves an expression for LValue assignment + /// + /// + /// + /// Currently ResolveLValue wraps DoResolveLValue to perform sanity + /// checking and assertion checking on what we expect from Resolve + /// + public Expression ResolveLValue (ResolveContext ec, Expression right_side) + { + int errors = ec.Report.Errors; + bool out_access = right_side == EmptyExpression.OutAccess; + + Expression e = DoResolveLValue (ec, right_side); + + if (e != null && out_access && !(e is IMemoryLocation)) { + // FIXME: There's no problem with correctness, the 'Expr = null' handles that. + // Enabling this 'throw' will "only" result in deleting useless code elsewhere, + + //throw new InternalErrorException ("ResolveLValue didn't return an IMemoryLocation: " + + // e.GetType () + " " + e.GetSignatureForError ()); + e = null; + } + + if (e == null) { + if (errors == ec.Report.Errors) { + if (out_access) + ec.Report.Error (1510, loc, "A ref or out argument must be an assignable variable"); + else + Error_ValueAssignment (ec, loc); + } + return null; + } + + if (e.eclass == ExprClass.Unresolved) + throw new Exception ("Expression " + e + " ExprClass is Invalid after resolve"); + + if ((e.type == null) && !(e is GenericTypeExpr)) + throw new Exception ("Expression " + e + " did not set its type after Resolve"); + + return e; + } + + public virtual void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + rc.Module.Compiler.Report.Error (182, loc, + "An attribute argument must be a constant expression, typeof expression or array creation expression"); + } + + /// + /// Emits the code for the expression + /// + /// + /// + /// The Emit method is invoked to generate the code + /// for the expression. + /// + public abstract void Emit (EmitContext ec); + + + // Emit code to branch to @target if this expression is equivalent to @on_true. + // The default implementation is to emit the value, and then emit a brtrue or brfalse. + // Subclasses can provide more efficient implementations, but those MUST be equivalent, + // including the use of conditional branches. Note also that a branch MUST be emitted + public virtual void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + Emit (ec); + ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + + // Emit this expression for its side effects, not for its value. + // The default implementation is to emit the value, and then throw it away. + // Subclasses can provide more efficient implementations, but those MUST be equivalent + public virtual void EmitSideEffect (EmitContext ec) + { + Emit (ec); + ec.Emit (OpCodes.Pop); + } + + /// + /// Protected constructor. Only derivate types should + /// be able to be created + /// + + protected Expression () + { + } + + /// + /// Returns a fully formed expression after a MemberLookup + /// + /// + static Expression ExprClassFromMemberInfo (MemberSpec spec, Location loc) + { + if (spec is EventSpec) + return new EventExpr ((EventSpec) spec, loc); + if (spec is ConstSpec) + return new ConstantExpr ((ConstSpec) spec, loc); + if (spec is FieldSpec) + return new FieldExpr ((FieldSpec) spec, loc); + if (spec is PropertySpec) + return new PropertyExpr ((PropertySpec) spec, loc); + if (spec is TypeSpec) + return new TypeExpression (((TypeSpec) spec), loc); + + return null; + } + + protected static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc) + { + var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true); + if (ctors == null) { + rc.Report.SymbolRelatedToPreviousError (type); + if (type.IsStruct) { + // Report meaningful error for struct as they always have default ctor in C# context + OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc); + } else { + rc.Report.Error (143, loc, "The class `{0}' has no constructors defined", + type.GetSignatureForError ()); + } + + return null; + } + + var r = new OverloadResolver (ctors, OverloadResolver.Restrictions.NoBaseMembers, loc); + var ctor = r.ResolveMember (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); + } + + return ctor; + } + + [Flags] + public enum MemberLookupRestrictions + { + None = 0, + InvocableOnly = 1, + ExactArity = 1 << 2, + ReadAccess = 1 << 3 + } + + // + // Lookup type `queried_type' for code in class `container_type' with a qualifier of + // `qualifier_type' or null to lookup members in the current class. + // + public static Expression MemberLookup (IMemberContext rc, bool errorMode, TypeSpec queried_type, string name, int arity, MemberLookupRestrictions restrictions, Location loc) + { + var members = MemberCache.FindMembers (queried_type, name, false); + if (members == null) + return null; + + MemberSpec non_method = null; + MemberSpec ambig_non_method = null; + do { + for (int i = 0; i < members.Count; ++i) { + var member = members[i]; + + // HACK: for events because +=/-= can appear at same class only, should use OverrideToBase there + if ((member.Modifiers & Modifiers.OVERRIDE) != 0 && member.Kind != MemberKind.Event) + continue; + + if ((arity > 0 || (restrictions & MemberLookupRestrictions.ExactArity) != 0) && member.Arity != arity) + continue; + + if (!errorMode) { + if (!member.IsAccessible (rc)) + continue; + + // + // With runtime binder we can have a situation where queried type is inaccessible + // because it came via dynamic object, the check about inconsisted accessibility + // had no effect as the type was unknown during compilation + // + // class A { + // private class N { } + // + // public dynamic Foo () + // { + // return new N (); + // } + // } + // + if (rc.Module.Compiler.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc)) + continue; + } + + if ((restrictions & MemberLookupRestrictions.InvocableOnly) != 0) { + if (member is MethodSpec) + return new MethodGroupExpr (members, queried_type, loc); + + if (!Invocation.IsMemberInvocable (member)) + continue; + } + + if (non_method == null || member is MethodSpec || non_method.IsNotCSharpCompatible) { + non_method = member; + } else if (!errorMode && !member.IsNotCSharpCompatible) { + ambig_non_method = member; + } + } + + if (non_method != null) { + if (ambig_non_method != null && rc != null) { + var report = rc.Module.Compiler.Report; + report.SymbolRelatedToPreviousError (non_method); + report.SymbolRelatedToPreviousError (ambig_non_method); + report.Error (229, loc, "Ambiguity between `{0}' and `{1}'", + non_method.GetSignatureForError (), ambig_non_method.GetSignatureForError ()); + } + + if (non_method is MethodSpec) + return new MethodGroupExpr (members, queried_type, loc); + + return ExprClassFromMemberInfo (non_method, loc); + } + + if (members[0].DeclaringType.BaseType == null) + members = null; + else + members = MemberCache.FindMembers (members[0].DeclaringType.BaseType, name, false); + + } while (members != null); + + return null; + } + + protected virtual void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + throw new NotImplementedException (); + } + + protected void Error_PointerInsideExpressionTree (ResolveContext ec) + { + ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation"); + } + + /// + /// Returns an expression that can be used to invoke operator true + /// on the expression if it exists. + /// + protected static Expression GetOperatorTrue (ResolveContext ec, Expression e, Location loc) + { + return GetOperatorTrueOrFalse (ec, e, true, loc); + } + + /// + /// Returns an expression that can be used to invoke operator false + /// on the expression if it exists. + /// + protected static Expression GetOperatorFalse (ResolveContext ec, Expression e, Location loc) + { + return GetOperatorTrueOrFalse (ec, e, false, loc); + } + + static Expression GetOperatorTrueOrFalse (ResolveContext ec, Expression e, bool is_true, Location loc) + { + var op = is_true ? Operator.OpType.True : Operator.OpType.False; + var methods = MemberCache.GetUserOperator (e.type, op, false); + if (methods == null) + return null; + + Arguments arguments = new Arguments (1); + arguments.Add (new Argument (e)); + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc); + var oper = res.ResolveOperator (ec, ref arguments); + + if (oper == null) + return null; + + return new UserOperatorCall (oper, arguments, null, loc); + } + + public virtual string ExprClassName + { + get { + switch (eclass){ + case ExprClass.Unresolved: + return "Unresolved"; + case ExprClass.Value: + return "value"; + case ExprClass.Variable: + return "variable"; + case ExprClass.Namespace: + return "namespace"; + case ExprClass.Type: + return "type"; + case ExprClass.MethodGroup: + return "method group"; + case ExprClass.PropertyAccess: + return "property access"; + case ExprClass.EventAccess: + return "event access"; + case ExprClass.IndexerAccess: + return "indexer access"; + case ExprClass.Nothing: + return "null"; + case ExprClass.TypeParameter: + return "type parameter"; + } + throw new Exception ("Should not happen"); + } + } + + /// + /// Reports that we were expecting `expr' to be of class `expected' + /// + public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, Location loc) + { + Error_UnexpectedKind (r, mc, expected, ExprClassName, loc); + } + + public void Error_UnexpectedKind (Report r, MemberCore mc, string expected, string was, Location loc) + { + string name; + if (mc != null) + name = mc.GetSignatureForError (); + else + name = GetSignatureForError (); + + r.Error (118, loc, "`{0}' is a `{1}' but a `{2}' was expected", + name, was, expected); + } + + public void Error_UnexpectedKind (ResolveContext ec, ResolveFlags flags, Location loc) + { + string [] valid = new string [4]; + int count = 0; + + if ((flags & ResolveFlags.VariableOrValue) != 0) { + valid [count++] = "variable"; + valid [count++] = "value"; + } + + if ((flags & ResolveFlags.Type) != 0) + valid [count++] = "type"; + + if ((flags & ResolveFlags.MethodGroup) != 0) + valid [count++] = "method group"; + + if (count == 0) + valid [count++] = "unknown"; + + StringBuilder sb = new StringBuilder (valid [0]); + for (int i = 1; i < count - 1; i++) { + sb.Append ("', `"); + sb.Append (valid [i]); + } + if (count > 1) { + sb.Append ("' or `"); + sb.Append (valid [count - 1]); + } + + ec.Report.Error (119, loc, + "Expression denotes a `{0}', where a `{1}' was expected", ExprClassName, sb.ToString ()); + } + + public static void UnsafeError (ResolveContext ec, Location loc) + { + UnsafeError (ec.Report, loc); + } + + public static void UnsafeError (Report Report, Location loc) + { + 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. + // + protected Expression ConvertExpressionToArrayIndex (ResolveContext ec, Expression source) + { + var btypes = ec.BuiltinTypes; + + if (source.type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (source)); + return new DynamicConversion (btypes.Int, CSharpBinderFlags.ConvertArrayIndex, args, loc).Resolve (ec); + } + + Expression converted; + + using (ec.Set (ResolveContext.Options.CheckedScope)) { + converted = Convert.ImplicitConversion (ec, source, btypes.Int, source.loc); + if (converted == null) + converted = Convert.ImplicitConversion (ec, source, btypes.UInt, source.loc); + if (converted == null) + converted = Convert.ImplicitConversion (ec, source, btypes.Long, source.loc); + if (converted == null) + converted = Convert.ImplicitConversion (ec, source, btypes.ULong, source.loc); + + if (converted == null) { + source.Error_ValueCannotBeConverted (ec, source.loc, btypes.Int, false); + return null; + } + } + + // + // Only positive constants are allowed at compile time + // + Constant c = converted as Constant; + if (c != null && c.IsNegative) + Error_NegativeArrayIndex (ec, source.loc); + + // No conversion needed to array index + if (converted.Type.BuiltinType == BuiltinTypeSpec.Type.Int) + return converted; + + return new ArrayIndexCast (converted, btypes.Int).Resolve (ec); + } + + // + // Derived classes implement this method by cloning the fields that + // could become altered during the Resolve stage + // + // Only expressions that are created for the parser need to implement + // this. + // + protected virtual void CloneTo (CloneContext clonectx, Expression target) + { + throw new NotImplementedException ( + String.Format ( + "CloneTo not implemented for expression {0}", this.GetType ())); + } + + // + // Clones an expression created by the parser. + // + // We only support expressions created by the parser so far, not + // expressions that have been resolved (many more classes would need + // to implement CloneTo). + // + // This infrastructure is here merely for Lambda expressions which + // compile the same code using different type values for the same + // arguments to find the correct overload + // + public virtual Expression Clone (CloneContext clonectx) + { + Expression cloned = (Expression) MemberwiseClone (); + CloneTo (clonectx, cloned); + + return cloned; + } + + // + // Implementation of expression to expression tree conversion + // + public abstract Expression CreateExpressionTree (ResolveContext ec); + + protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, Arguments args) + { + return CreateExpressionFactoryCall (ec, name, null, args, loc); + } + + protected Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args) + { + return CreateExpressionFactoryCall (ec, name, typeArguments, args, loc); + } + + public static Expression CreateExpressionFactoryCall (ResolveContext ec, string name, TypeArguments typeArguments, Arguments args, Location loc) + { + return new Invocation (new MemberAccess (CreateExpressionTypeExpression (ec, loc), name, typeArguments, loc), args); + } + + protected static TypeExpr CreateExpressionTypeExpression (ResolveContext ec, Location loc) + { + var t = ec.Module.PredefinedTypes.Expression.Resolve (); + if (t == null) + return null; + + return new TypeExpression (t, loc); + } + + // + // Implemented by all expressions which support conversion from + // compiler expression to invokable runtime expression. Used by + // dynamic C# binder. + // + public virtual SLE.Expression MakeExpression (BuilderContext ctx) + { + throw new NotImplementedException ("MakeExpression for " + GetType ()); + } + + public virtual object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This is just a base class for expressions that can + /// appear on statements (invocations, object creation, + /// assignments, post/pre increment and decrement). The idea + /// being that they would support an extra Emition interface that + /// does not leave a result on the stack. + /// + public abstract class ExpressionStatement : Expression { + + public ExpressionStatement ResolveStatement (BlockContext ec) + { + Expression e = Resolve (ec); + if (e == null) + return null; + + ExpressionStatement es = e as ExpressionStatement; + if (es == null) + Error_InvalidExpressionStatement (ec); + + return es; + } + + /// + /// Requests the expression to be emitted in a `statement' + /// context. This means that no new value is left on the + /// stack after invoking this method (constrasted with + /// Emit that will always leave a value on the stack). + /// + public abstract void EmitStatement (EmitContext ec); + + public override void EmitSideEffect (EmitContext ec) + { + EmitStatement (ec); + } + } + + /// + /// This kind of cast is used to encapsulate the child + /// whose type is child.Type into an expression that is + /// reported to return "return_type". This is used to encapsulate + /// expressions which have compatible types, but need to be dealt + /// at higher levels with. + /// + /// For example, a "byte" expression could be encapsulated in one + /// of these as an "unsigned int". The type for the expression + /// would be "unsigned int". + /// + /// + public abstract class TypeCast : Expression + { + protected readonly Expression child; + + protected TypeCast (Expression child, TypeSpec return_type) + { + eclass = child.eclass; + loc = child.Location; + type = return_type; + this.child = child; + } + + public Expression Child { + get { + return child; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (child.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOf (type, loc))); + + if (type.IsPointer || child.Type.IsPointer) + Error_PointerInsideExpressionTree (ec); + + return CreateExpressionFactoryCall (ec, ec.HasSet (ResolveContext.Options.CheckedScope) ? "ConvertChecked" : "Convert", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return ctx.HasSet (BuilderContext.Options.CheckedScope) ? + SLE.Expression.ConvertChecked (child.MakeExpression (ctx), type.GetMetaInfo ()) : + SLE.Expression.Convert (child.MakeExpression (ctx), type.GetMetaInfo ()); +#endif + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing to clone + } + + public override bool IsNull { + get { return child.IsNull; } + } + } + + public class EmptyCast : TypeCast { + EmptyCast (Expression child, TypeSpec target_type) + : base (child, target_type) + { + } + + public static Expression Create (Expression child, TypeSpec type) + { + Constant c = child as Constant; + if (c != null) + return new EmptyConstantCast (c, type); + + EmptyCast e = child as EmptyCast; + if (e != null) + return new EmptyCast (e.child, type); + + return new EmptyCast (child, type); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + child.EmitSideEffect (ec); + } + } + + // + // Used for predefined type user operator (no obsolete check, etc.) + // + public class OperatorCast : TypeCast + { + readonly MethodSpec conversion_operator; + + public OperatorCast (Expression expr, TypeSpec target_type) + : this (expr, target_type, target_type, false) + { + } + + public OperatorCast (Expression expr, TypeSpec target_type, bool find_explicit) + : this (expr, target_type, target_type, find_explicit) + { + } + + public OperatorCast (Expression expr, TypeSpec declaringType, TypeSpec returnType, bool isExplicit) + : base (expr, returnType) + { + var op = isExplicit ? Operator.OpType.Explicit : Operator.OpType.Implicit; + var mi = MemberCache.GetUserOperator (declaringType, op, true); + + if (mi != null) { + foreach (MethodSpec oper in mi) { + if (oper.ReturnType != returnType) + continue; + + if (oper.Parameters.Types[0] == expr.Type) { + conversion_operator = oper; + return; + } + } + } + + throw new InternalErrorException ("Missing predefined user operator between `{0}' and `{1}'", + returnType.GetSignatureForError (), expr.Type.GetSignatureForError ()); + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + ec.Emit (OpCodes.Call, conversion_operator); + } + } + + // + // Constant specialization of EmptyCast. + // We need to special case this since an empty cast of + // a constant is still a constant. + // + public class EmptyConstantCast : Constant + { + public readonly Constant child; + + public EmptyConstantCast (Constant child, TypeSpec type) + : base (child.Location) + { + if (child == null) + throw new ArgumentNullException ("child"); + + this.child = child; + this.eclass = child.eclass; + this.type = type; + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + if (child.Type == target_type) + return child; + + // FIXME: check that 'type' can be converted to 'target_type' first + return child.ConvertExplicitly (in_checked_context, target_type); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, null, + child.CreateExpressionTree (ec), + new TypeOf (type, loc)); + + if (type.IsPointer) + Error_PointerInsideExpressionTree (ec); + + return CreateExpressionFactoryCall (ec, "Convert", args); + } + + public override bool IsDefaultValue { + get { return child.IsDefaultValue; } + } + + public override bool IsNegative { + get { return child.IsNegative; } + } + + public override bool IsNull { + get { return child.IsNull; } + } + + public override bool IsOneInteger { + get { return child.IsOneInteger; } + } + + public override bool IsZeroInteger { + get { return child.IsZeroInteger; } + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + child.EmitBranchable (ec, label, on_true); + + // Only to make verifier happy + if (TypeManager.IsGenericParameter (type) && child.IsNull) + ec.Emit (OpCodes.Unbox_Any, type); + } + + public override void EmitSideEffect (EmitContext ec) + { + child.EmitSideEffect (ec); + } + + public override object GetValue () + { + return child.GetValue (); + } + + public override string GetValueAsLiteral () + { + return child.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return child.GetValueAsLong (); + } + + public override Constant ConvertImplicitly (TypeSpec target_type) + { + if (type == target_type) + return this; + + // FIXME: Do we need to check user conversions? + if (!Convert.ImplicitStandardConversionExists (this, target_type)) + return null; + + return child.ConvertImplicitly (target_type); + } + } + + /// + /// This class is used to wrap literals which belong inside Enums + /// + public class EnumConstant : Constant + { + public Constant Child; + + public EnumConstant (Constant child, TypeSpec enum_type) + : base (child.Location) + { + this.Child = child; + + this.eclass = ExprClass.Value; + this.type = enum_type; + } + + protected EnumConstant (Location loc) + : base (loc) + { + } + + public override void Emit (EmitContext ec) + { + Child.Emit (ec); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + Child.EncodeAttributeValue (rc, enc, Child.Type); + } + + public override void EmitBranchable (EmitContext ec, Label label, bool on_true) + { + Child.EmitBranchable (ec, label, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + Child.EmitSideEffect (ec); + } + + public override string GetSignatureForError() + { + return TypeManager.CSharpName (Type); + } + + public override object GetValue () + { + return Child.GetValue (); + } + +#if !STATIC + public override object GetTypedValue () + { + // + // The method can be used in dynamic context only (on closed types) + // + // System.Enum.ToObject cannot be called on dynamic types + // EnumBuilder has to be used, but we cannot use EnumBuilder + // because it does not properly support generics + // + return System.Enum.ToObject (type.GetMetaInfo (), Child.GetValue ()); + } +#endif + + public override string GetValueAsLiteral () + { + return Child.GetValueAsLiteral (); + } + + public override long GetValueAsLong () + { + return Child.GetValueAsLong (); + } + + public EnumConstant Increment() + { + return new EnumConstant (((IntegralConstant) Child).Increment (), type); + } + + public override bool IsDefaultValue { + get { + return Child.IsDefaultValue; + } + } + + public override bool IsZeroInteger { + get { return Child.IsZeroInteger; } + } + + public override bool IsNegative { + get { + return Child.IsNegative; + } + } + + public override Constant ConvertExplicitly(bool in_checked_context, TypeSpec target_type) + { + if (Child.Type == target_type) + return Child; + + return Child.ConvertExplicitly (in_checked_context, target_type); + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + if (this.type == type) { + return this; + } + + if (!Convert.ImplicitStandardConversionExists (this, type)){ + return null; + } + + return Child.ConvertImplicitly (type); + } + } + + /// + /// This kind of cast is used to encapsulate Value Types in objects. + /// + /// The effect of it is to box the value type emitted by the previous + /// operation. + /// + public class BoxedCast : TypeCast { + + public BoxedCast (Expression expr, TypeSpec target_type) + : base (expr, target_type) + { + eclass = ExprClass.Value; + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // Only boxing to object type is supported + if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + + enc.Encode (child.Type); + child.EncodeAttributeValue (rc, enc, child.Type); + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + ec.Emit (OpCodes.Box, child.Type); + } + + public override void EmitSideEffect (EmitContext ec) + { + // boxing is side-effectful, since it involves runtime checks, except when boxing to Object or ValueType + // so, we need to emit the box+pop instructions in most cases + if (child.Type.IsStruct && + (type.BuiltinType == BuiltinTypeSpec.Type.Object || type.BuiltinType == BuiltinTypeSpec.Type.ValueType)) + child.EmitSideEffect (ec); + else + base.EmitSideEffect (ec); + } + } + + public class UnboxCast : TypeCast { + public UnboxCast (Expression expr, TypeSpec return_type) + : base (expr, return_type) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + ec.Emit (OpCodes.Unbox_Any, type); + } + } + + /// + /// This is used to perform explicit numeric conversions. + /// + /// Explicit numeric conversions might trigger exceptions in a checked + /// context, so they should generate the conv.ovf opcodes instead of + /// conv opcodes. + /// + public class ConvCast : TypeCast { + public enum Mode : byte { + I1_U1, I1_U2, I1_U4, I1_U8, I1_CH, + U1_I1, U1_CH, + I2_I1, I2_U1, I2_U2, I2_U4, I2_U8, I2_CH, + U2_I1, U2_U1, U2_I2, U2_CH, + I4_I1, I4_U1, I4_I2, I4_U2, I4_U4, I4_U8, I4_CH, + U4_I1, U4_U1, U4_I2, U4_U2, U4_I4, U4_CH, + I8_I1, I8_U1, I8_I2, I8_U2, I8_I4, I8_U4, I8_U8, I8_CH, I8_I, + U8_I1, U8_U1, U8_I2, U8_U2, U8_I4, U8_U4, U8_I8, U8_CH, U8_I, + CH_I1, CH_U1, CH_I2, + R4_I1, R4_U1, R4_I2, R4_U2, R4_I4, R4_U4, R4_I8, R4_U8, R4_CH, + R8_I1, R8_U1, R8_I2, R8_U2, R8_I4, R8_U4, R8_I8, R8_U8, R8_CH, R8_R4, + I_I8, + } + + Mode mode; + + public ConvCast (Expression child, TypeSpec return_type, Mode m) + : base (child, return_type) + { + mode = m; + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override string ToString () + { + return String.Format ("ConvCast ({0}, {1})", mode, child); + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + switch (mode){ + case Mode.I1_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I1_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I1_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I1_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I1_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U1_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U1_CH: /* nothing */ break; + + case Mode.I2_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I2_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I2_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I2_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I2_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I2_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U2_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U2_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U2_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U2_CH: /* nothing */ break; + + case Mode.I4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.I4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.U4_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U4_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U4_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U4_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U4_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break; + case Mode.U4_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + + case Mode.I8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.I8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.I8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.I8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.I8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.I8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.I8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.I8_I: ec.Emit (OpCodes.Conv_Ovf_U); break; + + case Mode.U8_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.U8_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.U8_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + case Mode.U8_U2: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U8_I4: ec.Emit (OpCodes.Conv_Ovf_I4_Un); break; + case Mode.U8_U4: ec.Emit (OpCodes.Conv_Ovf_U4_Un); break; + case Mode.U8_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break; + case Mode.U8_CH: ec.Emit (OpCodes.Conv_Ovf_U2_Un); break; + case Mode.U8_I: ec.Emit (OpCodes.Conv_Ovf_U_Un); break; + + case Mode.CH_I1: ec.Emit (OpCodes.Conv_Ovf_I1_Un); break; + case Mode.CH_U1: ec.Emit (OpCodes.Conv_Ovf_U1_Un); break; + case Mode.CH_I2: ec.Emit (OpCodes.Conv_Ovf_I2_Un); break; + + case Mode.R4_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.R4_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.R4_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.R4_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R4_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.R4_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.R4_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break; + case Mode.R4_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.R4_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + + case Mode.R8_I1: ec.Emit (OpCodes.Conv_Ovf_I1); break; + case Mode.R8_U1: ec.Emit (OpCodes.Conv_Ovf_U1); break; + case Mode.R8_I2: ec.Emit (OpCodes.Conv_Ovf_I2); break; + case Mode.R8_U2: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R8_I4: ec.Emit (OpCodes.Conv_Ovf_I4); break; + case Mode.R8_U4: ec.Emit (OpCodes.Conv_Ovf_U4); break; + case Mode.R8_I8: ec.Emit (OpCodes.Conv_Ovf_I8); break; + case Mode.R8_U8: ec.Emit (OpCodes.Conv_Ovf_U8); break; + case Mode.R8_CH: ec.Emit (OpCodes.Conv_Ovf_U2); break; + case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break; + + case Mode.I_I8: ec.Emit (OpCodes.Conv_Ovf_I8_Un); break; + } + } else { + switch (mode){ + case Mode.I1_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I1_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I1_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I1_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I1_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U1_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U1_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.I2_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I2_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I2_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I2_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I2_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I2_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U2_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U2_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U2_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U2_CH: /* nothing */ break; + + case Mode.I4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.I4_U4: /* nothing */ break; + case Mode.I4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I4_U8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.I4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.U4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U4_I4: /* nothing */ break; + case Mode.U4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.I8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.I8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.I8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.I8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.I8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.I8_U8: /* nothing */ break; + case Mode.I8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.I8_I: ec.Emit (OpCodes.Conv_U); break; + + case Mode.U8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.U8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.U8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.U8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.U8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.U8_I8: /* nothing */ break; + case Mode.U8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.U8_I: ec.Emit (OpCodes.Conv_U); break; + + case Mode.CH_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.CH_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.CH_I2: ec.Emit (OpCodes.Conv_I2); break; + + case Mode.R4_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.R4_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.R4_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.R4_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R4_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.R4_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.R4_I8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.R4_U8: ec.Emit (OpCodes.Conv_U8); break; + case Mode.R4_CH: ec.Emit (OpCodes.Conv_U2); break; + + case Mode.R8_I1: ec.Emit (OpCodes.Conv_I1); break; + case Mode.R8_U1: ec.Emit (OpCodes.Conv_U1); break; + case Mode.R8_I2: ec.Emit (OpCodes.Conv_I2); break; + case Mode.R8_U2: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R8_I4: ec.Emit (OpCodes.Conv_I4); break; + case Mode.R8_U4: ec.Emit (OpCodes.Conv_U4); break; + case Mode.R8_I8: ec.Emit (OpCodes.Conv_I8); break; + case Mode.R8_U8: ec.Emit (OpCodes.Conv_U8); break; + case Mode.R8_CH: ec.Emit (OpCodes.Conv_U2); break; + case Mode.R8_R4: ec.Emit (OpCodes.Conv_R4); break; + + case Mode.I_I8: ec.Emit (OpCodes.Conv_U8); break; + } + } + } + } + + class OpcodeCast : TypeCast + { + readonly OpCode op; + + public OpcodeCast (Expression child, TypeSpec return_type, OpCode op) + : base (child, return_type) + { + this.op = op; + } + + protected override Expression DoResolve (ResolveContext ec) + { + // This should never be invoked, we are born in fully + // initialized state. + + return this; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + ec.Emit (op); + } + + public TypeSpec UnderlyingType { + get { return child.Type; } + } + } + + // + // Opcode casts expression with 2 opcodes but only + // single expression tree node + // + class OpcodeCastDuplex : OpcodeCast + { + readonly OpCode second; + + public OpcodeCastDuplex (Expression child, TypeSpec returnType, OpCode first, OpCode second) + : base (child, returnType, first) + { + this.second = second; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + ec.Emit (second); + } + } + + /// + /// This kind of cast is used to encapsulate a child and cast it + /// to the class requested + /// + public sealed class ClassCast : TypeCast { + readonly bool forced; + + public ClassCast (Expression child, TypeSpec return_type) + : base (child, return_type) + { + } + + public ClassCast (Expression child, TypeSpec return_type, bool forced) + : base (child, return_type) + { + this.forced = forced; + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + bool gen = TypeManager.IsGenericParameter (child.Type); + if (gen) + ec.Emit (OpCodes.Box, child.Type); + + if (type.IsGenericParameter) { + ec.Emit (OpCodes.Unbox_Any, type); + return; + } + + if (gen && !forced) + return; + + ec.Emit (OpCodes.Castclass, type); + } + } + + // + // Created during resolving pahse when an expression is wrapped or constantified + // and original expression can be used later (e.g. for expression trees) + // + public class ReducedExpression : Expression + { + sealed class ReducedConstantExpression : EmptyConstantCast + { + readonly Expression orig_expr; + + public ReducedConstantExpression (Constant expr, Expression orig_expr) + : base (expr, expr.Type) + { + this.orig_expr = orig_expr; + } + + public override Constant ConvertImplicitly (TypeSpec target_type) + { + Constant c = base.ConvertImplicitly (target_type); + if (c != null) + c = new ReducedConstantExpression (c, orig_expr); + + return c; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type) + { + Constant c = base.ConvertExplicitly (in_checked_context, target_type); + if (c != null) + c = new ReducedConstantExpression (c, orig_expr); + return c; + } + } + + sealed class ReducedExpressionStatement : ExpressionStatement + { + readonly Expression orig_expr; + readonly ExpressionStatement stm; + + public ReducedExpressionStatement (ExpressionStatement stm, Expression orig) + { + this.orig_expr = orig; + this.stm = stm; + this.eclass = stm.eclass; + this.type = stm.Type; + + this.loc = orig.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + stm.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + stm.EmitStatement (ec); + } + } + + readonly Expression expr, orig_expr; + + private ReducedExpression (Expression expr, Expression orig_expr) + { + this.expr = expr; + this.eclass = expr.eclass; + this.type = expr.Type; + this.orig_expr = orig_expr; + this.loc = orig_expr.Location; + } + + #region Properties + + public Expression OriginalExpression { + get { + return orig_expr; + } + } + + #endregion + + // + // Creates fully resolved expression switcher + // + public static Constant Create (Constant expr, Expression original_expr) + { + if (expr.eclass == ExprClass.Unresolved) + throw new ArgumentException ("Unresolved expression"); + + return new ReducedConstantExpression (expr, original_expr); + } + + public static ExpressionStatement Create (ExpressionStatement s, Expression orig) + { + return new ReducedExpressionStatement (s, orig); + } + + public static Expression Create (Expression expr, Expression original_expr) + { + return Create (expr, original_expr, true); + } + + // + // Creates unresolved reduce expression. The original expression has to be + // already resolved. Created expression is constant based based on `expr' + // value unless canBeConstant is used + // + public static Expression Create (Expression expr, Expression original_expr, bool canBeConstant) + { + if (canBeConstant) { + Constant c = expr as Constant; + if (c != null) + return Create (c, original_expr); + } + + ExpressionStatement s = expr as ExpressionStatement; + if (s != null) + return Create (s, original_expr); + + if (expr.eclass == ExprClass.Unresolved) + throw new ArgumentException ("Unresolved expression"); + + return new ReducedExpression (expr, original_expr); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return orig_expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + expr.EmitBranchable (ec, target, on_true); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return orig_expr.MakeExpression (ctx); + } + } + + // + // Standard composite pattern + // + public abstract class CompositeExpression : Expression + { + protected Expression expr; + + protected CompositeExpression (Expression expr) + { + this.expr = expr; + this.loc = expr.Location; + } + + public override Expression CreateExpressionTree (ResolveContext rc) + { + return expr.CreateExpressionTree (rc); + } + + public Expression Child { + get { return expr; } + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr != null) { + type = expr.Type; + eclass = expr.eclass; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + } + + public override bool IsNull { + get { return expr.IsNull; } + } + } + + // + // Base of expressions used only to narrow resolve flow + // + public abstract class ShimExpression : Expression + { + protected Expression expr; + + protected ShimExpression (Expression expr) + { + this.expr = expr; + } + + public Expression Expr { + get { + return expr; + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + if (expr == null) + return; + + ShimExpression target = (ShimExpression) t; + target.expr = expr.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("Missing Resolve call"); + } + + } + + // + // Unresolved type name expressions + // + public abstract class ATypeNameExpression : FullNamedExpression + { + string name; + protected TypeArguments targs; + + protected ATypeNameExpression (string name, Location l) + { + this.name = name; + loc = l; + } + + protected ATypeNameExpression (string name, TypeArguments targs, Location l) + { + this.name = name; + this.targs = targs; + loc = l; + } + + protected ATypeNameExpression (string name, int arity, Location l) + : this (name, new UnboundTypeArguments (arity), l) + { + } + + #region Properties + + protected int Arity { + get { + return targs == null ? 0 : targs.Count; + } + } + + public bool HasTypeArguments { + get { + return targs != null && !targs.IsEmpty; + } + } + + public string Name { + get { + return name; + } + set { + name = value; + } + } + + public TypeArguments TypeArguments { + get { + return targs; + } + } + + #endregion + + public override bool Equals (object obj) + { + ATypeNameExpression atne = obj as ATypeNameExpression; + return atne != null && atne.Name == Name && + (targs == null || targs.Equals (atne.targs)); + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + // TODO: Move it to MemberCore + public static string GetMemberType (MemberCore mc) + { + if (mc is Property) + return "property"; + if (mc is Indexer) + return "indexer"; + if (mc is FieldBase) + return "field"; + if (mc is MethodCore) + return "method"; + if (mc is EnumMember) + return "enum"; + if (mc is Event) + return "event"; + + return "type"; + } + + public override string GetSignatureForError () + { + if (targs != null) { + return Name + "<" + targs.GetSignatureForError () + ">"; + } + + return Name; + } + + public abstract Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restriction); + } + + /// + /// SimpleName expressions are formed of a single word and only happen at the beginning + /// of a dotted-name. + /// + public class SimpleName : ATypeNameExpression + { + public SimpleName (string name, Location l) + : base (name, l) + { + } + + public SimpleName (string name, TypeArguments args, Location l) + : base (name, args, l) + { + } + + public SimpleName (string name, int arity, Location l) + : base (name, arity, l) + { + } + + public SimpleName GetMethodGroup () + { + return new SimpleName (Name, targs, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return SimpleNameResolve (ec, null, false); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return SimpleNameResolve (ec, right_side, false); + } + + protected virtual void Error_TypeOrNamespaceNotFound (IMemberContext ctx) + { + if (ctx.CurrentType != null) { + if (ctx.CurrentMemberDefinition != null) { + MemberCore mc = ctx.CurrentMemberDefinition.Parent.GetDefinition (Name); + if (mc != null) { + Error_UnexpectedKind (ctx.Module.Compiler.Report, mc, "type", GetMemberType (mc), loc); + return; + } + } + } + + // MSAF + var retval = ctx.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc); + if (retval != null) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type); + ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc); + return; + } + + retval = ctx.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc); + if (retval != null) { + Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, Arity, loc); + return; + } + + NamespaceContainer.Error_NamespaceNotFound (loc, Name, ctx.Module.Compiler.Report); + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec) + { + FullNamedExpression fne = ec.LookupNamespaceOrType (Name, Arity, LookupMode.Normal, loc); + + if (fne != null) { + if (fne.Type != null && Arity > 0) { + if (HasTypeArguments) { + GenericTypeExpr ct = new GenericTypeExpr (fne.Type, targs, loc); + if (ct.ResolveAsType (ec) == null) + return null; + + return ct; + } + + return new GenericOpenTypeExpr (fne.Type, loc); + } + + // + // dynamic namespace is ignored when dynamic is allowed (does not apply to types) + // + if (!(fne is Namespace)) + return fne; + } + + if (Arity == 0 && Name == "dynamic" && ec.Module.Compiler.Settings.Version > LanguageVersion.V_3) { + if (!ec.Module.PredefinedAttributes.Dynamic.IsDefined) { + ec.Module.Compiler.Report.Error (1980, Location, + "Dynamic keyword requires `{0}' to be defined. Are you missing System.Core.dll assembly reference?", + ec.Module.PredefinedAttributes.Dynamic.GetSignatureForError ()); + } + + fne = new DynamicTypeExpr (loc); + fne.ResolveAsType (ec); + } + + if (fne != null) + return fne; + + Error_TypeOrNamespaceNotFound (ec); + return null; + } + + public bool IsPossibleTypeOrNamespace (IMemberContext mc) + { + return mc.LookupNamespaceOrType (Name, Arity, LookupMode.Probing, loc) != null; + } + + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) + { + int lookup_arity = Arity; + bool errorMode = false; + Expression e; + Block current_block = rc.CurrentBlock; + INamedBlockVariable variable = null; + bool variable_found = false; + + while (true) { + // + // Stage 1: binding to local variables or parameters + // + // LAMESPEC: It should take invocableOnly into account but that would break csc compatibility + // + if (current_block != null && lookup_arity == 0) { + if (current_block.ParametersBlock.TopBlock.GetLocalName (Name, current_block.Original, ref variable)) { + if (!variable.IsDeclared) { + // We found local name in accessible block but it's not + // initialized yet, maybe the user wanted to bind to something else + errorMode = true; + variable_found = true; + } else { + e = variable.CreateReferenceExpression (rc, loc); + if (e != null) { + if (Arity > 0) + Error_TypeArgumentsCannotBeUsed (rc, "variable", Name, loc); + + return e; + } + } + } + } + + // + // Stage 2: Lookup members if we are inside a type up to top level type for nested types + // + TypeSpec member_type = rc.CurrentType; + for (; member_type != null; member_type = member_type.DeclaringType) { + e = MemberLookup (rc, errorMode, member_type, Name, lookup_arity, restrictions, loc); + if (e == null) + continue; + + var me = e as MemberExpr; + if (me == null) { + // The name matches a type, defer to ResolveAsTypeStep + if (e is TypeExpr) + break; + + continue; + } + + if (errorMode) { + if (variable != null) { + if (me is FieldExpr || me is ConstantExpr || me is EventExpr || me is PropertyExpr) { + rc.Report.Error (844, loc, + "A local variable `{0}' cannot be used before it is declared. Consider renaming the local variable when it hides the member `{1}'", + Name, me.GetSignatureForError ()); + } else { + break; + } + } else if (me is MethodGroupExpr) { + // Leave it to overload resolution to report correct error + } else { + // TODO: rc.Report.SymbolRelatedToPreviousError () + ErrorIsInaccesible (rc, me.GetSignatureForError (), loc); + } + } else { + // LAMESPEC: again, ignores InvocableOnly + if (variable != null) { + rc.Report.SymbolRelatedToPreviousError (variable.Location, Name); + rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name); + } + + // + // MemberLookup does not check accessors availability, this is actually needed for properties only + // + var pe = me as PropertyExpr; + if (pe != null) { + + // Break as there is no other overload available anyway + if ((restrictions & MemberLookupRestrictions.ReadAccess) != 0) { + if (!pe.PropertyInfo.HasGet || !pe.PropertyInfo.Get.IsAccessible (rc)) + break; + + pe.Getter = pe.PropertyInfo.Get; + } else { + if (!pe.PropertyInfo.HasSet || !pe.PropertyInfo.Set.IsAccessible (rc)) + break; + + pe.Setter = pe.PropertyInfo.Set; + } + } + } + + // TODO: It's used by EventExpr -> FieldExpr transformation only + // TODO: Should go to MemberAccess + me = me.ResolveMemberAccess (rc, null, null); + + if (Arity > 0) { + targs.Resolve (rc); + me.SetTypeArguments (rc, targs); + } + + return me; + } + + // + // Stage 3: Lookup nested types, namespaces and type parameters in the context + // + if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0 && !variable_found) { + if (IsPossibleTypeOrNamespace (rc)) { + if (variable != null) { + rc.Report.SymbolRelatedToPreviousError (variable.Location, Name); + rc.Report.Error (135, loc, "`{0}' conflicts with a declaration in a child block", Name); + } + + return ResolveAsTypeOrNamespace (rc); + } + } + + if (errorMode) { + if (variable_found) { + rc.Report.Error (841, loc, "A local variable `{0}' cannot be used before it is declared", Name); + } else { + if (Arity > 0) { + TypeParameter[] tparams = rc.CurrentTypeParameters; + if (tparams != null) { + foreach (var ctp in tparams) { + if (ctp.Name == Name) { + Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc); + return null; + } + } + } + + var ct = rc.CurrentType; + do { + if (ct.MemberDefinition.TypeParametersCount > 0) { + foreach (var ctp in ct.MemberDefinition.TypeParameters) { + if (ctp.Name == Name) { + Error_TypeArgumentsCannotBeUsed (rc, "type parameter", Name, loc); + return null; + } + } + } + + ct = ct.DeclaringType; + } while (ct != null); + } + + if ((restrictions & MemberLookupRestrictions.InvocableOnly) == 0) { + e = rc.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc); + if (e != null) { + rc.Report.SymbolRelatedToPreviousError (e.Type); + ErrorIsInaccesible (rc, e.GetSignatureForError (), loc); + return e; + } + } + + e = rc.LookupNamespaceOrType (Name, -System.Math.Max (1, Arity), LookupMode.Probing, loc); + if (e != null) { + if (!(e is TypeExpr) || (restrictions & MemberLookupRestrictions.InvocableOnly) == 0 || !e.Type.IsDelegate) { + Error_TypeArgumentsCannotBeUsed (rc, e.Type, Arity, loc); + return e; + } + } + + rc.Report.Error (103, loc, "The name `{0}' does not exist in the current context", Name); + } + + return ErrorExpression.Instance; + } + + if (rc.Module.Evaluator != null) { + var fi = rc.Module.Evaluator.LookupField (Name); + if (fi != null) + return new FieldExpr (fi.Item1, loc); + } + + lookup_arity = 0; + errorMode = true; + } + } + + Expression SimpleNameResolve (ResolveContext ec, Expression right_side, bool intermediate) + { + Expression e = LookupNameExpression (ec, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None); + + if (e == null) + return null; + + if (right_side != null) { + if (e is TypeExpr) { + e.Error_UnexpectedKind (ec, ResolveFlags.VariableOrValue, loc); + return null; + } + + e = e.ResolveLValue (ec, right_side); + } else { + e = e.Resolve (ec); + } + + //if (ec.CurrentBlock == null || ec.CurrentBlock.CheckInvariantMeaningInBlock (Name, e, Location)) + return e; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Represents a namespace or a type. The name of the class was inspired by + /// section 10.8.1 (Fully Qualified Names). + /// + public abstract class FullNamedExpression : Expression + { + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // Do nothing, most unresolved type expressions cannot be + // resolved to different type + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public abstract FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc); + + // + // This is used to resolve the expression as a type, a null + // value will be returned if the expression is not a type + // reference + // + public override TypeSpec ResolveAsType (IMemberContext mc) + { + FullNamedExpression fne = ResolveAsTypeOrNamespace (mc); + + if (fne == null) + return null; + + TypeExpr te = fne as TypeExpr; + if (te == null) { + fne.Error_UnexpectedKind (mc.Module.Compiler.Report, null, "type", loc); + return null; + } + + te.loc = loc; + + type = te.Type; + + var dep = type.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc); + } + + // + // Obsolete checks cannot be done when resolving base context as they + // require type dependencies to be set but we are in process of resolving them + // + if (!(mc is TypeContainer.BaseContext)) { + ObsoleteAttribute obsolete_attr = type.GetAttributeObsolete (); + if (obsolete_attr != null && !mc.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (obsolete_attr, te.GetSignatureForError (), Location, mc.Module.Compiler.Report); + } + } + + return type; + } + + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("FullNamedExpression `{0}' found in resolved tree", + GetSignatureForError ()); + } + } + + /// + /// Expression that evaluates to a type + /// + public abstract class TypeExpr : FullNamedExpression + { + public sealed override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc) + { + ResolveAsType (mc); + return this; + } + + protected sealed override Expression DoResolve (ResolveContext ec) + { + ResolveAsType (ec); + return this; + } + + public override bool Equals (object obj) + { + TypeExpr tobj = obj as TypeExpr; + if (tobj == null) + return false; + + return Type == tobj.Type; + } + + public override int GetHashCode () + { + return Type.GetHashCode (); + } + } + + /// + /// Fully resolved Expression that already evaluated to a type + /// + public class TypeExpression : TypeExpr + { + public TypeExpression (TypeSpec t, Location l) + { + Type = t; + eclass = ExprClass.Type; + loc = l; + } + + public sealed override TypeSpec ResolveAsType (IMemberContext ec) + { + return type; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This class denotes an expression which evaluates to a member + /// of a struct or a class. + /// + public abstract class MemberExpr : Expression + { + // + // An instance expression associated with this member, if it's a + // non-static member + // + public Expression InstanceExpression; + + /// + /// The name of this member. + /// + public abstract string Name { + get; + } + + // + // When base.member is used + // + public bool IsBase { + get { return InstanceExpression is BaseThis; } + } + + /// + /// Whether this is an instance member. + /// + public abstract bool IsInstance { + get; + } + + /// + /// Whether this is a static member. + /// + public abstract bool IsStatic { + get; + } + + protected abstract TypeSpec DeclaringType { + get; + } + + // + // Converts best base candidate for virtual method starting from QueriedBaseType + // + protected MethodSpec CandidateToBaseOverride (ResolveContext rc, MethodSpec method) + { + // + // Only when base.member is used and method is virtual + // + if (!IsBase) + return method; + + // + // Overload resulution works on virtual or non-virtual members only (no overrides). That + // means for base.member access we have to find the closest match after we found best candidate + // + if ((method.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) { + // + // The method could already be what we are looking for + // + TypeSpec[] targs = null; + if (method.DeclaringType != InstanceExpression.Type) { + var base_override = MemberCache.FindMember (InstanceExpression.Type, new MemberFilter (method), BindingRestriction.InstanceOnly) as MethodSpec; + if (base_override != null && base_override.DeclaringType != method.DeclaringType) { + if (base_override.IsGeneric) + targs = method.TypeArguments; + + method = base_override; + } + } + + // TODO: For now we do it for any hoisted call even if it's needed for + // hoisted stories only but that requires a new expression wrapper + if (rc.CurrentAnonymousMethod != null) { + if (targs == null && method.IsGeneric) { + targs = method.TypeArguments; + method = method.GetGenericMethodDefinition (); + } + + if (method.Parameters.HasArglist) + throw new NotImplementedException ("__arglist base call proxy"); + + method = rc.CurrentMemberDefinition.Parent.PartialContainer.CreateHoistedBaseCallProxy (rc, method); + + // Ideally this should apply to any proxy rewrite but in the case of unary mutators on + // get/set member expressions second call would fail to proxy because left expression + // would be of 'this' and not 'base' + if (rc.CurrentType.IsStruct) + InstanceExpression = new This (loc).Resolve (rc); + } + + if (targs != null) + method = method.MakeGenericMethod (rc, targs); + } + + // + // Only base will allow this invocation to happen. + // + if (method.IsAbstract) { + Error_CannotCallAbstractBase (rc, method.GetSignatureForError ()); + } + + return method; + } + + protected void CheckProtectedMemberAccess (ResolveContext rc, T member) where T : MemberSpec + { + if (InstanceExpression == null) + return; + + if ((member.Modifiers & Modifiers.PROTECTED) != 0 && !(InstanceExpression is This)) { + CheckProtectedMemberAccess (rc, member, InstanceExpression.Type, loc); + } + } + + public static void CheckProtectedMemberAccess (ResolveContext rc, T member, TypeSpec qualifier, Location loc) where T : MemberSpec + { + var ct = rc.CurrentType; + if (ct == qualifier) + return; + + if ((member.Modifiers & Modifiers.INTERNAL) != 0 && member.DeclaringType.MemberDefinition.IsInternalAsPublic (ct.MemberDefinition.DeclaringAssembly)) + return; + + 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 ()); + } + } + + static bool IsSameOrBaseQualifier (TypeSpec type, TypeSpec qtype) + { + do { + type = type.GetDefinition (); + + if (type == qtype || TypeManager.IsFamilyAccessible (qtype, type)) + return true; + + type = type.DeclaringType; + } while (type != null); + + return false; + } + + protected void DoBestMemberChecks (ResolveContext rc, T member) where T : MemberSpec, IInterfaceMemberSpec + { + if (InstanceExpression != null) { + InstanceExpression = InstanceExpression.Resolve (rc); + CheckProtectedMemberAccess (rc, member); + } + + if (member.MemberType.IsPointer && !rc.IsUnsafe) { + UnsafeError (rc, loc); + } + + var dep = member.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); + } + + if (!rc.IsObsolete) { + ObsoleteAttribute oa = member.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, member.GetSignatureForError (), loc, rc.Report); + } + + if (!(member is FieldSpec)) + member.MemberDefinition.SetIsUsed (); + } + + protected virtual void Error_CannotCallAbstractBase (ResolveContext rc, string name) + { + rc.Report.Error (205, loc, "Cannot call an abstract base member `{0}'", name); + } + + // + // Implements identicial simple name and type-name + // + public Expression ProbeIdenticalTypeName (ResolveContext rc, Expression left, SimpleName name) + { + var t = left.Type; + if (t.Kind == MemberKind.InternalCompilerType || t is ElementTypeSpec || t.Arity > 0) + return left; + + // In a member access of the form E.I, if E is a single identifier, and if the meaning of E as a simple-name is + // a constant, field, property, local variable, or parameter with the same type as the meaning of E as a type-name + + if (left is MemberExpr || left is VariableReference) { + var identical_type = rc.LookupNamespaceOrType (name.Name, 0, LookupMode.Probing, loc) as TypeExpr; + if (identical_type != null && identical_type.Type == left.Type) + return identical_type; + } + + return left; + } + + public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs) + { + if (IsStatic) { + if (InstanceExpression != null) { + if (InstanceExpression is TypeExpr) { + var t = InstanceExpression.Type; + do { + ObsoleteAttribute oa = t.GetAttributeObsolete (); + if (oa != null && !rc.IsObsolete) { + AttributeTester.Report_ObsoleteMessage (oa, t.GetSignatureForError (), loc, rc.Report); + } + + t = t.DeclaringType; + } while (t != null); + } else { + var runtime_expr = InstanceExpression as RuntimeValueExpression; + if (runtime_expr == null || !runtime_expr.IsSuggestionOnly) { + rc.Report.Error (176, loc, + "Static member `{0}' cannot be accessed with an instance reference, qualify it with a type name instead", + GetSignatureForError ()); + } + } + + InstanceExpression = null; + } + + return false; + } + + if (InstanceExpression == null || InstanceExpression is TypeExpr) { + if (InstanceExpression != null || !This.IsThisAvailable (rc, true)) { + if (rc.HasSet (ResolveContext.Options.FieldInitializerScope)) + rc.Report.Error (236, loc, + "A field initializer cannot reference the nonstatic field, method, or property `{0}'", + GetSignatureForError ()); + else + rc.Report.Error (120, loc, + "An object reference is required to access non-static member `{0}'", + GetSignatureForError ()); + + return false; + } + + if (!TypeManager.IsFamilyAccessible (rc.CurrentType, DeclaringType)) { + rc.Report.Error (38, loc, + "Cannot access a nonstatic member of outer type `{0}' via nested type `{1}'", + DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ()); + } + + InstanceExpression = new This (loc); + if (this is FieldExpr && rc.CurrentType.IsStruct) { + using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { + InstanceExpression = InstanceExpression.Resolve (rc); + } + } else { + InstanceExpression = InstanceExpression.Resolve (rc); + } + + return false; + } + + var me = InstanceExpression as MemberExpr; + if (me != null) { + me.ResolveInstanceExpression (rc, rhs); + + var fe = me as FieldExpr; + if (fe != null && fe.IsMarshalByRefAccess (rc)) { + rc.Report.SymbolRelatedToPreviousError (me.DeclaringType); + rc.Report.Warning (1690, 1, loc, + "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class", + me.GetSignatureForError ()); + } + + return true; + } + + // + // Run member-access postponed check once we know that + // 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) { + ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc); + } + + // + // 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"); + } + } + + return true; + } + + public virtual MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) + { + if (left != null && left.IsNull && TypeSpec.IsReferenceType (left.Type)) { + ec.Report.Warning (1720, 1, left.Location, + "Expression will always cause a `{0}'", "System.NullReferenceException"); + } + + InstanceExpression = left; + return this; + } + + protected void EmitInstance (EmitContext ec, bool prepare_for_load) + { + TypeSpec instance_type = InstanceExpression.Type; + if (TypeSpec.IsValueType (instance_type)) { + if (InstanceExpression is IMemoryLocation) { + ((IMemoryLocation) InstanceExpression).AddressOf (ec, AddressOp.Load); + } else { + LocalTemporary t = new LocalTemporary (instance_type); + InstanceExpression.Emit (ec); + t.Store (ec); + t.AddressOf (ec, AddressOp.Store); + } + } else { + InstanceExpression.Emit (ec); + + // Only to make verifier happy + if (instance_type.IsGenericParameter && !(InstanceExpression is This) && TypeSpec.IsReferenceType (instance_type)) + ec.Emit (OpCodes.Box, instance_type); + } + + if (prepare_for_load) + ec.Emit (OpCodes.Dup); + } + + public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta); + } + + // + // Represents a group of extension method candidates for whole namespace + // + class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler + { + NamespaceContainer namespace_entry; + public readonly Expression ExtensionExpression; + + public ExtensionMethodGroupExpr (IList list, NamespaceContainer n, Expression extensionExpr, Location l) + : base (list.Cast().ToList (), extensionExpr.Type, l) + { + this.namespace_entry = n; + this.ExtensionExpression = extensionExpr; + } + + public override bool IsStatic { + get { return true; } + } + + public override IList GetBaseMembers (TypeSpec baseType) + { + if (namespace_entry == null) + return null; + + // + // For extension methodgroup we are not looking for base members but parent + // namespace extension methods + // + int arity = type_arguments == null ? 0 : type_arguments.Count; + var found = namespace_entry.LookupExtensionMethod (DeclaringType, Name, arity, ref namespace_entry); + if (found == null) + return null; + + return found.Cast ().ToList (); + } + + public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc) + { + // We are already here + return null; + } + + public override MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments arguments, OverloadResolver.IErrorHandler ehandler, OverloadResolver.Restrictions restr) + { + if (arguments == null) + arguments = new Arguments (1); + + arguments.Insert (0, new Argument (ExtensionExpression, Argument.AType.ExtensionType)); + var res = base.OverloadResolve (ec, ref arguments, ehandler ?? this, restr); + + // Store resolved argument and restore original arguments + if (res == null) { + // Clean-up modified arguments for error reporting + arguments.RemoveAt (0); + return null; + } + + var me = ExtensionExpression as MemberExpr; + if (me != null) + me.ResolveInstanceExpression (ec, null); + + InstanceExpression = null; + return this; + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous) + { + return false; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + rc.Report.SymbolRelatedToPreviousError (best); + rc.Report.Error (1928, loc, + "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' has some invalid arguments", + queried_type.GetSignatureForError (), Name, best.GetSignatureForError ()); + + if (index == 0) { + rc.Report.Error (1929, loc, + "Extension method instance type `{0}' cannot be converted to `{1}'", + arg.Type.GetSignatureForError (), ((MethodSpec)best).Parameters.ExtensionMethodType.GetSignatureForError ()); + } + + return true; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + return false; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + return false; + } + + #endregion + } + + /// + /// MethodGroupExpr represents a group of method candidates which + /// can be resolved to the best method overload + /// + public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider + { + protected IList Methods; + MethodSpec best_candidate; + TypeSpec best_candidate_return; + protected TypeArguments type_arguments; + + SimpleName simple_name; + protected TypeSpec queried_type; + + public MethodGroupExpr (IList mi, TypeSpec type, Location loc) + { + Methods = mi; + this.loc = loc; + this.type = InternalType.MethodGroup; + + eclass = ExprClass.MethodGroup; + queried_type = type; + } + + public MethodGroupExpr (MethodSpec m, TypeSpec type, Location loc) + : this (new MemberSpec[] { m }, type, loc) + { + } + + #region Properties + + public MethodSpec BestCandidate { + get { + return best_candidate; + } + } + + public TypeSpec BestCandidateReturnType { + get { + return best_candidate_return; + } + } + + public IList Candidates { + get { + return Methods; + } + } + + protected override TypeSpec DeclaringType { + get { + return queried_type; + } + } + + public override bool IsInstance { + get { + if (best_candidate != null) + return !best_candidate.IsStatic; + + return false; + } + } + + public override bool IsStatic { + get { + if (best_candidate != null) + return best_candidate.IsStatic; + + return false; + } + } + + public override string Name { + get { + if (best_candidate != null) + return best_candidate.Name; + + // TODO: throw ? + return Methods.First ().Name; + } + } + + #endregion + + // + // When best candidate is already know this factory can be used + // to avoid expensive overload resolution to be called + // + // NOTE: InstanceExpression has to be set manually + // + public static MethodGroupExpr CreatePredefined (MethodSpec best, TypeSpec queriedType, Location loc) + { + return new MethodGroupExpr (best, queriedType, loc) { + best_candidate = best, + best_candidate_return = best.ReturnType + }; + } + + public override string GetSignatureForError () + { + if (best_candidate != null) + return best_candidate.GetSignatureForError (); + + return Methods.First ().GetSignatureForError (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (best_candidate == null) { + ec.Report.Error (1953, loc, "An expression tree cannot contain an expression with method group"); + return null; + } + + if (best_candidate.IsConditionallyExcluded (ec.Module.Compiler, loc)) + ec.Report.Error (765, loc, + "Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree"); + + return new TypeOfMethod (best_candidate, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + this.eclass = ExprClass.MethodGroup; + + if (InstanceExpression != null) { + InstanceExpression = InstanceExpression.Resolve (ec); + if (InstanceExpression == null) + return null; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + } + + public void EmitCall (EmitContext ec, Arguments arguments) + { + Invocation.EmitCall (ec, InstanceExpression, best_candidate, arguments, loc); + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + ec.Report.Error (428, loc, "Cannot convert method group `{0}' to non-delegate type `{1}'. Consider using parentheses to invoke the method", + Name, TypeManager.CSharpName (target)); + } + + public static bool IsExtensionMethodArgument (Expression expr) + { + // + // LAMESPEC: No details about which expressions are not allowed + // + return !(expr is TypeExpr) && !(expr is BaseThis); + } + + /// + /// Find the Applicable Function Members (7.4.2.1) + /// + /// me: Method Group expression with the members to select. + /// it might contain constructors or methods (or anything + /// that maps to a method). + /// + /// Arguments: ArrayList containing resolved Argument objects. + /// + /// loc: The location if we want an error to be reported, or a Null + /// location for "probing" purposes. + /// + /// Returns: The MethodBase (either a ConstructorInfo or a MethodInfo) + /// that is the best match of me on Arguments. + /// + /// + public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments args, OverloadResolver.IErrorHandler cerrors, OverloadResolver.Restrictions restr) + { + // TODO: causes issues with probing mode, remove explicit Kind check + if (best_candidate != null && best_candidate.Kind == MemberKind.Destructor) + return this; + + var r = new OverloadResolver (Methods, type_arguments, restr, loc); + if ((restr & OverloadResolver.Restrictions.NoBaseMembers) == 0) { + r.BaseMembersProvider = this; + } + + if (cerrors != null) + r.CustomErrors = cerrors; + + // TODO: When in probing mode do IsApplicable only and when called again do VerifyArguments for full error reporting + best_candidate = r.ResolveMember (ec, ref args); + if (best_candidate == null) + return r.BestCandidateIsDynamic ? this : null; + + // Overload resolver had to create a new method group, all checks bellow have already been executed + if (r.BestCandidateNewMethodGroup != null) + return r.BestCandidateNewMethodGroup; + + if (best_candidate.Kind == MemberKind.Method && (restr & OverloadResolver.Restrictions.ProbingOnly) == 0) { + if (InstanceExpression != null) { + if (best_candidate.IsExtensionMethod && args[0].Expr == InstanceExpression) { + InstanceExpression = null; + } else { + if (best_candidate.IsStatic && simple_name != null) { + InstanceExpression = ProbeIdenticalTypeName (ec, InstanceExpression, simple_name); + } + + InstanceExpression.Resolve (ec); + } + } + + ResolveInstanceExpression (ec, null); + if (InstanceExpression != null) + CheckProtectedMemberAccess (ec, best_candidate); + } + + var base_override = CandidateToBaseOverride (ec, best_candidate); + if (base_override == best_candidate) { + best_candidate_return = r.BestCandidateReturnType; + } else { + best_candidate = base_override; + best_candidate_return = best_candidate.ReturnType; + } + + return this; + } + + public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) + { + simple_name = original; + return base.ResolveMemberAccess (ec, left, original); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + type_arguments = ta; + } + + #region IBaseMembersProvider Members + + public virtual IList GetBaseMembers (TypeSpec baseType) + { + return baseType == null ? null : MemberCache.FindMembers (baseType, Methods [0].Name, false); + } + + public IParametersMember GetOverrideMemberParameters (MemberSpec member) + { + if (queried_type == member.DeclaringType) + return null; + + return MemberCache.FindMember (queried_type, new MemberFilter ((MethodSpec) member), + BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember; + } + + // + // Extension methods lookup after ordinary methods candidates failed to apply + // + public virtual MethodGroupExpr LookupExtensionMethod (ResolveContext rc) + { + if (InstanceExpression == null) + return null; + + InstanceExpression = InstanceExpression.Resolve (rc); + if (!IsExtensionMethodArgument (InstanceExpression)) + return null; + + int arity = type_arguments == null ? 0 : type_arguments.Count; + NamespaceContainer methods_scope = null; + var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope); + if (methods == null) + return null; + + var emg = new ExtensionMethodGroupExpr (methods, methods_scope, InstanceExpression, loc); + emg.SetTypeArguments (rc, type_arguments); + return emg; + } + + #endregion + } + + public struct OverloadResolver + { + [Flags] + public enum Restrictions + { + None = 0, + DelegateInvoke = 1, + ProbingOnly = 1 << 1, + CovariantDelegate = 1 << 2, + NoBaseMembers = 1 << 3, + BaseMembersIncluded = 1 << 4 + } + + public interface IBaseMembersProvider + { + IList GetBaseMembers (TypeSpec baseType); + IParametersMember GetOverrideMemberParameters (MemberSpec member); + MethodGroupExpr LookupExtensionMethod (ResolveContext rc); + } + + public interface IErrorHandler + { + bool AmbiguousCandidates (ResolveContext rc, MemberSpec best, MemberSpec ambiguous); + bool ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument a, int index); + bool NoArgumentMatch (ResolveContext rc, MemberSpec best); + bool TypeInferenceFailed (ResolveContext rc, MemberSpec best); + } + + sealed class NoBaseMembers : IBaseMembersProvider + { + public static readonly IBaseMembersProvider Instance = new NoBaseMembers (); + + public IList GetBaseMembers (TypeSpec baseType) + { + return null; + } + + public IParametersMember GetOverrideMemberParameters (MemberSpec member) + { + return null; + } + + public MethodGroupExpr LookupExtensionMethod (ResolveContext rc) + { + return null; + } + } + + struct AmbiguousCandidate + { + public readonly MemberSpec Member; + public readonly bool Expanded; + public readonly AParametersCollection Parameters; + + public AmbiguousCandidate (MemberSpec member, AParametersCollection parameters, bool expanded) + { + Member = member; + Parameters = parameters; + Expanded = expanded; + } + } + + Location loc; + IList members; + TypeArguments type_arguments; + IBaseMembersProvider base_provider; + IErrorHandler custom_errors; + Restrictions restrictions; + MethodGroupExpr best_candidate_extension_group; + TypeSpec best_candidate_return_type; + + SessionReportPrinter lambda_conv_msgs; + ReportPrinter prev_recorder; + + public OverloadResolver (IList members, Restrictions restrictions, Location loc) + : this (members, null, restrictions, loc) + { + } + + public OverloadResolver (IList members, TypeArguments targs, Restrictions restrictions, Location loc) + : this () + { + if (members == null || members.Count == 0) + throw new ArgumentException ("empty members set"); + + this.members = members; + this.loc = loc; + type_arguments = targs; + this.restrictions = restrictions; + if (IsDelegateInvoke) + this.restrictions |= Restrictions.NoBaseMembers; + + base_provider = NoBaseMembers.Instance; + } + + #region Properties + + public IBaseMembersProvider BaseMembersProvider { + get { + return base_provider; + } + set { + base_provider = value; + } + } + + public bool BestCandidateIsDynamic { get; set; } + + // + // Best candidate was found in newly created MethodGroupExpr, used by extension methods + // + public MethodGroupExpr BestCandidateNewMethodGroup { + get { + return best_candidate_extension_group; + } + } + + // + // Return type can be different between best candidate and closest override + // + public TypeSpec BestCandidateReturnType { + get { + return best_candidate_return_type; + } + } + + public IErrorHandler CustomErrors { + get { + return custom_errors; + } + set { + custom_errors = value; + } + } + + TypeSpec DelegateType { + get { + if ((restrictions & Restrictions.DelegateInvoke) == 0) + throw new InternalErrorException ("Not running in delegate mode", loc); + + return members [0].DeclaringType; + } + } + + bool IsProbingOnly { + get { + return (restrictions & Restrictions.ProbingOnly) != 0; + } + } + + bool IsDelegateInvoke { + get { + return (restrictions & Restrictions.DelegateInvoke) != 0; + } + } + + #endregion + + // + // 7.4.3.3 Better conversion from expression + // Returns : 1 if a->p is better, + // 2 if a->q is better, + // 0 if neither is better + // + static int BetterExpressionConversion (ResolveContext ec, Argument a, TypeSpec p, TypeSpec q) + { + TypeSpec argument_type = a.Type; + + // + // If argument is an anonymous function + // + if (argument_type == InternalType.AnonymousMethod && ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2) { + // + // p and q are delegate types or expression tree types + // + if (p.IsExpressionTreeType || q.IsExpressionTreeType) { + if (q.MemberDefinition != p.MemberDefinition) { + return 0; + } + + // + // Uwrap delegate from Expression + // + q = TypeManager.GetTypeArguments (q)[0]; + p = TypeManager.GetTypeArguments (p)[0]; + } + + var p_m = Delegate.GetInvokeMethod (p); + var q_m = Delegate.GetInvokeMethod (q); + + // + // With identical parameter lists + // + if (!TypeSpecComparer.Equals (p_m.Parameters.Types, q_m.Parameters.Types)) + return 0; + + p = p_m.ReturnType; + q = q_m.ReturnType; + + // + // if p is void returning, and q has a return type Y, then C2 is the better conversion. + // + if (p.Kind == MemberKind.Void) { + return q.Kind != MemberKind.Void ? 2 : 0; + } + + // + // if p has a return type Y, and q is void returning, then C1 is the better conversion. + // + 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, and Q has a return type Task + // 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; + + if (argument_type == q) + return 2; + } + + return BetterTypeConversion (ec, p, q); + } + + // + // 7.4.3.4 Better conversion from type + // + public static int BetterTypeConversion (ResolveContext ec, TypeSpec p, TypeSpec q) + { + if (p == null || q == null) + throw new InternalErrorException ("BetterTypeConversion got a null conversion"); + + switch (p.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + if (q.BuiltinType == BuiltinTypeSpec.Type.UInt || q.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 1; + break; + case BuiltinTypeSpec.Type.Long: + if (q.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 1; + break; + case BuiltinTypeSpec.Type.SByte: + switch (q.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 1; + } + break; + case BuiltinTypeSpec.Type.Short: + switch (q.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 1; + } + break; + case BuiltinTypeSpec.Type.Dynamic: + // Dynamic is never better + return 2; + } + + switch (q.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + if (p.BuiltinType == BuiltinTypeSpec.Type.UInt || p.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 2; + break; + case BuiltinTypeSpec.Type.Long: + if (p.BuiltinType == BuiltinTypeSpec.Type.ULong) + return 2; + break; + case BuiltinTypeSpec.Type.SByte: + switch (p.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 2; + } + break; + case BuiltinTypeSpec.Type.Short: + switch (p.BuiltinType) { + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + return 2; + } + break; + case BuiltinTypeSpec.Type.Dynamic: + // Dynamic is never better + return 1; + } + + // FIXME: handle lifted operators + + // TODO: this is expensive + Expression p_tmp = new EmptyExpression (p); + Expression q_tmp = new EmptyExpression (q); + + bool p_to_q = Convert.ImplicitConversionExists (ec, p_tmp, q); + bool q_to_p = Convert.ImplicitConversionExists (ec, q_tmp, p); + + if (p_to_q && !q_to_p) + return 1; + + if (q_to_p && !p_to_q) + return 2; + + return 0; + } + + /// + /// Determines "Better function" between candidate + /// and the current best match + /// + /// + /// Returns a boolean indicating : + /// false if candidate ain't better + /// true if candidate is better than the current best match + /// + static bool BetterFunction (ResolveContext ec, Arguments args, MemberSpec candidate, AParametersCollection cparam, bool candidate_params, + MemberSpec best, AParametersCollection bparam, bool best_params) + { + AParametersCollection candidate_pd = ((IParametersMember) candidate).Parameters; + AParametersCollection best_pd = ((IParametersMember) best).Parameters; + + bool better_at_least_one = false; + bool same = true; + int args_count = args == null ? 0 : args.Count; + int j = 0; + Argument a = null; + TypeSpec ct, bt; + for (int c_idx = 0, b_idx = 0; j < args_count; ++j, ++c_idx, ++b_idx) { + a = args[j]; + + // Default arguments are ignored for better decision + if (a.IsDefaultArgument) + break; + + // + // When comparing named argument the parameter type index has to be looked up + // in original parameter set (override version for virtual members) + // + NamedArgument na = a as NamedArgument; + if (na != null) { + int idx = cparam.GetParameterIndexByName (na.Name); + ct = candidate_pd.Types[idx]; + if (candidate_params && candidate_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + ct = TypeManager.GetElementType (ct); + + idx = bparam.GetParameterIndexByName (na.Name); + bt = best_pd.Types[idx]; + if (best_params && best_pd.FixedParameters[idx].ModFlags == Parameter.Modifier.PARAMS) + bt = TypeManager.GetElementType (bt); + } else { + ct = candidate_pd.Types[c_idx]; + bt = best_pd.Types[b_idx]; + + if (candidate_params && candidate_pd.FixedParameters[c_idx].ModFlags == Parameter.Modifier.PARAMS) { + ct = TypeManager.GetElementType (ct); + --c_idx; + } + + if (best_params && best_pd.FixedParameters[b_idx].ModFlags == Parameter.Modifier.PARAMS) { + bt = TypeManager.GetElementType (bt); + --b_idx; + } + } + + if (TypeSpecComparer.IsEqual (ct, bt)) + continue; + + same = false; + int result = BetterExpressionConversion (ec, a, ct, bt); + + // for each argument, the conversion to 'ct' should be no worse than + // the conversion to 'bt'. + if (result == 2) + return false; + + // for at least one argument, the conversion to 'ct' should be better than + // the conversion to 'bt'. + if (result != 0) + better_at_least_one = true; + } + + if (better_at_least_one) + return true; + + // + // This handles the case + // + // Add (float f1, float f2, float f3); + // Add (params decimal [] foo); + // + // The call Add (3, 4, 5) should be ambiguous. Without this check, the + // first candidate would've chosen as better. + // + if (!same && !a.IsDefaultArgument) + return false; + + // + // The two methods have equal non-optional parameter types, apply tie-breaking rules + // + + // + // This handles the following cases: + // + // Foo (int i) is better than Foo (int i, long l = 0) + // Foo (params int[] args) is better than Foo (int i = 0, params int[] args) + // + // Prefer non-optional version + // + // LAMESPEC: Specification claims this should be done at last but the opposite is true + // + if (candidate_params == best_params && candidate_pd.Count != best_pd.Count) { + if (candidate_pd.Count >= best_pd.Count) + return false; + + if (j < candidate_pd.Count && candidate_pd.FixedParameters[j].HasDefaultValue) + return false; + + return true; + } + + // + // One is a non-generic method and second is a generic method, then non-generic is better + // + if (best.IsGeneric != candidate.IsGeneric) + return best.IsGeneric; + + // + // This handles the following cases: + // + // Trim () is better than Trim (params char[] chars) + // Concat (string s1, string s2, string s3) is better than + // Concat (string s1, params string [] srest) + // Foo (int, params int [] rest) is better than Foo (params int [] rest) + // + // Prefer non-expanded version + // + if (candidate_params != best_params) + return best_params; + + int candidate_param_count = candidate_pd.Count; + int best_param_count = best_pd.Count; + + if (candidate_param_count != best_param_count) + // can only happen if (candidate_params && best_params) + return candidate_param_count > best_param_count && best_pd.HasParams; + + // + // Both methods have the same number of parameters, and the parameters have equal types + // Pick the "more specific" signature using rules over original (non-inflated) types + // + var candidate_def_pd = ((IParametersMember) candidate.MemberDefinition).Parameters; + var best_def_pd = ((IParametersMember) best.MemberDefinition).Parameters; + + bool specific_at_least_once = false; + for (j = 0; j < args_count; ++j) { + NamedArgument na = args_count == 0 ? null : args [j] as NamedArgument; + if (na != null) { + ct = candidate_def_pd.Types[cparam.GetParameterIndexByName (na.Name)]; + bt = best_def_pd.Types[bparam.GetParameterIndexByName (na.Name)]; + } else { + ct = candidate_def_pd.Types[j]; + bt = best_def_pd.Types[j]; + } + + if (ct == bt) + continue; + TypeSpec specific = MoreSpecific (ct, bt); + if (specific == bt) + return false; + if (specific == ct) + specific_at_least_once = true; + } + + if (specific_at_least_once) + return true; + + return false; + } + + public static void Error_ConstructorMismatch (ResolveContext rc, TypeSpec type, int argCount, Location loc) + { + rc.Report.Error (1729, loc, + "The type `{0}' does not contain a constructor that takes `{1}' arguments", + type.GetSignatureForError (), argCount.ToString ()); + } + + // + // Determines if the candidate method is applicable to the given set of arguments + // There could be two different set of parameters for same candidate where one + // is the closest override for default values and named arguments checks and second + // one being the virtual base for the parameter types and modifiers. + // + // A return value rates candidate method compatibility, + // 0 = the best, int.MaxValue = the worst + // + int IsApplicable (ResolveContext ec, ref Arguments arguments, int arg_count, ref MemberSpec candidate, IParametersMember pm, ref bool params_expanded_form, ref bool dynamicArgument, ref TypeSpec returnType) + { + // Parameters of most-derived type used mainly for named and optional parameters + var pd = pm.Parameters; + + // Used for params modifier only, that's legacy of C# 1.0 which uses base type for + // params modifier instead of most-derived type + var cpd = ((IParametersMember) candidate).Parameters; + int param_count = pd.Count; + int optional_count = 0; + int score; + Arguments orig_args = arguments; + + if (arg_count != param_count) { + for (int i = 0; i < pd.Count; ++i) { + if (pd.FixedParameters[i].HasDefaultValue) { + optional_count = pd.Count - i; + break; + } + } + + if (optional_count != 0) { + // Readjust expected number when params used + if (cpd.HasParams) { + optional_count--; + if (arg_count < param_count) + param_count--; + } else if (arg_count > param_count) { + int args_gap = System.Math.Abs (arg_count - param_count); + return int.MaxValue - 10000 + args_gap; + } + } else if (arg_count != param_count) { + int args_gap = System.Math.Abs (arg_count - param_count); + if (!cpd.HasParams) + return int.MaxValue - 10000 + args_gap; + if (arg_count < param_count - 1) + return int.MaxValue - 10000 + args_gap; + } + + // Resize to fit optional arguments + if (optional_count != 0) { + if (arguments == null) { + arguments = new Arguments (optional_count); + } else { + // Have to create a new container, so the next run can do same + var resized = new Arguments (param_count); + resized.AddRange (arguments); + arguments = resized; + } + + for (int i = arg_count; i < param_count; ++i) + arguments.Add (null); + } + } + + if (arg_count > 0) { + // + // Shuffle named arguments to the right positions if there are any + // + if (arguments[arg_count - 1] is NamedArgument) { + arg_count = arguments.Count; + + for (int i = 0; i < arg_count; ++i) { + bool arg_moved = false; + while (true) { + NamedArgument na = arguments[i] as NamedArgument; + if (na == null) + break; + + int index = pd.GetParameterIndexByName (na.Name); + + // Named parameter not found + if (index < 0) + return (i + 1) * 3; + + // already reordered + if (index == i) + break; + + Argument temp; + if (index >= param_count) { + // When using parameters which should not be available to the user + if ((cpd.FixedParameters[index].ModFlags & Parameter.Modifier.PARAMS) == 0) + break; + + arguments.Add (null); + ++arg_count; + temp = null; + } else { + temp = arguments[index]; + + // The slot has been taken by positional argument + if (temp != null && !(temp is NamedArgument)) + break; + } + + if (!arg_moved) { + arguments = arguments.MarkOrderedArgument (na); + arg_moved = true; + } + + arguments[index] = arguments[i]; + arguments[i] = temp; + + if (temp == null) + break; + } + } + } else { + arg_count = arguments.Count; + } + } else if (arguments != null) { + arg_count = arguments.Count; + } + + // + // 1. Handle generic method using type arguments when specified or type inference + // + TypeSpec[] ptypes; + var ms = candidate as MethodSpec; + if (ms != null && ms.IsGeneric) { + // Setup constraint checker for probing only + ConstraintChecker cc = new ConstraintChecker (null); + + if (type_arguments != null) { + var g_args_count = ms.Arity; + if (g_args_count != type_arguments.Count) + return int.MaxValue - 20000 + System.Math.Abs (type_arguments.Count - g_args_count); + + ms = ms.MakeGenericMethod (ec, type_arguments.Arguments); + } else { + // TODO: It should not be here (we don't know yet whether any argument is lambda) but + // for now it simplifies things. I should probably add a callback to ResolveContext + if (lambda_conv_msgs == null) { + lambda_conv_msgs = new SessionReportPrinter (); + prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); + } + + var ti = new TypeInference (arguments); + TypeSpec[] i_args = ti.InferMethodArguments (ec, ms); + lambda_conv_msgs.EndSession (); + + if (i_args == null) + return ti.InferenceScore - 20000; + + if (i_args.Length != 0) { + ms = ms.MakeGenericMethod (ec, i_args); + } + + cc.IgnoreInferredDynamic = true; + } + + // + // Type arguments constraints have to match for the method to be applicable + // + if (!cc.CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc)) { + candidate = ms; + return int.MaxValue - 25000; + } + + // + // We have a generic return type and at same time the method is override which + // means we have to also inflate override return type in case the candidate is + // best candidate and override return type is different to base return type. + // + // virtual Foo with override Foo + // + if (candidate != pm) { + MethodSpec override_ms = (MethodSpec) pm; + var inflator = new TypeParameterInflator (ec, ms.DeclaringType, override_ms.GenericDefinition.TypeParameters, ms.TypeArguments); + returnType = inflator.Inflate (returnType); + } else { + returnType = ms.ReturnType; + } + + candidate = ms; + ptypes = ms.Parameters.Types; + } else { + if (type_arguments != null) + return int.MaxValue - 15000; + + ptypes = cpd.Types; + } + + // + // 2. Each argument has to be implicitly convertible to method parameter + // + Parameter.Modifier p_mod = 0; + TypeSpec pt = null; + + for (int i = 0; i < arg_count; i++) { + Argument a = arguments[i]; + if (a == null) { + if (!pd.FixedParameters[i].HasDefaultValue) { + arguments = orig_args; + return arg_count * 2 + 2; + } + + // + // Get the default value expression, we can use the same expression + // if the type matches + // + Expression e = pd.FixedParameters[i].DefaultValue; + if (!(e is Constant) || e.Type.IsGenericOrParentIsGeneric) { + // + // LAMESPEC: No idea what the exact rules are for System.Reflection.Missing.Value instead of null + // + if (e == EmptyExpression.MissingValue && ptypes[i].BuiltinType == BuiltinTypeSpec.Type.Object || ptypes[i].BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + e = new MemberAccess (new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Reflection", loc), "Missing", loc), "Value", loc); + } else { + e = new DefaultValueExpression (new TypeExpression (ptypes [i], loc), loc); + } + + e = e.Resolve (ec); + } + + arguments[i] = new Argument (e, Argument.AType.Default); + continue; + } + + if (p_mod != Parameter.Modifier.PARAMS) { + p_mod = (pd.FixedParameters[i].ModFlags & ~Parameter.Modifier.PARAMS) | (cpd.FixedParameters[i].ModFlags & Parameter.Modifier.PARAMS); + pt = ptypes [i]; + } else if (!params_expanded_form) { + params_expanded_form = true; + pt = ((ElementTypeSpec) pt).Element; + i -= 2; + continue; + } + + score = 1; + if (!params_expanded_form) { + if (a.ArgType == Argument.AType.ExtensionType) { + // + // Indentity, implicit reference or boxing conversion must exist for the extension parameter + // + var at = a.Type; + if (at == pt || TypeSpecComparer.IsEqual (at, pt) || + Convert.ImplicitReferenceConversionExists (at, pt) || + Convert.ImplicitBoxingConversion (null, at, pt) != null) { + score = 0; + continue; + } + } else { + score = IsArgumentCompatible (ec, a, p_mod & ~Parameter.Modifier.PARAMS, pt); + + if (score < 0) + dynamicArgument = true; + } + } + + // + // It can be applicable in expanded form (when not doing exact match like for delegates) + // + if (score != 0 && (p_mod & Parameter.Modifier.PARAMS) != 0 && (restrictions & Restrictions.CovariantDelegate) == 0) { + if (!params_expanded_form) + pt = ((ElementTypeSpec) pt).Element; + + if (score > 0) + score = IsArgumentCompatible (ec, a, Parameter.Modifier.NONE, pt); + + if (score == 0) { + params_expanded_form = true; + } else if (score < 0) { + params_expanded_form = true; + dynamicArgument = true; + } + } + + if (score > 0) { + if (params_expanded_form) + ++score; + return (arg_count - i) * 2 + score; + } + } + + // + // When params parameter has no argument it will be provided later if the method is the best candidate + // + if (arg_count + 1 == pd.Count && (cpd.FixedParameters [arg_count].ModFlags & Parameter.Modifier.PARAMS) != 0) + params_expanded_form = true; + + // + // Restore original arguments for dynamic binder to keep the intention of original source code + // + if (dynamicArgument) + arguments = orig_args; + + return 0; + } + + // + // Tests argument compatibility with the parameter + // The possible return values are + // 0 - success + // 1 - modifier mismatch + // 2 - type mismatch + // -1 - dynamic binding required + // + int IsArgumentCompatible (ResolveContext ec, Argument argument, Parameter.Modifier param_mod, TypeSpec parameter) + { + // + // Types have to be identical when ref or out modifer + // is used and argument is not of dynamic type + // + if ((argument.Modifier | param_mod) != 0) { + if (argument.Type != parameter) { + // + // Do full equality check after quick path + // + if (!TypeSpecComparer.IsEqual (argument.Type, parameter)) { + // + // Using dynamic for ref/out parameter can still succeed at runtime + // + if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + return 2; + } + } + + if (argument.Modifier != param_mod) { + // + // Using dynamic for ref/out parameter can still succeed at runtime + // + if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && argument.Modifier == 0 && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + return 1; + } + + } else { + if (argument.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic && (restrictions & Restrictions.CovariantDelegate) == 0) + return -1; + + // + // Deploy custom error reporting for lambda methods. When probing lambda methods + // keep all errors reported in separate set and once we are done and no best + // candidate was found, this set is used to report more details about what was wrong + // with lambda body + // + if (argument.Expr.Type == InternalType.AnonymousMethod) { + if (lambda_conv_msgs == null) { + lambda_conv_msgs = new SessionReportPrinter (); + prev_recorder = ec.Report.SetPrinter (lambda_conv_msgs); + } + } + + // + // Use implicit conversion in all modes to return same candidates when the expression + // is used as argument or delegate conversion + // + if (!Convert.ImplicitConversionExists (ec, argument.Expr, parameter)) { + if (lambda_conv_msgs != null) { + lambda_conv_msgs.EndSession (); + } + + return 2; + } + } + + return 0; + } + + static TypeSpec MoreSpecific (TypeSpec p, TypeSpec q) + { + if (TypeManager.IsGenericParameter (p) && !TypeManager.IsGenericParameter (q)) + return q; + if (!TypeManager.IsGenericParameter (p) && TypeManager.IsGenericParameter (q)) + return p; + + var ac_p = p as ArrayContainer; + if (ac_p != null) { + var ac_q = ((ArrayContainer) q); + TypeSpec specific = MoreSpecific (ac_p.Element, ac_q.Element); + if (specific == ac_p.Element) + return p; + if (specific == ac_q.Element) + return q; + } else if (TypeManager.IsGenericType (p)) { + var pargs = TypeManager.GetTypeArguments (p); + var qargs = TypeManager.GetTypeArguments (q); + + bool p_specific_at_least_once = false; + bool q_specific_at_least_once = false; + + for (int i = 0; i < pargs.Length; i++) { + TypeSpec specific = MoreSpecific (pargs[i], qargs[i]); + if (specific == pargs[i]) + p_specific_at_least_once = true; + if (specific == qargs[i]) + q_specific_at_least_once = true; + } + + if (p_specific_at_least_once && !q_specific_at_least_once) + return p; + if (!p_specific_at_least_once && q_specific_at_least_once) + return q; + } + + return null; + } + + // + // Find the best method from candidate list + // + public T ResolveMember (ResolveContext rc, ref Arguments args) where T : MemberSpec, IParametersMember + { + List ambiguous_candidates = null; + + MemberSpec best_candidate; + Arguments best_candidate_args = null; + bool best_candidate_params = false; + bool best_candidate_dynamic = false; + int best_candidate_rate; + IParametersMember best_parameter_member = null; + + int args_count = args != null ? args.Count : 0; + + Arguments candidate_args = args; + bool error_mode = false; + MemberSpec invocable_member = null; + + // Be careful, cannot return until error reporter is restored + while (true) { + best_candidate = null; + best_candidate_rate = int.MaxValue; + + var type_members = members; + try { + + do { + for (int i = 0; i < type_members.Count; ++i) { + var member = type_members[i]; + + // + // Methods in a base class are not candidates if any method in a derived + // class is applicable + // + if ((member.Modifiers & Modifiers.OVERRIDE) != 0) + continue; + + if (!error_mode) { + if (!member.IsAccessible (rc)) + continue; + + if (rc.IsRuntimeBinder && !member.DeclaringType.IsAccessible (rc)) + continue; + } + + IParametersMember pm = member as IParametersMember; + if (pm == null) { + // + // Will use it later to report ambiguity between best method and invocable member + // + if (Invocation.IsMemberInvocable (member)) + invocable_member = member; + + continue; + } + + // + // Overload resolution is looking for base member but using parameter names + // and default values from the closest member. That means to do expensive lookup + // for the closest override for virtual or abstract members + // + if ((member.Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) { + var override_params = base_provider.GetOverrideMemberParameters (member); + if (override_params != null) + pm = override_params; + } + + // + // Check if the member candidate is applicable + // + bool params_expanded_form = false; + bool dynamic_argument = false; + TypeSpec rt = pm.MemberType; + int candidate_rate = IsApplicable (rc, ref candidate_args, args_count, ref member, pm, ref params_expanded_form, ref dynamic_argument, ref rt); + + // + // How does it score compare to others + // + if (candidate_rate < best_candidate_rate) { + best_candidate_rate = candidate_rate; + best_candidate = member; + best_candidate_args = candidate_args; + best_candidate_params = params_expanded_form; + best_candidate_dynamic = dynamic_argument; + best_parameter_member = pm; + best_candidate_return_type = rt; + } else if (candidate_rate == 0) { + // + // The member look is done per type for most operations but sometimes + // it's not possible like for binary operators overload because they + // are unioned between 2 sides + // + if ((restrictions & Restrictions.BaseMembersIncluded) != 0) { + if (TypeSpec.IsBaseClass (best_candidate.DeclaringType, member.DeclaringType, true)) + continue; + } + + bool is_better; + if (best_candidate.DeclaringType.IsInterface && member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { + // + // We pack all interface members into top level type which makes the overload resolution + // more complicated for interfaces. We compensate it by removing methods with same + // signature when building the cache hence this path should not really be hit often + // + // Example: + // interface IA { void Foo (int arg); } + // interface IB : IA { void Foo (params int[] args); } + // + // IB::Foo is the best overload when calling IB.Foo (1) + // + is_better = true; + if (ambiguous_candidates != null) { + foreach (var amb_cand in ambiguous_candidates) { + if (member.DeclaringType.ImplementsInterface (best_candidate.DeclaringType, false)) { + continue; + } + + is_better = false; + break; + } + + if (is_better) + ambiguous_candidates = null; + } + } else { + // Is the new candidate better + is_better = BetterFunction (rc, candidate_args, member, pm.Parameters, params_expanded_form, best_candidate, best_parameter_member.Parameters, best_candidate_params); + } + + if (is_better) { + best_candidate = member; + best_candidate_args = candidate_args; + best_candidate_params = params_expanded_form; + best_candidate_dynamic = dynamic_argument; + best_parameter_member = pm; + best_candidate_return_type = rt; + } else { + // It's not better but any other found later could be but we are not sure yet + if (ambiguous_candidates == null) + ambiguous_candidates = new List (); + + ambiguous_candidates.Add (new AmbiguousCandidate (member, pm.Parameters, params_expanded_form)); + } + } + + // Restore expanded arguments + if (candidate_args != args) + candidate_args = args; + } + } while (best_candidate_rate != 0 && (type_members = base_provider.GetBaseMembers (type_members[0].DeclaringType.BaseType)) != null); + } finally { + if (prev_recorder != null) + rc.Report.SetPrinter (prev_recorder); + } + + // + // We've found exact match + // + if (best_candidate_rate == 0) + break; + + // + // Try extension methods lookup when no ordinary method match was found and provider enables it + // + if (!error_mode) { + var emg = base_provider.LookupExtensionMethod (rc); + if (emg != null) { + emg = emg.OverloadResolve (rc, ref args, null, restrictions); + if (emg != null) { + best_candidate_extension_group = emg; + return (T) (MemberSpec) emg.BestCandidate; + } + } + } + + // Don't run expensive error reporting mode for probing + if (IsProbingOnly) + return null; + + if (error_mode) + break; + + lambda_conv_msgs = null; + error_mode = true; + } + + // + // No best member match found, report an error + // + if (best_candidate_rate != 0 || error_mode) { + ReportOverloadError (rc, best_candidate, best_parameter_member, best_candidate_args, best_candidate_params); + return null; + } + + if (best_candidate_dynamic) { + if (args[0].ArgType == Argument.AType.ExtensionType) { + rc.Report.Error (1973, loc, + "Type `{0}' does not contain a member `{1}' and the best extension method overload `{2}' cannot be dynamically dispatched. Consider calling the method without the extension method syntax", + args [0].Type.GetSignatureForError (), best_candidate.Name, best_candidate.GetSignatureForError ()); + } + + BestCandidateIsDynamic = true; + return null; + } + + // + // These flags indicates we are running delegate probing conversion. No need to + // do more expensive checks + // + if ((restrictions & (Restrictions.ProbingOnly | Restrictions.CovariantDelegate)) == (Restrictions.CovariantDelegate | Restrictions.ProbingOnly)) + return (T) best_candidate; + + if (ambiguous_candidates != null) { + // + // Now check that there are no ambiguities i.e the selected method + // should be better than all the others + // + for (int ix = 0; ix < ambiguous_candidates.Count; ix++) { + var candidate = ambiguous_candidates [ix]; + + if (!BetterFunction (rc, best_candidate_args, best_candidate, best_parameter_member.Parameters, best_candidate_params, candidate.Member, candidate.Parameters, candidate.Expanded)) { + var ambiguous = candidate.Member; + if (custom_errors == null || !custom_errors.AmbiguousCandidates (rc, best_candidate, ambiguous)) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.SymbolRelatedToPreviousError (ambiguous); + rc.Report.Error (121, loc, "The call is ambiguous between the following methods or properties: `{0}' and `{1}'", + best_candidate.GetSignatureForError (), ambiguous.GetSignatureForError ()); + } + + return (T) best_candidate; + } + } + } + + if (invocable_member != null) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.SymbolRelatedToPreviousError (invocable_member); + rc.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and invocable non-method `{1}'. Using method group", + best_candidate.GetSignatureForError (), invocable_member.GetSignatureForError ()); + } + + // + // And now check if the arguments are all + // compatible, perform conversions if + // necessary etc. and return if everything is + // all right + // + if (!VerifyArguments (rc, ref best_candidate_args, best_candidate, best_parameter_member, best_candidate_params)) + return null; + + if (best_candidate == null) + return null; + + // + // Check ObsoleteAttribute on the best method + // + ObsoleteAttribute oa = best_candidate.GetAttributeObsolete (); + if (oa != null && !rc.IsObsolete) + AttributeTester.Report_ObsoleteMessage (oa, best_candidate.GetSignatureForError (), loc, rc.Report); + + var dep = best_candidate.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); + } + + best_candidate.MemberDefinition.SetIsUsed (); + + args = best_candidate_args; + return (T) best_candidate; + } + + public MethodSpec ResolveOperator (ResolveContext rc, ref Arguments args) + { + return ResolveMember (rc, ref args); + } + + void ReportArgumentMismatch (ResolveContext ec, int idx, MemberSpec method, + Argument a, AParametersCollection expected_par, TypeSpec paramType) + { + if (custom_errors != null && custom_errors.ArgumentMismatch (ec, method, a, idx)) + return; + + if (a is CollectionElementInitializer.ElementInitializerArgument) { + ec.Report.SymbolRelatedToPreviousError (method); + if ((expected_par.FixedParameters[idx].ModFlags & Parameter.Modifier.ISBYREF) != 0) { + ec.Report.Error (1954, loc, "The best overloaded collection initalizer method `{0}' cannot have 'ref', or `out' modifier", + TypeManager.CSharpSignature (method)); + return; + } + ec.Report.Error (1950, loc, "The best overloaded collection initalizer method `{0}' has some invalid arguments", + TypeManager.CSharpSignature (method)); + } else if (IsDelegateInvoke) { + ec.Report.Error (1594, loc, "Delegate `{0}' has some invalid arguments", + DelegateType.GetSignatureForError ()); + } else { + ec.Report.SymbolRelatedToPreviousError (method); + ec.Report.Error (1502, loc, "The best overloaded method match for `{0}' has some invalid arguments", + method.GetSignatureForError ()); + } + + Parameter.Modifier mod = idx >= expected_par.Count ? 0 : expected_par.FixedParameters[idx].ModFlags; + + string index = (idx + 1).ToString (); + if (((mod & (Parameter.Modifier.REF | Parameter.Modifier.OUT)) ^ + (a.Modifier & (Parameter.Modifier.REF | Parameter.Modifier.OUT))) != 0) { + if ((mod & Parameter.Modifier.ISBYREF) == 0) + ec.Report.Error (1615, loc, "Argument `#{0}' does not require `{1}' modifier. Consider removing `{1}' modifier", + index, Parameter.GetModifierSignature (a.Modifier)); + else + ec.Report.Error (1620, loc, "Argument `#{0}' is missing `{1}' modifier", + index, Parameter.GetModifierSignature (mod)); + } else if (a.Expr != ErrorExpression.Instance) { + string p1 = a.GetSignatureForError (); + string p2 = TypeManager.CSharpName (paramType); + + if (p1 == p2) { + p1 = a.Type.GetSignatureForErrorIncludingAssemblyName (); + p2 = paramType.GetSignatureForErrorIncludingAssemblyName (); + } + + ec.Report.Error (1503, loc, + "Argument `#{0}' cannot convert `{1}' expression to type `{2}'", index, p1, p2); + } + } + + // + // We have failed to find exact match so we return error info about the closest match + // + void ReportOverloadError (ResolveContext rc, MemberSpec best_candidate, IParametersMember pm, Arguments args, bool params_expanded) + { + int ta_count = type_arguments == null ? 0 : type_arguments.Count; + int arg_count = args == null ? 0 : args.Count; + + if (ta_count != best_candidate.Arity && (ta_count > 0 || ((IParametersMember) best_candidate).Parameters.IsEmpty)) { + var mg = new MethodGroupExpr (new [] { best_candidate }, best_candidate.DeclaringType, loc); + mg.Error_TypeArgumentsCannotBeUsed (rc, best_candidate, ta_count, loc); + return; + } + + if (lambda_conv_msgs != null) { + if (lambda_conv_msgs.Merge (rc.Report.Printer)) + return; + } + + // + // For candidates which match on parameters count report more details about incorrect arguments + // + if (pm != null) { + int unexpanded_count = ((IParametersMember) best_candidate).Parameters.HasParams ? pm.Parameters.Count - 1 : pm.Parameters.Count; + if (pm.Parameters.Count == arg_count || params_expanded || unexpanded_count == arg_count) { + // Reject any inaccessible member + if (!best_candidate.IsAccessible (rc) || !best_candidate.DeclaringType.IsAccessible (rc)) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + Expression.ErrorIsInaccesible (rc, best_candidate.GetSignatureForError (), loc); + return; + } + + var ms = best_candidate as MethodSpec; + if (ms != null && ms.IsGeneric) { + bool constr_ok = true; + if (ms.TypeArguments != null) + constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc); + + if (ta_count == 0) { + if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate)) + return; + + if (constr_ok) { + rc.Report.Error (411, loc, + "The type arguments for method `{0}' cannot be inferred from the usage. Try specifying the type arguments explicitly", + ms.GetGenericMethodDefinition ().GetSignatureForError ()); + } + + return; + } + } + + VerifyArguments (rc, ref args, best_candidate, pm, params_expanded); + return; + } + } + + // + // We failed to find any method with correct argument count, report best candidate + // + if (custom_errors != null && custom_errors.NoArgumentMatch (rc, best_candidate)) + return; + + if (best_candidate.Kind == MemberKind.Constructor) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + Error_ConstructorMismatch (rc, best_candidate.DeclaringType, arg_count, loc); + } else if (IsDelegateInvoke) { + rc.Report.SymbolRelatedToPreviousError (DelegateType); + rc.Report.Error (1593, loc, "Delegate `{0}' does not take `{1}' arguments", + DelegateType.GetSignatureForError (), arg_count.ToString ()); + } else { + string name = best_candidate.Kind == MemberKind.Indexer ? "this" : best_candidate.Name; + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.Error (1501, loc, "No overload for method `{0}' takes `{1}' arguments", + name, arg_count.ToString ()); + } + } + + bool VerifyArguments (ResolveContext ec, ref Arguments args, MemberSpec member, IParametersMember pm, bool chose_params_expanded) + { + var pd = pm.Parameters; + TypeSpec[] ptypes = ((IParametersMember) member).Parameters.Types; + + Parameter.Modifier p_mod = 0; + TypeSpec pt = null; + int a_idx = 0, a_pos = 0; + Argument a = null; + ArrayInitializer params_initializers = null; + bool has_unsafe_arg = pm.MemberType.IsPointer; + int arg_count = args == null ? 0 : args.Count; + + for (; a_idx < arg_count; a_idx++, ++a_pos) { + a = args[a_idx]; + if (p_mod != Parameter.Modifier.PARAMS) { + p_mod = pd.FixedParameters[a_idx].ModFlags; + pt = ptypes[a_idx]; + has_unsafe_arg |= pt.IsPointer; + + if (p_mod == Parameter.Modifier.PARAMS) { + if (chose_params_expanded) { + params_initializers = new ArrayInitializer (arg_count - a_idx, a.Expr.Location); + pt = TypeManager.GetElementType (pt); + } + } + } + + // + // Types have to be identical when ref or out modifer is used + // + if (a.Modifier != 0 || (p_mod & ~Parameter.Modifier.PARAMS) != 0) { + if ((p_mod & ~Parameter.Modifier.PARAMS) != a.Modifier) + break; + + if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) + continue; + + break; + } + + NamedArgument na = a as NamedArgument; + if (na != null) { + int name_index = pd.GetParameterIndexByName (na.Name); + if (name_index < 0 || name_index >= pd.Count) { + if (IsDelegateInvoke) { + ec.Report.SymbolRelatedToPreviousError (DelegateType); + ec.Report.Error (1746, na.Location, + "The delegate `{0}' does not contain a parameter named `{1}'", + DelegateType.GetSignatureForError (), na.Name); + } else { + ec.Report.SymbolRelatedToPreviousError (member); + ec.Report.Error (1739, na.Location, + "The best overloaded method match for `{0}' does not contain a parameter named `{1}'", + TypeManager.CSharpSignature (member), na.Name); + } + } else if (args[name_index] != a) { + if (IsDelegateInvoke) + ec.Report.SymbolRelatedToPreviousError (DelegateType); + else + ec.Report.SymbolRelatedToPreviousError (member); + + ec.Report.Error (1744, na.Location, + "Named argument `{0}' cannot be used for a parameter which has positional argument specified", + na.Name); + } + } + + if (a.Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + continue; + + if ((restrictions & Restrictions.CovariantDelegate) != 0 && !Delegate.IsTypeCovariant (ec, a.Expr.Type, pt)) { + custom_errors.NoArgumentMatch (ec, member); + return false; + } + + Expression conv = null; + if (a.ArgType == Argument.AType.ExtensionType) { + if (a.Expr.Type == pt || TypeSpecComparer.IsEqual (a.Expr.Type, pt)) { + conv = a.Expr; + } else { + conv = Convert.ImplicitReferenceConversion (a.Expr, pt, false); + if (conv == null) + conv = Convert.ImplicitBoxingConversion (a.Expr, a.Expr.Type, pt); + } + } else { + conv = Convert.ImplicitConversion (ec, a.Expr, pt, loc); + } + + if (conv == null) + break; + + // + // Convert params arguments to an array initializer + // + if (params_initializers != null) { + // we choose to use 'a.Expr' rather than 'conv' so that + // we don't hide the kind of expression we have (esp. CompoundAssign.Helper) + params_initializers.Add (a.Expr); + args.RemoveAt (a_idx--); + --arg_count; + continue; + } + + // Update the argument with the implicit conversion + a.Expr = conv; + } + + if (a_idx != arg_count) { + ReportArgumentMismatch (ec, a_pos, member, a, pd, pt); + return false; + } + + // + // Fill not provided arguments required by params modifier + // + if (params_initializers == null && pd.HasParams && arg_count + 1 == pd.Count) { + if (args == null) + args = new Arguments (1); + + pt = ptypes[pd.Count - 1]; + pt = TypeManager.GetElementType (pt); + has_unsafe_arg |= pt.IsPointer; + params_initializers = new ArrayInitializer (0, loc); + } + + // + // Append an array argument with all params arguments + // + if (params_initializers != null) { + args.Add (new Argument ( + new ArrayCreation (new TypeExpression (pt, loc), params_initializers, loc).Resolve (ec))); + arg_count++; + } + + if (has_unsafe_arg && !ec.IsUnsafe) { + Expression.UnsafeError (ec, loc); + } + + // + // We could infer inaccesible type arguments + // + if (type_arguments == null && member.IsGeneric) { + var ms = (MethodSpec) member; + foreach (var ta in ms.TypeArguments) { + if (!ta.IsAccessible (ec)) { + ec.Report.SymbolRelatedToPreviousError (ta); + Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc); + break; + } + } + } + + return true; + } + } + + public class ConstantExpr : MemberExpr + { + readonly ConstSpec constant; + + public ConstantExpr (ConstSpec constant, Location loc) + { + this.constant = constant; + this.loc = loc; + } + + public override string Name { + get { throw new NotImplementedException (); } + } + + public override bool IsInstance { + get { return !IsStatic; } + } + + public override bool IsStatic { + get { return true; } + } + + protected override TypeSpec DeclaringType { + get { return constant.DeclaringType; } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + ResolveInstanceExpression (rc, null); + DoBestMemberChecks (rc, constant); + + var c = constant.GetConstant (rc); + + // Creates reference expression to the constant value + return Constant.CreateConstant (constant.MemberType, c.GetValue (), loc); + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + } + + public override string GetSignatureForError () + { + return constant.GetSignatureForError (); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "constant", GetSignatureForError (), loc); + } + } + + /// + /// Fully resolved expression that evaluates to a Field + /// + public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference { + protected FieldSpec spec; + VariableInfo variable_info; + + LocalTemporary temp; + bool prepared; + + protected FieldExpr (Location l) + { + loc = l; + } + + public FieldExpr (FieldSpec spec, Location loc) + { + this.spec = spec; + this.loc = loc; + + type = spec.MemberType; + } + + public FieldExpr (FieldBase fi, Location l) + : this (fi.Spec, l) + { + } + + #region Properties + + public override string Name { + get { + return spec.Name; + } + } + + public bool IsHoisted { + get { + IVariableReference hv = InstanceExpression as IVariableReference; + return hv != null && hv.IsHoisted; + } + } + + public override bool IsInstance { + get { + return !spec.IsStatic; + } + } + + public override bool IsStatic { + get { + return spec.IsStatic; + } + } + + public FieldSpec Spec { + get { + return spec; + } + } + + protected override TypeSpec DeclaringType { + get { + return spec.DeclaringType; + } + } + + public VariableInfo VariableInfo { + get { + return variable_info; + } + } + +#endregion + + public override string GetSignatureForError () + { + return TypeManager.GetFullNameSignature (spec); + } + + public bool IsMarshalByRefAccess (ResolveContext rc) + { + // Checks possible ldflda of field access expression + return !spec.IsStatic && TypeSpec.IsValueType (spec.MemberType) && !(InstanceExpression is This) && + rc.Module.PredefinedTypes.MarshalByRefObject.Define () && + TypeSpec.IsBaseClass (spec.DeclaringType, rc.Module.PredefinedTypes.MarshalByRefObject.TypeSpec, false); + } + + public void SetHasAddressTaken () + { + IVariableReference vr = InstanceExpression as IVariableReference; + if (vr != null) + vr.SetHasAddressTaken (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Expression instance; + if (InstanceExpression == null) { + instance = new NullLiteral (loc); + } else { + instance = InstanceExpression.CreateExpressionTree (ec); + } + + Arguments args = Arguments.CreateForExpressionTree (ec, null, + instance, + CreateTypeOfExpression ()); + + return CreateExpressionFactoryCall (ec, "Field", args); + } + + public Expression CreateTypeOfExpression () + { + return new TypeOfField (spec, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return DoResolve (ec, null); + } + + Expression DoResolve (ResolveContext ec, Expression rhs) + { + bool lvalue_instance = rhs != null && IsInstance && spec.DeclaringType.IsStruct; + + if (rhs != this) { + if (ResolveInstanceExpression (ec, rhs)) { + // Resolve the field's instance expression while flow analysis is turned + // off: when accessing a field "a.b", we must check whether the field + // "a.b" is initialized, not whether the whole struct "a" is initialized. + + if (lvalue_instance) { + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess; + + Expression right_side = + out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess; + + InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side); + } + } else { + using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) { + InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue); + } + } + + if (InstanceExpression == null) + return null; + } + + DoBestMemberChecks (ec, spec); + } + + var fb = spec as FixedFieldSpec; + IVariableReference var = InstanceExpression as IVariableReference; + + if (lvalue_instance && var != null && var.VariableInfo != null) { + var.VariableInfo.SetFieldAssigned (ec, Name); + } + + if (fb != null) { + IFixedExpression fe = InstanceExpression as IFixedExpression; + if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) { + ec.Report.Error (1666, loc, "You cannot use fixed size buffers contained in unfixed expressions. Try using the fixed statement"); + } + + if (InstanceExpression.eclass != ExprClass.Variable) { + ec.Report.SymbolRelatedToPreviousError (spec); + ec.Report.Error (1708, loc, "`{0}': Fixed size buffers can only be accessed through locals or fields", + TypeManager.GetFullNameSignature (spec)); + } else if (var != null && var.IsHoisted) { + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc); + } + + return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); + } + + eclass = ExprClass.Variable; + + // If the instance expression is a local variable or parameter. + if (var == null || var.VariableInfo == null) + return this; + + VariableInfo vi = var.VariableInfo; + if (!vi.IsFieldAssigned (ec, Name, loc)) + return null; + + variable_info = vi.GetSubStruct (Name); + return this; + } + + static readonly int [] codes = { + 191, // instance, write access + 192, // instance, out access + 198, // static, write access + 199, // static, out access + 1648, // member of value instance, write access + 1649, // member of value instance, out access + 1650, // member of value static, write access + 1651 // member of value static, out access + }; + + static readonly string [] msgs = { + /*0191*/ "A readonly field `{0}' cannot be assigned to (except in a constructor or a variable initializer)", + /*0192*/ "A readonly field `{0}' cannot be passed ref or out (except in a constructor)", + /*0198*/ "A static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)", + /*0199*/ "A static readonly field `{0}' cannot be passed ref or out (except in a static constructor)", + /*1648*/ "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)", + /*1649*/ "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)", + /*1650*/ "Fields of static readonly field `{0}' cannot be assigned to (except in a static constructor or a variable initializer)", + /*1651*/ "Fields of static readonly field `{0}' cannot be passed ref or out (except in a static constructor)" + }; + + // The return value is always null. Returning a value simplifies calling code. + Expression Report_AssignToReadonly (ResolveContext ec, Expression right_side) + { + int i = 0; + if (right_side == EmptyExpression.OutAccess || right_side == EmptyExpression.LValueMemberOutAccess) + i += 1; + if (IsStatic) + i += 2; + if (right_side == EmptyExpression.LValueMemberAccess || right_side == EmptyExpression.LValueMemberOutAccess) + i += 4; + ec.Report.Error (codes [i], loc, msgs [i], GetSignatureForError ()); + + return null; + } + + override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + Expression e = DoResolve (ec, right_side); + + if (e == null) + return null; + + spec.MemberDefinition.SetIsAssigned (); + + if ((right_side == EmptyExpression.UnaryAddress || right_side == EmptyExpression.OutAccess) && + (spec.Modifiers & Modifiers.VOLATILE) != 0) { + ec.Report.Warning (420, 1, loc, + "`{0}': A volatile field references will not be treated as volatile", + spec.GetSignatureForError ()); + } + + if (spec.IsReadOnly) { + // InitOnly fields can only be assigned in constructors or initializers + if (!ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.ConstructorScope)) + return Report_AssignToReadonly (ec, right_side); + + if (ec.HasSet (ResolveContext.Options.ConstructorScope)) { + + // InitOnly fields cannot be assigned-to in a different constructor from their declaring type + if (ec.CurrentMemberDefinition.Parent.Definition != spec.DeclaringType.GetDefinition ()) + return Report_AssignToReadonly (ec, right_side); + // static InitOnly fields cannot be assigned-to in an instance constructor + if (IsStatic && !ec.IsStatic) + return Report_AssignToReadonly (ec, right_side); + // instance constructors can't modify InitOnly fields of other instances of the same type + if (!IsStatic && !(InstanceExpression is This)) + return Report_AssignToReadonly (ec, right_side); + } + } + + if (right_side == EmptyExpression.OutAccess && IsMarshalByRefAccess (ec)) { + ec.Report.SymbolRelatedToPreviousError (spec.DeclaringType); + ec.Report.Warning (197, 1, loc, + "Passing `{0}' as ref or out or taking its address may cause a runtime exception because it is a field of a marshal-by-reference class", + GetSignatureForError ()); + } + + eclass = ExprClass.Variable; + return this; + } + + public override int GetHashCode () + { + return spec.GetHashCode (); + } + + public bool IsFixed { + get { + // + // A variable of the form V.I is fixed when V is a fixed variable of a struct type + // + IVariableReference variable = InstanceExpression as IVariableReference; + if (variable != null) + return InstanceExpression.Type.IsStruct && variable.IsFixed; + + IFixedExpression fe = InstanceExpression as IFixedExpression; + return fe != null && fe.IsFixed; + } + } + + public override bool Equals (object obj) + { + FieldExpr fe = obj as FieldExpr; + if (fe == null) + return false; + + if (spec != fe.spec) + return false; + + if (InstanceExpression == null || fe.InstanceExpression == null) + return true; + + return InstanceExpression.Equals (fe.InstanceExpression); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + bool is_volatile = false; + + if ((spec.Modifiers & Modifiers.VOLATILE) != 0) + is_volatile = true; + + spec.MemberDefinition.SetIsUsed (); + + if (IsStatic){ + if (is_volatile) + ec.Emit (OpCodes.Volatile); + + ec.Emit (OpCodes.Ldsfld, spec); + } else { + if (!prepared) + EmitInstance (ec, false); + + // Optimization for build-in types + if (type.IsStruct && type == ec.CurrentType && InstanceExpression.Type == type) { + ec.EmitLoadFromPtr (type); + } else { + var ff = spec as FixedFieldSpec; + if (ff != null) { + ec.Emit (OpCodes.Ldflda, spec); + ec.Emit (OpCodes.Ldflda, ff.Element); + } else { + if (is_volatile) + ec.Emit (OpCodes.Volatile); + + ec.Emit (OpCodes.Ldfld, spec); + } + } + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + 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); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + + if ((spec.Modifiers & Modifiers.VOLATILE) != 0) + ec.Emit (OpCodes.Volatile); + + spec.MemberDefinition.SetIsAssigned (); + + if (IsStatic) + ec.Emit (OpCodes.Stsfld, spec); + else + ec.Emit (OpCodes.Stfld, spec); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + temp = null; + } + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public override void EmitSideEffect (EmitContext ec) + { + bool is_volatile = (spec.Modifiers & Modifiers.VOLATILE) != 0; + + if (is_volatile) // || is_marshal_by_ref ()) + base.EmitSideEffect (ec); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + if ((mode & AddressOp.Store) != 0) + spec.MemberDefinition.SetIsAssigned (); + if ((mode & AddressOp.Load) != 0) + spec.MemberDefinition.SetIsUsed (); + + // + // Handle initonly fields specially: make a copy and then + // get the address of the copy. + // + bool need_copy; + if (spec.IsReadOnly){ + need_copy = true; + if (ec.HasSet (EmitContext.Options.ConstructorScope) && spec.DeclaringType == ec.CurrentType) { + if (IsStatic){ + if (ec.IsStatic) + need_copy = false; + } else + need_copy = false; + } + } else + need_copy = false; + + if (need_copy){ + LocalBuilder local; + Emit (ec); + local = ec.DeclareLocal (type, false); + ec.Emit (OpCodes.Stloc, local); + ec.Emit (OpCodes.Ldloca, local); + return; + } + + + if (IsStatic){ + ec.Emit (OpCodes.Ldsflda, spec); + } else { + if (!prepared) + EmitInstance (ec, false); + ec.Emit (OpCodes.Ldflda, spec); + } + } + + public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { + return MakeExpression (ctx); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Field ( + IsStatic ? null : InstanceExpression.MakeExpression (ctx), + spec.GetMetaInfo ()); +#endif + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "field", GetSignatureForError (), loc); + } + } + + + /// + /// Expression that evaluates to a Property. The Assign class + /// might set the `Value' expression if we are in an assignment. + /// + /// This is not an LValue because we need to re-write the expression, we + /// can not take data from the stack and store it. + /// + class PropertyExpr : PropertyOrIndexerExpr + { + public PropertyExpr (PropertySpec spec, Location l) + : base (l) + { + best_candidate = spec; + type = spec.MemberType; + } + + #region Properties + + protected override TypeSpec DeclaringType { + get { + return best_candidate.DeclaringType; + } + } + + public override string Name { + get { + return best_candidate.Name; + } + } + + public override bool IsInstance { + get { + return !IsStatic; + } + } + + public override bool IsStatic { + get { + return best_candidate.IsStatic; + } + } + + public PropertySpec PropertyInfo { + get { + return best_candidate; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args; + if (IsSingleDimensionalArrayLength ()) { + args = new Arguments (1); + args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "ArrayLength", args); + } + + args = new Arguments (2); + if (InstanceExpression == null) + args.Add (new Argument (new NullLiteral (loc))); + else + args.Add (new Argument (InstanceExpression.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOfMethod (Getter, loc))); + return CreateExpressionFactoryCall (ec, "Property", args); + } + + public Expression CreateSetterTypeOfExpression () + { + return new TypeOfMethod (Setter, loc); + } + + public override string GetSignatureForError () + { + return best_candidate.GetSignatureForError (); + } + + public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo ()); +#endif + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Property (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo ()); +#endif + } + + void Error_PropertyNotValid (ResolveContext ec) + { + ec.Report.SymbolRelatedToPreviousError (best_candidate); + ec.Report.Error (1546, loc, "Property or event `{0}' is not supported by the C# language", + GetSignatureForError ()); + } + + bool IsSingleDimensionalArrayLength () + { + if (best_candidate.DeclaringType.BuiltinType != BuiltinTypeSpec.Type.Array || !best_candidate.HasGet || Name != "Length") + return false; + + ArrayContainer ac = InstanceExpression.Type as ArrayContainer; + return ac != null && ac.Rank == 1; + } + + public override void Emit (EmitContext ec, bool leave_copy) + { + // + // Special case: length of single dimension array property is turned into ldlen + // + if (IsSingleDimensionalArrayLength ()) { + if (!prepared) + EmitInstance (ec, false); + ec.Emit (OpCodes.Ldlen); + ec.Emit (OpCodes.Conv_I4); + return; + } + + Invocation.EmitCall (ec, InstanceExpression, Getter, null, loc, prepared, false); + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + } + + public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + Arguments args; + + if (prepare_for_load && !(source is DynamicExpressionStatement)) { + args = new Arguments (0); + prepared = true; + source.Emit (ec); + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (!IsStatic) { + temp = new LocalTemporary (this.Type); + temp.Store (ec); + } + } + } else { + args = new Arguments (1); + + if (leave_copy) { + source.Emit (ec); + temp = new LocalTemporary (this.Type); + temp.Store (ec); + args.Add (new Argument (temp)); + } else { + args.Add (new Argument (source)); + } + } + + Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + protected override Expression OverloadResolve (ResolveContext rc, Expression right_side) + { + eclass = ExprClass.PropertyAccess; + + if (best_candidate.IsNotCSharpCompatible) { + Error_PropertyNotValid (rc); + } + + ResolveInstanceExpression (rc, right_side); + + if ((best_candidate.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0 && best_candidate.DeclaringType != InstanceExpression.Type) { + var filter = new MemberFilter (best_candidate.Name, 0, MemberKind.Property, null, null); + var p = MemberCache.FindMember (InstanceExpression.Type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as PropertySpec; + if (p != null) { + type = p.MemberType; + } + } + + DoBestMemberChecks (rc, best_candidate); + return this; + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "property", GetSignatureForError (), loc); + } + } + + abstract class PropertyOrIndexerExpr : MemberExpr, IDynamicAssign where T : PropertySpec + { + // getter and setter can be different for base calls + MethodSpec getter, setter; + protected T best_candidate; + + protected LocalTemporary temp; + protected bool prepared; + + protected PropertyOrIndexerExpr (Location l) + { + loc = l; + } + + #region Properties + + public MethodSpec Getter { + get { + return getter; + } + set { + getter = value; + } + } + + public MethodSpec Setter { + get { + return setter; + } + set { + setter = value; + } + } + + #endregion + + protected override Expression DoResolve (ResolveContext ec) + { + if (eclass == ExprClass.Unresolved) { + var expr = OverloadResolve (ec, null); + if (expr == null) + return null; + + if (expr != this) + return expr.Resolve (ec); + } + + if (!ResolveGetter (ec)) + return null; + + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + if (right_side == EmptyExpression.OutAccess) { + // TODO: best_candidate can be null at this point + INamedBlockVariable variable = null; + if (best_candidate != null && ec.CurrentBlock.ParametersBlock.TopBlock.GetLocalName (best_candidate.Name, ec.CurrentBlock, ref variable) && variable is Linq.RangeVariable) { + ec.Report.Error (1939, loc, "A range variable `{0}' may not be passes as `ref' or `out' parameter", + best_candidate.Name); + } else { + right_side.DoResolveLValue (ec, this); + } + return null; + } + + // 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); + } + + if (eclass == ExprClass.Unresolved) { + var expr = OverloadResolve (ec, right_side); + if (expr == null) + return null; + + if (expr != this) + return expr.ResolveLValue (ec, right_side); + } + + if (!ResolveSetter (ec)) + return null; + + return this; + } + + // + // Implements the IAssignMethod interface for assignments + // + public abstract void Emit (EmitContext ec, bool leave_copy); + public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source); + + protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side); + + bool ResolveGetter (ResolveContext rc) + { + if (!best_candidate.HasGet) { + if (InstanceExpression != EmptyExpression.Null) { + rc.Report.SymbolRelatedToPreviousError (best_candidate); + rc.Report.Error (154, loc, "The property or indexer `{0}' cannot be used in this context because it lacks the `get' accessor", + best_candidate.GetSignatureForError ()); + return false; + } + } else if (!best_candidate.Get.IsAccessible (rc)) { + if (best_candidate.HasDifferentAccessibility) { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Get); + rc.Report.Error (271, loc, "The property or indexer `{0}' cannot be used in this context because the get accessor is inaccessible", + TypeManager.CSharpSignature (best_candidate)); + } else { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Get); + ErrorIsInaccesible (rc, best_candidate.Get.GetSignatureForError (), loc); + } + } + + if (best_candidate.HasDifferentAccessibility) { + CheckProtectedMemberAccess (rc, best_candidate.Get); + } + + getter = CandidateToBaseOverride (rc, best_candidate.Get); + return true; + } + + bool ResolveSetter (ResolveContext rc) + { + if (!best_candidate.HasSet) { + rc.Report.Error (200, loc, "Property or indexer `{0}' cannot be assigned to (it is read-only)", + GetSignatureForError ()); + return false; + } + + if (!best_candidate.Set.IsAccessible (rc)) { + if (best_candidate.HasDifferentAccessibility) { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Set); + rc.Report.Error (272, loc, "The property or indexer `{0}' cannot be used in this context because the set accessor is inaccessible", + GetSignatureForError ()); + } else { + rc.Report.SymbolRelatedToPreviousError (best_candidate.Set); + ErrorIsInaccesible (rc, best_candidate.Set.GetSignatureForError (), loc); + } + } + + if (best_candidate.HasDifferentAccessibility) + CheckProtectedMemberAccess (rc, best_candidate.Set); + + setter = CandidateToBaseOverride (rc, best_candidate.Set); + return true; + } + } + + /// + /// Fully resolved expression that evaluates to an Event + /// + public class EventExpr : MemberExpr, IAssignMethod + { + readonly EventSpec spec; + MethodSpec op; + + public EventExpr (EventSpec spec, Location loc) + { + this.spec = spec; + this.loc = loc; + } + + #region Properties + + protected override TypeSpec DeclaringType { + get { + return spec.DeclaringType; + } + } + + public override string Name { + get { + return spec.Name; + } + } + + public override bool IsInstance { + get { + return !spec.IsStatic; + } + } + + public override bool IsStatic { + get { + return spec.IsStatic; + } + } + + public MethodSpec Operator { + get { + return op; + } + } + + #endregion + + public override MemberExpr ResolveMemberAccess (ResolveContext ec, Expression left, SimpleName original) + { + // + // If the event is local to this class and we are not lhs of +=/-= we transform ourselves into a FieldExpr + // + if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { + if (spec.BackingField != null && + (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition))) { + + spec.MemberDefinition.SetIsUsed (); + + if (!ec.IsObsolete) { + ObsoleteAttribute oa = spec.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, spec.GetSignatureForError (), loc, ec.Report); + } + + if ((spec.Modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0) + Error_AssignmentEventOnly (ec); + + FieldExpr ml = new FieldExpr (spec.BackingField, loc); + + InstanceExpression = null; + + return ml.ResolveMemberAccess (ec, left, original); + } + } + + return base.ResolveMemberAccess (ec, left, original); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + if (right_side == EmptyExpression.EventAddition) { + op = spec.AccessorAdd; + } else if (right_side == EmptyExpression.EventSubtraction) { + op = spec.AccessorRemove; + } + + if (op == null) { + Error_AssignmentEventOnly (ec); + return null; + } + + op = CandidateToBaseOverride (ec, op); + return this; + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.EventAccess; + type = spec.MemberType; + + ResolveInstanceExpression (ec, null); + + if (!ec.HasSet (ResolveContext.Options.CompoundAssignmentScope)) { + Error_AssignmentEventOnly (ec); + } + + DoBestMemberChecks (ec, spec); + return this; + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException (); + //Error_CannotAssign (); + } + + #region IAssignMethod Members + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + if (leave_copy || !prepare_for_load) + throw new NotImplementedException ("EventExpr::EmitAssign"); + + Arguments args = new Arguments (1); + args.Add (new Argument (source)); + Invocation.EmitCall (ec, InstanceExpression, op, args, loc); + } + + #endregion + + void Error_AssignmentEventOnly (ResolveContext ec) + { + if (spec.DeclaringType == ec.CurrentType || TypeManager.IsNestedChildOf (ec.CurrentType, spec.DeclaringType.MemberDefinition)) { + ec.Report.Error (79, loc, + "The event `{0}' can only appear on the left hand side of `+=' or `-=' operator", + GetSignatureForError ()); + } else { + ec.Report.Error (70, loc, + "The event `{0}' can only appear on the left hand side of += or -= when used outside of the type `{1}'", + GetSignatureForError (), spec.DeclaringType.GetSignatureForError ()); + } + } + + protected override void Error_CannotCallAbstractBase (ResolveContext rc, string name) + { + name = name.Substring (0, name.LastIndexOf ('.')); + base.Error_CannotCallAbstractBase (rc, name); + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpSignature (spec); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "event", GetSignatureForError (), loc); + } + } + + public class TemporaryVariableReference : VariableReference + { + public class Declarator : Statement + { + TemporaryVariableReference variable; + + public Declarator (TemporaryVariableReference variable) + { + this.variable = variable; + loc = variable.loc; + } + + protected override void DoEmit (EmitContext ec) + { + variable.li.CreateBuilder (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing + } + } + + LocalVariable li; + + public TemporaryVariableReference (LocalVariable li, Location loc) + { + this.li = li; + this.type = li.Type; + this.loc = loc; + } + + public override bool IsLockedByStatement { + get { + return false; + } + set { + } + } + + public LocalVariable LocalInfo { + get { + return li; + } + } + + public static TemporaryVariableReference Create (TypeSpec type, Block block, Location loc) + { + var li = LocalVariable.CreateCompilerGenerated (type, block, loc); + return new TemporaryVariableReference (li, loc); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + + // + // Don't capture temporary variables except when using + // iterator redirection + // + if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) { + AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec); + storey.CaptureLocalVariable (ec, li); + } + + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return Resolve (ec); + } + + public override void Emit (EmitContext ec) + { + li.CreateBuilder (ec); + + Emit (ec, false); + } + + public void EmitAssign (EmitContext ec, Expression source) + { + li.CreateBuilder (ec); + + EmitAssign (ec, source, false, false); + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return li.HoistedVariant; + } + + public override bool IsFixed { + get { return true; } + } + + public override bool IsRef { + get { return false; } + } + + public override string Name { + get { throw new NotImplementedException (); } + } + + public override void SetHasAddressTaken () + { + throw new NotImplementedException (); + } + + protected override ILocalVariable Variable { + get { return li; } + } + + public override VariableInfo VariableInfo { + get { throw new NotImplementedException (); } + } + } + + /// + /// Handles `var' contextual keyword; var becomes a keyword only + /// if no type called var exists in a variable scope + /// + class VarExpr : SimpleName + { + public VarExpr (Location loc) + : base ("var", loc) + { + } + + public bool InferType (ResolveContext ec, Expression right_side) + { + if (type != null) + throw new InternalErrorException ("An implicitly typed local variable could not be redefined"); + + type = right_side.Type; + if (type == InternalType.NullLiteral || type.Kind == MemberKind.Void || type == InternalType.AnonymousMethod || type == InternalType.MethodGroup) { + ec.Report.Error (815, loc, + "An implicitly typed local variable declaration cannot be initialized with `{0}'", + type.GetSignatureForError ()); + return false; + } + + eclass = ExprClass.Variable; + return true; + } + + protected override void Error_TypeOrNamespaceNotFound (IMemberContext ec) + { + if (ec.Module.Compiler.Settings.Version < LanguageVersion.V_3) + base.Error_TypeOrNamespaceNotFound (ec); + else + ec.Module.Compiler.Report.Error (825, loc, "The contextual keyword `var' may only appear within a local variable declaration"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs new file mode 100644 index 0000000000..ec23b5267a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs @@ -0,0 +1,322 @@ +// +// enum.cs: Enum handling. +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2003 Novell, Inc (http://www.novell.com) +// + +using System; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +#else +using MetaType = System.Type; +using System.Reflection; +#endif + +namespace Mono.CSharp { + + public class EnumMember : Const + { + class EnumTypeExpr : TypeExpr + { + public override TypeSpec ResolveAsType (IMemberContext ec) + { + type = ec.CurrentType; + eclass = ExprClass.Type; + return type; + } + } + + public EnumMember (Enum parent, MemberName name, Attributes attrs) + : base (parent, new EnumTypeExpr (), Modifiers.PUBLIC, name, attrs) + { + } + + static bool IsValidEnumType (TypeSpec t) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + return true; + default: + return t.IsEnum; + } + } + + public override Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + if (expr is EnumConstant) + expr = ((EnumConstant) expr).Child; + + var underlying = ((Enum) Parent).UnderlyingType; + if (expr != null) { + expr = expr.ImplicitConversionRequired (rc, underlying, Location); + if (expr != null && !IsValidEnumType (expr.Type)) { + Enum.Error_1008 (Location, Report); + expr = null; + } + } + + if (expr == null) + expr = New.Constantify (underlying, Location); + + return new EnumConstant (expr, MemberType); + } + + public override bool Define () + { + if (!ResolveMemberType ()) + return false; + + const FieldAttributes attr = FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal; + FieldBuilder = Parent.TypeBuilder.DefineField (Name, MemberType.GetMetaInfo (), attr); + spec = new ConstSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags, initializer); + + Parent.MemberCache.AddMember (spec); + return true; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + } + + /// + /// Enumeration container + /// + public class Enum : TypeContainer + { + // + // Implicit enum member initializer, used when no constant value is provided + // + sealed class ImplicitInitializer : Expression + { + readonly EnumMember prev; + readonly EnumMember current; + + public ImplicitInitializer (EnumMember current, EnumMember prev) + { + this.current = current; + this.prev = prev; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("Missing Resolve call"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + // We are the first member + if (prev == null) { + return New.Constantify (current.Parent.Definition, Location); + } + + var c = ((ConstSpec) prev.Spec).GetConstant (rc) as EnumConstant; + try { + return c.Increment (); + } catch (OverflowException) { + rc.Report.Error (543, current.Location, + "The enumerator value `{0}' is outside the range of enumerator underlying type `{1}'", + current.GetSignatureForError (), ((Enum) current.Parent).UnderlyingType.GetSignatureForError ()); + + return New.Constantify (current.Parent.Definition, current.Location); + } + } + + public override void Emit (EmitContext ec) + { + throw new NotSupportedException ("Missing Resolve call"); + } + } + + public static readonly string UnderlyingValueField = "value__"; + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; + + readonly TypeExpr underlying_type_expr; + + public Enum (NamespaceContainer ns, DeclSpace parent, TypeExpression type, + Modifiers mod_flags, MemberName name, Attributes attrs) + : base (ns, parent, name, attrs, MemberKind.Enum) + { + underlying_type_expr = type; + var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE; + ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod_flags, accmods, Location, Report); + spec = new EnumSpec (null, this, null, null, ModFlags); + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Enum; + } + } + + public TypeExpr BaseTypeExpression { + get { + return underlying_type_expr; + } + } + + protected override TypeAttributes TypeAttr { + get { + return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | + TypeAttributes.Class | TypeAttributes.Sealed | base.TypeAttr; + } + } + + public TypeSpec UnderlyingType { + get { + return ((EnumSpec) spec).UnderlyingType; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public void AddEnumMember (EnumMember em) + { + if (em.Name == UnderlyingValueField) { + Report.Error (76, em.Location, "An item in an enumeration cannot have an identifier `{0}'", + UnderlyingValueField); + return; + } + + AddConstant (em); + } + + public static void Error_1008 (Location loc, Report Report) + { + Report.Error (1008, loc, + "Type byte, sbyte, short, ushort, int, uint, long or ulong expected"); + } + + protected override bool DefineNestedTypes () + { + ((EnumSpec) spec).UnderlyingType = underlying_type_expr == null ? Compiler.BuiltinTypes.Int : underlying_type_expr.Type; + + TypeBuilder.DefineField (UnderlyingValueField, UnderlyingType.GetMetaInfo (), + FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); + + return true; + } + + protected override bool DoDefineMembers () + { + if (constants != null) { + for (int i = 0; i < constants.Count; ++i) { + EnumMember em = (EnumMember) constants [i]; + if (em.Initializer == null) { + em.Initializer = new ImplicitInitializer (em, i == 0 ? null : (EnumMember) constants[i - 1]); + } + + em.Define (); + } + } + + return true; + } + + public override bool IsUnmanagedType () + { + return true; + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + base_type = Compiler.BuiltinTypes.Enum; + base_class = null; + return null; + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + switch (UnderlyingType.BuiltinType) { + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.UShort: + Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", + GetSignatureForError (), TypeManager.CSharpName (UnderlyingType)); + break; + } + + return true; + } + } + + class EnumSpec : TypeSpec + { + TypeSpec underlying; + + public EnumSpec (TypeSpec declaringType, ITypeDefinition definition, TypeSpec underlyingType, MetaType info, Modifiers modifiers) + : base (MemberKind.Enum, declaringType, definition, info, modifiers | Modifiers.SEALED) + { + this.underlying = underlyingType; + } + + public TypeSpec UnderlyingType { + get { + return underlying; + } + set { + if (underlying != null) + throw new InternalErrorException ("UnderlyingType reset"); + + underlying = value; + } + } + + public static TypeSpec GetUnderlyingType (TypeSpec t) + { + return ((EnumSpec) t.GetDefinition ()).UnderlyingType; + } + + public static bool IsValidUnderlyingType (TypeSpec type) + { + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.ULong: + return true; + } + + return false; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs new file mode 100644 index 0000000000..03097dfd84 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs @@ -0,0 +1,1128 @@ +// +// eval.cs: Evaluation and Hosting API for the C# compiler +// +// Authors: +// Miguel de Icaza (miguel@gnome.org) +// 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-2011 Novell, Inc +// + +using System; +using System.Threading; +using System.Collections.Generic; +using System.Reflection; +using System.Reflection.Emit; +using System.IO; +using System.Text; +using System.Linq; + +namespace Mono.CSharp +{ + + /// + /// Evaluator: provides an API to evaluate C# statements and + /// expressions dynamically. + /// + /// + /// This class exposes static methods to evaluate expressions in the + /// current program. + /// + /// To initialize the evaluator with a number of compiler + /// options call the Init(string[]args) method with a set of + /// command line options that the compiler recognizes. + /// + /// To interrupt execution of a statement, you can invoke the + /// Evaluator.Interrupt method. + /// + public class Evaluator { + + enum ParseMode { + // Parse silently, do not output any error messages + Silent, + + // Report errors during parse + ReportErrors, + + // Auto-complete, means that the tokenizer will start producing + // GETCOMPLETIONS tokens when it reaches a certain point. + GetCompletions + } + + static object evaluator_lock = new object (); + static volatile bool invoking; + + static int count; + static Thread invoke_thread; + + readonly Dictionary> fields; + + Type base_class; + bool inited; + int startup_files; + + readonly CompilerContext ctx; + readonly ModuleContainer module; + readonly ReflectionImporter importer; + readonly CompilationSourceFile source_file; + + public Evaluator (CompilerSettings settings, Report report) + { + ctx = new CompilerContext (settings, report); + + module = new ModuleContainer (ctx); + module.Evaluator = this; + + source_file = new CompilationSourceFile ("{interactive}", "", 1); + source_file.NamespaceContainer = new NamespaceContainer (null, module, null, source_file); + + startup_files = ctx.SourceFiles.Count; + ctx.SourceFiles.Add (source_file); + + // FIXME: Importer needs this assembly for internalsvisibleto + module.SetDeclaringAssembly (new AssemblyDefinitionDynamic (module, "evaluator")); + importer = new ReflectionImporter (module, ctx.BuiltinTypes); + + InteractiveBaseClass = typeof (InteractiveBase); + fields = new Dictionary> (); + } + + void Init () + { + var loader = new DynamicLoader (importer, ctx); + + CompilerCallableEntryPoint.Reset (); + RootContext.ToplevelTypes = module; + + //var startup_files = new List (); + //foreach (CompilationUnit file in Location.SourceFiles) + // startup_files.Add (file.Path); + + loader.LoadReferences (module); + ctx.BuiltinTypes.CheckDefinitions (module); + module.InitializePredefinedTypes (); + + inited = true; + } + + void ParseStartupFiles () + { + Driver d = new Driver (ctx); + + Location.Initialize (ctx.SourceFiles); + + for (int i = 0; i < startup_files; ++i) { + var sf = ctx.Settings.SourceFiles [i]; + d.Parse (sf, module); + } + } + + void Reset () + { + CompilerCallableEntryPoint.PartialReset (); + + Location.Reset (); + Location.Initialize (ctx.SourceFiles); + } + + /// + /// If true, turns type expressions into valid expressions + /// and calls the describe method on it + /// + public bool DescribeTypeExpressions; + + /// + /// The base class for the classes that host the user generated code + /// + /// + /// + /// This is the base class that will host the code + /// executed by the Evaluator. By default + /// this is the Mono.CSharp.InteractiveBase class + /// which is useful for interactive use. + /// + /// By changing this property you can control the + /// base class and the static members that are + /// available to your evaluated code. + /// + public Type InteractiveBaseClass { + get { + return base_class; + } + set { + base_class = value; + + if (value != null && typeof (InteractiveBase).IsAssignableFrom (value)) + InteractiveBase.Evaluator = this; + } + } + + /// + /// Interrupts the evaluation of an expression executing in Evaluate. + /// + /// + /// Use this method to interrupt long-running invocations. + /// + public void Interrupt () + { + if (!inited || !invoking) + return; + + if (invoke_thread != null) + invoke_thread.Abort (); + } + + /// + /// Compiles the input string and returns a delegate that represents the compiled code. + /// + /// + /// + /// Compiles the input string as a C# expression or + /// statement, unlike the Evaluate method, the + /// resulting delegate can be invoked multiple times + /// without incurring in the compilation overhead. + /// + /// If the return value of this function is null, + /// this indicates that the parsing was complete. + /// If the return value is a string it indicates + /// that the input string was partial and that the + /// invoking code should provide more code before + /// the code can be successfully compiled. + /// + /// If you know that you will always get full expressions or + /// statements and do not care about partial input, you can use + /// the other Compile overload. + /// + /// On success, in addition to returning null, the + /// compiled parameter will be set to the delegate + /// that can be invoked to execute the code. + /// + /// + public string Compile (string input, out CompiledMethod compiled) + { + if (input == null || input.Length == 0){ + compiled = null; + return null; + } + + lock (evaluator_lock){ + if (!inited) { + Init (); + ParseStartupFiles (); + } else { + ctx.Report.Printer.Reset (); + } + + bool partial_input; + CSharpParser parser = ParseString (ParseMode.Silent, input, out partial_input); + if (parser == null){ + compiled = null; + if (partial_input) + return input; + + ParseString (ParseMode.ReportErrors, input, out partial_input); + return null; + } + + Class parser_result = parser.InteractiveResult; + compiled = CompileBlock (parser_result, parser.undo, ctx.Report); + return null; + } + } + + /// + /// Compiles the input string and returns a delegate that represents the compiled code. + /// + /// + /// + /// Compiles the input string as a C# expression or + /// statement, unlike the Evaluate method, the + /// resulting delegate can be invoked multiple times + /// without incurring in the compilation overhead. + /// + /// This method can only deal with fully formed input + /// strings and does not provide a completion mechanism. + /// If you must deal with partial input (for example for + /// interactive use) use the other overload. + /// + /// On success, a delegate is returned that can be used + /// to invoke the method. + /// + /// + public CompiledMethod Compile (string input) + { + CompiledMethod compiled; + + // Ignore partial inputs + if (Compile (input, out compiled) != null){ + // Error, the input was partial. + return null; + } + + // Either null (on error) or the compiled method. + return compiled; + } + + /// + /// Evaluates and expression or statement and returns any result values. + /// + /// + /// Evaluates the input string as a C# expression or + /// statement. If the input string is an expression + /// the result will be stored in the result variable + /// and the result_set variable will be set to true. + /// + /// It is necessary to use the result/result_set + /// pair to identify when a result was set (for + /// example, execution of user-provided input can be + /// an expression, a statement or others, and + /// result_set would only be set if the input was an + /// expression. + /// + /// If the return value of this function is null, + /// this indicates that the parsing was complete. + /// If the return value is a string, it indicates + /// that the input is partial and that the user + /// should provide an updated string. + /// + public string Evaluate (string input, out object result, out bool result_set) + { + CompiledMethod compiled; + + result_set = false; + result = null; + + input = Compile (input, out compiled); + if (input != null) + return input; + + if (compiled == null) + return null; + + // + // The code execution does not need to keep the compiler lock + // + object retval = typeof (QuitValue); + + try { + invoke_thread = System.Threading.Thread.CurrentThread; + invoking = true; + compiled (ref retval); + } catch (ThreadAbortException e){ + Thread.ResetAbort (); + Console.WriteLine ("Interrupted!\n{0}", e); + } finally { + invoking = false; + } + + // + // We use a reference to a compiler type, in this case + // Driver as a flag to indicate that this was a statement + // + if (!ReferenceEquals (retval, typeof (QuitValue))) { + result_set = true; + result = retval; + } + + return null; + } + + public string [] GetCompletions (string input, out string prefix) + { + prefix = ""; + if (input == null || input.Length == 0) + return null; + + lock (evaluator_lock){ + if (!inited) + Init (); + + bool partial_input; + CSharpParser parser = ParseString (ParseMode.GetCompletions, input, out partial_input); + if (parser == null){ + if (CSharpParser.yacc_verbose_flag != 0) + Console.WriteLine ("DEBUG: No completions available"); + return null; + } + + Class parser_result = parser.InteractiveResult; + +#if NET_4_0 + var access = AssemblyBuilderAccess.RunAndCollect; +#else + var access = AssemblyBuilderAccess.Run; +#endif + var a = new AssemblyDefinitionDynamic (module, "completions"); + a.Create (AppDomain.CurrentDomain, access); + module.SetDeclaringAssembly (a); + + // Need to setup MemberCache + parser_result.CreateType (); + + var method = parser_result.Methods[0] as Method; + BlockContext bc = new BlockContext (method, method.Block, ctx.BuiltinTypes.Void); + + try { + method.Block.Resolve (null, bc, method); + } catch (CompletionResult cr) { + prefix = cr.BaseText; + return cr.Result; + } + } + return null; + } + + /// + /// Executes the given expression or statement. + /// + /// + /// Executes the provided statement, returns true + /// on success, false on parsing errors. Exceptions + /// might be thrown by the called code. + /// + public bool Run (string statement) + { + object result; + bool result_set; + + return Evaluate (statement, out result, out result_set) == null; + } + + /// + /// Evaluates and expression or statement and returns the result. + /// + /// + /// Evaluates the input string as a C# expression or + /// statement and returns the value. + /// + /// This method will throw an exception if there is a syntax error, + /// of if the provided input is not an expression but a statement. + /// + public object Evaluate (string input) + { + object result; + bool result_set; + + string r = Evaluate (input, out result, out result_set); + + if (r != null) + throw new ArgumentException ("Syntax error on input: partial input"); + + if (result_set == false) + throw new ArgumentException ("The expression did not set a result"); + + return result; + } + + enum InputKind { + EOF, + StatementOrExpression, + CompilationUnit, + Error + } + + // + // Deambiguates the input string to determine if we + // want to process a statement or if we want to + // process a compilation unit. + // + // This is done using a top-down predictive parser, + // since the yacc/jay parser can not deambiguage this + // without more than one lookahead token. There are very + // few ambiguities. + // + InputKind ToplevelOrStatement (SeekableStreamReader seekable) + { + Tokenizer tokenizer = new Tokenizer (seekable, source_file, ctx); + + int t = tokenizer.token (); + switch (t){ + case Token.EOF: + return InputKind.EOF; + + // These are toplevels + case Token.EXTERN: + case Token.OPEN_BRACKET: + case Token.ABSTRACT: + case Token.CLASS: + case Token.ENUM: + case Token.INTERFACE: + case Token.INTERNAL: + case Token.NAMESPACE: + case Token.PRIVATE: + case Token.PROTECTED: + case Token.PUBLIC: + case Token.SEALED: + case Token.STATIC: + case Token.STRUCT: + return InputKind.CompilationUnit; + + // Definitely expression + case Token.FIXED: + case Token.BOOL: + case Token.BYTE: + case Token.CHAR: + case Token.DECIMAL: + case Token.DOUBLE: + case Token.FLOAT: + case Token.INT: + case Token.LONG: + case Token.NEW: + case Token.OBJECT: + case Token.SBYTE: + case Token.SHORT: + case Token.STRING: + case Token.UINT: + case Token.ULONG: + return InputKind.StatementOrExpression; + + // These need deambiguation help + case Token.USING: + t = tokenizer.token (); + if (t == Token.EOF) + return InputKind.EOF; + + if (t == Token.IDENTIFIER) + return InputKind.CompilationUnit; + return InputKind.StatementOrExpression; + + + // Distinguish between: + // delegate opt_anonymous_method_signature block + // delegate type + case Token.DELEGATE: + t = tokenizer.token (); + if (t == Token.EOF) + return InputKind.EOF; + if (t == Token.OPEN_PARENS || t == Token.OPEN_BRACE) + return InputKind.StatementOrExpression; + return InputKind.CompilationUnit; + + // Distinguih between: + // unsafe block + // unsafe as modifier of a type declaration + case Token.UNSAFE: + t = tokenizer.token (); + if (t == Token.EOF) + return InputKind.EOF; + if (t == Token.OPEN_PARENS) + return InputKind.StatementOrExpression; + return InputKind.CompilationUnit; + + // These are errors: we list explicitly what we had + // from the grammar, ERROR and then everything else + + case Token.READONLY: + case Token.OVERRIDE: + case Token.ERROR: + return InputKind.Error; + + // This catches everything else allowed by + // expressions. We could add one-by-one use cases + // if needed. + default: + return InputKind.StatementOrExpression; + } + } + + // + // Parses the string @input and returns a CSharpParser if succeeful. + // + // if @silent is set to true then no errors are + // reported to the user. This is used to do various calls to the + // parser and check if the expression is parsable. + // + // @partial_input: if @silent is true, then it returns whether the + // parsed expression was partial, and more data is needed + // + CSharpParser ParseString (ParseMode mode, string input, out bool partial_input) + { + partial_input = false; + Reset (); + Tokenizer.LocatedToken.Initialize (); + + var enc = ctx.Settings.Encoding; + var s = new MemoryStream (enc.GetBytes (input)); + SeekableStreamReader seekable = new SeekableStreamReader (s, enc); + + InputKind kind = ToplevelOrStatement (seekable); + if (kind == InputKind.Error){ + if (mode == ParseMode.ReportErrors) + ctx.Report.Error (-25, "Detection Parsing Error"); + partial_input = false; + return null; + } + + if (kind == InputKind.EOF){ + if (mode == ParseMode.ReportErrors) + Console.Error.WriteLine ("Internal error: EOF condition should have been detected in a previous call with silent=true"); + partial_input = true; + return null; + + } + seekable.Position = 0; + + source_file.NamespaceContainer.DeclarationFound = false; + CSharpParser parser = new CSharpParser (seekable, source_file); + + if (kind == InputKind.StatementOrExpression){ + parser.Lexer.putback_char = Tokenizer.EvalStatementParserCharacter; + ctx.Settings.StatementMode = true; + } else { + parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter; + ctx.Settings.StatementMode = false; + } + + if (mode == ParseMode.GetCompletions) + parser.Lexer.CompleteOnEOF = true; + + ReportPrinter old_printer = null; + if ((mode == ParseMode.Silent || mode == ParseMode.GetCompletions) && CSharpParser.yacc_verbose_flag == 0) + old_printer = ctx.Report.SetPrinter (new StreamReportPrinter (TextWriter.Null)); + + try { + parser.parse (); + } finally { + if (ctx.Report.Errors != 0){ + if (mode != ParseMode.ReportErrors && parser.UnexpectedEOF) + partial_input = true; + + if (parser.undo != null) + parser.undo.ExecuteUndo (); + + parser = null; + } + + if (old_printer != null) + ctx.Report.SetPrinter (old_printer); + } + return parser; + } + + CompiledMethod CompileBlock (Class host, Undo undo, Report Report) + { + string current_debug_name = "eval-" + count + ".dll"; + ++count; +#if STATIC + throw new NotSupportedException (); +#else + AssemblyDefinitionDynamic assembly; + AssemblyBuilderAccess access; + + if (Environment.GetEnvironmentVariable ("SAVE") != null) { + access = AssemblyBuilderAccess.RunAndSave; + assembly = new AssemblyDefinitionDynamic (module, current_debug_name, current_debug_name); + assembly.Importer = importer; + } else { +#if NET_4_0 + access = AssemblyBuilderAccess.RunAndCollect; +#else + access = AssemblyBuilderAccess.Run; +#endif + assembly = new AssemblyDefinitionDynamic (module, current_debug_name); + } + + assembly.Create (AppDomain.CurrentDomain, access); + + Method expression_method; + if (host != null) { + var base_class_imported = importer.ImportType (base_class); + var baseclass_list = new List (1) { + new TypeExpression (base_class_imported, host.Location) + }; + + host.AddBasesForPart (host, baseclass_list); + + host.CreateType (); + host.DefineType (); + host.Define (); + + expression_method = (Method) host.Methods[0]; + } else { + expression_method = null; + } + + module.CreateType (); + module.Define (); + + if (Report.Errors != 0){ + if (undo != null) + undo.ExecuteUndo (); + + return null; + } + + if (host != null){ + host.EmitType (); + } + + module.Emit (); + if (Report.Errors != 0){ + if (undo != null) + undo.ExecuteUndo (); + return null; + } + + module.CloseType (); + if (host != null) + host.CloseType (); + + if (access == AssemblyBuilderAccess.RunAndSave) + assembly.Save (); + + if (host == null) + return null; + + // + // Unlike Mono, .NET requires that the MethodInfo is fetched, it cant + // work from MethodBuilders. Retarded, I know. + // + var tt = assembly.Builder.GetType (host.TypeBuilder.Name); + var mi = tt.GetMethod (expression_method.Name); + + if (host.Fields != null) { + // + // We need to then go from FieldBuilder to FieldInfo + // or reflection gets confused (it basically gets confused, and variables override each + // other). + // + foreach (Field field in host.Fields) { + var fi = tt.GetField (field.Name); + + Tuple old; + + // If a previous value was set, nullify it, so that we do + // not leak memory + if (fields.TryGetValue (field.Name, out old)) { + if (old.Item1.MemberType.IsStruct) { + // + // TODO: Clear fields for structs + // + } else { + try { + old.Item2.SetValue (null, null); + } catch { + } + } + } + + fields[field.Name] = Tuple.Create (field.Spec, fi); + } + } + + return (CompiledMethod) System.Delegate.CreateDelegate (typeof (CompiledMethod), mi); +#endif + } + + /// + /// A sentinel value used to indicate that no value was + /// was set by the compiled function. This is used to + /// differentiate between a function not returning a + /// value and null. + /// + internal static class QuitValue { } + + internal Tuple LookupField (string name) + { + Tuple fi; + fields.TryGetValue (name, out fi); + return fi; + } + + static string Quote (string s) + { + if (s.IndexOf ('"') != -1) + s = s.Replace ("\"", "\\\""); + + return "\"" + s + "\""; + } + + public string GetUsing () + { + StringBuilder sb = new StringBuilder (); + // TODO: + //foreach (object x in ns.using_alias_list) + // sb.AppendFormat ("using {0};\n", x); + + foreach (var ue in source_file.NamespaceContainer.Usings) { + sb.AppendFormat ("using {0};", ue.ToString ()); + sb.Append (Environment.NewLine); + } + + return sb.ToString (); + } + + internal ICollection GetUsingList () + { + var res = new List (); + + foreach (var ue in source_file.NamespaceContainer.Usings) + res.Add (ue.Name); + return res; + } + + internal string [] GetVarNames () + { + lock (evaluator_lock){ + return new List (fields.Keys).ToArray (); + } + } + + public string GetVars () + { + lock (evaluator_lock){ + StringBuilder sb = new StringBuilder (); + + foreach (var de in fields){ + var fi = LookupField (de.Key); + object value; + try { + value = fi.Item2.GetValue (null); + if (value is string) + value = Quote ((string)value); + } catch { + value = ""; + } + + sb.AppendFormat ("{0} {1} = {2}", fi.Item1.MemberType.GetSignatureForError (), de.Key, value); + sb.AppendLine (); + } + + return sb.ToString (); + } + } + + /// + /// Loads the given assembly and exposes the API to the user. + /// + public void LoadAssembly (string file) + { + var loader = new DynamicLoader (importer, ctx); + var assembly = loader.LoadAssemblyFile (file); + if (assembly == null) + return; + + lock (evaluator_lock){ + importer.ImportAssembly (assembly, module.GlobalRootNamespace); + } + } + + /// + /// Exposes the API of the given assembly to the Evaluator + /// + public void ReferenceAssembly (Assembly a) + { + lock (evaluator_lock){ + importer.ImportAssembly (a, module.GlobalRootNamespace); + } + } + } + + + /// + /// A delegate that can be used to invoke the + /// compiled expression or statement. + /// + /// + /// Since the Compile methods will compile + /// statements and expressions into the same + /// delegate, you can tell if a value was returned + /// by checking whether the returned value is of type + /// NoValueSet. + /// + + public delegate void CompiledMethod (ref object retvalue); + + /// + /// The default base class for every interaction line + /// + /// + /// The expressions and statements behave as if they were + /// a static method of this class. The InteractiveBase class + /// contains a number of useful methods, but can be overwritten + /// by setting the InteractiveBaseType property in the Evaluator + /// + public class InteractiveBase { + /// + /// Determines where the standard output of methods in this class will go. + /// + public static TextWriter Output = Console.Out; + + /// + /// Determines where the standard error of methods in this class will go. + /// + public static TextWriter Error = Console.Error; + + /// + /// The primary prompt used for interactive use. + /// + public static string Prompt = "csharp> "; + + /// + /// The secondary prompt used for interactive use (used when + /// an expression is incomplete). + /// + public static string ContinuationPrompt = " > "; + + /// + /// Used to signal that the user has invoked the `quit' statement. + /// + public static bool QuitRequested; + + public static Evaluator Evaluator; + + /// + /// Shows all the variables defined so far. + /// + static public void ShowVars () + { + Output.Write (Evaluator.GetVars ()); + Output.Flush (); + } + + /// + /// Displays the using statements in effect at this point. + /// + static public void ShowUsing () + { + Output.Write (Evaluator.GetUsing ()); + Output.Flush (); + } + + /// + /// Times the execution of the given delegate + /// + static public TimeSpan Time (Action a) + { + DateTime start = DateTime.Now; + a (); + return DateTime.Now - start; + } + + /// + /// Loads the assemblies from a package + /// + /// + /// Loads the assemblies from a package. This is equivalent + /// to passing the -pkg: command line flag to the C# compiler + /// on the command line. + /// + static public void LoadPackage (string pkg) + { + if (pkg == null){ + Error.WriteLine ("Invalid package specified"); + return; + } + + string pkgout = Driver.GetPackageFlags (pkg, null); + + string [] xargs = pkgout.Trim (new Char [] {' ', '\n', '\r', '\t'}). + Split (new Char [] { ' ', '\t'}); + + foreach (string s in xargs){ + if (s.StartsWith ("-r:") || s.StartsWith ("/r:") || s.StartsWith ("/reference:")){ + string lib = s.Substring (s.IndexOf (':')+1); + + Evaluator.LoadAssembly (lib); + continue; + } + } + } + + /// + /// Loads the assembly + /// + /// + /// Loads the specified assembly and makes its types + /// available to the evaluator. This is equivalent + /// to passing the -pkg: command line flag to the C# + /// compiler on the command line. + /// + static public void LoadAssembly (string assembly) + { + Evaluator.LoadAssembly (assembly); + } + + static public void print (object obj) + { + Output.WriteLine (obj); + } + + static public void print (string fmt, params object [] args) + { + Output.WriteLine (fmt, args); + } + + /// + /// Returns a list of available static methods. + /// + static public string help { + get { + return "Static methods:\n" + + " Describe (object); - Describes the object's type\n" + + " LoadPackage (package); - Loads the given Package (like -pkg:FILE)\n" + + " LoadAssembly (assembly); - Loads the given assembly (like -r:ASSEMBLY)\n" + + " ShowVars (); - Shows defined local variables.\n" + + " ShowUsing (); - Show active using declarations.\n" + + " Prompt - The prompt used by the C# shell\n" + + " ContinuationPrompt - The prompt for partial input\n" + + " Time (() => { }); - Times the specified code\n" + + " print (obj); - Shorthand for Console.WriteLine\n" + + " quit; - You'll never believe it - this quits the repl!\n" + + " help; - This help text\n"; + } + } + + /// + /// Indicates to the read-eval-print-loop that the interaction should be finished. + /// + static public object quit { + get { + QuitRequested = true; + + // To avoid print null at the exit + return typeof (Evaluator.QuitValue); + } + } + +#if !NET_2_1 + /// + /// Describes an object or a type. + /// + /// + /// This method will show a textual representation + /// of the object's type. If the object is a + /// System.Type it renders the type directly, + /// otherwise it renders the type returned by + /// invoking GetType on the object. + /// + static public string Describe (object x) + { + if (x == null) + return ""; + + var type = x as Type ?? x.GetType (); + + StringWriter sw = new StringWriter (); + new Outline (type, sw, true, false, false).OutlineType (); + return sw.ToString (); + } +#endif + } + + class HoistedEvaluatorVariable : HoistedVariable + { + public HoistedEvaluatorVariable (Field field) + : base (null, field) + { + } + + public override void EmitSymbolInfo () + { + } + + protected override FieldExpr GetFieldExpression (EmitContext ec) + { + return new FieldExpr (field, field.Location); + } + } + + /// + /// A class used to assign values if the source expression is not void + /// + /// Used by the interactive shell to allow it to call this code to set + /// the return value for an invocation. + /// + class OptionalAssign : SimpleAssign { + public OptionalAssign (Expression t, Expression s, Location loc) + : base (t, s, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression clone = source.Clone (new CloneContext ()); + + clone = clone.Resolve (ec); + if (clone == null) + return null; + + // + // A useful feature for the REPL: if we can resolve the expression + // as a type, Describe the type; + // + if (ec.Module.Evaluator.DescribeTypeExpressions){ + var old_printer = ec.Report.SetPrinter (new SessionReportPrinter ()); + Expression tclone; + try { + // Note: clone context cannot be shared otherwise block mapping would leak + tclone = source.Clone (new CloneContext ()); + tclone = tclone.Resolve (ec, ResolveFlags.Type); + if (ec.Report.Errors > 0) + tclone = null; + } finally { + ec.Report.SetPrinter (old_printer); + } + + if (tclone != null) { + Arguments args = new Arguments (1); + args.Add (new Argument (new TypeOf ((TypeExpr) clone, Location))); + return new Invocation (new SimpleName ("Describe", Location), args).Resolve (ec); + } + } + + // This means its really a statement. + if (clone.Type.Kind == MemberKind.Void || clone is DynamicInvocation || clone is Assign) { + return clone; + } + + source = clone; + return base.DoResolve (ec); + } + } + + public class Undo + { + List undo_actions; + + public Undo () + { + } + + public void AddTypeContainer (TypeContainer current_container, TypeContainer tc) + { + if (current_container == tc){ + Console.Error.WriteLine ("Internal error: inserting container into itself"); + return; + } + + if (undo_actions == null) + undo_actions = new List (); + + var existing = current_container.Types.FirstOrDefault (l => l.MemberName.Basename == tc.MemberName.Basename); + if (existing != null) { + current_container.RemoveTypeContainer (existing); + existing.NamespaceEntry.SlaveDeclSpace.RemoveTypeContainer (existing); + undo_actions.Add (() => current_container.AddTypeContainer (existing)); + } + + undo_actions.Add (() => current_container.RemoveTypeContainer (tc)); + } + + public void ExecuteUndo () + { + if (undo_actions == null) + return; + + foreach (var p in undo_actions){ + p (); + } + + undo_actions = null; + } + } + +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs new file mode 100644 index 0000000000..3349a7c000 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs @@ -0,0 +1,9943 @@ +// +// expression.cs: Expression representation for the IL tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Linq; +using SLE = System.Linq.Expressions; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // + // This is an user operator expression, automatically created during + // resolve phase + // + public class UserOperatorCall : Expression { + protected readonly Arguments arguments; + protected readonly MethodSpec oper; + readonly Func expr_tree; + + public UserOperatorCall (MethodSpec oper, Arguments args, Func expr_tree, Location loc) + { + this.oper = oper; + this.arguments = args; + this.expr_tree = expr_tree; + + type = oper.ReturnType; + eclass = ExprClass.Value; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (expr_tree != null) + return expr_tree (ec, new TypeOfMethod (oper, loc)); + + Arguments args = Arguments.CreateForExpressionTree (ec, arguments, + new NullLiteral (loc), + new TypeOfMethod (oper, loc)); + + return CreateExpressionFactoryCall (ec, "Call", args); + } + + protected override void CloneTo (CloneContext context, Expression target) + { + // Nothing to clone + } + + protected override Expression DoResolve (ResolveContext ec) + { + // + // We are born fully resolved + // + return this; + } + + public override void Emit (EmitContext ec) + { + Invocation.EmitCall (ec, null, oper, arguments, loc); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Call ((MethodInfo) oper.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx)); +#endif + } + } + + public class ParenthesizedExpression : ShimExpression + { + public ParenthesizedExpression (Expression expr) + : base (expr) + { + loc = expr.Location; + } + + protected override Expression DoResolve (ResolveContext ec) + { + return expr.Resolve (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return expr.DoResolveLValue (ec, right_side); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Unary implements unary expressions. + // + public class Unary : Expression + { + public enum Operator : byte { + UnaryPlus, UnaryNegation, LogicalNot, OnesComplement, + AddressOf, TOP + } + + public readonly Operator Oper; + public Expression Expr; + Expression enum_conversion; + + public Unary (Operator op, Expression expr, Location loc) + { + Oper = op; + Expr = expr; + this.loc = loc; + } + + // + // This routine will attempt to simplify the unary expression when the + // argument is a constant. + // + Constant TryReduceConstant (ResolveContext ec, Constant e) + { + if (e is EmptyConstantCast) + return TryReduceConstant (ec, ((EmptyConstantCast) e).child); + + if (e is SideEffectConstant) { + Constant r = TryReduceConstant (ec, ((SideEffectConstant) e).value); + return r == null ? null : new SideEffectConstant (r, e, r.Location); + } + + TypeSpec expr_type = e.Type; + + switch (Oper){ + case Operator.UnaryPlus: + // Unary numeric promotions + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new IntConstant (ec.BuiltinTypes, ((ByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.SByte: + return new IntConstant (ec.BuiltinTypes, ((SByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Short: + return new IntConstant (ec.BuiltinTypes, ((ShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.UShort: + return new IntConstant (ec.BuiltinTypes, ((UShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Char: + return new IntConstant (ec.BuiltinTypes, ((CharConstant) e).Value, e.Location); + + // Predefined operators + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Decimal: + return e; + } + + return null; + + case Operator.UnaryNegation: + // Unary numeric promotions + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new IntConstant (ec.BuiltinTypes, -((ByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.SByte: + return new IntConstant (ec.BuiltinTypes, -((SByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Short: + return new IntConstant (ec.BuiltinTypes, -((ShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.UShort: + return new IntConstant (ec.BuiltinTypes, -((UShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Char: + return new IntConstant (ec.BuiltinTypes, -((CharConstant) e).Value, e.Location); + + // Predefined operators + case BuiltinTypeSpec.Type.Int: + int ivalue = ((IntConstant) e).Value; + if (ivalue == int.MinValue) { + if (ec.ConstantCheckState) { + ConstantFold.Error_CompileTimeOverflow (ec, loc); + return null; + } + return e; + } + return new IntConstant (ec.BuiltinTypes, -ivalue, e.Location); + + case BuiltinTypeSpec.Type.Long: + long lvalue = ((LongConstant) e).Value; + if (lvalue == long.MinValue) { + if (ec.ConstantCheckState) { + ConstantFold.Error_CompileTimeOverflow (ec, loc); + return null; + } + return e; + } + return new LongConstant (ec.BuiltinTypes, -lvalue, e.Location); + + case BuiltinTypeSpec.Type.UInt: + UIntLiteral uil = e as UIntLiteral; + if (uil != null) { + if (uil.Value == int.MaxValue + (uint) 1) + return new IntLiteral (ec.BuiltinTypes, int.MinValue, e.Location); + return new LongLiteral (ec.BuiltinTypes, -uil.Value, e.Location); + } + return new LongConstant (ec.BuiltinTypes, -((UIntConstant) e).Value, e.Location); + + + case BuiltinTypeSpec.Type.ULong: + ULongLiteral ull = e as ULongLiteral; + if (ull != null && ull.Value == 9223372036854775808) + return new LongLiteral (ec.BuiltinTypes, long.MinValue, e.Location); + return null; + + case BuiltinTypeSpec.Type.Float: + FloatLiteral fl = e as FloatLiteral; + // For better error reporting + if (fl != null) + return new FloatLiteral (ec.BuiltinTypes, -fl.Value, e.Location); + + return new FloatConstant (ec.BuiltinTypes, -((FloatConstant) e).Value, e.Location); + + case BuiltinTypeSpec.Type.Double: + DoubleLiteral dl = e as DoubleLiteral; + // For better error reporting + if (dl != null) + return new DoubleLiteral (ec.BuiltinTypes, -dl.Value, e.Location); + + return new DoubleConstant (ec.BuiltinTypes, -((DoubleConstant) e).Value, e.Location); + + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (ec.BuiltinTypes, -((DecimalConstant) e).Value, e.Location); + } + + return null; + + case Operator.LogicalNot: + if (expr_type.BuiltinType != BuiltinTypeSpec.Type.Bool) + return null; + + bool b = (bool)e.GetValue (); + return new BoolConstant (ec.BuiltinTypes, !b, e.Location); + + case Operator.OnesComplement: + // Unary numeric promotions + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + return new IntConstant (ec.BuiltinTypes, ~((ByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.SByte: + return new IntConstant (ec.BuiltinTypes, ~((SByteConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Short: + return new IntConstant (ec.BuiltinTypes, ~((ShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.UShort: + return new IntConstant (ec.BuiltinTypes, ~((UShortConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Char: + return new IntConstant (ec.BuiltinTypes, ~((CharConstant) e).Value, e.Location); + + // Predefined operators + case BuiltinTypeSpec.Type.Int: + return new IntConstant (ec.BuiltinTypes, ~((IntConstant)e).Value, e.Location); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (ec.BuiltinTypes, ~((UIntConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (ec.BuiltinTypes, ~((LongConstant) e).Value, e.Location); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (ec.BuiltinTypes, ~((ULongConstant) e).Value, e.Location); + } + if (e is EnumConstant) { + e = TryReduceConstant (ec, ((EnumConstant)e).Child); + if (e != null) + e = new EnumConstant (e, expr_type); + return e; + } + return null; + } + throw new Exception ("Can not constant fold: " + Oper.ToString()); + } + + protected virtual Expression ResolveOperator (ResolveContext ec, Expression expr) + { + eclass = ExprClass.Value; + + TypeSpec expr_type = expr.Type; + Expression best_expr; + + TypeSpec[] predefined = ec.BuiltinTypes.OperatorsUnary [(int) Oper]; + + // + // Primitive types first + // + if (BuiltinTypeSpec.IsPrimitiveType (expr_type)) { + best_expr = ResolvePrimitivePredefinedType (ec, expr, predefined); + if (best_expr == null) + return null; + + type = best_expr.Type; + Expr = best_expr; + return this; + } + + // + // E operator ~(E x); + // + if (Oper == Operator.OnesComplement && TypeManager.IsEnumType (expr_type)) + return ResolveEnumOperator (ec, expr, predefined); + + return ResolveUserType (ec, expr, predefined); + } + + protected virtual Expression ResolveEnumOperator (ResolveContext ec, Expression expr, TypeSpec[] predefined) + { + TypeSpec underlying_type = EnumSpec.GetUnderlyingType (expr.Type); + Expression best_expr = ResolvePrimitivePredefinedType (ec, EmptyCast.Create (expr, underlying_type), predefined); + if (best_expr == null) + return null; + + Expr = best_expr; + enum_conversion = Convert.ExplicitNumericConversion (ec, new EmptyExpression (best_expr.Type), underlying_type); + type = expr.Type; + return EmptyCast.Create (this, type); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return CreateExpressionTree (ec, null); + } + + Expression CreateExpressionTree (ResolveContext ec, Expression user_op) + { + string method_name; + switch (Oper) { + case Operator.AddressOf: + Error_PointerInsideExpressionTree (ec); + return null; + case Operator.UnaryNegation: + if (ec.HasSet (ResolveContext.Options.CheckedScope) && user_op == null && !IsFloat (type)) + method_name = "NegateChecked"; + else + method_name = "Negate"; + break; + case Operator.OnesComplement: + case Operator.LogicalNot: + method_name = "Not"; + break; + case Operator.UnaryPlus: + method_name = "UnaryPlus"; + break; + default: + throw new InternalErrorException ("Unknown unary operator " + Oper.ToString ()); + } + + Arguments args = new Arguments (2); + args.Add (new Argument (Expr.CreateExpressionTree (ec))); + if (user_op != null) + args.Add (new Argument (user_op)); + + return CreateExpressionFactoryCall (ec, method_name, args); + } + + public static TypeSpec[][] CreatePredefinedOperatorsTable (BuiltinTypes types) + { + var predefined_operators = new TypeSpec[(int) Operator.TOP][]; + + // + // 7.6.1 Unary plus operator + // + predefined_operators [(int) Operator.UnaryPlus] = new TypeSpec [] { + types.Int, types.UInt, + types.Long, types.ULong, + types.Float, types.Double, + types.Decimal + }; + + // + // 7.6.2 Unary minus operator + // + predefined_operators [(int) Operator.UnaryNegation] = new TypeSpec [] { + types.Int, types.Long, + types.Float, types.Double, + types.Decimal + }; + + // + // 7.6.3 Logical negation operator + // + predefined_operators [(int) Operator.LogicalNot] = new TypeSpec [] { + types.Bool + }; + + // + // 7.6.4 Bitwise complement operator + // + predefined_operators [(int) Operator.OnesComplement] = new TypeSpec [] { + types.Int, types.UInt, + types.Long, types.ULong + }; + + return predefined_operators; + } + + // + // Unary numeric promotions + // + static Expression DoNumericPromotion (ResolveContext rc, Operator op, Expression expr) + { + TypeSpec expr_type = expr.Type; + if (op == Operator.UnaryPlus || op == Operator.UnaryNegation || op == Operator.OnesComplement) { + switch (expr_type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Int); + } + } + + if (op == Operator.UnaryNegation && expr_type.BuiltinType == BuiltinTypeSpec.Type.UInt) + return Convert.ImplicitNumericConversion (expr, rc.BuiltinTypes.Long); + + return expr; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (Oper == Operator.AddressOf) { + return ResolveAddressOf (ec); + } + + Expr = Expr.Resolve (ec); + if (Expr == null) + return null; + + if (Expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (Expr)); + return new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc).Resolve (ec); + } + + if (Expr.Type.IsNullableType) + return new Nullable.LiftedUnaryOperator (Oper, Expr, loc).Resolve (ec); + + // + // Attempt to use a constant folding operation. + // + Constant cexpr = Expr as Constant; + if (cexpr != null) { + cexpr = TryReduceConstant (ec, cexpr); + if (cexpr != null) + return cexpr; + } + + Expression expr = ResolveOperator (ec, Expr); + if (expr == null) + Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), Expr.Type); + + // + // Reduce unary operator on predefined types + // + if (expr == this && Oper == Operator.UnaryPlus) + return Expr; + + return expr; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right) + { + return null; + } + + public override void Emit (EmitContext ec) + { + EmitOperator (ec, type); + } + + protected void EmitOperator (EmitContext ec, TypeSpec type) + { + switch (Oper) { + case Operator.UnaryPlus: + Expr.Emit (ec); + break; + + case Operator.UnaryNegation: + if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) { + ec.Emit (OpCodes.Ldc_I4_0); + if (type.BuiltinType == BuiltinTypeSpec.Type.Long) + ec.Emit (OpCodes.Conv_U8); + Expr.Emit (ec); + ec.Emit (OpCodes.Sub_Ovf); + } else { + Expr.Emit (ec); + ec.Emit (OpCodes.Neg); + } + + break; + + case Operator.LogicalNot: + Expr.Emit (ec); + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + break; + + case Operator.OnesComplement: + Expr.Emit (ec); + ec.Emit (OpCodes.Not); + break; + + case Operator.AddressOf: + ((IMemoryLocation)Expr).AddressOf (ec, AddressOp.LoadStore); + break; + + default: + throw new Exception ("This should not happen: Operator = " + + Oper.ToString ()); + } + + // + // Same trick as in Binary expression + // + if (enum_conversion != null) + enum_conversion.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + if (Oper == Operator.LogicalNot) + Expr.EmitBranchable (ec, target, !on_true); + else + base.EmitBranchable (ec, target, on_true); + } + + public override void EmitSideEffect (EmitContext ec) + { + 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 + // + string GetOperatorExpressionTypeName () + { + switch (Oper) { + case Operator.OnesComplement: + return "OnesComplement"; + case Operator.LogicalNot: + return "Not"; + case Operator.UnaryNegation: + return "Negate"; + case Operator.UnaryPlus: + return "UnaryPlus"; + default: + throw new NotImplementedException ("Unknown express type operator " + Oper.ToString ()); + } + } + + static bool IsFloat (TypeSpec t) + { + return t.BuiltinType == BuiltinTypeSpec.Type.Double || t.BuiltinType == BuiltinTypeSpec.Type.Float; + } + + // + // Returns a stringified representation of the Operator + // + public static string OperName (Operator oper) + { + switch (oper) { + case Operator.UnaryPlus: + return "+"; + case Operator.UnaryNegation: + return "-"; + case Operator.LogicalNot: + return "!"; + case Operator.OnesComplement: + return "~"; + case Operator.AddressOf: + return "&"; + } + + throw new NotImplementedException (oper.ToString ()); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + var expr = Expr.MakeExpression (ctx); + bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope); + + switch (Oper) { + case Operator.UnaryNegation: + return is_checked ? SLE.Expression.NegateChecked (expr) : SLE.Expression.Negate (expr); + case Operator.LogicalNot: + return SLE.Expression.Not (expr); +#if NET_4_0 + case Operator.OnesComplement: + return SLE.Expression.OnesComplement (expr); +#endif + default: + throw new NotImplementedException (Oper.ToString ()); + } + } + + Expression ResolveAddressOf (ResolveContext ec) + { + if (!ec.IsUnsafe) + UnsafeError (ec, loc); + + Expr = Expr.DoResolveLValue (ec, EmptyExpression.UnaryAddress); + if (Expr == null || Expr.eclass != ExprClass.Variable) { + ec.Report.Error (211, loc, "Cannot take the address of the given expression"); + return null; + } + + if (!TypeManager.VerifyUnmanaged (ec.Module, Expr.Type, loc)) { + return null; + } + + 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 (); + + if (vr.IsHoisted) { + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, vr, loc); + } + } else { + IFixedExpression fe = Expr as IFixedExpression; + is_fixed = fe != null && fe.IsFixed; + } + + if (!is_fixed && !ec.HasSet (ResolveContext.Options.FixedInitializerScope)) { + ec.Report.Error (212, loc, "You can only take the address of unfixed expression inside of a fixed statement initializer"); + } + + type = PointerContainer.MakeType (ec.Module, Expr.Type); + eclass = ExprClass.Value; + return this; + } + + Expression ResolvePrimitivePredefinedType (ResolveContext rc, Expression expr, TypeSpec[] predefined) + { + expr = DoNumericPromotion (rc, Oper, expr); + TypeSpec expr_type = expr.Type; + foreach (TypeSpec t in predefined) { + if (t == expr_type) + return expr; + } + return null; + } + + // + // Perform user-operator overload resolution + // + protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression expr) + { + CSharp.Operator.OpType op_type; + switch (Oper) { + case Operator.LogicalNot: + op_type = CSharp.Operator.OpType.LogicalNot; break; + case Operator.OnesComplement: + op_type = CSharp.Operator.OpType.OnesComplement; break; + case Operator.UnaryNegation: + op_type = CSharp.Operator.OpType.UnaryNegation; break; + case Operator.UnaryPlus: + op_type = CSharp.Operator.OpType.UnaryPlus; break; + default: + throw new InternalErrorException (Oper.ToString ()); + } + + var methods = MemberCache.GetUserOperator (expr.Type, op_type, false); + if (methods == null) + return null; + + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc); + var oper = res.ResolveOperator (ec, ref args); + + if (oper == null) + return null; + + Expr = args [0].Expr; + return new UserOperatorCall (oper, args, CreateExpressionTree, expr.Location); + } + + // + // Unary user type overload resolution + // + Expression ResolveUserType (ResolveContext ec, Expression expr, TypeSpec[] predefined) + { + Expression best_expr = ResolveUserOperator (ec, expr); + if (best_expr != null) + return best_expr; + + foreach (TypeSpec t in predefined) { + Expression oper_expr = Convert.ImplicitUserConversion (ec, expr, t, expr.Location); + if (oper_expr == null) + continue; + + if (oper_expr == ErrorExpression.Instance) + return oper_expr; + + // + // decimal type is predefined but has user-operators + // + if (oper_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) + oper_expr = ResolveUserType (ec, oper_expr, predefined); + else + oper_expr = ResolvePrimitivePredefinedType (ec, oper_expr, predefined); + + if (oper_expr == null) + continue; + + if (best_expr == null) { + best_expr = oper_expr; + continue; + } + + int result = OverloadResolver.BetterTypeConversion (ec, best_expr.Type, t); + if (result == 0) { + if ((oper_expr is UserOperatorCall || oper_expr is UserCast) && (best_expr is UserOperatorCall || best_expr is UserCast)) { + ec.Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'", + OperName (Oper), expr.Type.GetSignatureForError ()); + } else { + Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), expr.Type); + } + + break; + } + + if (result == 2) + best_expr = oper_expr; + } + + if (best_expr == null) + return null; + + // + // HACK: Decimal user-operator is included in standard operators + // + if (best_expr.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) + return best_expr; + + Expr = best_expr; + type = best_expr.Type; + return this; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Unary target = (Unary) t; + + target.Expr = Expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + // + // Unary operators are turned into Indirection expressions + // after semantic analysis (this is so we can take the address + // of an indirection). + // + public class Indirection : Expression, IMemoryLocation, IAssignMethod, IFixedExpression { + Expression expr; + LocalTemporary temporary; + bool prepared; + + public Expression Expr { + get { + return expr; + } + } + + public Indirection (Expression expr, Location l) + { + this.expr = expr; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Indirection target = (Indirection) t; + target.expr = expr.Clone (clonectx); + } + + public override void Emit (EmitContext ec) + { + if (!prepared) + expr.Emit (ec); + + ec.EmitLoadFromPtr (Type); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + Emit (ec); + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temporary = new LocalTemporary (expr.Type); + temporary.Store (ec); + } + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + prepared = prepare_for_load; + + expr.Emit (ec); + + if (prepare_for_load) + ec.Emit (OpCodes.Dup); + + source.Emit (ec); + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temporary = new LocalTemporary (source.Type); + temporary.Store (ec); + } + + ec.EmitStoreFromPtr (type); + + if (temporary != null) { + temporary.Emit (ec); + temporary.Release (ec); + } + } + + public void AddressOf (EmitContext ec, AddressOp Mode) + { + expr.Emit (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return DoResolve (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (!ec.IsUnsafe) + UnsafeError (ec, loc); + + var pc = expr.Type as PointerContainer; + + if (pc == null) { + ec.Report.Error (193, loc, "The * or -> operator must be applied to a pointer"); + return null; + } + + type = pc.Element; + + if (type.Kind == MemberKind.Void) { + Error_VoidPointerOperation (ec); + return null; + } + + eclass = ExprClass.Variable; + return this; + } + + public bool IsFixed { + get { return true; } + } + + public override string ToString () + { + return "*(" + expr + ")"; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Unary Mutator expressions (pre and post ++ and --) + /// + /// + /// + /// UnaryMutator implements ++ and -- expressions. It derives from + /// ExpressionStatement becuase the pre/post increment/decrement + /// operators can be used in a statement context. + /// + /// FIXME: Idea, we could split this up in two classes, one simpler + /// for the common case, and one with the extra fields for more complex + /// classes (indexers require temporary access; overloaded require method) + /// + /// + public class UnaryMutator : ExpressionStatement + { + class DynamicPostMutator : Expression, IAssignMethod + { + LocalTemporary temp; + Expression expr; + + public DynamicPostMutator (Expression expr) + { + this.expr = expr; + this.type = expr.Type; + this.loc = expr.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotImplementedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext rc) + { + eclass = expr.eclass; + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + expr.DoResolveLValue (ec, right_side); + return DoResolve (ec); + } + + public override void Emit (EmitContext ec) + { + temp.Emit (ec); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + throw new NotImplementedException (); + } + + // + // Emits target assignment using unmodified source value + // + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + // + // Allocate temporary variable to keep original value before it's modified + // + temp = new LocalTemporary (type); + expr.Emit (ec); + temp.Store (ec); + + ((IAssignMethod) expr).EmitAssign (ec, source, false, prepare_for_load); + + if (leave_copy) + Emit (ec); + + temp.Release (ec); + temp = null; + } + } + + [Flags] + public enum Mode : byte { + IsIncrement = 0, + IsDecrement = 1, + IsPre = 0, + IsPost = 2, + + PreIncrement = 0, + PreDecrement = IsDecrement, + PostIncrement = IsPost, + PostDecrement = IsPost | IsDecrement + } + + Mode mode; + bool is_expr, recurse; + + Expression expr; + + // Holds the real operation + Expression operation; + + public Mode UnaryMutatorMode { + get { + return mode; + } + } + + public Expression Expr { + get { + return expr; + } + } + + public UnaryMutator (Mode m, Expression e, Location loc) + { + mode = m; + this.loc = loc; + expr = e; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return new SimpleAssign (this, this).CreateExpressionTree (ec); + } + + public static TypeSpec[] CreatePredefinedOperatorsTable (BuiltinTypes types) + { + // + // Predefined ++ and -- operators exist for the following types: + // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal + // + return new TypeSpec[] { + types.Int, + types.Long, + + types.SByte, + types.Byte, + types.Short, + types.UInt, + types.ULong, + types.Char, + types.Float, + types.Double, + types.Decimal + }; + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + + if (expr == null) + return null; + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + // + // Handle postfix unary operators using local + // temporary variable + // + if ((mode & Mode.IsPost) != 0) + expr = new DynamicPostMutator (expr); + + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return new SimpleAssign (expr, new DynamicUnaryConversion (GetOperatorExpressionTypeName (), args, loc)).Resolve (ec); + } + + if (expr.Type.IsNullableType) + return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec); + + eclass = ExprClass.Value; + type = expr.Type; + + if (expr is RuntimeValueExpression) { + operation = expr; + } else { + // Use itself at the top of the stack + operation = new EmptyExpression (type); + } + + // + // The operand of the prefix/postfix increment decrement operators + // should be an expression that is classified as a variable, + // a property access or an indexer access + // + // TODO: Move to parser, expr is ATypeNameExpression + if (expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.IndexerAccess || expr.eclass == ExprClass.PropertyAccess) { + expr = expr.ResolveLValue (ec, expr); + } else { + ec.Report.Error (1059, loc, "The operand of an increment or decrement operator must be a variable, property or indexer"); + } + + // + // Step 1: Try to find a user operator, it has priority over predefined ones + // + var user_op = IsDecrement ? Operator.OpType.Decrement : Operator.OpType.Increment; + var methods = MemberCache.GetUserOperator (type, user_op, false); + + if (methods != null) { + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.BaseMembersIncluded | OverloadResolver.Restrictions.NoBaseMembers, loc); + var method = res.ResolveOperator (ec, ref args); + if (method == null) + return null; + + args[0].Expr = operation; + operation = new UserOperatorCall (method, args, null, loc); + operation = Convert.ImplicitConversionRequired (ec, operation, type, loc); + return this; + } + + // + // Step 2: Try predefined types + // + + Expression source = null; + bool primitive_type; + + // + // Predefined without user conversion first for speed-up + // + // Predefined ++ and -- operators exist for the following types: + // sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal + // + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Decimal: + source = operation; + primitive_type = true; + break; + default: + primitive_type = false; + + // ++/-- on pointer variables of all types except void* + if (type.IsPointer) { + if (((PointerContainer) type).Element.Kind == MemberKind.Void) { + Error_VoidPointerOperation (ec); + return null; + } + + source = operation; + } else { + foreach (var t in ec.BuiltinTypes.OperatorsUnaryMutator) { + source = Convert.ImplicitUserConversion (ec, operation, t, loc); + + // LAMESPEC: It should error on ambiguous operators but that would make us incompatible + if (source != null) { + break; + } + } + } + + // ++/-- on enum types + if (source == null && type.IsEnum) + source = operation; + + if (source == null) { + Unary.Error_OperatorCannotBeApplied (ec, loc, Operator.GetName (user_op), type); + return null; + } + + break; + } + + var one = new IntConstant (ec.BuiltinTypes, 1, loc); + var op = IsDecrement ? Binary.Operator.Subtraction : Binary.Operator.Addition; + operation = new Binary (op, source, one, loc); + operation = operation.Resolve (ec); + if (operation == null) + throw new NotImplementedException ("should not be reached"); + + if (operation.Type != type) { + if (primitive_type) + operation = Convert.ExplicitNumericConversion (ec, operation, type); + else + operation = Convert.ImplicitConversionRequired (ec, operation, type, loc); + } + + return this; + } + + void EmitCode (EmitContext ec, bool is_expr) + { + recurse = true; + this.is_expr = is_expr; + ((IAssignMethod) expr).EmitAssign (ec, this, is_expr && (mode == Mode.PreIncrement || mode == Mode.PreDecrement), true); + } + + public override void Emit (EmitContext ec) + { + // + // We use recurse to allow ourselfs to be the source + // of an assignment. This little hack prevents us from + // having to allocate another expression + // + if (recurse) { + ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement)); + + operation.Emit (ec); + + recurse = false; + return; + } + + EmitCode (ec, true); + } + + public override void EmitStatement (EmitContext ec) + { + EmitCode (ec, false); + } + + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + return IsDecrement ? "Decrement" : "Increment"; + } + + bool IsDecrement { + get { return (mode & Mode.IsDecrement) != 0; } + } + + +#if NET_4_0 + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + var target = ((RuntimeValueExpression) expr).MetaObject.Expression; + var source = SLE.Expression.Convert (operation.MakeExpression (ctx), target.Type); + return SLE.Expression.Assign (target, source); + } +#endif + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + UnaryMutator target = (UnaryMutator) t; + + target.expr = expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + /// + /// Base class for the `Is' and `As' classes. + /// + /// + /// + /// FIXME: Split this in two, and we get to save the `Operator' Oper + /// size. + /// + public abstract class Probe : Expression { + public Expression ProbeType; + protected Expression expr; + protected TypeSpec probe_type_expr; + + public Probe (Expression expr, Expression probe_type, Location l) + { + ProbeType = probe_type; + loc = l; + this.expr = expr; + } + + public Expression Expr { + get { + return expr; + } + } + + protected override Expression DoResolve (ResolveContext ec) + { + probe_type_expr = ProbeType.ResolveAsType (ec); + if (probe_type_expr == null) + return null; + + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (probe_type_expr.IsStatic) { + ec.Report.Error (-244, loc, "The `{0}' operator cannot be applied to an operand of a static type", + OperatorName); + } + + if (expr.Type.IsPointer || probe_type_expr.IsPointer) { + ec.Report.Error (244, loc, "The `{0}' operator cannot be applied to an operand of pointer type", + OperatorName); + return null; + } + + if (expr.Type == InternalType.AnonymousMethod) { + ec.Report.Error (837, loc, "The `{0}' operator cannot be applied to a lambda expression or anonymous method", + OperatorName); + return null; + } + + return this; + } + + protected abstract string OperatorName { get; } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Probe target = (Probe) t; + + target.expr = expr.Clone (clonectx); + target.ProbeType = ProbeType.Clone (clonectx); + } + + } + + /// + /// Implementation of the `is' operator. + /// + public class Is : Probe { + Nullable.Unwrap expr_unwrap; + + public Is (Expression expr, Expression probe_type, Location l) + : base (expr, probe_type, l) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, null, + expr.CreateExpressionTree (ec), + new TypeOf (probe_type_expr, loc)); + + return CreateExpressionFactoryCall (ec, "TypeIs", args); + } + + public override void Emit (EmitContext ec) + { + if (expr_unwrap != null) { + expr_unwrap.EmitCheck (ec); + return; + } + + expr.Emit (ec); + + // Only to make verifier happy + if (probe_type_expr.IsGenericParameter && TypeSpec.IsValueType (expr.Type)) + ec.Emit (OpCodes.Box, expr.Type); + + ec.Emit (OpCodes.Isinst, probe_type_expr); + ec.Emit (OpCodes.Ldnull); + ec.Emit (OpCodes.Cgt_Un); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + if (expr_unwrap != null) { + expr_unwrap.EmitCheck (ec); + } else { + expr.Emit (ec); + ec.Emit (OpCodes.Isinst, probe_type_expr); + } + ec.Emit (on_true ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + + Expression CreateConstantResult (ResolveContext ec, bool result) + { + if (result) + ec.Report.Warning (183, 1, loc, "The given expression is always of the provided (`{0}') type", + TypeManager.CSharpName (probe_type_expr)); + else + ec.Report.Warning (184, 1, loc, "The given expression is never of the provided (`{0}') type", + TypeManager.CSharpName (probe_type_expr)); + + return ReducedExpression.Create (new BoolConstant (ec.BuiltinTypes, result, loc), this); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (base.DoResolve (ec) == null) + return null; + + TypeSpec d = expr.Type; + bool d_is_nullable = false; + + // + // If E is a method group or the null literal, or if the type of E is a reference + // type or a nullable type and the value of E is null, the result is false + // + if (expr.IsNull || expr.eclass == ExprClass.MethodGroup) + return CreateConstantResult (ec, false); + + if (d.IsNullableType) { + var ut = Nullable.NullableInfo.GetUnderlyingType (d); + if (!ut.IsGenericParameter) { + d = ut; + d_is_nullable = true; + } + } + + type = ec.BuiltinTypes.Bool; + eclass = ExprClass.Value; + TypeSpec t = probe_type_expr; + bool t_is_nullable = false; + if (t.IsNullableType) { + var ut = Nullable.NullableInfo.GetUnderlyingType (t); + if (!ut.IsGenericParameter) { + t = ut; + t_is_nullable = true; + } + } + + if (t.IsStruct) { + if (d == t) { + // + // D and T are the same value types but D can be null + // + if (d_is_nullable && !t_is_nullable) { + expr_unwrap = Nullable.Unwrap.Create (expr, false); + return this; + } + + // + // The result is true if D and T are the same value types + // + return CreateConstantResult (ec, true); + } + + var tp = d as TypeParameterSpec; + if (tp != null) + return ResolveGenericParameter (ec, t, tp); + + // + // An unboxing conversion exists + // + if (Convert.ExplicitReferenceConversionExists (d, t)) + return this; + } else { + if (TypeManager.IsGenericParameter (t)) + return ResolveGenericParameter (ec, d, (TypeParameterSpec) t); + + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + ec.Report.Warning (1981, 3, loc, + "Using `{0}' to test compatibility with `{1}' is identical to testing compatibility with `object'", + OperatorName, t.GetSignatureForError ()); + } + + if (TypeManager.IsGenericParameter (d)) + return ResolveGenericParameter (ec, t, (TypeParameterSpec) d); + + if (TypeSpec.IsValueType (d)) { + if (Convert.ImplicitBoxingConversion (null, d, t) != null) { + if (d_is_nullable && !t_is_nullable) { + expr_unwrap = Nullable.Unwrap.Create (expr, false); + return this; + } + + return CreateConstantResult (ec, true); + } + } else { + // if (InflatedTypeSpec.ContainsTypeParameter (d)) + // return this; + + if (Convert.ImplicitReferenceConversionExists (d, t) || + Convert.ExplicitReferenceConversionExists (d, t)) { + return this; + } + } + } + + return CreateConstantResult (ec, false); + } + + Expression ResolveGenericParameter (ResolveContext ec, TypeSpec d, TypeParameterSpec t) + { + if (t.IsReferenceType) { + if (d.IsStruct) + return CreateConstantResult (ec, false); + } + + if (TypeManager.IsGenericParameter (expr.Type)) { + if (expr.Type == d && TypeSpec.IsValueType (t)) + return CreateConstantResult (ec, true); + + expr = new BoxedCast (expr, d); + } + + return this; + } + + protected override string OperatorName { + get { return "is"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implementation of the `as' operator. + /// + public class As : Probe { + Expression resolved_type; + + public As (Expression expr, Expression probe_type, Location l) + : base (expr, probe_type, l) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, null, + expr.CreateExpressionTree (ec), + new TypeOf (probe_type_expr, loc)); + + return CreateExpressionFactoryCall (ec, "TypeAs", args); + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + + ec.Emit (OpCodes.Isinst, type); + + if (TypeManager.IsGenericParameter (type) || type.IsNullableType) + ec.Emit (OpCodes.Unbox_Any, type); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (resolved_type == null) { + resolved_type = base.DoResolve (ec); + + if (resolved_type == null) + return null; + } + + type = probe_type_expr; + eclass = ExprClass.Value; + TypeSpec etype = expr.Type; + + if (!TypeSpec.IsReferenceType (type) && !type.IsNullableType) { + if (TypeManager.IsGenericParameter (type)) { + ec.Report.Error (413, loc, + "The `as' operator cannot be used with a non-reference type parameter `{0}'. Consider adding `class' or a reference type constraint", + probe_type_expr.GetSignatureForError ()); + } else { + ec.Report.Error (77, loc, + "The `as' operator cannot be used with a non-nullable value type `{0}'", + TypeManager.CSharpName (type)); + } + return null; + } + + if (expr.IsNull && type.IsNullableType) { + return Nullable.LiftedNull.CreateFromExpression (ec, this); + } + + // If the compile-time type of E is dynamic, unlike the cast operator the as operator is not dynamically bound + if (etype.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return this; + } + + Expression e = Convert.ImplicitConversionStandard (ec, expr, type, loc); + if (e != null) { + e = EmptyCast.Create (e, type); + return ReducedExpression.Create (e, this).Resolve (ec); + } + + if (Convert.ExplicitReferenceConversionExists (etype, type)){ + if (TypeManager.IsGenericParameter (etype)) + expr = new BoxedCast (expr, etype); + + return this; + } + + if (InflatedTypeSpec.ContainsTypeParameter (etype) || InflatedTypeSpec.ContainsTypeParameter (type)) { + expr = new BoxedCast (expr, etype); + return this; + } + + ec.Report.Error (39, loc, "Cannot convert type `{0}' to `{1}' via a built-in conversion", + TypeManager.CSharpName (etype), TypeManager.CSharpName (type)); + + return null; + } + + protected override string OperatorName { + get { return "as"; } + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + // + // This represents a typecast in the source language. + // + public class Cast : ShimExpression { + Expression target_type; + + public Cast (Expression cast_type, Expression expr, Location loc) + : base (expr) + { + this.target_type = cast_type; + this.loc = loc; + } + + public Expression TargetType { + get { return target_type; } + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + type = target_type.ResolveAsType (ec); + if (type == null) + return null; + + if (type.IsStatic) { + ec.Report.Error (716, loc, "Cannot convert to static type `{0}'", TypeManager.CSharpName (type)); + return null; + } + + eclass = ExprClass.Value; + + Constant c = expr as Constant; + if (c != null) { + c = c.TryReduce (ec, type, loc); + if (c != null) + return c; + } + + if (type.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, loc); + } + + var res = Convert.ExplicitConversion (ec, expr, type, loc); + if (res == expr) + return EmptyCast.Create (res, type); + + return res; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Cast target = (Cast) t; + + target.target_type = target_type.Clone (clonectx); + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ImplicitCast : ShimExpression + { + bool arrayAccess; + + public ImplicitCast (Expression expr, TypeSpec target, bool arrayAccess) + : base (expr) + { + this.loc = expr.Location; + this.type = target; + this.arrayAccess = arrayAccess; + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (arrayAccess) + expr = ConvertExpressionToArrayIndex (ec, expr); + else + expr = Convert.ImplicitConversionRequired (ec, expr, type, loc); + + return expr; + } + } + + // + // C# 2.0 Default value expression + // + public class DefaultValueExpression : Expression + { + Expression expr; + + + public Expression Expr { + get { + return this.expr; + } + } + + public DefaultValueExpression (Expression expr, Location loc) + { + this.expr = expr; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (type, loc))); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = expr.ResolveAsType (ec); + if (type == null) + return null; + + if (type.IsStatic) { + ec.Report.Error (-244, loc, "The `default value' operator cannot be applied to an operand of a static type"); + } + + if (type.IsPointer) + return new NullLiteral (Location).ConvertImplicitly (type); + + if (TypeSpec.IsReferenceType (type)) + return new NullConstant (type, loc); + + Constant c = New.Constantify (type, expr.Location); + if (c != null) + return c; + + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + LocalTemporary temp_storage = new LocalTemporary(type); + + temp_storage.AddressOf(ec, AddressOp.LoadStore); + ec.Emit(OpCodes.Initobj, type); + temp_storage.Emit(ec); + } + +#if NET_4_0 && !STATIC + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return SLE.Expression.Default (type.GetMetaInfo ()); + } +#endif + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + DefaultValueExpression target = (DefaultValueExpression) t; + + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Binary operators + /// + public class Binary : Expression, IDynamicBinder + { + public class PredefinedOperator + { + protected readonly TypeSpec left; + protected readonly TypeSpec right; + public readonly Operator OperatorsMask; + public TypeSpec ReturnType; + + public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) + : this (ltype, rtype, op_mask, ltype) + { + } + + public PredefinedOperator (TypeSpec type, Operator op_mask, TypeSpec return_type) + : this (type, type, op_mask, return_type) + { + } + + public PredefinedOperator (TypeSpec type, Operator op_mask) + : this (type, type, op_mask, type) + { + } + + public PredefinedOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec return_type) + { + if ((op_mask & Operator.ValuesOnlyMask) != 0) + throw new InternalErrorException ("Only masked values can be used"); + + this.left = ltype; + this.right = rtype; + this.OperatorsMask = op_mask; + this.ReturnType = return_type; + } + + public virtual Expression ConvertResult (ResolveContext ec, Binary b) + { + b.type = ReturnType; + + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + // + // A user operators does not support multiple user conversions, but decimal type + // is considered to be predefined type therefore we apply predefined operators rules + // and then look for decimal user-operator implementation + // + if (left.BuiltinType == BuiltinTypeSpec.Type.Decimal) + return b.ResolveUserOperator (ec, b.left, b.right); + + var c = b.right as Constant; + if (c != null) { + if (c.IsDefaultValue && (b.oper == Operator.Addition || b.oper == Operator.Subtraction || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator)))) + return ReducedExpression.Create (b.left, b).Resolve (ec); + if ((b.oper == Operator.Multiply || b.oper == Operator.Division) && c.IsOneInteger) + return ReducedExpression.Create (b.left, b).Resolve (ec); + return b; + } + + c = b.left as Constant; + if (c != null) { + if (c.IsDefaultValue && (b.oper == Operator.Addition || (b.oper == Operator.BitwiseOr && !(b is Nullable.LiftedBinaryOperator)))) + return ReducedExpression.Create (b.right, b).Resolve (ec); + if (b.oper == Operator.Multiply && c.IsOneInteger) + return ReducedExpression.Create (b.right, b).Resolve (ec); + return b; + } + + return b; + } + + public bool IsPrimitiveApplicable (TypeSpec ltype, TypeSpec rtype) + { + // + // We are dealing with primitive types only + // + return left == ltype && ltype == rtype; + } + + public virtual bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr) + { + // Quick path + if (left == lexpr.Type && right == rexpr.Type) + return true; + + return Convert.ImplicitConversionExists (ec, lexpr, left) && + Convert.ImplicitConversionExists (ec, rexpr, right); + } + + public PredefinedOperator ResolveBetterOperator (ResolveContext ec, PredefinedOperator best_operator) + { + int result = 0; + if (left != null && best_operator.left != null) { + result = OverloadResolver.BetterTypeConversion (ec, best_operator.left, left); + } + + // + // When second argument is same as the first one, the result is same + // + if (right != null && (left != right || best_operator.left != best_operator.right)) { + result |= OverloadResolver.BetterTypeConversion (ec, best_operator.right, right); + } + + if (result == 0 || result > 2) + return null; + + return result == 1 ? best_operator : this; + } + } + + sealed class PredefinedStringOperator : PredefinedOperator + { + public PredefinedStringOperator (TypeSpec type, Operator op_mask, TypeSpec retType) + : base (type, type, op_mask, retType) + { + } + + public PredefinedStringOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType) + : base (ltype, rtype, op_mask, retType) + { + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + // + // Use original expression for nullable arguments + // + Nullable.Unwrap unwrap = b.left as Nullable.Unwrap; + if (unwrap != null) + b.left = unwrap.Original; + + unwrap = b.right as Nullable.Unwrap; + if (unwrap != null) + b.right = unwrap.Original; + + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + // + // Start a new concat expression using converted expression + // + return StringConcat.Create (ec, b.left, b.right, b.loc); + } + } + + sealed class PredefinedShiftOperator : PredefinedOperator + { + public PredefinedShiftOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) + : base (ltype, rtype, op_mask) + { + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + + Expression expr_tree_expr = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + int right_mask = left.BuiltinType == BuiltinTypeSpec.Type.Int || left.BuiltinType == BuiltinTypeSpec.Type.UInt ? 0x1f : 0x3f; + + // + // b = b.left >> b.right & (0x1f|0x3f) + // + b.right = new Binary (Operator.BitwiseAnd, + b.right, new IntConstant (ec.BuiltinTypes, right_mask, b.right.Location), b.loc).Resolve (ec); + + // + // Expression tree representation does not use & mask + // + b.right = ReducedExpression.Create (b.right, expr_tree_expr).Resolve (ec); + b.type = ReturnType; + + // + // Optimize shift by 0 + // + var c = b.right as Constant; + if (c != null && c.IsDefaultValue) + return ReducedExpression.Create (b.left, b).Resolve (ec); + + return b; + } + } + + sealed class PredefinedEqualityOperator : PredefinedOperator + { + MethodSpec equal_method, inequal_method; + + public PredefinedEqualityOperator (TypeSpec arg, TypeSpec retType) + : base (arg, arg, Operator.EqualityMask, retType) + { + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + b.type = ReturnType; + + b.left = Convert.ImplicitConversion (ec, b.left, left, b.left.Location); + b.right = Convert.ImplicitConversion (ec, b.right, right, b.right.Location); + + Arguments args = new Arguments (2); + args.Add (new Argument (b.left)); + args.Add (new Argument (b.right)); + + MethodSpec method; + if (b.oper == Operator.Equality) { + if (equal_method == null) { + if (left.BuiltinType == BuiltinTypeSpec.Type.String) + equal_method = ec.Module.PredefinedMembers.StringEqual.Resolve (b.loc); + else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate) + equal_method = ec.Module.PredefinedMembers.DelegateEqual.Resolve (b.loc); + else + throw new NotImplementedException (left.GetSignatureForError ()); + } + + method = equal_method; + } else { + if (inequal_method == null) { + if (left.BuiltinType == BuiltinTypeSpec.Type.String) + inequal_method = ec.Module.PredefinedMembers.StringInequal.Resolve (b.loc); + else if (left.BuiltinType == BuiltinTypeSpec.Type.Delegate) + inequal_method = ec.Module.PredefinedMembers.DelegateInequal.Resolve (b.loc); + else + throw new NotImplementedException (left.GetSignatureForError ()); + } + + method = inequal_method; + } + + return new UserOperatorCall (method, args, b.CreateExpressionTree, b.loc); + } + } + + class PredefinedPointerOperator : PredefinedOperator + { + public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask) + : base (ltype, rtype, op_mask) + { + } + + public PredefinedPointerOperator (TypeSpec ltype, TypeSpec rtype, Operator op_mask, TypeSpec retType) + : base (ltype, rtype, op_mask, retType) + { + } + + public PredefinedPointerOperator (TypeSpec type, Operator op_mask, TypeSpec return_type) + : base (type, op_mask, return_type) + { + } + + public override bool IsApplicable (ResolveContext ec, Expression lexpr, Expression rexpr) + { + if (left == null) { + if (!lexpr.Type.IsPointer) + return false; + } else { + if (!Convert.ImplicitConversionExists (ec, lexpr, left)) + return false; + } + + if (right == null) { + if (!rexpr.Type.IsPointer) + return false; + } else { + if (!Convert.ImplicitConversionExists (ec, rexpr, right)) + return false; + } + + return true; + } + + public override Expression ConvertResult (ResolveContext ec, Binary b) + { + if (left != null) { + b.left = EmptyCast.Create (b.left, left); + } else if (right != null) { + b.right = EmptyCast.Create (b.right, right); + } + + TypeSpec r_type = ReturnType; + Expression left_arg, right_arg; + if (r_type == null) { + if (left == null) { + left_arg = b.left; + right_arg = b.right; + r_type = b.left.Type; + } else { + left_arg = b.right; + right_arg = b.left; + r_type = b.right.Type; + } + } else { + left_arg = b.left; + right_arg = b.right; + } + + return new PointerArithmetic (b.oper, left_arg, right_arg, r_type, b.loc).Resolve (ec); + } + } + + [Flags] + public enum Operator { + Multiply = 0 | ArithmeticMask, + Division = 1 | ArithmeticMask, + Modulus = 2 | ArithmeticMask, + Addition = 3 | ArithmeticMask | AdditionMask, + Subtraction = 4 | ArithmeticMask | SubtractionMask, + + LeftShift = 5 | ShiftMask, + RightShift = 6 | ShiftMask, + + LessThan = 7 | ComparisonMask | RelationalMask, + GreaterThan = 8 | ComparisonMask | RelationalMask, + LessThanOrEqual = 9 | ComparisonMask | RelationalMask, + GreaterThanOrEqual = 10 | ComparisonMask | RelationalMask, + Equality = 11 | ComparisonMask | EqualityMask, + Inequality = 12 | ComparisonMask | EqualityMask, + + BitwiseAnd = 13 | BitwiseMask, + ExclusiveOr = 14 | BitwiseMask, + BitwiseOr = 15 | BitwiseMask, + + LogicalAnd = 16 | LogicalMask, + LogicalOr = 17 | LogicalMask, + + // + // Operator masks + // + ValuesOnlyMask = ArithmeticMask - 1, + ArithmeticMask = 1 << 5, + ShiftMask = 1 << 6, + ComparisonMask = 1 << 7, + EqualityMask = 1 << 8, + BitwiseMask = 1 << 9, + LogicalMask = 1 << 10, + AdditionMask = 1 << 11, + SubtractionMask = 1 << 12, + RelationalMask = 1 << 13 + } + + protected enum State + { + None = 0, + Compound = 1 << 1, + LeftNullLifted = 1 << 2, + RightNullLifted = 1 << 3 + } + + readonly Operator oper; + protected Expression left, right; + protected State state; + Expression enum_conversion; + + public Binary (Operator oper, Expression left, Expression right, bool isCompound, Location loc) + : this (oper, left, right, loc) + { + if (isCompound) + state |= State.Compound; + } + + public Binary (Operator oper, Expression left, Expression right, Location loc) + { + this.oper = oper; + this.left = left; + this.right = right; + this.loc = loc; + } + + #region Properties + + public bool IsCompound { + get { + return (state & State.Compound) != 0; + } + } + + public Operator Oper { + get { + return oper; + } + } + + public Expression Left { + get { return this.left; } + } + + public Expression Right { + get { return this.right; } + } + + #endregion + + /// + /// Returns a stringified representation of the Operator + /// + string OperName (Operator oper) + { + string s; + switch (oper){ + case Operator.Multiply: + s = "*"; + break; + case Operator.Division: + s = "/"; + break; + case Operator.Modulus: + s = "%"; + break; + case Operator.Addition: + s = "+"; + break; + case Operator.Subtraction: + s = "-"; + break; + case Operator.LeftShift: + s = "<<"; + break; + case Operator.RightShift: + s = ">>"; + break; + case Operator.LessThan: + s = "<"; + break; + case Operator.GreaterThan: + s = ">"; + break; + case Operator.LessThanOrEqual: + s = "<="; + break; + case Operator.GreaterThanOrEqual: + s = ">="; + break; + case Operator.Equality: + s = "=="; + break; + case Operator.Inequality: + s = "!="; + break; + case Operator.BitwiseAnd: + s = "&"; + break; + case Operator.BitwiseOr: + s = "|"; + break; + case Operator.ExclusiveOr: + s = "^"; + break; + case Operator.LogicalOr: + s = "||"; + break; + case Operator.LogicalAnd: + s = "&&"; + break; + default: + s = oper.ToString (); + break; + } + + if (IsCompound) + return s + "="; + + return s; + } + + public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, Operator oper, Location loc) + { + new Binary (oper, left, right, loc).Error_OperatorCannotBeApplied (ec, left, right); + } + + public static void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right, string oper, Location loc) + { + if (left.Type == InternalType.FakeInternalType || right.Type == InternalType.FakeInternalType) + return; + + string l, r; + l = TypeManager.CSharpName (left.Type); + r = TypeManager.CSharpName (right.Type); + + ec.Report.Error (19, loc, "Operator `{0}' cannot be applied to operands of type `{1}' and `{2}'", + oper, l, r); + } + + protected void Error_OperatorCannotBeApplied (ResolveContext ec, Expression left, Expression right) + { + Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc); + } + + // + // Converts operator to System.Linq.Expressions.ExpressionType enum name + // + string GetOperatorExpressionTypeName () + { + switch (oper) { + case Operator.Addition: + return IsCompound ? "AddAssign" : "Add"; + case Operator.BitwiseAnd: + return IsCompound ? "AndAssign" : "And"; + case Operator.BitwiseOr: + return IsCompound ? "OrAssign" : "Or"; + case Operator.Division: + return IsCompound ? "DivideAssign" : "Divide"; + case Operator.ExclusiveOr: + return IsCompound ? "ExclusiveOrAssign" : "ExclusiveOr"; + case Operator.Equality: + return "Equal"; + case Operator.GreaterThan: + return "GreaterThan"; + case Operator.GreaterThanOrEqual: + return "GreaterThanOrEqual"; + case Operator.Inequality: + return "NotEqual"; + case Operator.LeftShift: + return IsCompound ? "LeftShiftAssign" : "LeftShift"; + case Operator.LessThan: + return "LessThan"; + case Operator.LessThanOrEqual: + return "LessThanOrEqual"; + case Operator.LogicalAnd: + return "And"; + case Operator.LogicalOr: + return "Or"; + case Operator.Modulus: + return IsCompound ? "ModuloAssign" : "Modulo"; + case Operator.Multiply: + return IsCompound ? "MultiplyAssign" : "Multiply"; + case Operator.RightShift: + return IsCompound ? "RightShiftAssign" : "RightShift"; + case Operator.Subtraction: + return IsCompound ? "SubtractAssign" : "Subtract"; + default: + throw new NotImplementedException ("Unknown expression type operator " + oper.ToString ()); + } + } + + static CSharp.Operator.OpType ConvertBinaryToUserOperator (Operator op) + { + switch (op) { + case Operator.Addition: + return CSharp.Operator.OpType.Addition; + case Operator.BitwiseAnd: + case Operator.LogicalAnd: + return CSharp.Operator.OpType.BitwiseAnd; + case Operator.BitwiseOr: + case Operator.LogicalOr: + return CSharp.Operator.OpType.BitwiseOr; + case Operator.Division: + return CSharp.Operator.OpType.Division; + case Operator.Equality: + return CSharp.Operator.OpType.Equality; + case Operator.ExclusiveOr: + return CSharp.Operator.OpType.ExclusiveOr; + case Operator.GreaterThan: + return CSharp.Operator.OpType.GreaterThan; + case Operator.GreaterThanOrEqual: + return CSharp.Operator.OpType.GreaterThanOrEqual; + case Operator.Inequality: + return CSharp.Operator.OpType.Inequality; + case Operator.LeftShift: + return CSharp.Operator.OpType.LeftShift; + case Operator.LessThan: + return CSharp.Operator.OpType.LessThan; + case Operator.LessThanOrEqual: + return CSharp.Operator.OpType.LessThanOrEqual; + case Operator.Modulus: + return CSharp.Operator.OpType.Modulus; + case Operator.Multiply: + return CSharp.Operator.OpType.Multiply; + case Operator.RightShift: + return CSharp.Operator.OpType.RightShift; + case Operator.Subtraction: + return CSharp.Operator.OpType.Subtraction; + default: + throw new InternalErrorException (op.ToString ()); + } + } + + public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l) + { + OpCode opcode; + + switch (oper){ + case Operator.Multiply: + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long) + opcode = OpCodes.Mul_Ovf; + else if (!IsFloat (l)) + opcode = OpCodes.Mul_Ovf_Un; + else + opcode = OpCodes.Mul; + } else + opcode = OpCodes.Mul; + + break; + + case Operator.Division: + if (IsUnsigned (l)) + opcode = OpCodes.Div_Un; + else + opcode = OpCodes.Div; + break; + + case Operator.Modulus: + if (IsUnsigned (l)) + opcode = OpCodes.Rem_Un; + else + opcode = OpCodes.Rem; + break; + + case Operator.Addition: + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long) + opcode = OpCodes.Add_Ovf; + else if (!IsFloat (l)) + opcode = OpCodes.Add_Ovf_Un; + else + opcode = OpCodes.Add; + } else + opcode = OpCodes.Add; + break; + + case Operator.Subtraction: + if (ec.HasSet (EmitContext.Options.CheckedScope)) { + if (l.BuiltinType == BuiltinTypeSpec.Type.Int || l.BuiltinType == BuiltinTypeSpec.Type.Long) + opcode = OpCodes.Sub_Ovf; + else if (!IsFloat (l)) + opcode = OpCodes.Sub_Ovf_Un; + else + opcode = OpCodes.Sub; + } else + opcode = OpCodes.Sub; + break; + + case Operator.RightShift: + if (IsUnsigned (l)) + opcode = OpCodes.Shr_Un; + else + opcode = OpCodes.Shr; + break; + + case Operator.LeftShift: + opcode = OpCodes.Shl; + break; + + case Operator.Equality: + opcode = OpCodes.Ceq; + break; + + case Operator.Inequality: + ec.Emit (OpCodes.Ceq); + ec.Emit (OpCodes.Ldc_I4_0); + + opcode = OpCodes.Ceq; + break; + + case Operator.LessThan: + if (IsUnsigned (l)) + opcode = OpCodes.Clt_Un; + else + opcode = OpCodes.Clt; + break; + + case Operator.GreaterThan: + if (IsUnsigned (l)) + opcode = OpCodes.Cgt_Un; + else + opcode = OpCodes.Cgt; + break; + + case Operator.LessThanOrEqual: + if (IsUnsigned (l) || IsFloat (l)) + ec.Emit (OpCodes.Cgt_Un); + else + ec.Emit (OpCodes.Cgt); + ec.Emit (OpCodes.Ldc_I4_0); + + opcode = OpCodes.Ceq; + break; + + case Operator.GreaterThanOrEqual: + if (IsUnsigned (l) || IsFloat (l)) + ec.Emit (OpCodes.Clt_Un); + else + ec.Emit (OpCodes.Clt); + + ec.Emit (OpCodes.Ldc_I4_0); + + opcode = OpCodes.Ceq; + break; + + case Operator.BitwiseOr: + opcode = OpCodes.Or; + break; + + case Operator.BitwiseAnd: + opcode = OpCodes.And; + break; + + case Operator.ExclusiveOr: + opcode = OpCodes.Xor; + break; + + default: + throw new InternalErrorException (oper.ToString ()); + } + + ec.Emit (opcode); + } + + static bool IsUnsigned (TypeSpec t) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Byte: + return true; + } + + return t.IsPointer; + } + + static bool IsFloat (TypeSpec t) + { + return t.BuiltinType == BuiltinTypeSpec.Type.Float || t.BuiltinType == BuiltinTypeSpec.Type.Double; + } + + Expression ResolveOperator (ResolveContext ec) + { + TypeSpec l = left.Type; + TypeSpec r = right.Type; + Expression expr; + bool primitives_only = false; + + // + // Handles predefined primitive types + // + if (BuiltinTypeSpec.IsPrimitiveType (l) && BuiltinTypeSpec.IsPrimitiveType (r)) { + if ((oper & Operator.ShiftMask) == 0) { + if (l.BuiltinType != BuiltinTypeSpec.Type.Bool && !DoBinaryOperatorPromotion (ec)) + return null; + + primitives_only = true; + } + } else { + // Pointers + if (l.IsPointer || r.IsPointer) + return ResolveOperatorPointer (ec, l, r); + + // Enums + bool lenum = l.IsEnum; + bool renum = r.IsEnum; + if (lenum || renum) { + expr = ResolveOperatorEnum (ec, lenum, renum, l, r); + + if (expr != null) + return expr; + } + + // Delegates + if ((oper == Operator.Addition || oper == Operator.Subtraction) && (l.IsDelegate || r.IsDelegate)) { + + expr = ResolveOperatorDelegate (ec, l, r); + + // TODO: Can this be ambiguous + if (expr != null) + return expr; + } + + // User operators + expr = ResolveUserOperator (ec, left, right); + if (expr != null) + return expr; + + // Predefined reference types equality + if ((oper & Operator.EqualityMask) != 0) { + expr = ResolveOperatorEquality (ec, l, r); + if (expr != null) + return expr; + } + } + + return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryStandard, primitives_only, null); + } + + // at least one of 'left' or 'right' is an enumeration constant (EnumConstant or SideEffectConstant or ...) + // if 'left' is not an enumeration constant, create one from the type of 'right' + Constant EnumLiftUp (ResolveContext ec, Constant left, Constant right, Location loc) + { + switch (oper) { + case Operator.BitwiseOr: + case Operator.BitwiseAnd: + case Operator.ExclusiveOr: + case Operator.Equality: + case Operator.Inequality: + case Operator.LessThan: + case Operator.LessThanOrEqual: + case Operator.GreaterThan: + case Operator.GreaterThanOrEqual: + if (TypeManager.IsEnumType (left.Type)) + return left; + + if (left.IsZeroInteger) + return left.TryReduce (ec, right.Type, loc); + + break; + + case Operator.Addition: + case Operator.Subtraction: + return left; + + case Operator.Multiply: + case Operator.Division: + case Operator.Modulus: + case Operator.LeftShift: + case Operator.RightShift: + if (TypeManager.IsEnumType (right.Type) || TypeManager.IsEnumType (left.Type)) + break; + return left; + } + + return null; + } + + // + // The `|' operator used on types which were extended is dangerous + // + void CheckBitwiseOrOnSignExtended (ResolveContext ec) + { + OpcodeCast lcast = left as OpcodeCast; + if (lcast != null) { + if (IsUnsigned (lcast.UnderlyingType)) + lcast = null; + } + + OpcodeCast rcast = right as OpcodeCast; + if (rcast != null) { + if (IsUnsigned (rcast.UnderlyingType)) + rcast = null; + } + + if (lcast == null && rcast == null) + return; + + // FIXME: consider constants + + ec.Report.Warning (675, 3, loc, + "The operator `|' used on the sign-extended type `{0}'. Consider casting to a smaller unsigned type first", + TypeManager.CSharpName (lcast != null ? lcast.UnderlyingType : rcast.UnderlyingType)); + } + + public static PredefinedOperator[] CreatePointerOperatorsTable (BuiltinTypes types) + { + return new PredefinedOperator[] { + // + // Pointer arithmetic: + // + // T* operator + (T* x, int y); T* operator - (T* x, int y); + // T* operator + (T* x, uint y); T* operator - (T* x, uint y); + // T* operator + (T* x, long y); T* operator - (T* x, long y); + // T* operator + (T* x, ulong y); T* operator - (T* x, ulong y); + // + new PredefinedPointerOperator (null, types.Int, Operator.AdditionMask | Operator.SubtractionMask), + new PredefinedPointerOperator (null, types.UInt, Operator.AdditionMask | Operator.SubtractionMask), + new PredefinedPointerOperator (null, types.Long, Operator.AdditionMask | Operator.SubtractionMask), + new PredefinedPointerOperator (null, types.ULong, Operator.AdditionMask | Operator.SubtractionMask), + + // + // T* operator + (int y, T* x); + // T* operator + (uint y, T *x); + // T* operator + (long y, T *x); + // T* operator + (ulong y, T *x); + // + new PredefinedPointerOperator (types.Int, null, Operator.AdditionMask, null), + new PredefinedPointerOperator (types.UInt, null, Operator.AdditionMask, null), + new PredefinedPointerOperator (types.Long, null, Operator.AdditionMask, null), + new PredefinedPointerOperator (types.ULong, null, Operator.AdditionMask, null), + + // + // long operator - (T* x, T *y) + // + new PredefinedPointerOperator (null, Operator.SubtractionMask, types.Long) + }; + } + + public static PredefinedOperator[] CreateStandardOperatorsTable (BuiltinTypes types) + { + TypeSpec bool_type = types.Bool; + return new PredefinedOperator[] { + new PredefinedOperator (types.Int, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.UInt, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.Long, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.ULong, Operator.ArithmeticMask | Operator.BitwiseMask), + new PredefinedOperator (types.Float, Operator.ArithmeticMask), + new PredefinedOperator (types.Double, Operator.ArithmeticMask), + new PredefinedOperator (types.Decimal, Operator.ArithmeticMask), + + new PredefinedOperator (types.Int, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.UInt, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Long, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.ULong, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Float, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Double, Operator.ComparisonMask, bool_type), + new PredefinedOperator (types.Decimal, Operator.ComparisonMask, bool_type), + + new PredefinedStringOperator (types.String, Operator.AdditionMask, types.String), + new PredefinedStringOperator (types.String, types.Object, Operator.AdditionMask, types.String), + new PredefinedStringOperator (types.Object, types.String, Operator.AdditionMask, types.String), + + new PredefinedOperator (bool_type, Operator.BitwiseMask | Operator.LogicalMask | Operator.EqualityMask, bool_type), + + new PredefinedShiftOperator (types.Int, types.Int, Operator.ShiftMask), + new PredefinedShiftOperator (types.UInt, types.Int, Operator.ShiftMask), + new PredefinedShiftOperator (types.Long, types.Int, Operator.ShiftMask), + new PredefinedShiftOperator (types.ULong, types.Int, Operator.ShiftMask) + }; + } + + public static PredefinedOperator[] CreateEqualityOperatorsTable (BuiltinTypes types) + { + TypeSpec bool_type = types.Bool; + + return new PredefinedOperator[] { + new PredefinedEqualityOperator (types.String, bool_type), + new PredefinedEqualityOperator (types.Delegate, bool_type), + new PredefinedOperator (bool_type, Operator.EqualityMask, bool_type) + }; + } + + // + // Rules used during binary numeric promotion + // + static bool DoNumericPromotion (ResolveContext rc, ref Expression prim_expr, ref Expression second_expr, TypeSpec type) + { + Expression temp; + + Constant c = prim_expr as Constant; + if (c != null) { + temp = c.ConvertImplicitly (type); + if (temp != null) { + prim_expr = temp; + return true; + } + } + + if (type.BuiltinType == BuiltinTypeSpec.Type.UInt) { + switch (prim_expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Long: + type = rc.BuiltinTypes.Long; + + if (type != second_expr.Type) { + c = second_expr as Constant; + if (c != null) + temp = c.ConvertImplicitly (type); + else + temp = Convert.ImplicitNumericConversion (second_expr, type); + if (temp == null) + return false; + second_expr = temp; + } + break; + } + } else if (type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + // + // A compile-time error occurs if the other operand is of type sbyte, short, int, or long + // + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.SByte: + return false; + } + } + + temp = Convert.ImplicitNumericConversion (prim_expr, type); + if (temp == null) + return false; + + prim_expr = temp; + return true; + } + + // + // 7.2.6.2 Binary numeric promotions + // + public bool DoBinaryOperatorPromotion (ResolveContext ec) + { + TypeSpec ltype = left.Type; + TypeSpec rtype = right.Type; + Expression temp; + + foreach (TypeSpec t in ec.BuiltinTypes.BinaryPromotionsTypes) { + if (t == ltype) + return t == rtype || DoNumericPromotion (ec, ref right, ref left, t); + + if (t == rtype) + return t == ltype || DoNumericPromotion (ec, ref left, ref right, t); + } + + TypeSpec int32 = ec.BuiltinTypes.Int; + if (ltype != int32) { + Constant c = left as Constant; + if (c != null) + temp = c.ConvertImplicitly (int32); + else + temp = Convert.ImplicitNumericConversion (left, int32); + + if (temp == null) + return false; + left = temp; + } + + if (rtype != int32) { + Constant c = right as Constant; + if (c != null) + temp = c.ConvertImplicitly (int32); + else + temp = Convert.ImplicitNumericConversion (right, int32); + + if (temp == null) + return false; + right = temp; + } + + return true; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (left == null) + return null; + + if ((oper == Operator.Subtraction) && (left is ParenthesizedExpression)) { + left = ((ParenthesizedExpression) left).Expr; + left = left.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.Type); + if (left == null) + return null; + + if (left.eclass == ExprClass.Type) { + ec.Report.Error (75, loc, "To cast a negative value, you must enclose the value in parentheses"); + return null; + } + } else + left = left.Resolve (ec); + + if (left == null) + return null; + + Constant lc = left as Constant; + + if (lc != null && lc.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && + ((oper == Operator.LogicalAnd && lc.IsDefaultValue) || + (oper == Operator.LogicalOr && !lc.IsDefaultValue))) { + + // FIXME: resolve right expression as unreachable + // right.Resolve (ec); + + ec.Report.Warning (429, 4, loc, "Unreachable expression code detected"); + return left; + } + + right = right.Resolve (ec); + if (right == null) + return null; + + eclass = ExprClass.Value; + 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))) { + lc = EnumLiftUp (ec, lc, rc, loc); + if (lc != null) + rc = EnumLiftUp (ec, rc, lc, loc); + } + + if (rc != null && lc != null) { + int prev_e = ec.Report.Errors; + Expression e = ConstantFold.BinaryFold (ec, oper, lc, rc, loc); + if (e != null || ec.Report.Errors != prev_e) + return e; + } + + // Comparison warnings + if ((oper & Operator.ComparisonMask) != 0) { + if (left.Equals (right)) { + ec.Report.Warning (1718, 3, loc, "A comparison made to same variable. Did you mean to compare something else?"); + } + CheckOutOfRangeComparison (ec, lc, right.Type); + CheckOutOfRangeComparison (ec, rc, left.Type); + } + + if (left.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic || right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + var lt = left.Type; + var rt = right.Type; + if (lt.Kind == MemberKind.Void || lt == InternalType.MethodGroup || lt == InternalType.AnonymousMethod || + rt.Kind == MemberKind.Void || rt == InternalType.MethodGroup || rt == InternalType.AnonymousMethod) { + Error_OperatorCannotBeApplied (ec, left, right); + return null; + } + + Arguments args; + + // + // Special handling for logical boolean operators which require rhs not to be + // evaluated based on lhs value + // + if ((oper & Operator.LogicalMask) != 0) { + Expression cond_left, cond_right, expr; + + args = new Arguments (2); + + if (lt.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + LocalVariable temp = LocalVariable.CreateCompilerGenerated (lt, ec.CurrentBlock, loc); + + var cond_args = new Arguments (1); + cond_args.Add (new Argument (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left).Resolve (ec))); + + // + // dynamic && bool => IsFalse (temp = left) ? temp : temp && right; + // dynamic || bool => IsTrue (temp = left) ? temp : temp || right; + // + left = temp.CreateReferenceExpression (ec, loc); + if (oper == Operator.LogicalAnd) { + expr = DynamicUnaryConversion.CreateIsFalse (ec, cond_args, loc); + cond_left = left; + } else { + expr = DynamicUnaryConversion.CreateIsTrue (ec, cond_args, loc); + cond_left = left; + } + + args.Add (new Argument (left)); + args.Add (new Argument (right)); + cond_right = new DynamicExpressionStatement (this, args, loc); + } else { + LocalVariable temp = LocalVariable.CreateCompilerGenerated (ec.BuiltinTypes.Bool, ec.CurrentBlock, loc); + + args.Add (new Argument (temp.CreateReferenceExpression (ec, loc).Resolve (ec))); + args.Add (new Argument (right)); + right = new DynamicExpressionStatement (this, args, loc); + + // + // bool && dynamic => (temp = left) ? temp && right : temp; + // bool || dynamic => (temp = left) ? temp : temp || right; + // + if (oper == Operator.LogicalAnd) { + cond_left = right; + cond_right = temp.CreateReferenceExpression (ec, loc); + } else { + cond_left = temp.CreateReferenceExpression (ec, loc); + cond_right = right; + } + + expr = new BooleanExpression (new SimpleAssign (temp.CreateReferenceExpression (ec, loc), left)); + } + + return new Conditional (expr, cond_left, cond_right, loc).Resolve (ec); + } + + args = new Arguments (2); + args.Add (new Argument (left)); + args.Add (new Argument (right)); + return new DynamicExpressionStatement (this, args, loc).Resolve (ec); + } + + if (ec.Module.Compiler.Settings.Version >= LanguageVersion.ISO_2 && + ((left.Type.IsNullableType && (right is NullLiteral || right.Type.IsNullableType || TypeSpec.IsValueType (right.Type))) || + (TypeSpec.IsValueType (left.Type) && right is NullLiteral) || + (right.Type.IsNullableType && (left is NullLiteral || left.Type.IsNullableType || TypeSpec.IsValueType (left.Type))) || + (TypeSpec.IsValueType (right.Type) && left is NullLiteral))) { + var lifted = new Nullable.LiftedBinaryOperator (oper, left, right, loc); + lifted.state = state; + return lifted.Resolve (ec); + } + + return DoResolveCore (ec, left, right); + } + + protected Expression DoResolveCore (ResolveContext ec, Expression left_orig, Expression right_orig) + { + Expression expr = ResolveOperator (ec); + if (expr == null) + Error_OperatorCannotBeApplied (ec, left_orig, right_orig); + + if (left == null || right == null) + throw new InternalErrorException ("Invalid conversion"); + + if (oper == Operator.BitwiseOr) + CheckBitwiseOrOnSignExtended (ec); + + return expr; + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + var le = left.MakeExpression (ctx); + var re = right.MakeExpression (ctx); + bool is_checked = ctx.HasSet (BuilderContext.Options.CheckedScope); + + switch (oper) { + case Operator.Addition: + return is_checked ? SLE.Expression.AddChecked (le, re) : SLE.Expression.Add (le, re); + case Operator.BitwiseAnd: + return SLE.Expression.And (le, re); + case Operator.BitwiseOr: + return SLE.Expression.Or (le, re); + case Operator.Division: + return SLE.Expression.Divide (le, re); + case Operator.Equality: + return SLE.Expression.Equal (le, re); + case Operator.ExclusiveOr: + return SLE.Expression.ExclusiveOr (le, re); + case Operator.GreaterThan: + return SLE.Expression.GreaterThan (le, re); + case Operator.GreaterThanOrEqual: + return SLE.Expression.GreaterThanOrEqual (le, re); + case Operator.Inequality: + return SLE.Expression.NotEqual (le, re); + case Operator.LeftShift: + return SLE.Expression.LeftShift (le, re); + case Operator.LessThan: + return SLE.Expression.LessThan (le, re); + case Operator.LessThanOrEqual: + return SLE.Expression.LessThanOrEqual (le, re); + case Operator.LogicalAnd: + return SLE.Expression.AndAlso (le, re); + case Operator.LogicalOr: + return SLE.Expression.OrElse (le, re); + case Operator.Modulus: + return SLE.Expression.Modulo (le, re); + case Operator.Multiply: + return is_checked ? SLE.Expression.MultiplyChecked (le, re) : SLE.Expression.Multiply (le, re); + case Operator.RightShift: + return SLE.Expression.RightShift (le, re); + case Operator.Subtraction: + return is_checked ? SLE.Expression.SubtractChecked (le, re) : SLE.Expression.Subtract (le, re); + default: + throw new NotImplementedException (oper.ToString ()); + } + } + + // + // D operator + (D x, D y) + // D operator - (D x, D y) + // + Expression ResolveOperatorDelegate (ResolveContext ec, TypeSpec l, TypeSpec r) + { + if (l != r && !TypeSpecComparer.Variant.IsEqual (r, l)) { + Expression tmp; + if (right.eclass == ExprClass.MethodGroup || r == InternalType.AnonymousMethod || r == InternalType.NullLiteral) { + tmp = Convert.ImplicitConversionRequired (ec, right, l, loc); + if (tmp == null) + return null; + right = tmp; + r = right.Type; + } else if (left.eclass == ExprClass.MethodGroup || (l == InternalType.AnonymousMethod || l == InternalType.NullLiteral)) { + tmp = Convert.ImplicitConversionRequired (ec, left, r, loc); + if (tmp == null) + return null; + left = tmp; + l = left.Type; + } else { + return null; + } + } + + MethodSpec method = null; + Arguments args = new Arguments (2); + args.Add (new Argument (left)); + args.Add (new Argument (right)); + + if (oper == Operator.Addition) { + method = ec.Module.PredefinedMembers.DelegateCombine.Resolve (loc); + } else if (oper == Operator.Subtraction) { + method = ec.Module.PredefinedMembers.DelegateRemove.Resolve (loc); + } + + if (method == null) + return new EmptyExpression (ec.BuiltinTypes.Decimal); + + MethodGroupExpr mg = MethodGroupExpr.CreatePredefined (method, ec.BuiltinTypes.Delegate, loc); + Expression expr = new UserOperatorCall (mg.BestCandidate, args, CreateExpressionTree, loc); + return new ClassCast (expr, l); + } + + // + // Enumeration operators + // + Expression ResolveOperatorEnum (ResolveContext ec, bool lenum, bool renum, TypeSpec ltype, TypeSpec rtype) + { + // + // bool operator == (E x, E y); + // bool operator != (E x, E y); + // bool operator < (E x, E y); + // bool operator > (E x, E y); + // bool operator <= (E x, E y); + // bool operator >= (E x, E y); + // + // E operator & (E x, E y); + // E operator | (E x, E y); + // E operator ^ (E x, E y); + // + // U operator - (E e, E f) + // E operator - (E e, U x) + // E operator - (U x, E e) // LAMESPEC: Not covered by the specification + // + // E operator + (E e, U x) + // E operator + (U x, E e) + // + Expression ltemp = left; + Expression rtemp = right; + TypeSpec underlying_type; + TypeSpec underlying_type_result; + TypeSpec res_type; + Expression expr; + + // + // LAMESPEC: There is never ambiguous conversion between enum operators + // the one which contains more enum parameters always wins even if there + // is an implicit conversion involved + // + if ((oper & (Operator.ComparisonMask | Operator.BitwiseMask)) != 0) { + if (renum) { + underlying_type = EnumSpec.GetUnderlyingType (rtype); + expr = Convert.ImplicitConversion (ec, left, rtype, loc); + if (expr == null) + return null; + + left = expr; + ltype = expr.Type; + } else if (lenum) { + underlying_type = EnumSpec.GetUnderlyingType (ltype); + expr = Convert.ImplicitConversion (ec, right, ltype, loc); + if (expr == null) + return null; + + right = expr; + rtype = expr.Type; + } else { + return null; + } + + if ((oper & Operator.BitwiseMask) != 0) { + res_type = ltype; + underlying_type_result = underlying_type; + } else { + res_type = null; + underlying_type_result = null; + } + } else if (oper == Operator.Subtraction) { + if (renum) { + underlying_type = EnumSpec.GetUnderlyingType (rtype); + if (ltype != rtype) { + expr = Convert.ImplicitConversion (ec, left, rtype, left.Location); + if (expr == null) { + expr = Convert.ImplicitConversion (ec, left, underlying_type, left.Location); + if (expr == null) + return null; + + res_type = rtype; + } else { + res_type = underlying_type; + } + + left = expr; + } else { + res_type = underlying_type; + } + + underlying_type_result = underlying_type; + } else if (lenum) { + underlying_type = EnumSpec.GetUnderlyingType (ltype); + expr = Convert.ImplicitConversion (ec, right, ltype, right.Location); + if (expr == null || expr is EnumConstant) { + expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location); + if (expr == null) + return null; + + res_type = ltype; + } else { + res_type = underlying_type; + } + + right = expr; + underlying_type_result = underlying_type; + } else { + return null; + } + } else if (oper == Operator.Addition) { + if (lenum) { + underlying_type = EnumSpec.GetUnderlyingType (ltype); + res_type = ltype; + + if (rtype != underlying_type && (state & (State.RightNullLifted | State.LeftNullLifted)) == 0) { + expr = Convert.ImplicitConversion (ec, right, underlying_type, right.Location); + if (expr == null) + return null; + + right = expr; + } + } else { + underlying_type = EnumSpec.GetUnderlyingType (rtype); + res_type = rtype; + if (ltype != underlying_type) { + expr = Convert.ImplicitConversion (ec, left, underlying_type, left.Location); + if (expr == null) + return null; + + left = expr; + } + } + + underlying_type_result = underlying_type; + } else { + return null; + } + + // Unwrap the constant correctly, so DoBinaryOperatorPromotion can do the magic + // with constants and expressions + if (left.Type != underlying_type) { + if (left is Constant) + left = ((Constant) left).ConvertExplicitly (false, underlying_type); + else + left = EmptyCast.Create (left, underlying_type); + } + + if (right.Type != underlying_type) { + if (right is Constant) + right = ((Constant) right).ConvertExplicitly (false, underlying_type); + else + right = EmptyCast.Create (right, underlying_type); + } + + // + // C# specification uses explicit cast syntax which means binary promotion + // should happen, however it seems that csc does not do that + // + if (!DoBinaryOperatorPromotion (ec)) { + left = ltemp; + right = rtemp; + return null; + } + + if (underlying_type_result != null && left.Type != underlying_type_result) { + enum_conversion = Convert.ExplicitNumericConversion (ec, new EmptyExpression (left.Type), underlying_type_result); + } + + expr = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryStandard, true, res_type); + if (expr == null) + return null; + + if (!IsCompound) + return expr; + + // + // Section: 7.16.2 + // + + // + // If the return type of the selected operator is implicitly convertible to the type of x + // + if (Convert.ImplicitConversionExists (ec, expr, ltype)) + return expr; + + // + // Otherwise, if the selected operator is a predefined operator, if the return type of the + // selected operator is explicitly convertible to the type of x, and if y is implicitly + // convertible to the type of x or the operator is a shift operator, then the operation + // is evaluated as x = (T)(x op y), where T is the type of x + // + expr = Convert.ExplicitConversion (ec, expr, ltype, loc); + if (expr == null) + return null; + + if (Convert.ImplicitConversionExists (ec, ltemp, ltype)) + return expr; + + return null; + } + + // + // 7.9.6 Reference type equality operators + // + Expression ResolveOperatorEquality (ResolveContext ec, TypeSpec l, TypeSpec r) + { + Expression result; + type = ec.BuiltinTypes.Bool; + + // + // a, Both operands are reference-type values or the value null + // b, One operand is a value of type T where T is a type-parameter and + // the other operand is the value null. Furthermore T does not have the + // value type constraint + // + // LAMESPEC: Very confusing details in the specification, basically any + // reference like type-parameter is allowed + // + var tparam_l = l as TypeParameterSpec; + var tparam_r = r as TypeParameterSpec; + if (tparam_l != null) { + if (right is NullLiteral && !tparam_l.HasSpecialStruct) { + left = new BoxedCast (left, ec.BuiltinTypes.Object); + return this; + } + + if (!tparam_l.IsReferenceType) + return null; + + l = tparam_l.GetEffectiveBase (); + left = new BoxedCast (left, l); + } else if (left is NullLiteral && tparam_r == null) { + if (!TypeSpec.IsReferenceType (r) || r.Kind == MemberKind.InternalCompilerType) + return null; + + return this; + } + + if (tparam_r != null) { + if (left is NullLiteral && !tparam_r.HasSpecialStruct) { + right = new BoxedCast (right, ec.BuiltinTypes.Object); + return this; + } + + if (!tparam_r.IsReferenceType) + return null; + + r = tparam_r.GetEffectiveBase (); + right = new BoxedCast (right, r); + } else if (right is NullLiteral) { + if (!TypeSpec.IsReferenceType (l) || l.Kind == MemberKind.InternalCompilerType) + return null; + + return this; + } + + // + // LAMESPEC: method groups can be compared when they convert to other side delegate + // + if (l.IsDelegate) { + if (right.eclass == ExprClass.MethodGroup) { + result = Convert.ImplicitConversion (ec, right, l, loc); + if (result == null) + return null; + + right = result; + r = l; + } else if (r.IsDelegate && l != r) { + return null; + } + } else if (left.eclass == ExprClass.MethodGroup && r.IsDelegate) { + result = Convert.ImplicitConversionRequired (ec, left, r, loc); + if (result == null) + return null; + + left = result; + l = r; + } + + // + // bool operator != (string a, string b) + // bool operator == (string a, string b) + // + // bool operator != (Delegate a, Delegate b) + // bool operator == (Delegate a, Delegate b) + // + // bool operator != (bool a, bool b) + // bool operator == (bool a, bool b) + // + // LAMESPEC: Reference equality comparison can apply to value types when + // they implement an implicit conversion to any of types above. + // + if (r.BuiltinType != BuiltinTypeSpec.Type.Object && l.BuiltinType != BuiltinTypeSpec.Type.Object) { + result = ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryEquality, false, null); + if (result != null) + return result; + } + + // + // bool operator != (object a, object b) + // bool operator == (object a, object b) + // + // An explicit reference conversion exists from the + // type of either operand to the type of the other operand. + // + + // Optimize common path + if (l == r) { + return l.Kind == MemberKind.InternalCompilerType || l.Kind == MemberKind.Struct ? null : this; + } + + if (!Convert.ExplicitReferenceConversionExists (l, r) && + !Convert.ExplicitReferenceConversionExists (r, l)) + return null; + + // Reject allowed explicit conversions like int->object + if (!TypeSpec.IsReferenceType (l) || !TypeSpec.IsReferenceType (r)) + return null; + + if (l.BuiltinType == BuiltinTypeSpec.Type.String || l.BuiltinType == BuiltinTypeSpec.Type.Delegate || MemberCache.GetUserOperator (l, CSharp.Operator.OpType.Equality, false) != null) + ec.Report.Warning (253, 2, loc, + "Possible unintended reference comparison. Consider casting the right side expression to type `{0}' to get value comparison", + l.GetSignatureForError ()); + + if (r.BuiltinType == BuiltinTypeSpec.Type.String || r.BuiltinType == BuiltinTypeSpec.Type.Delegate || MemberCache.GetUserOperator (r, CSharp.Operator.OpType.Equality, false) != null) + ec.Report.Warning (252, 2, loc, + "Possible unintended reference comparison. Consider casting the left side expression to type `{0}' to get value comparison", + r.GetSignatureForError ()); + + return this; + } + + + Expression ResolveOperatorPointer (ResolveContext ec, TypeSpec l, TypeSpec r) + { + // + // bool operator == (void* x, void* y); + // bool operator != (void* x, void* y); + // bool operator < (void* x, void* y); + // bool operator > (void* x, void* y); + // bool operator <= (void* x, void* y); + // bool operator >= (void* x, void* y); + // + if ((oper & Operator.ComparisonMask) != 0) { + Expression temp; + if (!l.IsPointer) { + temp = Convert.ImplicitConversion (ec, left, r, left.Location); + if (temp == null) + return null; + left = temp; + } + + if (!r.IsPointer) { + temp = Convert.ImplicitConversion (ec, right, l, right.Location); + if (temp == null) + return null; + right = temp; + } + + type = ec.BuiltinTypes.Bool; + return this; + } + + return ResolveOperatorPredefined (ec, ec.BuiltinTypes.OperatorsBinaryUnsafe, false, null); + } + + // + // Build-in operators method overloading + // + protected virtual Expression ResolveOperatorPredefined (ResolveContext ec, PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type) + { + PredefinedOperator best_operator = null; + TypeSpec l = left.Type; + TypeSpec r = right.Type; + Operator oper_mask = oper & ~Operator.ValuesOnlyMask; + + foreach (PredefinedOperator po in operators) { + if ((po.OperatorsMask & oper_mask) == 0) + continue; + + if (primitives_only) { + if (!po.IsPrimitiveApplicable (l, r)) + continue; + } else { + if (!po.IsApplicable (ec, left, right)) + continue; + } + + if (best_operator == null) { + best_operator = po; + if (primitives_only) + break; + + continue; + } + + best_operator = po.ResolveBetterOperator (ec, best_operator); + + if (best_operator == null) { + ec.Report.Error (34, loc, "Operator `{0}' is ambiguous on operands of type `{1}' and `{2}'", + OperName (oper), TypeManager.CSharpName (l), TypeManager.CSharpName (r)); + + best_operator = po; + break; + } + } + + if (best_operator == null) + return null; + + Expression expr = best_operator.ConvertResult (ec, this); + + // + // Optimize &/&& constant expressions with 0 value + // + if (oper == Operator.BitwiseAnd || oper == Operator.LogicalAnd) { + Constant rc = right as Constant; + Constant lc = left as Constant; + if (((lc != null && lc.IsDefaultValue) || (rc != null && rc.IsDefaultValue)) && !(this is Nullable.LiftedBinaryOperator)) { + // + // The result is a constant with side-effect + // + Constant side_effect = rc == null ? + new SideEffectConstant (lc, right, loc) : + new SideEffectConstant (rc, left, loc); + + return ReducedExpression.Create (side_effect, expr); + } + } + + if (enum_type == null) + return expr; + + // + // HACK: required by enum_conversion + // + expr.Type = enum_type; + return EmptyCast.Create (expr, enum_type); + } + + // + // Performs user-operator overloading + // + protected virtual Expression ResolveUserOperator (ResolveContext ec, Expression left, Expression right) + { + var op = ConvertBinaryToUserOperator (oper); + var l = left.Type; + if (l.IsNullableType) + l = Nullable.NullableInfo.GetUnderlyingType (l); + var r = right.Type; + if (r.IsNullableType) + r = Nullable.NullableInfo.GetUnderlyingType (r); + + IList left_operators = MemberCache.GetUserOperator (l, op, false); + IList right_operators = null; + + if (l != r) { + right_operators = MemberCache.GetUserOperator (r, op, false); + if (right_operators == null && left_operators == null) + return null; + } else if (left_operators == null) { + return null; + } + + Arguments args = new Arguments (2); + Argument larg = new Argument (left); + args.Add (larg); + Argument rarg = new Argument (right); + args.Add (rarg); + + // + // User-defined operator implementations always take precedence + // over predefined operator implementations + // + if (left_operators != null && right_operators != null) { + left_operators = CombineUserOperators (left_operators, right_operators); + } else if (right_operators != null) { + left_operators = right_operators; + } + + var res = new OverloadResolver (left_operators, OverloadResolver.Restrictions.ProbingOnly | + OverloadResolver.Restrictions.NoBaseMembers | OverloadResolver.Restrictions.BaseMembersIncluded, loc); + + var oper_method = res.ResolveOperator (ec, ref args); + if (oper_method == null) + return null; + + var llifted = (state & State.LeftNullLifted) != 0; + var rlifted = (state & State.RightNullLifted) != 0; + if ((Oper & Operator.EqualityMask) != 0) { + var parameters = oper_method.Parameters; + // LAMESPEC: No idea why this is not allowed + if ((left is Nullable.Unwrap || right is Nullable.Unwrap) && parameters.Types [0] != parameters.Types [1]) + return null; + + // Binary operation was lifted but we have found a user operator + // which requires value-type argument, we downgrade ourself back to + // binary operation + // LAMESPEC: The user operator is not called (it cannot be we are passing null to struct) + // but compilation succeeds + if ((llifted && !parameters.Types[0].IsStruct) || (rlifted && !parameters.Types[1].IsStruct)) { + state &= ~(State.LeftNullLifted | State.RightNullLifted); + } + } + + Expression oper_expr; + + // TODO: CreateExpressionTree is allocated every time + if ((oper & Operator.LogicalMask) != 0) { + oper_expr = new ConditionalLogicalOperator (oper_method, args, CreateExpressionTree, + oper == Operator.LogicalAnd, loc).Resolve (ec); + } else { + oper_expr = new UserOperatorCall (oper_method, args, CreateExpressionTree, loc); + } + + if (!llifted) + this.left = larg.Expr; + + if (!rlifted) + this.right = rarg.Expr; + + return oper_expr; + } + + // + // Merge two sets of user operators into one, they are mostly distinguish + // expect when they share base type and it contains an operator + // + static IList CombineUserOperators (IList left, IList right) + { + var combined = new List (left.Count + right.Count); + combined.AddRange (left); + foreach (var r in right) { + bool same = false; + foreach (var l in left) { + if (l.DeclaringType == r.DeclaringType) { + same = true; + break; + } + } + + if (!same) + combined.Add (r); + } + + return combined; + } + + void CheckOutOfRangeComparison (ResolveContext ec, Constant c, TypeSpec type) + { + if (c is IntegralConstant || c is CharConstant) { + try { + c.ConvertExplicitly (true, type); + } catch (OverflowException) { + ec.Report.Warning (652, 2, loc, + "A comparison between a constant and a variable is useless. The constant is out of the range of the variable type `{0}'", + TypeManager.CSharpName (type)); + } + } + } + + /// + /// EmitBranchable is called from Statement.EmitBoolExpression in the + /// context of a conditional bool expression. This function will return + /// false if it is was possible to use EmitBranchable, or true if it was. + /// + /// The expression's code is generated, and we will generate a branch to `target' + /// if the resulting expression value is equal to isTrue + /// + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + // + // This is more complicated than it looks, but its just to avoid + // duplicated tests: basically, we allow ==, !=, >, <, >= and <= + // but on top of that we want for == and != to use a special path + // if we are comparing against null + // + if ((oper & Operator.EqualityMask) != 0 && (left is Constant || right is Constant)) { + bool my_on_true = oper == Operator.Inequality ? on_true : !on_true; + + // + // put the constant on the rhs, for simplicity + // + if (left is Constant) { + Expression swap = right; + right = left; + left = swap; + } + + // + // brtrue/brfalse works with native int only + // + if (((Constant) right).IsZeroInteger && right.Type.BuiltinType != BuiltinTypeSpec.Type.Long && right.Type.BuiltinType != BuiltinTypeSpec.Type.ULong) { + left.EmitBranchable (ec, target, my_on_true); + return; + } + if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) { + // right is a boolean, and it's not 'false' => it is 'true' + left.EmitBranchable (ec, target, !my_on_true); + return; + } + + } else if (oper == Operator.LogicalAnd) { + + if (on_true) { + Label tests_end = ec.DefineLabel (); + + left.EmitBranchable (ec, tests_end, false); + right.EmitBranchable (ec, target, true); + ec.MarkLabel (tests_end); + } else { + // + // This optimizes code like this + // if (true && i > 4) + // + if (!(left is Constant)) + left.EmitBranchable (ec, target, false); + + if (!(right is Constant)) + right.EmitBranchable (ec, target, false); + } + + return; + + } else if (oper == Operator.LogicalOr){ + if (on_true) { + left.EmitBranchable (ec, target, true); + right.EmitBranchable (ec, target, true); + + } else { + Label tests_end = ec.DefineLabel (); + left.EmitBranchable (ec, tests_end, true); + right.EmitBranchable (ec, target, false); + ec.MarkLabel (tests_end); + } + + return; + + } else if ((oper & Operator.ComparisonMask) == 0) { + base.EmitBranchable (ec, target, on_true); + return; + } + + left.Emit (ec); + right.Emit (ec); + + TypeSpec t = left.Type; + bool is_float = IsFloat (t); + bool is_unsigned = is_float || IsUnsigned (t); + + switch (oper){ + case Operator.Equality: + if (on_true) + ec.Emit (OpCodes.Beq, target); + else + ec.Emit (OpCodes.Bne_Un, target); + break; + + case Operator.Inequality: + if (on_true) + ec.Emit (OpCodes.Bne_Un, target); + else + ec.Emit (OpCodes.Beq, target); + break; + + case Operator.LessThan: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Blt_Un, target); + else + ec.Emit (OpCodes.Blt, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Bge_Un, target); + else + ec.Emit (OpCodes.Bge, target); + break; + + case Operator.GreaterThan: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Bgt_Un, target); + else + ec.Emit (OpCodes.Bgt, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Ble_Un, target); + else + ec.Emit (OpCodes.Ble, target); + break; + + case Operator.LessThanOrEqual: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Ble_Un, target); + else + ec.Emit (OpCodes.Ble, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Bgt_Un, target); + else + ec.Emit (OpCodes.Bgt, target); + break; + + + case Operator.GreaterThanOrEqual: + if (on_true) + if (is_unsigned && !is_float) + ec.Emit (OpCodes.Bge_Un, target); + else + ec.Emit (OpCodes.Bge, target); + else + if (is_unsigned) + ec.Emit (OpCodes.Blt_Un, target); + else + ec.Emit (OpCodes.Blt, target); + break; + default: + throw new InternalErrorException (oper.ToString ()); + } + } + + public override void Emit (EmitContext ec) + { + EmitOperator (ec, left.Type); + } + + protected virtual void EmitOperator (EmitContext ec, TypeSpec l) + { + // + // Handle short-circuit operators differently + // than the rest + // + if ((oper & Operator.LogicalMask) != 0) { + Label load_result = ec.DefineLabel (); + Label end = ec.DefineLabel (); + + bool is_or = oper == Operator.LogicalOr; + left.EmitBranchable (ec, load_result, is_or); + right.Emit (ec); + ec.Emit (OpCodes.Br_S, end); + + ec.MarkLabel (load_result); + ec.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + ec.MarkLabel (end); + return; + } + + // + // Optimize zero-based operations which cannot be optimized at expression level + // + if (oper == Operator.Subtraction) { + var lc = left as IntegralConstant; + if (lc != null && lc.IsDefaultValue) { + right.Emit (ec); + ec.Emit (OpCodes.Neg); + return; + } + } + + left.Emit (ec); + right.Emit (ec); + EmitOperatorOpcode (ec, oper, l); + + // + // Nullable enum could require underlying type cast and we cannot simply wrap binary + // expression because that would wrap lifted binary operation + // + if (enum_conversion != null) + enum_conversion.Emit (ec); + } + + public override void EmitSideEffect (EmitContext ec) + { + if ((oper & Operator.LogicalMask) != 0 || + (ec.HasSet (EmitContext.Options.CheckedScope) && (oper == Operator.Multiply || oper == Operator.Addition || oper == Operator.Subtraction))) { + base.EmitSideEffect (ec); + } else { + left.EmitSideEffect (ec); + right.EmitSideEffect (ec); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Binary target = (Binary) t; + + target.left = left.Clone (clonectx); + target.right = right.Clone (clonectx); + } + + public Expression CreateCallSiteBinder (ResolveContext ec, Arguments args) + { + Arguments binder_args = new Arguments (4); + + MemberAccess sle = new MemberAccess (new MemberAccess ( + new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Linq", loc), "Expressions", loc); + + CSharpBinderFlags flags = 0; + if (ec.HasSet (ResolveContext.Options.CheckedScope)) + flags = CSharpBinderFlags.CheckedContext; + + if ((oper & Operator.LogicalMask) != 0) + flags |= CSharpBinderFlags.BinaryOperationLogical; + + binder_args.Add (new Argument (new EnumConstant (new IntLiteral (ec.BuiltinTypes, (int) flags, loc), ec.Module.PredefinedTypes.BinderFlags.Resolve ()))); + binder_args.Add (new Argument (new MemberAccess (new MemberAccess (sle, "ExpressionType", loc), GetOperatorExpressionTypeName (), loc))); + binder_args.Add (new Argument (new TypeOf (ec.CurrentType, loc))); + binder_args.Add (new Argument (new ImplicitlyTypedArrayCreation (args.CreateDynamicBinderArguments (ec), loc))); + + return new Invocation (new MemberAccess (new TypeExpression (ec.Module.PredefinedTypes.Binder.TypeSpec, loc), "BinaryOperation", loc), binder_args); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return CreateExpressionTree (ec, null); + } + + Expression CreateExpressionTree (ResolveContext ec, Expression method) + { + string method_name; + bool lift_arg = false; + + switch (oper) { + case Operator.Addition: + if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type)) + method_name = "AddChecked"; + else + method_name = "Add"; + break; + case Operator.BitwiseAnd: + method_name = "And"; + break; + case Operator.BitwiseOr: + method_name = "Or"; + break; + case Operator.Division: + method_name = "Divide"; + break; + case Operator.Equality: + method_name = "Equal"; + lift_arg = true; + break; + case Operator.ExclusiveOr: + method_name = "ExclusiveOr"; + break; + case Operator.GreaterThan: + method_name = "GreaterThan"; + lift_arg = true; + break; + case Operator.GreaterThanOrEqual: + method_name = "GreaterThanOrEqual"; + lift_arg = true; + break; + case Operator.Inequality: + method_name = "NotEqual"; + lift_arg = true; + break; + case Operator.LeftShift: + method_name = "LeftShift"; + break; + case Operator.LessThan: + method_name = "LessThan"; + lift_arg = true; + break; + case Operator.LessThanOrEqual: + method_name = "LessThanOrEqual"; + lift_arg = true; + break; + case Operator.LogicalAnd: + method_name = "AndAlso"; + break; + case Operator.LogicalOr: + method_name = "OrElse"; + break; + case Operator.Modulus: + method_name = "Modulo"; + break; + case Operator.Multiply: + if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type)) + method_name = "MultiplyChecked"; + else + method_name = "Multiply"; + break; + case Operator.RightShift: + method_name = "RightShift"; + break; + case Operator.Subtraction: + if (method == null && ec.HasSet (ResolveContext.Options.CheckedScope) && !IsFloat (type)) + method_name = "SubtractChecked"; + else + method_name = "Subtract"; + break; + + default: + throw new InternalErrorException ("Unknown expression tree binary operator " + oper); + } + + Arguments args = new Arguments (2); + args.Add (new Argument (left.CreateExpressionTree (ec))); + args.Add (new Argument (right.CreateExpressionTree (ec))); + if (method != null) { + if (lift_arg) + args.Add (new Argument (new BoolLiteral (ec.BuiltinTypes, false, loc))); + + args.Add (new Argument (method)); + } + + return CreateExpressionFactoryCall (ec, method_name, args); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + // + // Represents the operation a + b [+ c [+ d [+ ...]]], where a is a string + // b, c, d... may be strings or objects. + // + public class StringConcat : Expression + { + Arguments arguments; + + StringConcat (Location loc) + { + this.loc = loc; + arguments = new Arguments (2); + } + + public static StringConcat Create (ResolveContext rc, Expression left, Expression right, Location loc) + { + if (left.eclass == ExprClass.Unresolved || right.eclass == ExprClass.Unresolved) + throw new ArgumentException (); + + var s = new StringConcat (loc); + s.type = rc.BuiltinTypes.String; + s.eclass = ExprClass.Value; + + s.Append (rc, left); + s.Append (rc, right); + return s; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Argument arg = arguments [0]; + return CreateExpressionAddCall (ec, arg, arg.CreateExpressionTree (ec), 1); + } + + // + // Creates nested calls tree from an array of arguments used for IL emit + // + Expression CreateExpressionAddCall (ResolveContext ec, Argument left, Expression left_etree, int pos) + { + Arguments concat_args = new Arguments (2); + Arguments add_args = new Arguments (3); + + concat_args.Add (left); + add_args.Add (new Argument (left_etree)); + + concat_args.Add (arguments [pos]); + add_args.Add (new Argument (arguments [pos].CreateExpressionTree (ec))); + + var methods = GetConcatMethodCandidates (); + if (methods == null) + return null; + + var res = new OverloadResolver (methods, OverloadResolver.Restrictions.NoBaseMembers, loc); + var method = res.ResolveMember (ec, ref concat_args); + if (method == null) + return null; + + add_args.Add (new Argument (new TypeOfMethod (method, loc))); + + Expression expr = CreateExpressionFactoryCall (ec, "Add", add_args); + if (++pos == arguments.Count) + return expr; + + left = new Argument (new EmptyExpression (method.ReturnType)); + return CreateExpressionAddCall (ec, left, expr, pos); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + void Append (ResolveContext rc, Expression operand) + { + // + // Constant folding + // + StringConstant sc = operand as StringConstant; + if (sc != null) { + if (arguments.Count != 0) { + Argument last_argument = arguments [arguments.Count - 1]; + StringConstant last_expr_constant = last_argument.Expr as StringConstant; + if (last_expr_constant != null) { + last_argument.Expr = new StringConstant (rc.BuiltinTypes, last_expr_constant.Value + sc.Value, sc.Location); + return; + } + } + } else { + // + // Multiple (3+) concatenation are resolved as multiple StringConcat instances + // + StringConcat concat_oper = operand as StringConcat; + if (concat_oper != null) { + arguments.AddRange (concat_oper.arguments); + return; + } + } + + arguments.Add (new Argument (operand)); + } + + IList GetConcatMethodCandidates () + { + return MemberCache.FindMembers (type, "Concat", true); + } + + public override void Emit (EmitContext ec) + { + var members = GetConcatMethodCandidates (); + var res = new OverloadResolver (members, OverloadResolver.Restrictions.NoBaseMembers, loc); + var method = res.ResolveMember (new ResolveContext (ec.MemberContext), ref arguments); + if (method != null) + Invocation.EmitCall (ec, null, method, arguments, loc); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + if (arguments.Count != 2) + throw new NotImplementedException ("arguments.Count != 2"); + + var concat = typeof (string).GetMethod ("Concat", new[] { typeof (object), typeof (object) }); + return SLE.Expression.Add (arguments[0].Expr.MakeExpression (ctx), arguments[1].Expr.MakeExpression (ctx), concat); + } + } + + // + // User-defined conditional logical operator + // + public class ConditionalLogicalOperator : UserOperatorCall { + readonly bool is_and; + Expression oper_expr; + + public ConditionalLogicalOperator (MethodSpec oper, Arguments arguments, Func expr_tree, bool is_and, Location loc) + : base (oper, arguments, expr_tree, loc) + { + this.is_and = is_and; + eclass = ExprClass.Unresolved; + } + + protected override Expression DoResolve (ResolveContext ec) + { + AParametersCollection pd = oper.Parameters; + if (!TypeSpecComparer.IsEqual (type, pd.Types[0]) || !TypeSpecComparer.IsEqual (type, pd.Types[1])) { + ec.Report.Error (217, loc, + "A user-defined operator `{0}' must have parameters and return values of the same type in order to be applicable as a short circuit operator", + oper.GetSignatureForError ()); + return null; + } + + Expression left_dup = new EmptyExpression (type); + Expression op_true = GetOperatorTrue (ec, left_dup, loc); + Expression op_false = GetOperatorFalse (ec, left_dup, loc); + if (op_true == null || op_false == null) { + ec.Report.Error (218, loc, + "The type `{0}' must have operator `true' and operator `false' defined when `{1}' is used as a short circuit operator", + TypeManager.CSharpName (type), oper.GetSignatureForError ()); + return null; + } + + oper_expr = is_and ? op_false : op_true; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + Label end_target = ec.DefineLabel (); + + // + // Emit and duplicate left argument + // + arguments [0].Expr.Emit (ec); + ec.Emit (OpCodes.Dup); + arguments.RemoveAt (0); + + oper_expr.EmitBranchable (ec, end_target, true); + base.Emit (ec); + ec.MarkLabel (end_target); + } + } + + public class PointerArithmetic : Expression { + Expression left, right; + Binary.Operator op; + + // + // We assume that `l' is always a pointer + // + public PointerArithmetic (Binary.Operator op, Expression l, Expression r, TypeSpec t, Location loc) + { + type = t; + this.loc = loc; + left = l; + right = r; + this.op = op; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + + var pc = left.Type as PointerContainer; + if (pc != null && pc.Element.Kind == MemberKind.Void) { + Error_VoidPointerOperation (ec); + return null; + } + + return this; + } + + public override void Emit (EmitContext ec) + { + TypeSpec op_type = left.Type; + + // It must be either array or fixed buffer + TypeSpec element; + if (TypeManager.HasElementType (op_type)) { + element = TypeManager.GetElementType (op_type); + } else { + FieldExpr fe = left as FieldExpr; + if (fe != null) + element = ((FixedFieldSpec) (fe.Spec)).ElementType; + else + element = op_type; + } + + int size = BuiltinTypeSpec.GetSize(element); + TypeSpec rtype = right.Type; + + if ((op & Binary.Operator.SubtractionMask) != 0 && rtype.IsPointer){ + // + // handle (pointer - pointer) + // + left.Emit (ec); + right.Emit (ec); + ec.Emit (OpCodes.Sub); + + if (size != 1){ + if (size == 0) + ec.Emit (OpCodes.Sizeof, element); + else + ec.EmitInt (size); + ec.Emit (OpCodes.Div); + } + ec.Emit (OpCodes.Conv_I8); + } else { + // + // handle + and - on (pointer op int) + // + Constant left_const = left as Constant; + if (left_const != null) { + // + // Optimize ((T*)null) pointer operations + // + if (left_const.IsDefaultValue) { + left = EmptyExpression.Null; + } else { + left_const = null; + } + } + + left.Emit (ec); + + var right_const = right as Constant; + if (right_const != null) { + // + // Optimize 0-based arithmetic + // + if (right_const.IsDefaultValue) + return; + + if (size != 0) + right = new IntConstant (ec.BuiltinTypes, size, right.Location); + else + right = new SizeOf (new TypeExpression (element, right.Location), right.Location); + + // TODO: Should be the checks resolve context sensitive? + ResolveContext rc = new ResolveContext (ec.MemberContext, ResolveContext.Options.UnsafeScope); + right = new Binary (Binary.Operator.Multiply, right, right_const, loc).Resolve (rc); + if (right == null) + return; + } + + right.Emit (ec); + switch (rtype.BuiltinType) { + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + ec.Emit (OpCodes.Conv_I); + break; + case BuiltinTypeSpec.Type.UInt: + ec.Emit (OpCodes.Conv_U); + break; + } + + if (right_const == null && size != 1){ + if (size == 0) + ec.Emit (OpCodes.Sizeof, element); + else + ec.EmitInt (size); + if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long || rtype.BuiltinType == BuiltinTypeSpec.Type.ULong) + ec.Emit (OpCodes.Conv_I8); + + Binary.EmitOperatorOpcode (ec, Binary.Operator.Multiply, rtype); + } + + if (left_const == null) { + if (rtype.BuiltinType == BuiltinTypeSpec.Type.Long) + ec.Emit (OpCodes.Conv_I); + else if (rtype.BuiltinType == BuiltinTypeSpec.Type.ULong) + ec.Emit (OpCodes.Conv_U); + + Binary.EmitOperatorOpcode (ec, op, op_type); + } + } + } + } + + // + // A boolean-expression is an expression that yields a result + // of type bool + // + public class BooleanExpression : ShimExpression + { + public BooleanExpression (Expression expr) + : base (expr) + { + this.loc = expr.Location; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + // TODO: We should emit IsTrue (v4) instead of direct user operator + // call but that would break csc compatibility + return base.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // A boolean-expression is required to be of a type + // that can be implicitly converted to bool or of + // a type that implements operator true + + expr = expr.Resolve (ec); + if (expr == null) + return null; + + Assign ass = expr as Assign; + if (ass != null && ass.Source is Constant) { + ec.Report.Warning (665, 3, loc, + "Assignment in conditional expression is always constant. Did you mean to use `==' instead ?"); + } + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) + return expr; + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return DynamicUnaryConversion.CreateIsTrue (ec, args, loc).Resolve (ec); + } + + type = ec.BuiltinTypes.Bool; + Expression converted = Convert.ImplicitConversion (ec, expr, type, loc); + if (converted != null) + return converted; + + // + // If no implicit conversion to bool exists, try using `operator true' + // + converted = GetOperatorTrue (ec, expr, loc); + if (converted == null) { + expr.Error_ValueCannotBeConverted (ec, loc, type, false); + return null; + } + + return converted; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class BooleanExpressionFalse : Unary + { + public BooleanExpressionFalse (Expression expr) + : base (Operator.LogicalNot, expr, expr.Location) + { + } + + protected override Expression ResolveOperator (ResolveContext ec, Expression expr) + { + return GetOperatorFalse (ec, expr, loc) ?? base.ResolveOperator (ec, expr); + } + } + + /// + /// Implements the ternary conditional operator (?:) + /// + public class Conditional : Expression { + Expression expr, true_expr, false_expr; + + public Conditional (Expression expr, Expression true_expr, Expression false_expr, Location loc) + { + this.expr = expr; + this.true_expr = true_expr; + this.false_expr = false_expr; + this.loc = loc; + } + + public Expression Expr { + get { + return expr; + } + } + + public Expression TrueExpr { + get { + return true_expr; + } + } + + public Expression FalseExpr { + get { + return false_expr; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (3); + args.Add (new Argument (expr.CreateExpressionTree (ec))); + args.Add (new Argument (true_expr.CreateExpressionTree (ec))); + args.Add (new Argument (false_expr.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, "Condition", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + true_expr = true_expr.Resolve (ec); + false_expr = false_expr.Resolve (ec); + + if (true_expr == null || false_expr == null || expr == null) + return null; + + eclass = ExprClass.Value; + TypeSpec true_type = true_expr.Type; + TypeSpec false_type = false_expr.Type; + type = true_type; + + // + // First, if an implicit conversion exists from true_expr + // to false_expr, then the result type is of type false_expr.Type + // + if (!TypeSpecComparer.IsEqual (true_type, false_type)) { + Expression conv = Convert.ImplicitConversion (ec, true_expr, false_type, loc); + if (conv != null && true_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic) { + // + // Check if both can convert implicitly to each other's type + // + type = false_type; + + if (false_type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && Convert.ImplicitConversion (ec, false_expr, true_type, loc) != null) { + ec.Report.Error (172, true_expr.Location, + "Type of conditional expression cannot be determined as `{0}' and `{1}' convert implicitly to each other", + true_type.GetSignatureForError (), false_type.GetSignatureForError ()); + return null; + } + + true_expr = conv; + } else if ((conv = Convert.ImplicitConversion (ec, false_expr, true_type, loc)) != null) { + false_expr = conv; + } else { + ec.Report.Error (173, true_expr.Location, + "Type of conditional expression cannot be determined because there is no implicit conversion between `{0}' and `{1}'", + TypeManager.CSharpName (true_type), TypeManager.CSharpName (false_type)); + return null; + } + } + + // Dead code optimalization + Constant c = expr as Constant; + if (c != null){ + bool is_false = c.IsDefaultValue; + ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected"); + return ReducedExpression.Create ( + is_false ? false_expr : true_expr, this, + false_expr is Constant && true_expr is Constant).Resolve (ec); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + Label false_target = ec.DefineLabel (); + Label end_target = ec.DefineLabel (); + + expr.EmitBranchable (ec, false_target, false); + true_expr.Emit (ec); + + if (type.IsInterface) { + LocalBuilder temp = ec.GetTemporaryLocal (type); + ec.Emit (OpCodes.Stloc, temp); + ec.Emit (OpCodes.Ldloc, temp); + ec.FreeTemporaryLocal (temp, type); + } + + ec.Emit (OpCodes.Br, end_target); + ec.MarkLabel (false_target); + false_expr.Emit (ec); + ec.MarkLabel (end_target); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Conditional target = (Conditional) t; + + target.expr = expr.Clone (clonectx); + target.true_expr = true_expr.Clone (clonectx); + target.false_expr = false_expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference { + LocalTemporary temp; + + #region Abstract + public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae); + + 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 + // + protected abstract ILocalVariable Variable { get; } + + // + // Variable flow-analysis data + // + public abstract VariableInfo VariableInfo { get; } + #endregion + + public virtual void AddressOf (EmitContext ec, AddressOp mode) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.AddressOf (ec, mode); + return; + } + + Variable.EmitAddressOf (ec); + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + if (IsLockedByStatement) { + rc.Report.Warning (728, 2, loc, + "Possibly incorrect assignment to `{0}' which is the argument to a using or lock statement", + Name); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public override void EmitSideEffect (EmitContext ec) + { + // do nothing + } + + // + // This method is used by parameters that are references, that are + // being passed as references: we only want to pass the pointer (that + // is already stored in the parameter, not the address of the pointer, + // and not the value of the variable). + // + public void EmitLoad (EmitContext ec) + { + Variable.Emit (ec); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.Emit (ec, leave_copy); + return; + } + + EmitLoad (ec); + + if (IsRef) { + // + // If we are a reference, we loaded on the stack a pointer + // Now lets load the real value + // + ec.EmitLoadFromPtr (type); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + + if (IsRef) { + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, + bool prepare_for_load) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + hv.EmitAssign (ec, source, leave_copy, prepare_for_load); + return; + } + + New n_source = source as New; + if (n_source != null) { + if (!n_source.Emit (ec, this)) { + if (leave_copy) { + EmitLoad (ec); + if (IsRef) + ec.EmitLoadFromPtr (type); + } + return; + } + } else { + if (IsRef) + EmitLoad (ec); + + source.Emit (ec); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + if (IsRef) { + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + + if (IsRef) + ec.EmitStoreFromPtr (type); + else + Variable.EmitAssign (ec); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + + public HoistedVariable GetHoistedVariable (ResolveContext rc) + { + return GetHoistedVariable (rc.CurrentAnonymousMethod); + } + + public HoistedVariable GetHoistedVariable (EmitContext ec) + { + return GetHoistedVariable (ec.CurrentAnonymousMethod); + } + + public override string GetSignatureForError () + { + return Name; + } + + public bool IsHoisted { + get { return GetHoistedVariable ((AnonymousExpression) null) != null; } + } + } + + // + // Resolved reference to a local variable + // + public class LocalVariableReference : VariableReference + { + public LocalVariable local_info; + + public LocalVariableReference (LocalVariable li, Location l) + { + this.local_info = li; + loc = l; + } + + public override VariableInfo VariableInfo { + get { return local_info.VariableInfo; } + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return local_info.HoistedVariant; + } + + #region Properties + + // + // A local variable is always fixed + // + public override bool IsFixed { + get { + return true; + } + } + + public override bool IsLockedByStatement { + get { + return local_info.IsLocked; + } + set { + local_info.IsLocked = value; + } + } + + public override bool IsRef { + get { return false; } + } + + public override string Name { + get { return local_info.Name; } + } + + #endregion + + public bool VerifyAssigned (ResolveContext ec) + { + VariableInfo variable_info = local_info.VariableInfo; + return variable_info == null || variable_info.IsAssigned (ec, loc); + } + + public override void SetHasAddressTaken () + { + local_info.AddressTaken = true; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (); + + Arguments arg = new Arguments (1); + arg.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", arg); + } + + void DoResolveBase (ResolveContext ec) + { + VerifyAssigned (ec); + + // + // If we are referencing a variable from the external block + // flag it for capturing + // + if (ec.MustCaptureVariable (local_info)) { + if (local_info.AddressTaken) { + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc); + } else if (local_info.IsFixed) { + ec.Report.Error (1764, loc, + "Cannot use fixed local `{0}' inside an anonymous method, lambda expression or query expression", + GetSignatureForError ()); + } + + if (ec.IsVariableCapturingRequired) { + AnonymousMethodStorey storey = local_info.Block.Explicit.CreateAnonymousMethodStorey (ec); + storey.CaptureLocalVariable (ec, local_info); + } + } + + eclass = ExprClass.Variable; + type = local_info.Type; + } + + protected override Expression DoResolve (ResolveContext ec) + { + local_info.SetIsUsed (); + + DoResolveBase (ec); + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + // is out param + if (right_side == EmptyExpression.OutAccess) + local_info.SetIsUsed (); + + if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) { + int code; + string msg; + if (right_side == EmptyExpression.OutAccess) { + code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberAccess) { + code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'"; + } else if (right_side == EmptyExpression.LValueMemberOutAccess) { + code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'"; + } else if (right_side == EmptyExpression.UnaryAddress) { + code = 459; msg = "Cannot take the address of {1} `{0}'"; + } else { + code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'"; + } + ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ()); + } else if (VariableInfo != null) { + VariableInfo.SetAssigned (ec); + } + + DoResolveBase (ec); + + return base.DoResolveLValue (ec, right_side); + } + + public override int GetHashCode () + { + return local_info.GetHashCode (); + } + + public override bool Equals (object obj) + { + LocalVariableReference lvr = obj as LocalVariableReference; + if (lvr == null) + return false; + + return local_info == lvr.local_info; + } + + protected override ILocalVariable Variable { + get { return local_info; } + } + + public override string ToString () + { + return String.Format ("{0} ({1}:{2})", GetType (), Name, loc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This represents a reference to a parameter in the intermediate + /// representation. + /// + public class ParameterReference : VariableReference + { + protected ParametersBlock.ParameterInfo pi; + + public ParameterReference (ParametersBlock.ParameterInfo pi, Location loc) + { + this.pi = pi; + this.loc = loc; + } + + #region Properties + + public override bool IsLockedByStatement { + get { + return pi.IsLocked; + } + set { + pi.IsLocked = value; + } + } + + public override bool IsRef { + get { return (pi.Parameter.ModFlags & Parameter.Modifier.ISBYREF) != 0; } + } + + bool HasOutModifier { + get { return pi.Parameter.ModFlags == Parameter.Modifier.OUT; } + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return pi.Parameter.HoistedVariant; + } + + // + // A ref or out parameter is classified as a moveable variable, even + // if the argument given for the parameter is a fixed variable + // + public override bool IsFixed { + get { return !IsRef; } + } + + public override string Name { + get { return Parameter.Name; } + } + + public Parameter Parameter { + get { return pi.Parameter; } + } + + public override VariableInfo VariableInfo { + get { return pi.VariableInfo; } + } + + protected override ILocalVariable Variable { + get { return Parameter; } + } + + #endregion + + public bool IsAssigned (ResolveContext ec, Location loc) + { + // HACK: Variables are not captured in probing mode + if (ec.IsInProbingMode) + return true; + + if (!ec.DoFlowAnalysis || !HasOutModifier || ec.CurrentBranching.IsAssigned (VariableInfo)) + return true; + + ec.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name); + return false; + } + + public override void SetHasAddressTaken () + { + Parameter.HasAddressTaken = true; + } + + void SetAssigned (ResolveContext ec) + { + if (HasOutModifier && ec.DoFlowAnalysis) + ec.CurrentBranching.SetAssigned (VariableInfo); + } + + bool DoResolveBase (ResolveContext ec) + { + if (eclass != ExprClass.Unresolved) + return true; + + type = pi.ParameterType; + eclass = ExprClass.Variable; + + // + // If we are referencing a parameter from the external block + // flag it for capturing + // + if (ec.MustCaptureVariable (pi)) { + if (Parameter.HasAddressTaken) + AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, this, loc); + + if (IsRef) { + ec.Report.Error (1628, loc, + "Parameter `{0}' cannot be used inside `{1}' when using `ref' or `out' modifier", + Name, ec.CurrentAnonymousMethod.ContainerType); + } + + if (ec.IsVariableCapturingRequired && !pi.Block.ParametersBlock.IsExpressionTree) { + AnonymousMethodStorey storey = pi.Block.Explicit.CreateAnonymousMethodStorey (ec); + storey.CaptureParameter (ec, this); + } + } + + return true; + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + public override bool Equals (object obj) + { + ParameterReference pr = obj as ParameterReference; + if (pr == null) + return false; + + 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 + return; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (); + + return Parameter.ExpressionTreeVariableReference (); + } + + // + // Notice that for ref/out parameters, the type exposed is not the + // same type exposed externally. + // + // for "ref int a": + // externally we expose "int&" + // here we expose "int". + // + // We record this in "is_ref". This means that the type system can treat + // the type as it is expected, but when we generate the code, we generate + // the alternate kind of code. + // + protected override Expression DoResolve (ResolveContext ec) + { + 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; + + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + if (!DoResolveBase (ec)) + return null; + + SetAssigned (ec); + return base.DoResolveLValue (ec, right_side); + } + + static public void EmitLdArg (EmitContext ec, int x) + { + switch (x) { + case 0: ec.Emit (OpCodes.Ldarg_0); break; + case 1: ec.Emit (OpCodes.Ldarg_1); break; + case 2: ec.Emit (OpCodes.Ldarg_2); break; + case 3: ec.Emit (OpCodes.Ldarg_3); break; + default: + if (x > byte.MaxValue) + ec.Emit (OpCodes.Ldarg, x); + else + ec.Emit (OpCodes.Ldarg_S, (byte) x); + break; + } + } + } + + /// + /// Invocation of methods or delegates. + /// + public class Invocation : ExpressionStatement + { + protected Arguments arguments; + protected Expression expr; + protected MethodGroupExpr mg; + + // + // arguments is an ArrayList, but we do not want to typecast, + // as it might be null. + // + public Invocation (Expression expr, Arguments arguments) + { + this.expr = expr; + this.arguments = arguments; + if (expr != null) + loc = expr.Location; + } + + #region Properties + public Arguments Arguments { + get { + return arguments; + } + } + + public Expression Expression { + get { + return expr; + } + } + #endregion + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Invocation target = (Invocation) t; + + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + + target.expr = expr.Clone (clonectx); + } + + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Expression instance = mg.IsInstance ? + mg.InstanceExpression.CreateExpressionTree (ec) : + new NullLiteral (loc); + + var args = Arguments.CreateForExpressionTree (ec, arguments, + instance, + mg.CreateExpressionTree (ec)); + + return CreateExpressionFactoryCall (ec, "Call", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression member_expr; + var atn = expr as ATypeNameExpression; + if (atn != null) { + member_expr = atn.LookupNameExpression (ec, MemberLookupRestrictions.InvocableOnly | MemberLookupRestrictions.ReadAccess); + if (member_expr != null) + member_expr = member_expr.Resolve (ec); + } else { + member_expr = expr.Resolve (ec, ResolveFlags.VariableOrValue | ResolveFlags.MethodGroup); + } + + if (member_expr == null) + return null; + + // + // Next, evaluate all the expressions in the argument list + // + bool dynamic_arg = false; + if (arguments != null) + arguments.Resolve (ec, out dynamic_arg); + + TypeSpec expr_type = member_expr.Type; + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return DoResolveDynamic (ec, member_expr); + + mg = member_expr as MethodGroupExpr; + Expression invoke = null; + + if (mg == null) { + if (expr_type != null && TypeManager.IsDelegateType (expr_type)) { + invoke = new DelegateInvocation (member_expr, arguments, loc); + invoke = invoke.Resolve (ec); + if (invoke == null || !dynamic_arg) + return invoke; + } else { + if (member_expr is RuntimeValueExpression) { + ec.Report.Error (Report.RuntimeErrorId, loc, "Cannot invoke a non-delegate type `{0}'", + member_expr.Type.GetSignatureForError ()); ; + return null; + } + + MemberExpr me = member_expr as MemberExpr; + if (me == null) { + member_expr.Error_UnexpectedKind (ec, ResolveFlags.MethodGroup, loc); + return null; + } + + ec.Report.Error (1955, loc, "The member `{0}' cannot be used as method or delegate", + member_expr.GetSignatureForError ()); + return null; + } + } + + if (invoke == null) { + mg = DoResolveOverload (ec); + if (mg == null) + return null; + } + + if (dynamic_arg) + return DoResolveDynamic (ec, member_expr); + + var method = mg.BestCandidate; + type = mg.BestCandidateReturnType; + + if (arguments == null && method.DeclaringType.BuiltinType == BuiltinTypeSpec.Type.Object && method.Name == Destructor.MetadataName) { + if (mg.IsBase) + ec.Report.Error (250, loc, "Do not directly call your base class Finalize method. It is called automatically from your destructor"); + else + ec.Report.Error (245, loc, "Destructors and object.Finalize cannot be called directly. Consider calling IDisposable.Dispose if available"); + return null; + } + + IsSpecialMethodInvocation (ec, method, loc); + + eclass = ExprClass.Value; + return this; + } + + protected virtual Expression DoResolveDynamic (ResolveContext ec, Expression memberExpr) + { + Arguments args; + DynamicMemberBinder dmb = memberExpr as DynamicMemberBinder; + if (dmb != null) { + args = dmb.Arguments; + if (arguments != null) + args.AddRange (arguments); + } else if (mg == null) { + if (arguments == null) + args = new Arguments (1); + else + args = arguments; + + args.Insert (0, new Argument (memberExpr)); + this.expr = null; + } else { + if (mg.IsBase) { + ec.Report.Error (1971, loc, + "The base call to method `{0}' cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access", + mg.Name); + return null; + } + + if (arguments == null) + args = new Arguments (1); + else + args = arguments; + + MemberAccess ma = expr as MemberAccess; + if (ma != null) { + var left_type = ma.LeftExpression as TypeExpr; + if (left_type != null) { + args.Insert (0, new Argument (new TypeOf (left_type.Type, loc).Resolve (ec), Argument.AType.DynamicTypeName)); + } else { + // + // Any value type has to be pass as by-ref to get back the same + // instance on which the member was called + // + var mod = TypeSpec.IsValueType (ma.LeftExpression.Type) ? Argument.AType.Ref : Argument.AType.None; + args.Insert (0, new Argument (ma.LeftExpression.Resolve (ec), mod)); + } + } else { // is SimpleName + if (ec.IsStatic) { + args.Insert (0, new Argument (new TypeOf (ec.CurrentType, loc).Resolve (ec), Argument.AType.DynamicTypeName)); + } else { + args.Insert (0, new Argument (new This (loc).Resolve (ec))); + } + } + } + + return new DynamicInvocation (expr as ATypeNameExpression, args, loc).Resolve (ec); + } + + protected virtual MethodGroupExpr DoResolveOverload (ResolveContext ec) + { + return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None); + } + + static MetaType[] GetVarargsTypes (MethodSpec mb, Arguments arguments) + { + AParametersCollection pd = mb.Parameters; + + Argument a = arguments[pd.Count - 1]; + Arglist list = (Arglist) a.Expr; + + return list.ArgumentTypes; + } + + // + // 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 + // + public static bool IsMemberInvocable (MemberSpec member) + { + switch (member.Kind) { + case MemberKind.Event: + return true; + case MemberKind.Field: + case MemberKind.Property: + var m = member as IInterfaceMemberSpec; + return m.MemberType.IsDelegate || m.MemberType.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + default: + return false; + } + } + + public static bool IsSpecialMethodInvocation (ResolveContext ec, MethodSpec method, Location loc) + { + if (!method.IsReservedMethod) + return false; + + if (ec.HasSet (ResolveContext.Options.InvokeSpecialName) || ec.CurrentMemberDefinition.IsCompilerGenerated) + return false; + + ec.Report.SymbolRelatedToPreviousError (method); + ec.Report.Error (571, loc, "`{0}': cannot explicitly call operator or accessor", + method.GetSignatureForError ()); + + return true; + } + + // + // Used to decide whether call or callvirt is needed + // + static bool IsVirtualCallRequired (Expression instance, MethodSpec method) + { + // + // There are 2 scenarious where we emit callvirt + // + // Case 1: A method is virtual and it's not used to call base + // Case 2: A method instance expression can be null. In this casen callvirt ensures + // correct NRE exception when the method is called + // + var decl_type = method.DeclaringType; + if (decl_type.IsStruct || decl_type.IsEnum) + return false; + + if (instance is BaseThis) + return false; + + // + // It's non-virtual and will never be null + // + if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation)) + return false; + + return true; + } + + /// + /// is_base tells whether we want to force the use of the `call' + /// opcode instead of using callvirt. Call is required to call + /// a specific method, while callvirt will always use the most + /// recent method in the vtable. + /// + /// is_static tells whether this is an invocation on a static method + /// + /// instance_expr is an expression that represents the instance + /// it must be non-null if is_static is false. + /// + /// method is the method to invoke. + /// + /// Arguments is the list of arguments to pass to the method or constructor. + /// + public static void EmitCall (EmitContext ec, Expression instance_expr, + MethodSpec method, Arguments Arguments, Location loc) + { + EmitCall (ec, instance_expr, method, Arguments, loc, false, false); + } + + // `dup_args' leaves an extra copy of the arguments on the stack + // `omit_args' does not leave any arguments at all. + // So, basically, you could make one call with `dup_args' set to true, + // and then another with `omit_args' set to true, and the two calls + // would have the same set of arguments. However, each argument would + // only have been evaluated once. + public static void EmitCall (EmitContext ec, Expression instance_expr, + MethodSpec method, Arguments Arguments, Location loc, + bool dup_args, bool omit_args) + { + LocalTemporary this_arg = null; + + // Speed up the check by not doing it on not allowed targets + if (method.ReturnType.Kind == MemberKind.Void && method.IsConditionallyExcluded (ec.Module.Compiler, loc)) + return; + + OpCode call_op; + TypeSpec iexpr_type; + + if (method.IsStatic) { + iexpr_type = null; + call_op = OpCodes.Call; + } else { + iexpr_type = instance_expr.Type; + + if (IsVirtualCallRequired (instance_expr, method)) { + call_op = OpCodes.Callvirt; + } else { + call_op = OpCodes.Call; + } + + // + // If this is ourselves, push "this" + // + if (!omit_args) { + TypeSpec t = iexpr_type; + + // + // Push the instance expression + // + if ((iexpr_type.IsStruct && (call_op == OpCodes.Callvirt || (call_op == OpCodes.Call && method.DeclaringType == iexpr_type))) || + iexpr_type.IsGenericParameter || method.DeclaringType.IsNullableType) { + // + // If the expression implements IMemoryLocation, then + // we can optimize and use AddressOf on the + // return. + // + // If not we have to use some temporary storage for + // it. + var iml = instance_expr as IMemoryLocation; + if (iml != null) { + iml.AddressOf (ec, AddressOp.Load); + } else { + LocalTemporary temp = new LocalTemporary (iexpr_type); + instance_expr.Emit (ec); + temp.Store (ec); + temp.AddressOf (ec, AddressOp.Load); + } + + // avoid the overhead of doing this all the time. + if (dup_args) + t = ReferenceContainer.MakeType (ec.Module, iexpr_type); + } else if (iexpr_type.IsEnum || iexpr_type.IsStruct) { + instance_expr.Emit (ec); + ec.Emit (OpCodes.Box, iexpr_type); + t = iexpr_type = ec.BuiltinTypes.Object; + } else { + instance_expr.Emit (ec); + } + + if (dup_args) { + ec.Emit (OpCodes.Dup); + if (Arguments != null && Arguments.Count != 0) { + this_arg = new LocalTemporary (t); + this_arg.Store (ec); + } + } + } + } + + if (!omit_args && Arguments != null) { + var dup_arg_exprs = Arguments.Emit (ec, dup_args); + if (dup_args) { + this_arg.Emit (ec); + LocalTemporary lt; + foreach (var dup in dup_arg_exprs) { + dup.Emit (ec); + lt = dup as LocalTemporary; + if (lt != null) + lt.Release (ec); + } + } + } + + if (call_op == OpCodes.Callvirt && (iexpr_type.IsGenericParameter || iexpr_type.IsStruct)) { + ec.Emit (OpCodes.Constrained, iexpr_type); + } + + if (method.Parameters.HasArglist) { + var varargs_types = GetVarargsTypes (method, Arguments); + ec.Emit (call_op, method, varargs_types); + return; + } + + // + // If you have: + // this.DoFoo (); + // and DoFoo is not virtual, you can omit the callvirt, + // because you don't need the null checking behavior. + // + ec.Emit (call_op, method); + } + + public override void Emit (EmitContext ec) + { + mg.EmitCall (ec, arguments); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec); + + // + // Pop the return value if there is one + // + if (type.Kind != MemberKind.Void) + ec.Emit (OpCodes.Pop); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return MakeExpression (ctx, mg.InstanceExpression, mg.BestCandidate, arguments); + } + + public static SLE.Expression MakeExpression (BuilderContext ctx, Expression instance, MethodSpec mi, Arguments args) + { +#if STATIC + throw new NotSupportedException (); +#else + var instance_expr = instance == null ? null : instance.MakeExpression (ctx); + return SLE.Expression.Call (instance_expr, (MethodInfo) mi.GetMetaInfo (), Arguments.MakeExpression (args, ctx)); +#endif + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Implements simple new expression + // + public class New : ExpressionStatement, IMemoryLocation + { + protected Arguments arguments; + + // + // During bootstrap, it contains the RequestedType, + // but if `type' is not null, it *might* contain a NewDelegate + // (because of field multi-initialization) + // + protected Expression RequestedType; + + protected MethodSpec method; + + public New (Expression requested_type, Arguments arguments, Location l) + { + RequestedType = requested_type; + this.arguments = arguments; + loc = l; + } + + #region Properties + public Arguments Arguments { + get { + return arguments; + } + } + + public Expression TypeRequested { + get { + return RequestedType; + } + } + + // + // Returns true for resolved `new S()' + // + public bool IsDefaultStruct { + get { + return arguments == null && type.IsStruct && GetType () == typeof (New); + } + } + + #endregion + + /// + /// Converts complex core type syntax like 'new int ()' to simple constant + /// + public static Constant Constantify (TypeSpec t, Location loc) + { + switch (t.BuiltinType) { + case BuiltinTypeSpec.Type.Int: + return new IntConstant (t, 0, loc); + case BuiltinTypeSpec.Type.UInt: + return new UIntConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Long: + return new LongConstant (t, 0, loc); + case BuiltinTypeSpec.Type.ULong: + return new ULongConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Float: + return new FloatConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Double: + return new DoubleConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Short: + return new ShortConstant (t, 0, loc); + case BuiltinTypeSpec.Type.UShort: + return new UShortConstant (t, 0, loc); + case BuiltinTypeSpec.Type.SByte: + return new SByteConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Byte: + return new ByteConstant (t, 0, loc); + case BuiltinTypeSpec.Type.Char: + return new CharConstant (t, '\0', loc); + case BuiltinTypeSpec.Type.Bool: + return new BoolConstant (t, false, loc); + case BuiltinTypeSpec.Type.Decimal: + return new DecimalConstant (t, 0, loc); + } + + if (t.IsEnum) + return new EnumConstant (Constantify (EnumSpec.GetUnderlyingType (t), loc), t); + + if (t.IsNullableType) + return Nullable.LiftedNull.Create (t, loc); + + return null; + } + + // + // Checks whether the type is an interface that has the + // [ComImport, CoClass] attributes and must be treated + // specially + // + public Expression CheckComImport (ResolveContext ec) + { + if (!type.IsInterface) + return null; + + // + // Turn the call into: + // (the-interface-stated) (new class-referenced-in-coclassattribute ()) + // + var real_class = type.MemberDefinition.GetAttributeCoClass (); + if (real_class == null) + return null; + + New proxy = new New (new TypeExpression (real_class, loc), arguments, loc); + Cast cast = new Cast (new TypeExpression (type, loc), proxy, loc); + return cast.Resolve (ec); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args; + if (method == null) { + args = new Arguments (1); + args.Add (new Argument (new TypeOf (type, loc))); + } else { + args = Arguments.CreateForExpressionTree (ec, + arguments, new TypeOfMethod (method, loc)); + } + + return CreateExpressionFactoryCall (ec, "New", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = RequestedType.ResolveAsType (ec); + if (type == null) + return null; + + eclass = ExprClass.Value; + + if (type.IsPointer) { + ec.Report.Error (1919, loc, "Unsafe type `{0}' cannot be used in an object creation expression", + TypeManager.CSharpName (type)); + return null; + } + + if (arguments == null) { + Constant c = Constantify (type, RequestedType.Location); + if (c != null) + return ReducedExpression.Create (c, this); + } + + if (TypeManager.IsDelegateType (type)) { + return (new NewDelegate (type, arguments, loc)).Resolve (ec); + } + + var tparam = type as TypeParameterSpec; + if (tparam != null) { + // + // 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) { + 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)); + } + + if ((arguments != null) && (arguments.Count != 0)) { + ec.Report.Error (417, loc, + "`{0}': cannot provide arguments when creating an instance of a variable type", + TypeManager.CSharpName (type)); + } + + return this; + } + + if (type.IsStatic) { + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (712, loc, "Cannot create an instance of the static class `{0}'", TypeManager.CSharpName (type)); + return null; + } + + if (type.IsInterface || type.IsAbstract){ + if (!TypeManager.IsGenericType (type)) { + RequestedType = CheckComImport (ec); + if (RequestedType != null) + return RequestedType; + } + + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (144, loc, "Cannot create an instance of the abstract class or interface `{0}'", TypeManager.CSharpName (type)); + return null; + } + + // + // Any struct always defines parameterless constructor + // + if (type.IsStruct && arguments == null) + return this; + + bool dynamic; + if (arguments != null) { + arguments.Resolve (ec, out dynamic); + } else { + dynamic = false; + } + + method = ConstructorLookup (ec, type, ref arguments, loc); + + if (dynamic) { + arguments.Insert (0, new Argument (new TypeOf (type, loc).Resolve (ec), Argument.AType.DynamicTypeName)); + return new DynamicConstructorBinder (type, arguments, loc).Resolve (ec); + } + + return this; + } + + bool DoEmitTypeParameter (EmitContext ec) + { + var m = ec.Module.PredefinedMembers.ActivatorCreateInstance.Resolve (loc); + if (m == null) + return true; + + var ctor_factory = m.MakeGenericMethod (ec.MemberContext, type); + var tparam = (TypeParameterSpec) type; + + if (tparam.IsReferenceType) { + ec.Emit (OpCodes.Call, ctor_factory); + return true; + } + + // Allow DoEmit() to be called multiple times. + // We need to create a new LocalTemporary each time since + // you can't share LocalBuilders among ILGeneators. + LocalTemporary temp = new LocalTemporary (type); + + Label label_activator = ec.DefineLabel (); + Label label_end = ec.DefineLabel (); + + temp.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + + temp.Emit (ec); + ec.Emit (OpCodes.Box, type); + ec.Emit (OpCodes.Brfalse, label_activator); + + temp.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + temp.Emit (ec); + ec.Emit (OpCodes.Br_S, label_end); + + ec.MarkLabel (label_activator); + + ec.Emit (OpCodes.Call, ctor_factory); + ec.MarkLabel (label_end); + return true; + } + + // + // This Emit can be invoked in two contexts: + // * As a mechanism that will leave a value on the stack (new object) + // * As one that wont (init struct) + // + // If we are dealing with a ValueType, we have a few + // situations to deal with: + // + // * The target is a ValueType, and we have been provided + // the instance (this is easy, we are being assigned). + // + // * The target of New is being passed as an argument, + // to a boxing operation or a function that takes a + // ValueType. + // + // In this case, we need to create a temporary variable + // that is the argument of New. + // + // Returns whether a value is left on the stack + // + // *** Implementation note *** + // + // To benefit from this optimization, each assignable expression + // has to manually cast to New and call this Emit. + // + // TODO: It's worth to implement it for arrays and fields + // + public virtual bool Emit (EmitContext ec, IMemoryLocation target) + { + bool is_value_type = TypeSpec.IsValueType (type); + VariableReference vr = target as VariableReference; + + if (target != null && is_value_type && (vr != null || method == null)) { + target.AddressOf (ec, AddressOp.Store); + } else if (vr != null && vr.IsRef) { + vr.EmitLoad (ec); + } + + if (arguments != null) + arguments.Emit (ec); + + if (is_value_type) { + if (method == null) { + ec.Emit (OpCodes.Initobj, type); + return false; + } + + if (vr != null) { + ec.Emit (OpCodes.Call, method); + return false; + } + } + + if (type is TypeParameterSpec) + return DoEmitTypeParameter (ec); + + ec.Emit (OpCodes.Newobj, method); + return true; + } + + public override void Emit (EmitContext ec) + { + LocalTemporary v = null; + if (method == null && TypeSpec.IsValueType (type)) { + // TODO: Use temporary variable from pool + v = new LocalTemporary (type); + } + + if (!Emit (ec, v)) + v.Emit (ec); + } + + public override void EmitStatement (EmitContext ec) + { + LocalTemporary v = null; + if (method == null && TypeSpec.IsValueType (type)) { + // TODO: Use temporary variable from pool + v = new LocalTemporary (type); + } + + if (Emit (ec, v)) + ec.Emit (OpCodes.Pop); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + EmitAddressOf (ec, mode); + } + + protected virtual IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp mode) + { + LocalTemporary value_target = new LocalTemporary (type); + + if (type is TypeParameterSpec) { + DoEmitTypeParameter (ec); + value_target.Store (ec); + value_target.AddressOf (ec, mode); + return value_target; + } + + value_target.AddressOf (ec, AddressOp.Store); + + if (method == null) { + ec.Emit (OpCodes.Initobj, type); + } else { + if (arguments != null) + arguments.Emit (ec); + + ec.Emit (OpCodes.Call, method); + } + + value_target.AddressOf (ec, mode); + return value_target; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + New target = (New) t; + + target.RequestedType = RequestedType.Clone (clonectx); + if (arguments != null){ + target.arguments = arguments.Clone (clonectx); + } + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.New ((ConstructorInfo) method.GetMetaInfo (), Arguments.MakeExpression (arguments, ctx)); +#endif + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Array initializer expression, the expression is allowed in + // variable or field initialization only which makes it tricky as + // the type has to be infered based on the context either from field + // type or variable type (think of multiple declarators) + // + public class ArrayInitializer : Expression + { + List elements; + BlockVariableDeclaration variable; + + public ArrayInitializer (List init, Location loc) + { + elements = init; + this.loc = loc; + } + + public ArrayInitializer (int count, Location loc) + : this (new List (count), loc) + { + } + + public ArrayInitializer (Location loc) + : this (4, loc) + { + } + + #region Properties + + public int Count { + get { return elements.Count; } + } + + public Expression this [int index] { + get { + return elements [index]; + } + } + + public BlockVariableDeclaration VariableDeclaration { + get { + return variable; + } + set { + variable = value; + } + } + + public List Elements { + get { + return this.elements; + } + } + #endregion + + public void Add (Expression expr) + { + elements.Add (expr); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + var target = (ArrayInitializer) t; + + target.elements = new List (elements.Count); + foreach (var element in elements) + target.elements.Add (element.Clone (clonectx)); + } + + protected override Expression DoResolve (ResolveContext rc) + { + var current_field = rc.CurrentMemberDefinition as FieldBase; + TypeExpression type; + if (current_field != null) { + type = new TypeExpression (current_field.MemberType, current_field.Location); + } else if (variable != null) { + if (variable.TypeExpression is VarExpr) { + rc.Report.Error (820, loc, "An implicitly typed local variable declarator cannot use an array initializer"); + return EmptyExpression.Null; + } + + type = new TypeExpression (variable.Variable.Type, variable.Variable.Location); + } else { + throw new NotImplementedException ("Unexpected array initializer context"); + } + + return new ArrayCreation (type, this).Resolve (rc); + } + + public override void Emit (EmitContext ec) + { + throw new InternalErrorException ("Missing Resolve call"); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// 14.5.10.2: Represents an array creation expression. + /// + /// + /// + /// There are two possible scenarios here: one is an array creation + /// expression that specifies the dimensions and optionally the + /// initialization data and the other which does not need dimensions + /// specified but where initialization data is mandatory. + /// + public class ArrayCreation : Expression + { + FullNamedExpression requested_base_type; + ArrayInitializer initializers; + + // + // The list of Argument types. + // This is used to construct the `newarray' or constructor signature + // + protected List arguments; + + protected TypeSpec array_element_type; + int num_arguments = 0; + protected int dimensions; + protected readonly ComposedTypeSpecifier rank; + Expression first_emit; + LocalTemporary first_emit_temp; + + protected List array_data; + + Dictionary bounds; + + // The number of constants in array initializers + int const_initializers_count; + bool only_constant_initializers; + + public List Arguments { + get { return this.arguments; } + } + + public ComposedTypeSpecifier Rank { + get { return this.rank; } + } + + public FullNamedExpression NewType { + get { return this.requested_base_type; } + } + + public ArrayInitializer Initializers { + get { return this.initializers; } + } + + public ArrayCreation (FullNamedExpression requested_base_type, List exprs, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location l) + : this (requested_base_type, rank, initializers, l) + { + arguments = exprs; + num_arguments = arguments.Count; + } + + // + // For expressions like int[] foo = new int[] { 1, 2, 3 }; + // + public ArrayCreation (FullNamedExpression requested_base_type, ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc) + { + this.requested_base_type = requested_base_type; + this.rank = rank; + this.initializers = initializers; + this.loc = loc; + + if (rank != null) + num_arguments = rank.Dimension; + } + + // + // For compiler generated single dimensional arrays only + // + public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers, Location loc) + : this (requested_base_type, ComposedTypeSpecifier.SingleDimension, initializers, loc) + { + } + + // + // For expressions like int[] foo = { 1, 2, 3 }; + // + public ArrayCreation (FullNamedExpression requested_base_type, ArrayInitializer initializers) + : this (requested_base_type, null, initializers, initializers.Location) + { + } + + protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + ec.Report.Error (248, loc, "Cannot create an array with a negative size"); + } + + bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds) + { + if (initializers != null && bounds == null) { + // + // We use this to store all the date values in the order in which we + // will need to store them in the byte blob later + // + array_data = new List (); + bounds = new Dictionary (); + } + + if (specified_dims) { + Expression a = arguments [idx]; + a = a.Resolve (ec); + if (a == null) + return false; + + a = ConvertExpressionToArrayIndex (ec, a); + if (a == null) + return false; + + arguments[idx] = a; + + if (initializers != null) { + Constant c = a as Constant; + if (c == null && a is ArrayIndexCast) + c = ((ArrayIndexCast) a).Child as Constant; + + if (c == null) { + ec.Report.Error (150, a.Location, "A constant value is expected"); + return false; + } + + int value; + try { + value = System.Convert.ToInt32 (c.GetValue ()); + } catch { + ec.Report.Error (150, a.Location, "A constant value is expected"); + return false; + } + + // TODO: probe.Count does not fit ulong in + if (value != probe.Count) { + ec.Report.Error (847, loc, "An array initializer of length `{0}' was expected", value.ToString ()); + return false; + } + + bounds[idx] = value; + } + } + + if (initializers == null) + return true; + + for (int i = 0; i < probe.Count; ++i) { + var o = probe [i]; + if (o is ArrayInitializer) { + var sub_probe = o as ArrayInitializer; + if (idx + 1 >= dimensions){ + ec.Report.Error (623, loc, "Array initializers can only be used in a variable or field initializer. Try using a new expression instead"); + return false; + } + + bool ret = CheckIndices (ec, sub_probe, idx + 1, specified_dims, child_bounds - 1); + if (!ret) + return false; + } else if (child_bounds > 1) { + ec.Report.Error (846, o.Location, "A nested array initializer was expected"); + } else { + Expression element = ResolveArrayElement (ec, o); + if (element == null) + continue; + + // Initializers with the default values can be ignored + Constant c = element as Constant; + if (c != null) { + if (!c.IsDefaultInitializer (array_element_type)) { + ++const_initializers_count; + } + } else { + only_constant_initializers = false; + } + + array_data.Add (element); + } + } + + return true; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args; + + if (array_data == null) { + args = new Arguments (arguments.Count + 1); + args.Add (new Argument (new TypeOf (array_element_type, loc))); + foreach (Expression a in arguments) + args.Add (new Argument (a.CreateExpressionTree (ec))); + + return CreateExpressionFactoryCall (ec, "NewArrayBounds", args); + } + + if (dimensions > 1) { + ec.Report.Error (838, loc, "An expression tree cannot contain a multidimensional array initializer"); + return null; + } + + args = new Arguments (array_data == null ? 1 : array_data.Count + 1); + args.Add (new Argument (new TypeOf (array_element_type, loc))); + if (array_data != null) { + for (int i = 0; i < array_data.Count; ++i) { + Expression e = array_data [i]; + args.Add (new Argument (e.CreateExpressionTree (ec))); + } + } + + return CreateExpressionFactoryCall (ec, "NewArrayInit", args); + } + + void UpdateIndices (ResolveContext rc) + { + int i = 0; + for (var probe = initializers; probe != null;) { + Expression e = new IntConstant (rc.BuiltinTypes, probe.Count, Location.Null); + arguments.Add (e); + bounds[i++] = probe.Count; + + if (probe.Count > 0 && probe [0] is ArrayInitializer) { + probe = (ArrayInitializer) probe[0]; + } else if (dimensions > i) { + continue; + } else { + return; + } + } + } + + protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element) + { + element = element.Resolve (ec); + if (element == null) + return null; + + if (element is CompoundAssign.TargetExpression) { + if (first_emit != null) + throw new InternalErrorException ("Can only handle one mutator at a time"); + first_emit = element; + element = first_emit_temp = new LocalTemporary (element.Type); + } + + return Convert.ImplicitConversionRequired ( + ec, element, array_element_type, loc); + } + + protected bool ResolveInitializers (ResolveContext ec) + { + only_constant_initializers = true; + + if (arguments != null) { + bool res = true; + for (int i = 0; i < arguments.Count; ++i) { + res &= CheckIndices (ec, initializers, i, true, dimensions); + if (initializers != null) + break; + } + + return res; + } + + arguments = new List (); + + if (!CheckIndices (ec, initializers, 0, false, dimensions)) + return false; + + UpdateIndices (ec); + + return true; + } + + // + // Resolved the type of the array + // + bool ResolveArrayType (ResolveContext ec) + { + // + // Lookup the type + // + FullNamedExpression array_type_expr; + if (num_arguments > 0) { + array_type_expr = new ComposedCast (requested_base_type, rank); + } else { + array_type_expr = requested_base_type; + } + + type = array_type_expr.ResolveAsType (ec); + if (array_type_expr == null) + return false; + + var ac = type as ArrayContainer; + if (ac == null) { + ec.Report.Error (622, loc, "Can only use array initializer expressions to assign to array types. Try using a new expression instead"); + return false; + } + + array_element_type = ac.Element; + dimensions = ac.Rank; + + return true; + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (type != null) + return this; + + if (!ResolveArrayType (ec)) + return null; + + // + // validate the initializers and fill in any missing bits + // + if (!ResolveInitializers (ec)) + return null; + + eclass = ExprClass.Value; + return this; + } + + byte [] MakeByteBlob () + { + int factor; + byte [] data; + byte [] element; + int count = array_data.Count; + + TypeSpec element_type = array_element_type; + if (TypeManager.IsEnumType (element_type)) + element_type = EnumSpec.GetUnderlyingType (element_type); + + factor = BuiltinTypeSpec.GetSize (element_type); + if (factor == 0) + throw new Exception ("unrecognized type in MakeByteBlob: " + element_type); + + data = new byte [(count * factor + 3) & ~3]; + int idx = 0; + + for (int i = 0; i < count; ++i) { + var c = array_data[i] as Constant; + if (c == null) { + idx += factor; + continue; + } + + object v = c.GetValue (); + + switch (element_type.BuiltinType) { + case BuiltinTypeSpec.Type.Long: + long lval = (long) v; + + for (int j = 0; j < factor; ++j) { + data[idx + j] = (byte) (lval & 0xFF); + lval = (lval >> 8); + } + break; + case BuiltinTypeSpec.Type.ULong: + ulong ulval = (ulong) v; + + for (int j = 0; j < factor; ++j) { + data[idx + j] = (byte) (ulval & 0xFF); + ulval = (ulval >> 8); + } + break; + case BuiltinTypeSpec.Type.Float: + element = BitConverter.GetBytes ((float) v); + + for (int j = 0; j < factor; ++j) + data[idx + j] = element[j]; + if (!BitConverter.IsLittleEndian) + System.Array.Reverse (data, idx, 4); + break; + case BuiltinTypeSpec.Type.Double: + element = BitConverter.GetBytes ((double) v); + + for (int j = 0; j < factor; ++j) + data[idx + j] = element[j]; + + // FIXME: Handle the ARM float format. + if (!BitConverter.IsLittleEndian) + System.Array.Reverse (data, idx, 8); + break; + case BuiltinTypeSpec.Type.Char: + int chval = (int) ((char) v); + + data[idx] = (byte) (chval & 0xff); + data[idx + 1] = (byte) (chval >> 8); + break; + case BuiltinTypeSpec.Type.Short: + int sval = (int) ((short) v); + + data[idx] = (byte) (sval & 0xff); + data[idx + 1] = (byte) (sval >> 8); + break; + case BuiltinTypeSpec.Type.UShort: + int usval = (int) ((ushort) v); + + data[idx] = (byte) (usval & 0xff); + data[idx + 1] = (byte) (usval >> 8); + break; + case BuiltinTypeSpec.Type.Int: + int val = (int) v; + + data[idx] = (byte) (val & 0xff); + data[idx + 1] = (byte) ((val >> 8) & 0xff); + data[idx + 2] = (byte) ((val >> 16) & 0xff); + data[idx + 3] = (byte) (val >> 24); + break; + case BuiltinTypeSpec.Type.UInt: + uint uval = (uint) v; + + data[idx] = (byte) (uval & 0xff); + data[idx + 1] = (byte) ((uval >> 8) & 0xff); + data[idx + 2] = (byte) ((uval >> 16) & 0xff); + data[idx + 3] = (byte) (uval >> 24); + break; + case BuiltinTypeSpec.Type.SByte: + data[idx] = (byte) (sbyte) v; + break; + case BuiltinTypeSpec.Type.Byte: + data[idx] = (byte) v; + break; + case BuiltinTypeSpec.Type.Bool: + data[idx] = (byte) ((bool) v ? 1 : 0); + break; + case BuiltinTypeSpec.Type.Decimal: + int[] bits = Decimal.GetBits ((decimal) v); + int p = idx; + + // FIXME: For some reason, this doesn't work on the MS runtime. + int[] nbits = new int[4]; + nbits[0] = bits[3]; + nbits[1] = bits[2]; + nbits[2] = bits[0]; + nbits[3] = bits[1]; + + for (int j = 0; j < 4; j++) { + data[p++] = (byte) (nbits[j] & 0xff); + data[p++] = (byte) ((nbits[j] >> 8) & 0xff); + data[p++] = (byte) ((nbits[j] >> 16) & 0xff); + data[p++] = (byte) (nbits[j] >> 24); + } + break; + default: + throw new Exception ("Unrecognized type in MakeByteBlob: " + element_type); + } + + idx += factor; + } + + return data; + } + +#if NET_4_0 + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + var initializers = new SLE.Expression [array_data.Count]; + for (var i = 0; i < initializers.Length; i++) { + if (array_data [i] == null) + initializers [i] = SLE.Expression.Default (array_element_type.GetMetaInfo ()); + else + initializers [i] = array_data [i].MakeExpression (ctx); + } + + return SLE.Expression.NewArrayInit (array_element_type.GetMetaInfo (), initializers); +#endif + } +#endif +#if STATIC + // + // Emits the initializers for the array + // + void EmitStaticInitializers (EmitContext ec) + { + var m = ec.Module.PredefinedMembers.RuntimeHelpersInitializeArray.Resolve (loc); + if (m == null) + return; + + // + // First, the static data + // + byte [] data = MakeByteBlob (); + var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (data, loc); + + ec.Emit (OpCodes.Dup); + ec.Emit (OpCodes.Ldtoken, fb); + ec.Emit (OpCodes.Call, m); + } +#endif + + // + // Emits pieces of the array that can not be computed at compile + // time (variables and string locations). + // + // This always expect the top value on the stack to be the array + // + void EmitDynamicInitializers (EmitContext ec, bool emitConstants) + { + int dims = bounds.Count; + var current_pos = new int [dims]; + + for (int i = 0; i < array_data.Count; i++){ + + Expression e = array_data [i]; + var c = e as Constant; + + // Constant can be initialized via StaticInitializer + if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) { + TypeSpec etype = e.Type; + + ec.Emit (OpCodes.Dup); + + for (int idx = 0; idx < dims; idx++) + ec.EmitInt (current_pos [idx]); + + // + // If we are dealing with a struct, get the + // address of it, so we can store it. + // + if (dims == 1 && etype.IsStruct) { + switch (etype.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + break; + default: + ec.Emit (OpCodes.Ldelema, etype); + break; + } + } + + e.Emit (ec); + + ec.EmitArrayStore ((ArrayContainer) type); + } + + // + // Advance counter + // + for (int j = dims - 1; j >= 0; j--){ + current_pos [j]++; + if (current_pos [j] < bounds [j]) + break; + current_pos [j] = 0; + } + } + } + + public override void Emit (EmitContext ec) + { + if (first_emit != null) { + first_emit.Emit (ec); + first_emit_temp.Store (ec); + } + + foreach (Expression e in arguments) + e.Emit (ec); + + ec.EmitArrayNew ((ArrayContainer) type); + + if (initializers == null) + return; + +#if STATIC + // Emit static initializer for arrays which have contain more than 2 items and + // the static initializer will initialize at least 25% of array values or there + // is more than 10 items to be initialized + // NOTE: const_initializers_count does not contain default constant values. + if (const_initializers_count > 2 && (array_data.Count > 10 || const_initializers_count * 4 > (array_data.Count)) && + (BuiltinTypeSpec.IsPrimitiveType (array_element_type) || array_element_type.IsEnum)) { + EmitStaticInitializers (ec); + + if (!only_constant_initializers) + EmitDynamicInitializers (ec, false); + } else +#endif + { + EmitDynamicInitializers (ec, true); + } + + if (first_emit_temp != null) + first_emit_temp.Release (ec); + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // no multi dimensional or jagged arrays + if (arguments.Count != 1 || array_element_type.IsArray) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + + // No array covariance, except for array -> object + if (type != targetType) { + if (targetType.BuiltinType != BuiltinTypeSpec.Type.Object) { + base.EncodeAttributeValue (rc, enc, targetType); + return; + } + + if (enc.Encode (type) == AttributeEncoder.EncodedTypeProperties.DynamicType) { + Attribute.Error_AttributeArgumentIsDynamic (rc, loc); + return; + } + } + + // Single dimensional array of 0 size + if (array_data == null) { + IntConstant ic = arguments[0] as IntConstant; + if (ic == null || !ic.IsDefaultValue) { + base.EncodeAttributeValue (rc, enc, targetType); + } else { + enc.Encode (0); + } + + return; + } + + enc.Encode (array_data.Count); + foreach (var element in array_data) { + element.EncodeAttributeValue (rc, enc, array_element_type); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + ArrayCreation target = (ArrayCreation) t; + + if (requested_base_type != null) + target.requested_base_type = (FullNamedExpression)requested_base_type.Clone (clonectx); + + if (arguments != null){ + target.arguments = new List (arguments.Count); + foreach (Expression e in arguments) + target.arguments.Add (e.Clone (clonectx)); + } + + if (initializers != null) + target.initializers = (ArrayInitializer) initializers.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Represents an implicitly typed array epxression + // + class ImplicitlyTypedArrayCreation : ArrayCreation + { + sealed class InferenceContext : TypeInferenceContext + { + class ExpressionBoundInfo : BoundInfo + { + readonly Expression expr; + + public ExpressionBoundInfo (Expression expr) + : base (expr.Type, BoundKind.Lower) + { + this.expr = expr; + } + + public override bool Equals (BoundInfo other) + { + // We are using expression not type for conversion check + // no optimization based on types is possible + return false; + } + + public override Expression GetTypeExpression () + { + return expr; + } + } + + public void AddExpression (Expression expr) + { + AddToBounds (new ExpressionBoundInfo (expr), 0); + } + } + + InferenceContext best_type_inference; + + public ImplicitlyTypedArrayCreation (ComposedTypeSpecifier rank, ArrayInitializer initializers, Location loc) + : base (null, rank, initializers, loc) + { + } + + public ImplicitlyTypedArrayCreation (ArrayInitializer initializers, Location loc) + : base (null, initializers, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (type != null) + return this; + + dimensions = rank.Dimension; + + best_type_inference = new InferenceContext (); + + if (!ResolveInitializers (ec)) + return null; + + best_type_inference.FixAllTypes (ec); + 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 || + 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"); + return null; + } + + // + // At this point we found common base type for all initializer elements + // but we have to be sure that all static initializer elements are of + // same type + // + UnifyInitializerElement (ec); + + type = ArrayContainer.MakeType (ec.Module, array_element_type, dimensions); + eclass = ExprClass.Value; + return this; + } + + // + // Converts static initializer only + // + void UnifyInitializerElement (ResolveContext ec) + { + for (int i = 0; i < array_data.Count; ++i) { + Expression e = array_data[i]; + if (e != null) + array_data [i] = Convert.ImplicitConversion (ec, e, array_element_type, Location.Null); + } + } + + protected override Expression ResolveArrayElement (ResolveContext ec, Expression element) + { + element = element.Resolve (ec); + if (element != null) + best_type_inference.AddExpression (element); + + return element; + } + } + + sealed class CompilerGeneratedThis : This + { + public CompilerGeneratedThis (TypeSpec type, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Variable; + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + return null; + } + } + + /// + /// Represents the `this' construct + /// + + public class This : VariableReference + { + sealed class ThisVariable : ILocalVariable + { + public static readonly ILocalVariable Instance = new ThisVariable (); + + public void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldarg_0); + } + + public void EmitAssign (EmitContext ec) + { + throw new InvalidOperationException (); + } + + public void EmitAddressOf (EmitContext ec) + { + ec.Emit (OpCodes.Ldarg_0); + } + } + + VariableInfo variable_info; + + public This (Location loc) + { + this.loc = loc; + } + + #region Properties + + public override string Name { + get { return "this"; } + } + + public override bool IsLockedByStatement { + get { + return false; + } + set { + } + } + + public override bool IsRef { + get { return type.IsStruct; } + } + + protected override ILocalVariable Variable { + get { return ThisVariable.Instance; } + } + + public override VariableInfo VariableInfo { + get { return variable_info; } + } + + public override bool IsFixed { + get { return false; } + } + + #endregion + + public void CheckStructThisDefiniteAssignment (ResolveContext rc) + { + if (variable_info != null && !variable_info.IsAssigned (rc)) { + rc.Report.Error (188, loc, + "The `this' object cannot be used before all of its fields are assigned to"); + } + } + + protected virtual void Error_ThisNotAvailable (ResolveContext ec) + { + if (ec.IsStatic && !ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (26, loc, "Keyword `this' is not valid in a static property, static method, or static field initializer"); + } else if (ec.CurrentAnonymousMethod != null) { + ec.Report.Error (1673, loc, + "Anonymous methods inside structs cannot access instance members of `this'. " + + "Consider copying `this' to a local variable outside the anonymous method and using the local instead"); + } else { + ec.Report.Error (27, loc, "Keyword `this' is not available in the current context"); + } + } + + public override HoistedVariable GetHoistedVariable (AnonymousExpression ae) + { + if (ae == null) + return null; + + AnonymousMethodStorey storey = ae.Storey; + while (storey != null) { + AnonymousMethodStorey temp = storey.Parent as AnonymousMethodStorey; + if (temp == null) + return storey.HoistedThis; + + storey = temp; + } + + return null; + } + + public static bool IsThisAvailable (ResolveContext ec, bool ignoreAnonymous) + { + if (ec.IsStatic || ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.BaseInitializer | ResolveContext.Options.ConstantScope)) + return false; + + if (ignoreAnonymous || ec.CurrentAnonymousMethod == null) + return true; + + if (ec.CurrentType.IsStruct && ec.CurrentIterator == null) + return false; + + return true; + } + + public virtual void ResolveBase (ResolveContext ec) + { + eclass = ExprClass.Variable; + type = ec.CurrentType; + + if (!IsThisAvailable (ec, false)) { + Error_ThisNotAvailable (ec); + return; + } + + var block = ec.CurrentBlock; + if (block != null) { + if (block.ParametersBlock.TopBlock.ThisVariable != null) + variable_info = block.ParametersBlock.TopBlock.ThisVariable.VariableInfo; + + AnonymousExpression am = ec.CurrentAnonymousMethod; + if (am != null && ec.IsVariableCapturingRequired) { + am.SetHasThisAccess (); + } + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (1); + args.Add (new Argument (this)); + + // Use typeless constant for ldarg.0 to save some + // space and avoid problems with anonymous stories + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + ResolveBase (ec); + + if (variable_info != null && type.IsStruct) { + CheckStructThisDefiniteAssignment (ec); + } + + return this; + } + + override public Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + ResolveBase (ec); + + if (variable_info != null) + variable_info.SetAssigned (ec); + + if (type.IsClass){ + if (right_side == EmptyExpression.UnaryAddress) + ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only"); + else if (right_side == EmptyExpression.OutAccess) + ec.Report.Error (1605, loc, "Cannot pass `this' as a ref or out argument because it is read-only"); + else + ec.Report.Error (1604, loc, "Cannot assign to `this' because it is read-only"); + } + + return this; + } + + public override int GetHashCode() + { + throw new NotImplementedException (); + } + + public override bool Equals (object obj) + { + This t = obj as This; + if (t == null) + return false; + + return true; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + + public override void SetHasAddressTaken () + { + // Nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Represents the `__arglist' construct + /// + public class ArglistAccess : Expression + { + public ArglistAccess (Location loc) + { + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + type = ec.Module.PredefinedTypes.RuntimeArgumentHandle.Resolve (); + + if (ec.HasSet (ResolveContext.Options.FieldInitializerScope) || !ec.CurrentBlock.ParametersBlock.Parameters.HasArglist) { + ec.Report.Error (190, loc, + "The __arglist construct is valid only within a variable argument method"); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Arglist); + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // nothing. + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Represents the `__arglist (....)' construct + /// + public class Arglist : Expression + { + public Arguments Arguments { get; private set; } + + public Arglist (Location loc) + : this (null, loc) + { + } + + public Arglist (Arguments args, Location l) + { + Arguments = args; + loc = l; + } + + public MetaType[] ArgumentTypes { + get { + if (Arguments == null) + return MetaType.EmptyTypes; + + var retval = new MetaType[Arguments.Count]; + for (int i = 0; i < retval.Length; i++) + retval[i] = Arguments[i].Expr.Type.GetMetaInfo (); + + return retval; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (1952, loc, "An expression tree cannot contain a method with variable arguments"); + return null; + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Variable; + type = InternalType.Arglist; + if (Arguments != null) { + bool dynamic; // Can be ignored as there is always only 1 overload + Arguments.Resolve (ec, out dynamic); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + if (Arguments != null) + Arguments.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + Arglist target = (Arglist) t; + + if (Arguments != null) + target.Arguments = Arguments.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class RefValueExpr : ShimExpression + { + FullNamedExpression texpr; + + public FullNamedExpression FullNamedExpression { + get { return texpr;} + } + + public RefValueExpr (Expression expr, FullNamedExpression texpr, Location loc) + : base (expr) + { + this.texpr = texpr; + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + type = texpr.ResolveAsType (rc); + if (expr == null || type == null) + return null; + + expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc); + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.Emit (OpCodes.Refanyval, type); + ec.EmitLoadFromPtr (type); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class RefTypeExpr : ShimExpression + { + public RefTypeExpr (Expression expr, Location loc) + : base (expr) + { + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.Resolve (rc); + if (expr == null) + return null; + + expr = Convert.ImplicitConversionRequired (rc, expr, rc.Module.PredefinedTypes.TypedReference.Resolve (), loc); + if (expr == null) + return null; + + type = rc.BuiltinTypes.Type; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.Emit (OpCodes.Refanytype); + var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class MakeRefExpr : ShimExpression + { + public MakeRefExpr (Expression expr, Location loc) + : base (expr) + { + this.loc = loc; + } + + protected override Expression DoResolve (ResolveContext rc) + { + expr = expr.ResolveLValue (rc, EmptyExpression.LValueMemberAccess); + type = rc.Module.PredefinedTypes.TypedReference.Resolve (); + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + ((IMemoryLocation) expr).AddressOf (ec, AddressOp.Load); + ec.Emit (OpCodes.Mkrefany, expr.Type); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the typeof operator + /// + public class TypeOf : Expression { + FullNamedExpression QueriedType; + TypeSpec typearg; + + public TypeOf (FullNamedExpression queried_type, Location l) + { + QueriedType = queried_type; + loc = l; + } + + // + // Use this constructor for any compiler generated typeof expression + // + public TypeOf (TypeSpec type, Location loc) + { + this.typearg = type; + this.loc = loc; + } + + #region Properties + public TypeSpec TypeArgument { + get { + return typearg; + } + } + + public FullNamedExpression TypeExpression { + get { + return QueriedType; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc))); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (eclass != ExprClass.Unresolved) + return this; + + if (typearg == null) { + // + // Pointer types are allowed without explicit unsafe, they are just tokens + // + using (ec.Set (ResolveContext.Options.UnsafeScope)) { + typearg = QueriedType.ResolveAsType (ec); + } + + if (typearg == null) + return null; + + if (typearg.Kind == MemberKind.Void && !(QueriedType is TypeExpression)) { + ec.Report.Error (673, loc, "System.Void cannot be used from C#. Use typeof (void) to get the void type object"); + } else if (typearg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + ec.Report.Error (1962, QueriedType.Location, + "The typeof operator cannot be used on the dynamic type"); + } + } + + type = ec.BuiltinTypes.Type; + + // Even though what is returned is a type object, it's treated as a value by the compiler. + // In particular, 'typeof (Foo).X' is something totally different from 'Foo.X'. + eclass = ExprClass.Value; + return this; + } + + static bool ContainsDynamicType (TypeSpec type) + { + if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + var element_container = type as ElementTypeSpec; + if (element_container != null) + return ContainsDynamicType (element_container.Element); + + foreach (var t in type.TypeArguments) { + if (ContainsDynamicType (t)) { + return true; + } + } + + return false; + } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // Target type is not System.Type therefore must be object + // and we need to use different encoding sequence + if (targetType != type) + enc.Encode (type); + + if (typearg is InflatedTypeSpec) { + var gt = typearg; + do { + if (InflatedTypeSpec.ContainsTypeParameter (gt)) { + rc.Module.Compiler.Report.Error (416, loc, "`{0}': an attribute argument cannot use type parameters", + typearg.GetSignatureForError ()); + return; + } + + gt = gt.DeclaringType; + } while (gt != null); + } + + if (ContainsDynamicType (typearg)) { + Attribute.Error_AttributeArgumentIsDynamic (rc, loc); + return; + } + + enc.EncodeTypeName (typearg); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldtoken, typearg); + var m = ec.Module.PredefinedMembers.TypeGetTypeFromHandle.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + TypeOf target = (TypeOf) t; + if (QueriedType != null) + target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + sealed class TypeOfMethod : TypeOfMember + { + public TypeOfMethod (MethodSpec method, Location loc) + : base (method, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (member.IsConstructor) { + type = ec.Module.PredefinedTypes.ConstructorInfo.Resolve (); + } else { + type = ec.Module.PredefinedTypes.MethodInfo.Resolve (); + } + + if (type == null) + return null; + + return base.DoResolve (ec); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldtoken, member); + + base.Emit (ec); + ec.Emit (OpCodes.Castclass, type); + } + + protected override PredefinedMember GetTypeFromHandle (EmitContext ec) + { + return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle; + } + + protected override PredefinedMember GetTypeFromHandleGeneric (EmitContext ec) + { + return ec.Module.PredefinedMembers.MethodInfoGetMethodFromHandle2; + } + } + + abstract class TypeOfMember : Expression where T : MemberSpec + { + protected readonly T member; + + protected TypeOfMember (T member, Location loc) + { + this.member = member; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (this)); + args.Add (new Argument (new TypeOf (type, loc))); + return CreateExpressionFactoryCall (ec, "Constant", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + bool is_generic = member.DeclaringType.IsGenericOrParentIsGeneric; + PredefinedMember p; + if (is_generic) { + p = GetTypeFromHandleGeneric (ec); + ec.Emit (OpCodes.Ldtoken, member.DeclaringType); + } else { + p = GetTypeFromHandle (ec); + } + + var mi = p.Resolve (loc); + if (mi != null) + ec.Emit (OpCodes.Call, mi); + } + + protected abstract PredefinedMember GetTypeFromHandle (EmitContext ec); + protected abstract PredefinedMember GetTypeFromHandleGeneric (EmitContext ec); + } + + sealed class TypeOfField : TypeOfMember + { + public TypeOfField (FieldSpec field, Location loc) + : base (field, loc) + { + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = ec.Module.PredefinedTypes.FieldInfo.Resolve (); + if (type == null) + return null; + + return base.DoResolve (ec); + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Ldtoken, member); + base.Emit (ec); + } + + protected override PredefinedMember GetTypeFromHandle (EmitContext ec) + { + return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle; + } + + protected override PredefinedMember GetTypeFromHandleGeneric (EmitContext ec) + { + return ec.Module.PredefinedMembers.FieldInfoGetFieldFromHandle2; + } + } + + /// + /// Implements the sizeof expression + /// + public class SizeOf : Expression { + public readonly Expression QueriedType; + TypeSpec type_queried; + + public SizeOf (Expression queried_type, Location l) + { + this.QueriedType = queried_type; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + protected override Expression DoResolve (ResolveContext ec) + { + type_queried = QueriedType.ResolveAsType (ec); + if (type_queried == null) + return null; + + if (TypeManager.IsEnumType (type_queried)) + type_queried = EnumSpec.GetUnderlyingType (type_queried); + + int size_of = BuiltinTypeSpec.GetSize (type_queried); + if (size_of > 0) { + return new IntConstant (ec.BuiltinTypes, size_of, loc); + } + + if (!TypeManager.VerifyUnmanaged (ec.Module, type_queried, loc)){ + return null; + } + + if (!ec.IsUnsafe) { + ec.Report.Error (233, loc, + "`{0}' does not have a predefined size, therefore sizeof can only be used in an unsafe context (consider using System.Runtime.InteropServices.Marshal.SizeOf)", + TypeManager.CSharpName (type_queried)); + } + + type = ec.BuiltinTypes.Int; + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + ec.Emit (OpCodes.Sizeof, type_queried); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the qualified-alias-member (::) expression. + /// + public class QualifiedAliasMember : MemberAccess + { + public readonly string alias; + public static readonly string GlobalAlias = "global"; + + public QualifiedAliasMember (string alias, string identifier, Location l) + : base (null, identifier, l) + { + this.alias = alias; + } + + public QualifiedAliasMember (string alias, string identifier, TypeArguments targs, Location l) + : base (null, identifier, targs, l) + { + this.alias = alias; + } + + public QualifiedAliasMember (string alias, string identifier, int arity, Location l) + : base (null, identifier, arity, l) + { + this.alias = alias; + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec) + { + if (alias == GlobalAlias) { + expr = ec.Module.GlobalRootNamespace; + return base.ResolveAsTypeOrNamespace (ec); + } + + int errors = ec.Module.Compiler.Report.Errors; + expr = ec.LookupNamespaceAlias (alias); + if (expr == null) { + if (errors == ec.Module.Compiler.Report.Errors) + ec.Module.Compiler.Report.Error (432, loc, "Alias `{0}' not found", alias); + return null; + } + + FullNamedExpression fne = base.ResolveAsTypeOrNamespace (ec); + if (fne == null) + return null; + + if (expr.eclass == ExprClass.Type) { + ec.Module.Compiler.Report.Error (431, loc, + "Alias `{0}' cannot be used with '::' since it denotes a type. Consider replacing '::' with '.'", alias); + + return null; + } + + return fne; + } + + protected override Expression DoResolve (ResolveContext ec) + { + return ResolveAsTypeOrNamespace (ec); + } + + protected override void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier) + { + rc.Module.Compiler.Report.Error (687, loc, + "A namespace alias qualifier `{0}' did not resolve to a namespace or a type", + GetSignatureForError ()); + } + + public override string GetSignatureForError () + { + string name = Name; + if (targs != null) { + name = Name + "<" + targs.GetSignatureForError () + ">"; + } + + return alias + "::" + name; + } + + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) + { + return DoResolve (rc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + // Nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the member access expression + /// + public class MemberAccess : ATypeNameExpression + { + protected Expression expr; + + public MemberAccess (Expression expr, string id) + : base (id, expr.Location) + { + this.expr = expr; + } + + public MemberAccess (Expression expr, string identifier, Location loc) + : base (identifier, loc) + { + this.expr = expr; + } + + public MemberAccess (Expression expr, string identifier, TypeArguments args, Location loc) + : base (identifier, args, loc) + { + this.expr = expr; + } + + public MemberAccess (Expression expr, string identifier, int arity, Location loc) + : base (identifier, arity, loc) + { + this.expr = expr; + } + + public Expression LeftExpression { + get { + return expr; + } + } + + protected override Expression DoResolve (ResolveContext ec) + { + return DoResolveName (ec, null); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return DoResolveName (ec, right_side); + } + + Expression DoResolveName (ResolveContext rc, Expression right_side) + { + Expression e = LookupNameExpression (rc, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None); + if (e == null) + return null; + + if (right_side != null) { + if (e is TypeExpr) { + e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc); + return null; + } + + e = e.ResolveLValue (rc, right_side); + } else { + e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type); + } + + return e; + } + + protected virtual void Error_OperatorCannotBeApplied (ResolveContext rc, TypeSpec type) + { + 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); + } + + public static bool IsValidDotExpression (TypeSpec type) + { + const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | + MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; + + return (type.Kind & dot_kinds) != 0; + } + + public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) + { + var sn = expr as SimpleName; + const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type; + + // + // Resolve the expression with flow analysis turned off, we'll do the definite + // assignment checks later. This is because we don't know yet what the expression + // will resolve to - it may resolve to a FieldExpr and in this case we must do the + // definite assignment check on the actual field and not on the whole struct. + // + using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) { + 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 + if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) { + using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) { + expr = expr.Resolve (rc); + } + } else if (expr is TypeParameterExpr) { + expr.Error_UnexpectedKind (rc, flags, sn.Location); + expr = null; + } + } else { + expr = expr.Resolve (rc, flags); + } + } + + if (expr == null) + return null; + + Namespace ns = expr as Namespace; + if (ns != null) { + var retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc); + + if (retval == null) { + ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc); + return null; + } + + if (HasTypeArguments) + return new GenericTypeExpr (retval.Type, targs, loc); + + return retval; + } + + MemberExpr me; + TypeSpec expr_type = expr.Type; + if (expr_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + me = expr as MemberExpr; + if (me != null) + me.ResolveInstanceExpression (rc, null); + + Arguments args = new Arguments (1); + args.Add (new Argument (expr)); + return new DynamicMemberBinder (Name, args, loc); + } + + if (!IsValidDotExpression (expr_type)) { + Error_OperatorCannotBeApplied (rc, expr_type); + return null; + } + + var lookup_arity = Arity; + bool errorMode = false; + Expression member_lookup; + while (true) { + member_lookup = MemberLookup (rc, errorMode, expr_type, Name, lookup_arity, restrictions, loc); + if (member_lookup == null) { + // + // Try to look for extension method when member lookup failed + // + if (MethodGroupExpr.IsExtensionMethodArgument (expr)) { + NamespaceContainer scope = null; + var methods = rc.LookupExtensionMethod (expr_type, Name, lookup_arity, ref scope); + if (methods != null) { + var emg = new ExtensionMethodGroupExpr (methods, scope, expr, loc); + if (HasTypeArguments) { + if (!targs.Resolve (rc)) + return null; + + emg.SetTypeArguments (rc, targs); + } + + // TODO: it should really skip the checks bellow + return emg.Resolve (rc); + } + } + } + + if (errorMode) { + if (member_lookup == null) { + var dep = expr_type.GetMissingDependencies (); + if (dep != null) { + ImportedTypeDefinition.Error_MissingDependency (rc, dep, loc); + } else if (expr is TypeExpr) { + base.Error_TypeDoesNotContainDefinition (rc, expr_type, Name); + } else { + Error_TypeDoesNotContainDefinition (rc, expr_type, Name); + } + + return null; + } + + if (member_lookup is MethodGroupExpr) { + // Leave it to overload resolution to report correct error + } else if (!(member_lookup is TypeExpr)) { + // TODO: rc.SymbolRelatedToPreviousError + ErrorIsInaccesible (rc, member_lookup.GetSignatureForError (), loc); + } + break; + } + + if (member_lookup != null) + break; + + lookup_arity = 0; + restrictions &= ~MemberLookupRestrictions.InvocableOnly; + errorMode = true; + } + + TypeExpr texpr = member_lookup as TypeExpr; + if (texpr != null) { + if (!(expr is TypeExpr)) { + me = expr as MemberExpr; + if (me == null || me.ProbeIdenticalTypeName (rc, expr, sn) == expr) { + rc.Report.Error (572, loc, "`{0}': cannot reference a type through an expression; try `{1}' instead", + Name, member_lookup.GetSignatureForError ()); + return null; + } + } + + if (!texpr.Type.IsAccessible (rc)) { + rc.Report.SymbolRelatedToPreviousError (member_lookup.Type); + ErrorIsInaccesible (rc, member_lookup.Type.GetSignatureForError (), loc); + return null; + } + + if (HasTypeArguments) { + return new GenericTypeExpr (member_lookup.Type, targs, loc); + } + + return member_lookup; + } + + me = member_lookup as MemberExpr; + + if (sn != null && me.IsStatic) + expr = me.ProbeIdenticalTypeName (rc, expr, sn); + + me = me.ResolveMemberAccess (rc, expr, sn); + + if (Arity > 0) { + if (!targs.Resolve (rc)) + return null; + + 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; + } + } + + return me; + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext rc) + { + FullNamedExpression fexpr = expr as FullNamedExpression; + if (fexpr == null) { + expr.ResolveAsType (rc); + return null; + } + + FullNamedExpression expr_resolved = fexpr.ResolveAsTypeOrNamespace (rc); + + if (expr_resolved == null) + return null; + + Namespace ns = expr_resolved as Namespace; + if (ns != null) { + FullNamedExpression retval = ns.LookupTypeOrNamespace (rc, Name, Arity, LookupMode.Normal, loc); + + if (retval == null) { + ns.Error_NamespaceDoesNotExist (rc, Name, Arity, loc); + } else if (HasTypeArguments) { + retval = new GenericTypeExpr (retval.Type, targs, loc); + if (retval.ResolveAsType (rc) == null) + return null; + } + + return retval; + } + + var tnew_expr = expr_resolved.ResolveAsType (rc); + if (tnew_expr == null) + return null; + + TypeSpec expr_type = tnew_expr; + if (TypeManager.IsGenericParameter (expr_type)) { + rc.Module.Compiler.Report.Error (704, loc, "A nested type cannot be specified through a type parameter `{0}'", + tnew_expr.GetSignatureForError ()); + return null; + } + + TypeSpec nested = null; + while (expr_type != null) { + nested = MemberCache.FindNestedType (expr_type, Name, Arity); + if (nested == null) { + if (expr_type == tnew_expr) { + Error_IdentifierNotFound (rc, expr_type, Name); + return null; + } + + expr_type = tnew_expr; + nested = MemberCache.FindNestedType (expr_type, Name, Arity); + ErrorIsInaccesible (rc, nested.GetSignatureForError (), loc); + break; + } + + if (nested.IsAccessible (rc)) + break; + + // Keep looking after inaccessible candidate + expr_type = nested.DeclaringType.BaseType; + } + + TypeExpr texpr; + if (Arity > 0) { + if (HasTypeArguments) { + texpr = new GenericTypeExpr (nested, targs, loc); + } else { + texpr = new GenericOpenTypeExpr (nested, loc); + } + } else { + texpr = new TypeExpression (nested, loc); + } + + if (texpr.ResolveAsType (rc) == null) + return null; + + return texpr; + } + + protected virtual void Error_IdentifierNotFound (IMemberContext rc, TypeSpec expr_type, string identifier) + { + var nested = MemberCache.FindNestedType (expr_type, Name, -System.Math.Max (1, Arity)); + + if (nested != null) { + Error_TypeArgumentsCannotBeUsed (rc, nested, Arity, expr.Location); + return; + } + + var any_other_member = MemberLookup (rc, true, expr_type, Name, 0, MemberLookupRestrictions.None, loc); + if (any_other_member != null) { + any_other_member.Error_UnexpectedKind (rc.Module.Compiler.Report, null, "type", loc); + return; + } + + rc.Module.Compiler.Report.Error (426, loc, "The nested type `{0}' does not exist in the type `{1}'", + Name, expr_type.GetSignatureForError ()); + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + if (ec.Module.Compiler.Settings.Version > LanguageVersion.ISO_2 && !ec.IsRuntimeBinder && MethodGroupExpr.IsExtensionMethodArgument (expr)) { + ec.Report.SymbolRelatedToPreviousError (type); + ec.Report.Error (1061, loc, + "Type `{0}' does not contain a definition for `{1}' and no extension method `{1}' of type `{0}' could be found (are you missing a using directive or an assembly reference?)", + type.GetSignatureForError (), name); + return; + } + + base.Error_TypeDoesNotContainDefinition (ec, type, name); + } + + public override string GetSignatureForError () + { + return expr.GetSignatureForError () + "." + base.GetSignatureForError (); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + MemberAccess target = (MemberAccess) t; + + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements checked expressions + /// + public class CheckedExpr : Expression { + + public Expression Expr; + + public CheckedExpr (Expression e, Location l) + { + Expr = e; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, true)) + return Expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, true)) + Expr = Expr.Resolve (ec); + + if (Expr == null) + return null; + + if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression) + return Expr; + + eclass = Expr.eclass; + type = Expr.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + Expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + Expr.EmitBranchable (ec, target, on_true); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { + return Expr.MakeExpression (ctx); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CheckedExpr target = (CheckedExpr) t; + + target.Expr = Expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements the unchecked expression + /// + public class UnCheckedExpr : Expression { + + public Expression Expr; + + public UnCheckedExpr (Expression e, Location l) + { + Expr = e; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, false)) + return Expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, false)) + Expr = Expr.Resolve (ec); + + if (Expr == null) + return null; + + if (Expr is Constant || Expr is MethodGroupExpr || Expr is AnonymousMethodExpression || Expr is DefaultValueExpression) + return Expr; + + eclass = Expr.eclass; + type = Expr.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + Expr.Emit (ec); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool on_true) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + Expr.EmitBranchable (ec, target, on_true); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + UnCheckedExpr target = (UnCheckedExpr) t; + + target.Expr = Expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// An Element Access expression. + /// + /// During semantic analysis these are transformed into + /// IndexerAccess, ArrayAccess or a PointerArithmetic. + /// + public class ElementAccess : Expression { + public Arguments Arguments; + public Expression Expr; + + public ElementAccess (Expression e, Arguments args, Location loc) + { + Expr = e; + this.loc = loc; + this.Arguments = args; + } + + // + // We perform some simple tests, and then to "split" the emit and store + // code we create an instance of a different class, and return that. + // + Expression CreateAccessExpression (ResolveContext ec) + { + if (type.IsArray) + return (new ArrayAccess (this, loc)); + + if (type.IsPointer) + return MakePointerAccess (ec, type); + + FieldExpr fe = Expr as FieldExpr; + if (fe != null) { + var ff = fe.Spec as FixedFieldSpec; + if (ff != null) { + return MakePointerAccess (ec, ff.ElementType); + } + } + + var indexers = MemberCache.FindMembers (type, MemberCache.IndexerNameAlias, false); + if (indexers != null || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return new IndexerExpr (indexers, type, this); + } + + ec.Report.Error (21, loc, "Cannot apply indexing with [] to an expression of type `{0}'", + type.GetSignatureForError ()); + return null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, Arguments, + Expr.CreateExpressionTree (ec)); + + return CreateExpressionFactoryCall (ec, "ArrayIndex", args); + } + + Expression MakePointerAccess (ResolveContext ec, TypeSpec type) + { + if (Arguments.Count != 1){ + ec.Report.Error (196, loc, "A pointer must be indexed by only one value"); + return null; + } + + if (Arguments [0] is NamedArgument) + Error_NamedArgument ((NamedArgument) Arguments[0], ec.Report); + + Expression p = new PointerArithmetic (Binary.Operator.Addition, Expr, Arguments [0].Expr.Resolve (ec), type, loc); + return new Indirection (p, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expr = Expr.Resolve (ec); + if (Expr == null) + return null; + + type = Expr.Type; + + // TODO: Create 1 result for Resolve and ResolveLValue ? + var res = CreateAccessExpression (ec); + if (res == null) + return null; + + return res.Resolve (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + Expr = Expr.Resolve (ec); + if (Expr == null) + return null; + + type = Expr.Type; + + var res = CreateAccessExpression (ec); + if (res == null) + return null; + + return res.ResolveLValue (ec, right_side); + } + + public override void Emit (EmitContext ec) + { + throw new Exception ("Should never be reached"); + } + + public static void Error_NamedArgument (NamedArgument na, Report Report) + { + Report.Error (1742, na.Location, "An element access expression cannot use named argument"); + } + + public override string GetSignatureForError () + { + return Expr.GetSignatureForError (); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + ElementAccess target = (ElementAccess) t; + + target.Expr = Expr.Clone (clonectx); + if (Arguments != null) + target.Arguments = Arguments.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implements array access + /// + public class ArrayAccess : Expression, IDynamicAssign, IMemoryLocation { + // + // Points to our "data" repository + // + ElementAccess ea; + + LocalTemporary temp, expr_copy; + Expression[] prepared_arguments; + bool prepared; + + public ArrayAccess (ElementAccess ea_data, Location l) + { + ea = ea_data; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return ea.CreateExpressionTree (ec); + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return DoResolve (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // dynamic is used per argument in ConvertExpressionToArrayIndex case + bool dynamic; + ea.Arguments.Resolve (ec, out dynamic); + + var ac = ea.Expr.Type as ArrayContainer; + int rank = ea.Arguments.Count; + if (ac.Rank != rank) { + ec.Report.Error (22, ea.Location, "Wrong number of indexes `{0}' inside [], expected `{1}'", + rank.ToString (), ac.Rank.ToString ()); + return null; + } + + type = ac.Element; + if (type.IsPointer && !ec.IsUnsafe) { + UnsafeError (ec, ea.Location); + } + + foreach (Argument a in ea.Arguments) { + if (a is NamedArgument) + ElementAccess.Error_NamedArgument ((NamedArgument) a, ec.Report); + + a.Expr = ConvertExpressionToArrayIndex (ec, a.Expr); + } + + eclass = ExprClass.Variable; + + return this; + } + + protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)"); + } + + // + // Load the array arguments into the stack. + // + void LoadArrayAndArguments (EmitContext ec) + { + ea.Expr.Emit (ec); + ea.Arguments.Emit (ec); + } + + public void Emit (EmitContext ec, bool leave_copy) + { + var ac = ea.Expr.Type as ArrayContainer; + + if (prepared) { + ec.EmitLoadFromPtr (type); + } else { + if (prepared_arguments == null) { + LoadArrayAndArguments (ec); + } else { + expr_copy.Emit (ec); + LocalTemporary lt; + foreach (var expr in prepared_arguments) { + expr.Emit (ec); + lt = expr as LocalTemporary; + if (lt != null) + lt.Release (ec); + } + } + + ec.EmitArrayLoad (ac); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (this.type); + temp.Store (ec); + } + } + + public override void Emit (EmitContext ec) + { + Emit (ec, false); + } + + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + var ac = (ArrayContainer) ea.Expr.Type; + TypeSpec t = source.Type; + + // + // When we are dealing with a struct, get the address of it to avoid value copy + // Same cannot be done for reference type because array covariance and the + // check in ldelema requires to specify the type of array element stored at the index + // + if (t.IsStruct && ((prepare_for_load && !(source is DynamicExpressionStatement)) || !BuiltinTypeSpec.IsPrimitiveType (t))) { + LoadArrayAndArguments (ec); + ec.EmitArrayAddress (ac); + + if (prepare_for_load) { + ec.Emit (OpCodes.Dup); + } + + prepared = true; + } else if (prepare_for_load) { + ea.Expr.Emit (ec); + ec.Emit (OpCodes.Dup); + + expr_copy = new LocalTemporary (ea.Expr.Type); + expr_copy.Store (ec); + prepared_arguments = ea.Arguments.Emit (ec, true); + } else { + LoadArrayAndArguments (ec); + } + + source.Emit (ec); + + if (expr_copy != null) { + expr_copy.Release (ec); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (this.type); + temp.Store (ec); + } + + if (prepared) { + ec.EmitStoreFromPtr (t); + } else { + ec.EmitArrayStore (ac); + } + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + public void EmitNew (EmitContext ec, New source, bool leave_copy) + { + if (!source.Emit (ec, this)) { + if (leave_copy) + throw new NotImplementedException (); + + return; + } + + throw new NotImplementedException (); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + var ac = (ArrayContainer) ea.Expr.Type; + + LoadArrayAndArguments (ec); + + if (ac.Element.IsGenericParameter && mode == AddressOp.Load) + ec.Emit (OpCodes.Readonly); + + ec.EmitArrayAddress (ac); + } + + public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { +#if NET_4_0 + return SLE.Expression.ArrayAccess (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx)); +#else + throw new NotImplementedException (); +#endif + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { + return SLE.Expression.ArrayIndex (ea.Expr.MakeExpression (ctx), MakeExpressionArguments (ctx)); + } + + SLE.Expression[] MakeExpressionArguments (BuilderContext ctx) + { + using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { + return Arguments.MakeExpression (ea.Arguments, ctx); + } + } + } + + // + // Indexer access expression + // + class IndexerExpr : PropertyOrIndexerExpr, OverloadResolver.IBaseMembersProvider + { + LocalTemporary prepared_value; + IList indexers; + Arguments arguments; + TypeSpec queried_type; + + public IndexerExpr (IList indexers, TypeSpec queriedType, ElementAccess ea) + : base (ea.Location) + { + this.indexers = indexers; + this.queried_type = queriedType; + this.InstanceExpression = ea.Expr; + this.arguments = ea.Arguments; + } + + #region Properties + + protected override TypeSpec DeclaringType { + get { + return best_candidate.DeclaringType; + } + } + + public override bool IsInstance { + get { + return true; + } + } + + public override bool IsStatic { + get { + return false; + } + } + + public override string Name { + get { + return "this"; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = Arguments.CreateForExpressionTree (ec, arguments, + InstanceExpression.CreateExpressionTree (ec), + new TypeOfMethod (Getter, loc)); + + return CreateExpressionFactoryCall (ec, "Call", args); + } + + public override void Emit (EmitContext ec, bool leave_copy) + { + if (prepared) { + prepared_value.Emit (ec); + } else { + Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc); + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + + public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + { + prepared = prepare_for_load; + Expression value = source; + + if (prepared) { + Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc, true, false); + + prepared_value = new LocalTemporary (type); + prepared_value.Store (ec); + source.Emit (ec); + prepared_value.Release (ec); + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } else if (leave_copy) { + temp = new LocalTemporary (Type); + source.Emit (ec); + temp.Store (ec); + value = temp; + } + + if (!prepared) + arguments.Add (new Argument (value)); + + Invocation.EmitCall (ec, InstanceExpression, Setter, arguments, loc, false, prepared); + + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } + } + + public override string GetSignatureForError () + { + return best_candidate.GetSignatureForError (); + } + + public override SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) + { +#if STATIC + throw new NotSupportedException (); +#else + var value = new[] { source.MakeExpression (ctx) }; + var args = Arguments.MakeExpression (arguments, ctx).Concat (value); +#if NET_4_0 + return SLE.Expression.Block ( + SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Setter.GetMetaInfo (), args), + value [0]); +#else + return args.First (); +#endif +#endif + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + var args = Arguments.MakeExpression (arguments, ctx); + return SLE.Expression.Call (InstanceExpression.MakeExpression (ctx), (MethodInfo) Getter.GetMetaInfo (), args); +#endif + } + + protected override Expression OverloadResolve (ResolveContext rc, Expression right_side) + { + if (best_candidate != null) + return this; + + eclass = ExprClass.IndexerAccess; + + bool dynamic; + arguments.Resolve (rc, out dynamic); + + if (indexers == null && InstanceExpression.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + dynamic = true; + } else { + var res = new OverloadResolver (indexers, OverloadResolver.Restrictions.None, loc); + res.BaseMembersProvider = this; + + // TODO: Do I need 2 argument sets? + best_candidate = res.ResolveMember (rc, ref arguments); + if (best_candidate != null) + type = res.BestCandidateReturnType; + else if (!res.BestCandidateIsDynamic) + return null; + } + + // + // It has dynamic arguments + // + if (dynamic) { + Arguments args = new Arguments (arguments.Count + 1); + if (IsBase) { + rc.Report.Error (1972, loc, + "The indexer base access cannot be dynamically dispatched. Consider casting the dynamic arguments or eliminating the base access"); + } else { + args.Add (new Argument (InstanceExpression)); + } + args.AddRange (arguments); + + best_candidate = null; + return new DynamicIndexBinder (args, loc); + } + + ResolveInstanceExpression (rc, right_side); + CheckProtectedMemberAccess (rc, best_candidate); + return this; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + IndexerExpr target = (IndexerExpr) t; + + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + } + + public override void SetTypeArguments (ResolveContext ec, TypeArguments ta) + { + Error_TypeArgumentsCannotBeUsed (ec, "indexer", GetSignatureForError (), loc); + } + + #region IBaseMembersProvider Members + + IList OverloadResolver.IBaseMembersProvider.GetBaseMembers (TypeSpec baseType) + { + return baseType == null ? null : MemberCache.FindMembers (baseType, MemberCache.IndexerNameAlias, false); + } + + IParametersMember OverloadResolver.IBaseMembersProvider.GetOverrideMemberParameters (MemberSpec member) + { + if (queried_type == member.DeclaringType) + return null; + + var filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, MemberKind.Indexer, ((IndexerSpec) member).Parameters, null); + return MemberCache.FindMember (queried_type, filter, BindingRestriction.InstanceOnly | BindingRestriction.OverrideOnly) as IParametersMember; + } + + MethodGroupExpr OverloadResolver.IBaseMembersProvider.LookupExtensionMethod (ResolveContext rc) + { + return null; + } + + #endregion + } + + // + // A base access expression + // + public class BaseThis : This + { + public BaseThis (Location loc) + : base (loc) + { + } + + public BaseThis (TypeSpec type, Location loc) + : base (loc) + { + this.type = type; + eclass = ExprClass.Variable; + } + + #region Properties + + public override string Name { + get { + return "base"; + } + } + + #endregion + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (831, loc, "An expression tree may not contain a base access"); + return base.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + var context_type = ec.CurrentType; + if (context_type.IsStruct) { + ec.Emit (OpCodes.Ldobj, context_type); + ec.Emit (OpCodes.Box, context_type); + } + } + + protected override void Error_ThisNotAvailable (ResolveContext ec) + { + if (ec.IsStatic) { + ec.Report.Error (1511, loc, "Keyword `base' is not available in a static method"); + } else { + ec.Report.Error (1512, loc, "Keyword `base' is not available in the current context"); + } + } + + public override void ResolveBase (ResolveContext ec) + { + base.ResolveBase (ec); + type = ec.CurrentType.BaseType; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// This class exists solely to pass the Type around and to be a dummy + /// that can be passed to the conversion functions (this is used by + /// foreach implementation to typecast the object return value from + /// get_Current into the proper type. All code has been generated and + /// we only care about the side effect conversions to be performed + /// + /// This is also now used as a placeholder where a no-action expression + /// is needed (the `New' class). + /// + class EmptyExpression : Expression + { + sealed class OutAccessExpression : EmptyExpression + { + public OutAccessExpression (TypeSpec t) + : base (t) + { + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + rc.Report.Error (206, right_side.Location, + "A property, indexer or dynamic member access may not be passed as `ref' or `out' parameter"); + + return null; + } + } + + public static readonly EmptyExpression LValueMemberAccess = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression LValueMemberOutAccess = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression UnaryAddress = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression EventAddition = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression EventSubtraction = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression MissingValue = new EmptyExpression (InternalType.FakeInternalType); + public static readonly Expression Null = new EmptyExpression (InternalType.FakeInternalType); + public static readonly EmptyExpression OutAccess = new OutAccessExpression (InternalType.FakeInternalType); + + public EmptyExpression (TypeSpec t) + { + type = t; + eclass = ExprClass.Value; + loc = Location.Null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + // nothing, as we only exist to not do anything. + } + + public override void EmitSideEffect (EmitContext ec) + { + } + } + + // + // Empty statement expression + // + public sealed class EmptyExpressionStatement : ExpressionStatement + { + public static readonly EmptyExpressionStatement Instance = new EmptyExpressionStatement (); + + private EmptyExpressionStatement () + { + loc = Location.Null; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return null; + } + + public override void EmitStatement (EmitContext ec) + { + // Do nothing + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + type = ec.BuiltinTypes.Object; + return this; + } + + public override void Emit (EmitContext ec) + { + // Do nothing + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + class ErrorExpression : EmptyExpression + { + public static readonly ErrorExpression Instance = new ErrorExpression (); + + private ErrorExpression () + : base (InternalType.FakeInternalType) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + return this; + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + } + } + + public class UserCast : Expression { + MethodSpec method; + Expression source; + + public UserCast (MethodSpec method, Expression source, Location l) + { + this.method = method; + this.source = source; + type = method.ReturnType; + loc = l; + } + + public Expression Source { + get { + return source; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (3); + args.Add (new Argument (source.CreateExpressionTree (ec))); + args.Add (new Argument (new TypeOf (type, loc))); + args.Add (new Argument (new TypeOfMethod (method, loc))); + return CreateExpressionFactoryCall (ec, "Convert", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + ObsoleteAttribute oa = method.GetAttributeObsolete (); + if (oa != null) + AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report); + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + source.Emit (ec); + ec.Emit (OpCodes.Call, method); + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpSignature (method); + } + + public override SLE.Expression MakeExpression (BuilderContext ctx) + { +#if STATIC + return base.MakeExpression (ctx); +#else + return SLE.Expression.Convert (source.MakeExpression (ctx), type.GetMetaInfo (), (MethodInfo) method.GetMetaInfo ()); +#endif + } + } + + // + // Holds additional type specifiers like ?, *, [] + // + public class ComposedTypeSpecifier + { + public static readonly ComposedTypeSpecifier SingleDimension = new ComposedTypeSpecifier (1, Location.Null); + + public readonly int Dimension; + public readonly Location Location; + + public ComposedTypeSpecifier (int specifier, Location loc) + { + this.Dimension = specifier; + this.Location = loc; + } + + #region Properties + public bool IsNullable { + get { + return Dimension == -1; + } + } + + public bool IsPointer { + get { + return Dimension == -2; + } + } + + public ComposedTypeSpecifier Next { get; set; } + + #endregion + + public static ComposedTypeSpecifier CreateArrayDimension (int dimension, Location loc) + { + return new ComposedTypeSpecifier (dimension, loc); + } + + public static ComposedTypeSpecifier CreateNullable (Location loc) + { + return new ComposedTypeSpecifier (-1, loc); + } + + public static ComposedTypeSpecifier CreatePointer (Location loc) + { + return new ComposedTypeSpecifier (-2, loc); + } + + public string GetSignatureForError () + { + string s = + IsPointer ? "*" : + IsNullable ? "?" : + ArrayContainer.GetPostfixSignature (Dimension); + + return Next != null ? s + Next.GetSignatureForError () : s; + } + } + + // + // This class is used to "construct" the type during a typecast + // operation. Since the Type.GetType class in .NET can parse + // the type specification, we just use this to construct the type + // one bit at a time. + // + public class ComposedCast : TypeExpr { + FullNamedExpression left; + ComposedTypeSpecifier spec; + + public FullNamedExpression Left { + get { return this.left; } + } + + public ComposedTypeSpecifier Spec { + get { + return this.spec; + } + } + + public ComposedCast (FullNamedExpression left, ComposedTypeSpecifier spec) + { + if (spec == null) + throw new ArgumentNullException ("spec"); + + this.left = left; + this.spec = spec; + this.loc = spec.Location; + } + + public override TypeSpec ResolveAsType (IMemberContext ec) + { + type = left.ResolveAsType (ec); + if (type == null) + return null; + + eclass = ExprClass.Type; + + var single_spec = spec; + + if (single_spec.IsNullable) { + type = new Nullable.NullableType (type, loc).ResolveAsType (ec); + if (type == null) + return null; + + single_spec = single_spec.Next; + } else if (single_spec.IsPointer) { + if (!TypeManager.VerifyUnmanaged (ec.Module, type, loc)) + return null; + + if (!ec.IsUnsafe) { + UnsafeError (ec.Module.Compiler.Report, loc); + } + + do { + type = PointerContainer.MakeType (ec.Module, type); + single_spec = single_spec.Next; + } while (single_spec != null && single_spec.IsPointer); + } + + if (single_spec != null && single_spec.Dimension > 0) { + if (type.IsSpecialRuntimeType) { + ec.Module.Compiler.Report.Error (611, loc, "Array elements cannot be of type `{0}'", type.GetSignatureForError ()); + } else if (type.IsStatic) { + ec.Module.Compiler.Report.SymbolRelatedToPreviousError (type); + ec.Module.Compiler.Report.Error (719, loc, "Array elements cannot be of static type `{0}'", + type.GetSignatureForError ()); + } else { + MakeArray (ec.Module, single_spec); + } + } + + return type; + } + + void MakeArray (ModuleContainer module, ComposedTypeSpecifier spec) + { + if (spec.Next != null) + MakeArray (module, spec.Next); + + type = ArrayContainer.MakeType (module, type, spec.Dimension); + } + + public override string GetSignatureForError () + { + return left.GetSignatureForError () + spec.GetSignatureForError (); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + class FixedBufferPtr : Expression + { + readonly Expression array; + + public FixedBufferPtr (Expression array, TypeSpec array_type, Location l) + { + this.type = array_type; + this.array = array; + this.loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } + + public override void Emit(EmitContext ec) + { + array.Emit (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + type = PointerContainer.MakeType (ec.Module, type); + eclass = ExprClass.Value; + return this; + } + } + + + // + // This class is used to represent the address of an array, used + // only by the Fixed statement, this generates "&a [0]" construct + // for fixed (char *pa = a) + // + class ArrayPtr : FixedBufferPtr + { + public ArrayPtr (Expression array, TypeSpec array_type, Location l): + base (array, array_type, l) + { + } + + public override void Emit (EmitContext ec) + { + base.Emit (ec); + + ec.EmitInt (0); + ec.Emit (OpCodes.Ldelema, ((PointerContainer) type).Element); + } + } + + // + // Encapsulates a conversion rules required for array indexes + // + public class ArrayIndexCast : TypeCast + { + public ArrayIndexCast (Expression expr, TypeSpec returnType) + : base (expr, returnType) + { + if (expr.Type == returnType) // int -> int + throw new ArgumentException ("unnecessary array index conversion"); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + using (ec.Set (ResolveContext.Options.CheckedScope)) { + return base.CreateExpressionTree (ec); + } + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + + switch (child.Type.BuiltinType) { + case BuiltinTypeSpec.Type.UInt: + ec.Emit (OpCodes.Conv_U); + break; + case BuiltinTypeSpec.Type.Long: + ec.Emit (OpCodes.Conv_Ovf_I); + break; + case BuiltinTypeSpec.Type.ULong: + ec.Emit (OpCodes.Conv_Ovf_I_Un); + break; + default: + throw new InternalErrorException ("Cannot emit cast to unknown array element type", type); + } + } + } + + // + // Implements the `stackalloc' keyword + // + public class StackAlloc : Expression { + TypeSpec otype; + Expression t; + Expression count; + + public Expression TypeExpression { + get { return this.t; } + } + + public Expression CountExpression { + get { return this.count; } + } + + public StackAlloc (Expression type, Expression count, Location l) + { + t = type; + this.count = count; + loc = l; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + count = count.Resolve (ec); + if (count == null) + return null; + + if (count.Type.BuiltinType != BuiltinTypeSpec.Type.UInt){ + count = Convert.ImplicitConversionRequired (ec, count, ec.BuiltinTypes.Int, loc); + if (count == null) + return null; + } + + Constant c = count as Constant; + if (c != null && c.IsNegative) { + ec.Report.Error (247, loc, "Cannot use a negative size with stackalloc"); + } + + if (ec.HasAny (ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope)) { + ec.Report.Error (255, loc, "Cannot use stackalloc in finally or catch"); + } + + otype = t.ResolveAsType (ec); + if (otype == null) + return null; + + if (!TypeManager.VerifyUnmanaged (ec.Module, otype, loc)) + return null; + + type = PointerContainer.MakeType (ec.Module, otype); + eclass = ExprClass.Value; + + return this; + } + + public override void Emit (EmitContext ec) + { + int size = BuiltinTypeSpec.GetSize (otype); + + count.Emit (ec); + + if (size == 0) + ec.Emit (OpCodes.Sizeof, otype); + else + ec.EmitInt (size); + + ec.Emit (OpCodes.Mul_Ovf_Un); + ec.Emit (OpCodes.Localloc); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + StackAlloc target = (StackAlloc) t; + target.count = count.Clone (clonectx); + target.t = t.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // An object initializer expression + // + public class ElementInitializer : Assign + { + public readonly string Name; + + public ElementInitializer (string name, Expression initializer, Location loc) + : base (null, initializer, loc) + { + this.Name = name; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + ElementInitializer target = (ElementInitializer) t; + target.source = source.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + FieldExpr fe = target as FieldExpr; + if (fe != null) + args.Add (new Argument (fe.CreateTypeOfExpression ())); + else + args.Add (new Argument (((PropertyExpr)target).CreateSetterTypeOfExpression ())); + + args.Add (new Argument (source.CreateExpressionTree (ec))); + return CreateExpressionFactoryCall (ec, + source is CollectionOrObjectInitializers ? "ListBind" : "Bind", + args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (source == null) + return EmptyExpressionStatement.Instance; + + var t = ec.CurrentInitializerVariable.Type; + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Arguments args = new Arguments (1); + args.Add (new Argument (ec.CurrentInitializerVariable)); + target = new DynamicMemberBinder (Name, args, loc); + } else { + + var member = MemberLookup (ec, false, t, Name, 0, MemberLookupRestrictions.ExactArity, loc); + if (member == null) { + member = Expression.MemberLookup (ec, true, t, Name, 0, MemberLookupRestrictions.ExactArity, loc); + + if (member != null) { + // TODO: ec.Report.SymbolRelatedToPreviousError (member); + ErrorIsInaccesible (ec, member.GetSignatureForError (), loc); + return null; + } + } + + if (member == null) { + Error_TypeDoesNotContainDefinition (ec, loc, t, Name); + return null; + } + + if (!(member is PropertyExpr || member is FieldExpr)) { + ec.Report.Error (1913, loc, + "Member `{0}' cannot be initialized. An object initializer may only be used for fields, or properties", + member.GetSignatureForError ()); + + return null; + } + + var me = member as MemberExpr; + if (me.IsStatic) { + ec.Report.Error (1914, loc, + "Static field or property `{0}' cannot be assigned in an object initializer", + me.GetSignatureForError ()); + } + + target = me; + me.InstanceExpression = ec.CurrentInitializerVariable; + } + + if (source is CollectionOrObjectInitializers) { + Expression previous = ec.CurrentInitializerVariable; + ec.CurrentInitializerVariable = target; + source = source.Resolve (ec); + ec.CurrentInitializerVariable = previous; + if (source == null) + return null; + + eclass = source.eclass; + type = source.Type; + return this; + } + + return base.DoResolve (ec); + } + + public override void EmitStatement (EmitContext ec) + { + if (source is CollectionOrObjectInitializers) + source.Emit (ec); + else + base.EmitStatement (ec); + } + } + + // + // A collection initializer expression + // + class CollectionElementInitializer : Invocation + { + public class ElementInitializerArgument : Argument + { + public ElementInitializerArgument (Expression e) + : base (e) + { + } + } + + sealed class AddMemberAccess : MemberAccess + { + public AddMemberAccess (Expression expr, Location loc) + : base (expr, "Add", loc) + { + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + if (TypeManager.HasElementType (type)) + return; + + base.Error_TypeDoesNotContainDefinition (ec, type, name); + } + } + + public CollectionElementInitializer (Expression argument) + : base (null, new Arguments (1)) + { + base.arguments.Add (new ElementInitializerArgument (argument)); + this.loc = argument.Location; + } + + public CollectionElementInitializer (List arguments, Location loc) + : base (null, new Arguments (arguments.Count)) + { + foreach (Expression e in arguments) + base.arguments.Add (new ElementInitializerArgument (e)); + + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (mg.CreateExpressionTree (ec))); + + var expr_initializers = new ArrayInitializer (arguments.Count, loc); + foreach (Argument a in arguments) + expr_initializers.Add (a.CreateExpressionTree (ec)); + + args.Add (new Argument (new ArrayCreation ( + CreateExpressionTypeExpression (ec, loc), expr_initializers, loc))); + return CreateExpressionFactoryCall (ec, "ElementInit", args); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + CollectionElementInitializer target = (CollectionElementInitializer) t; + if (arguments != null) + target.arguments = arguments.Clone (clonectx); + } + + protected override Expression DoResolve (ResolveContext ec) + { + base.expr = new AddMemberAccess (ec.CurrentInitializerVariable, loc); + + return base.DoResolve (ec); + } + } + + // + // A block of object or collection initializers + // + public class CollectionOrObjectInitializers : ExpressionStatement + { + IList initializers; + bool is_collection_initialization; + + public static readonly CollectionOrObjectInitializers Empty = + new CollectionOrObjectInitializers (Array.AsReadOnly (new Expression [0]), Location.Null); + + public CollectionOrObjectInitializers (IList initializers, Location loc) + { + this.initializers = initializers; + this.loc = loc; + } + + public bool IsEmpty { + get { + return initializers.Count == 0; + } + } + + public bool IsCollectionInitializer { + get { + return is_collection_initialization; + } + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target; + + t.initializers = new List (initializers.Count); + foreach (var e in initializers) + t.initializers.Add (e.Clone (clonectx)); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + var expr_initializers = new ArrayInitializer (initializers.Count, loc); + foreach (Expression e in initializers) { + Expression expr = e.CreateExpressionTree (ec); + if (expr != null) + expr_initializers.Add (expr); + } + + return new ImplicitlyTypedArrayCreation (expr_initializers, loc); + } + + protected override Expression DoResolve (ResolveContext ec) + { + List element_names = null; + for (int i = 0; i < initializers.Count; ++i) { + Expression initializer = initializers [i]; + ElementInitializer element_initializer = initializer as ElementInitializer; + + if (i == 0) { + if (element_initializer != null) { + element_names = new List (initializers.Count); + element_names.Add (element_initializer.Name); + } else if (initializer is CompletingExpression){ + initializer.Resolve (ec); + throw new InternalErrorException ("This line should never be reached"); + } else { + var t = ec.CurrentInitializerVariable.Type; + // LAMESPEC: The collection must implement IEnumerable only, no dynamic support + if (!t.ImplementsInterface (ec.BuiltinTypes.IEnumerable, false) && t.BuiltinType != BuiltinTypeSpec.Type.Dynamic) { + ec.Report.Error (1922, loc, "A field or property `{0}' cannot be initialized with a collection " + + "object initializer because type `{1}' does not implement `{2}' interface", + ec.CurrentInitializerVariable.GetSignatureForError (), + TypeManager.CSharpName (ec.CurrentInitializerVariable.Type), + TypeManager.CSharpName (ec.BuiltinTypes.IEnumerable)); + return null; + } + is_collection_initialization = true; + } + } else { + if (is_collection_initialization != (element_initializer == null)) { + ec.Report.Error (747, initializer.Location, "Inconsistent `{0}' member declaration", + is_collection_initialization ? "collection initializer" : "object initializer"); + continue; + } + + if (!is_collection_initialization) { + if (element_names.Contains (element_initializer.Name)) { + ec.Report.Error (1912, element_initializer.Location, + "An object initializer includes more than one member `{0}' initialization", + element_initializer.Name); + } else { + element_names.Add (element_initializer.Name); + } + } + } + + Expression e = initializer.Resolve (ec); + if (e == EmptyExpressionStatement.Instance) + initializers.RemoveAt (i--); + else + initializers [i] = e; + } + + type = ec.CurrentInitializerVariable.Type; + if (is_collection_initialization) { + if (TypeManager.HasElementType (type)) { + ec.Report.Error (1925, loc, "Cannot initialize object of type `{0}' with a collection initializer", + TypeManager.CSharpName (type)); + } + } + + eclass = ExprClass.Variable; + return this; + } + + public override void Emit (EmitContext ec) + { + EmitStatement (ec); + } + + public override void EmitStatement (EmitContext ec) + { + foreach (ExpressionStatement e in initializers) + e.EmitStatement (ec); + } + } + + // + // New expression with element/object initializers + // + public class NewInitialize : New + { + // + // This class serves as a proxy for variable initializer target instances. + // A real variable is assigned later when we resolve left side of an + // assignment + // + sealed class InitializerTargetExpression : Expression, IMemoryLocation + { + NewInitialize new_instance; + + public InitializerTargetExpression (NewInitialize newInstance) + { + this.type = newInstance.type; + this.loc = newInstance.loc; + this.eclass = newInstance.eclass; + this.new_instance = newInstance; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + // Should not be reached + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + return this; + } + + public override void Emit (EmitContext ec) + { + Expression e = (Expression) new_instance.instance; + e.Emit (ec); + } + + #region IMemoryLocation Members + + public void AddressOf (EmitContext ec, AddressOp mode) + { + new_instance.instance.AddressOf (ec, mode); + } + + #endregion + } + + CollectionOrObjectInitializers initializers; + IMemoryLocation instance; + + public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l) + : base (requested_type, arguments, l) + { + this.initializers = initializers; + } + + protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode) + { + instance = base.EmitAddressOf (ec, Mode); + + if (!initializers.IsEmpty) + initializers.Emit (ec); + + return instance; + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + base.CloneTo (clonectx, t); + + NewInitialize target = (NewInitialize) t; + target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Arguments args = new Arguments (2); + args.Add (new Argument (base.CreateExpressionTree (ec))); + if (!initializers.IsEmpty) + args.Add (new Argument (initializers.CreateExpressionTree (ec))); + + return CreateExpressionFactoryCall (ec, + initializers.IsCollectionInitializer ? "ListInit" : "MemberInit", + args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = base.DoResolve (ec); + if (type == null) + return null; + + Expression previous = ec.CurrentInitializerVariable; + ec.CurrentInitializerVariable = new InitializerTargetExpression (this); + initializers.Resolve (ec); + ec.CurrentInitializerVariable = previous; + return e; + } + + public override bool Emit (EmitContext ec, IMemoryLocation target) + { + bool left_on_stack = base.Emit (ec, target); + + if (initializers.IsEmpty) + return left_on_stack; + + LocalTemporary temp = target as LocalTemporary; + if (temp == null) { + if (!left_on_stack) { + VariableReference vr = target as VariableReference; + + // FIXME: This still does not work correctly for pre-set variables + if (vr != null && vr.IsRef) + target.AddressOf (ec, AddressOp.Load); + + ((Expression) target).Emit (ec); + left_on_stack = true; + } + + temp = new LocalTemporary (type); + } + + instance = temp; + if (left_on_stack) + temp.Store (ec); + + initializers.Emit (ec); + + if (left_on_stack) { + temp.Emit (ec); + temp.Release (ec); + } + + return left_on_stack; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class NewAnonymousType : New + { + static readonly AnonymousTypeParameter[] EmptyParameters = new AnonymousTypeParameter[0]; + + List parameters; + readonly TypeContainer parent; + AnonymousTypeClass anonymous_type; + + public List Parameters { + get { return this.parameters; } + } + + public NewAnonymousType (List parameters, TypeContainer parent, Location loc) + : base (null, null, loc) + { + this.parameters = parameters; + this.parent = parent; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + if (parameters == null) + return; + + NewAnonymousType t = (NewAnonymousType) target; + t.parameters = new List (parameters.Count); + foreach (AnonymousTypeParameter atp in parameters) + t.parameters.Add ((AnonymousTypeParameter) atp.Clone (clonectx)); + } + + AnonymousTypeClass CreateAnonymousType (ResolveContext ec, IList parameters) + { + AnonymousTypeClass type = parent.Module.GetAnonymousType (parameters); + if (type != null) + return type; + + type = AnonymousTypeClass.Create (parent, parameters, loc); + if (type == null) + return null; + + type.CreateType (); + type.DefineType (); + type.ResolveTypeParameters (); + type.Define (); + type.EmitType (); + if (ec.Report.Errors == 0) + type.CloseType (); + + parent.Module.AddAnonymousType (type); + return type; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (parameters == null) + return base.CreateExpressionTree (ec); + + var init = new ArrayInitializer (parameters.Count, loc); + foreach (Property p in anonymous_type.Properties) + init.Add (new TypeOfMethod (MemberCache.GetMember (type, p.Get.Spec), loc)); + + var ctor_args = new ArrayInitializer (arguments.Count, loc); + foreach (Argument a in arguments) + ctor_args.Add (a.CreateExpressionTree (ec)); + + Arguments args = new Arguments (3); + args.Add (new Argument (new TypeOfMethod (method, loc))); + args.Add (new Argument (new ArrayCreation (CreateExpressionTypeExpression (ec, loc), ctor_args, loc))); + args.Add (new Argument (new ImplicitlyTypedArrayCreation (init, loc))); + + return CreateExpressionFactoryCall (ec, "New", args); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (ec.HasSet (ResolveContext.Options.ConstantScope)) { + ec.Report.Error (836, loc, "Anonymous types cannot be used in this expression"); + return null; + } + + if (parameters == null) { + anonymous_type = CreateAnonymousType (ec, EmptyParameters); + RequestedType = new TypeExpression (anonymous_type.Definition, loc); + return base.DoResolve (ec); + } + + bool error = false; + arguments = new Arguments (parameters.Count); + TypeExpression [] t_args = new TypeExpression [parameters.Count]; + for (int i = 0; i < parameters.Count; ++i) { + Expression e = ((AnonymousTypeParameter) parameters [i]).Resolve (ec); + if (e == null) { + error = true; + continue; + } + + arguments.Add (new Argument (e)); + t_args [i] = new TypeExpression (e.Type, e.Location); + } + + if (error) + return null; + + anonymous_type = CreateAnonymousType (ec, parameters); + if (anonymous_type == null) + return null; + + RequestedType = new GenericTypeExpr (anonymous_type.Definition, new TypeArguments (t_args), loc); + return base.DoResolve (ec); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class AnonymousTypeParameter : ShimExpression + { + public readonly string Name; + + public AnonymousTypeParameter (Expression initializer, string name, Location loc) + : base (initializer) + { + this.Name = name; + this.loc = loc; + } + + public AnonymousTypeParameter (Parameter parameter) + : base (new SimpleName (parameter.Name, parameter.Location)) + { + this.Name = parameter.Name; + this.loc = parameter.Location; + } + + public override bool Equals (object o) + { + AnonymousTypeParameter other = o as AnonymousTypeParameter; + return other != null && Name == other.Name; + } + + public override int GetHashCode () + { + return Name.GetHashCode (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = expr.Resolve (ec); + if (e == null) + return null; + + if (e.eclass == ExprClass.MethodGroup) { + Error_InvalidInitializer (ec, e.ExprClassName); + return null; + } + + type = e.Type; + if (type.Kind == MemberKind.Void || type == InternalType.NullLiteral || type == InternalType.AnonymousMethod || type.IsPointer) { + Error_InvalidInitializer (ec, e.GetSignatureForError ()); + return null; + } + + return e; + } + + protected virtual void Error_InvalidInitializer (ResolveContext ec, string initializer) + { + ec.Report.Error (828, loc, "An anonymous type property `{0}' cannot be initialized with `{1}'", + Name, initializer); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs new file mode 100644 index 0000000000..b818546951 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs @@ -0,0 +1,690 @@ +// +// field.cs: All field handlers +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// 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 +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public class FieldDeclarator + { + public FieldDeclarator (SimpleMemberName name, Expression initializer) + { + this.Name = name; + this.Initializer = initializer; + } + + #region Properties + + public SimpleMemberName Name { get; private set; } + public Expression Initializer { get; private set; } + + #endregion + } + + // + // Abstract class for all fields + // + abstract public class FieldBase : MemberBase + { + protected FieldBuilder FieldBuilder; + protected FieldSpec spec; + public Status status; + protected Expression initializer; + protected List declarators; + + [Flags] + public enum Status : byte { + HAS_OFFSET = 4 // Used by FieldMember. + } + + static readonly string[] attribute_targets = new string [] { "field" }; + + protected FieldBase (DeclSpace parent, FullNamedExpression type, Modifiers mod, + Modifiers allowed_mod, MemberName name, Attributes attrs) + : base (parent, null, type, mod, allowed_mod | Modifiers.ABSTRACT, Modifiers.PRIVATE, + name, attrs) + { + if ((mod & Modifiers.ABSTRACT) != 0) + Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead"); + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Field; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + this.initializer = value; + } + } + + public FieldSpec Spec { + get { + return spec; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + public List Declarators { + get { + return this.declarators; + } + } + #endregion + + public void AddDeclarator (FieldDeclarator declarator) + { + if (declarators == null) + declarators = new List (2); + + declarators.Add (declarator); + + // TODO: This will probably break + Parent.AddMember (this, declarator.Name.Value); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.FieldOffset) { + status |= Status.HAS_OFFSET; + + if (!Parent.PartialContainer.HasExplicitLayout) { + Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)"); + return; + } + + if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) { + Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields"); + return; + } + } + + if (a.Type == pa.FixedBuffer) { + Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead"); + return; + } + +#if false + if (a.Type == pa.MarshalAs) { + UnmanagedMarshal marshal = a.GetMarshal (this); + if (marshal != null) { + FieldBuilder.SetMarshal (marshal); + } + return; + } +#endif + if ((a.HasSecurityAttribute)) { + a.Error_InvalidSecurityParent (); + return; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public void SetCustomAttribute (MethodSpec ctor, byte[] data) + { + FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), data); + } + + protected override bool CheckBase () + { + if (!base.CheckBase ()) + return false; + + MemberSpec candidate; + bool overrides = false; + var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides); + if (conflict_symbol == null) + conflict_symbol = candidate; + + if (conflict_symbol == null) { + if ((ModFlags & Modifiers.NEW) != 0) { + Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", + GetSignatureForError ()); + } + } else { + if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE | Modifiers.BACKING_FIELD)) == 0) { + Report.SymbolRelatedToPreviousError (conflict_symbol); + Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended", + GetSignatureForError (), conflict_symbol.GetSignatureForError ()); + } + + if (conflict_symbol.IsAbstract) { + Report.SymbolRelatedToPreviousError (conflict_symbol); + Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'", + GetSignatureForError (), conflict_symbol.GetSignatureForError ()); + } + } + + return true; + } + + public virtual Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + return expr.ConvertImplicitly (MemberType); + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + if (MemberType.IsGenericParameter) + return; + + if (MemberType.IsStatic) + Error_VariableOfStaticClass (Location, GetSignatureForError (), MemberType, Report); + + CheckBase (); + IsTypePermitted (); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { return "F:"; } + } + + public override void Emit () + { + if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder); + } else if (!(Parent is CompilerGeneratedClass) && member_type.HasDynamicElement) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (FieldBuilder, member_type, Location); + } + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (FieldBuilder); + + if (OptAttributes != null) { + OptAttributes.Emit (); + } + + if (((status & Status.HAS_OFFSET) == 0) && (ModFlags & (Modifiers.STATIC | Modifiers.BACKING_FIELD)) == 0 && Parent.PartialContainer.HasExplicitLayout) { + Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute", GetSignatureForError ()); + } + + ConstraintChecker.Check (this, member_type, type_expr.Location); + + base.Emit (); + } + + public static void Error_VariableOfStaticClass (Location loc, string variable_name, TypeSpec static_class, Report Report) + { + Report.SymbolRelatedToPreviousError (static_class); + Report.Error (723, loc, "`{0}': cannot declare variables of static types", + variable_name); + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (!MemberType.IsCLSCompliant () || this is FixedField) { + Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + return true; + } + } + + // + // Field specification + // + public class FieldSpec : MemberSpec, IInterfaceMemberSpec + { + FieldInfo metaInfo; + TypeSpec memberType; + + public FieldSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, FieldInfo info, Modifiers modifiers) + : base (MemberKind.Field, declaringType, definition, modifiers) + { + this.metaInfo = info; + this.memberType = memberType; + } + + #region Properties + + public bool IsReadOnly { + get { + return (Modifiers & Modifiers.READONLY) != 0; + } + } + + public TypeSpec MemberType { + get { + return memberType; + } + } + +#endregion + + public FieldInfo GetMetaInfo () + { + if ((state & StateFlags.PendingMetaInflate) != 0) { + var decl_meta = DeclaringType.GetMetaInfo (); + if (DeclaringType.IsTypeBuilder) { + metaInfo = TypeBuilder.GetField (decl_meta, metaInfo); + } else { + var orig_token = metaInfo.MetadataToken; + metaInfo = decl_meta.GetField (Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); + if (metaInfo.MetadataToken != orig_token) + throw new NotImplementedException ("Resolved to wrong meta token"); + + // What a stupid API, does not work because field handle is imported + // metaInfo = FieldInfo.GetFieldFromHandle (metaInfo.FieldHandle, DeclaringType.MetaInfo.TypeHandle); + } + + state &= ~StateFlags.PendingMetaInflate; + } + + return metaInfo; + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var fs = (FieldSpec) base.InflateMember (inflator); + fs.memberType = inflator.Inflate (memberType); + return fs; + } + + public FieldSpec Mutate (TypeParameterMutator mutator) + { + var decl = DeclaringType; + if (DeclaringType.IsGenericOrParentIsGeneric) + decl = mutator.Mutate (decl); + + if (decl == DeclaringType) + return this; + + var fs = (FieldSpec) MemberwiseClone (); + fs.declaringType = decl; + fs.state |= StateFlags.PendingMetaInflate; + + // Gets back FieldInfo in case of metaInfo was inflated + fs.metaInfo = MemberCache.GetMember (TypeParameterMutator.GetMemberDeclaringType (DeclaringType), this).metaInfo; + return fs; + } + + public override List ResolveMissingDependencies () + { + return memberType.ResolveMissingDependencies (); + } + } + + /// + /// Fixed buffer implementation + /// + public class FixedField : FieldBase + { + public const string FixedElementName = "FixedElementField"; + static int GlobalCounter = 0; + + TypeBuilder fixed_buffer_type; + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.UNSAFE; + + public FixedField (DeclSpace parent, FullNamedExpression type, Modifiers mod, MemberName name, Attributes attrs) + : base (parent, type, mod, AllowedModifiers, name, attrs) + { + } + + #region Properties + + // + // Explicit struct layout set by parent + // + public CharSet? CharSet { + get; set; + } + + #endregion + + public override Constant ConvertInitializer (ResolveContext rc, Constant expr) + { + return expr.ImplicitConversionRequired (rc, rc.BuiltinTypes.Int, Location); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!BuiltinTypeSpec.IsPrimitiveType (MemberType)) { + Report.Error (1663, Location, + "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double", + GetSignatureForError ()); + } else if (declarators != null) { + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Fields.IndexOf (this); + foreach (var d in declarators) { + var f = new FixedField (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + f.initializer = d.Initializer; + ((ConstInitializer) f.initializer).Name = d.Name.Value; + Parent.PartialContainer.Fields.Insert (++index, f); + } + } + + // Create nested fixed buffer container + string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++); + fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name, + TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, + Compiler.BuiltinTypes.ValueType.GetMetaInfo ()); + + var ffield = fixed_buffer_type.DefineField (FixedElementName, MemberType.GetMetaInfo (), FieldAttributes.Public); + + FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, ModifiersExtensions.FieldAttr (ModFlags)); + + var element_spec = new FieldSpec (null, this, MemberType, ffield, ModFlags); + spec = new FixedFieldSpec (Parent.Definition, this, FieldBuilder, element_spec, ModFlags); + + Parent.MemberCache.AddMember (spec); + return true; + } + + protected override void DoMemberTypeIndependentChecks () + { + base.DoMemberTypeIndependentChecks (); + + if (!IsUnsafe) + Expression.UnsafeError (Report, Location); + + if (Parent.PartialContainer.Kind != MemberKind.Struct) { + Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs", + GetSignatureForError ()); + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override void Emit() + { + ResolveContext rc = new ResolveContext (this); + IntConstant buffer_size_const = initializer.Resolve (rc) as IntConstant; + if (buffer_size_const == null) + return; + + int buffer_size = buffer_size_const.Value; + + if (buffer_size <= 0) { + Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ()); + return; + } + + EmitFieldSize (buffer_size); + +#if STATIC + if (Module.HasDefaultCharSet) + fixed_buffer_type.__SetAttributes (fixed_buffer_type.Attributes | Module.DefaultCharSetType); +#endif + + Module.PredefinedAttributes.UnsafeValueType.EmitAttribute (fixed_buffer_type); + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (fixed_buffer_type); + fixed_buffer_type.CreateType (); + + base.Emit (); + } + + void EmitFieldSize (int buffer_size) + { + int type_size = BuiltinTypeSpec.GetSize (MemberType); + + if (buffer_size > int.MaxValue / type_size) { + Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit", + GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType)); + return; + } + + AttributeEncoder encoder; + + var ctor = Module.PredefinedMembers.StructLayoutAttributeCtor.Resolve (Location); + if (ctor == null) + return; + + var field_size = Module.PredefinedMembers.StructLayoutSize.Resolve (Location); + var field_charset = Module.PredefinedMembers.StructLayoutCharSet.Resolve (Location); + if (field_size == null || field_charset == null) + return; + + var char_set = CharSet ?? Module.DefaultCharSet ?? 0; + + encoder = new AttributeEncoder (); + encoder.Encode ((short)LayoutKind.Sequential); + encoder.EncodeNamedArguments ( + new [] { field_size, field_charset }, + new Constant [] { + new IntConstant (Compiler.BuiltinTypes, buffer_size * type_size, Location), + new IntConstant (Compiler.BuiltinTypes, (int) char_set, Location) + } + ); + + fixed_buffer_type.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + + // + // Don't emit FixedBufferAttribute attribute for private types + // + if ((ModFlags & Modifiers.PRIVATE) != 0) + return; + + ctor = Module.PredefinedMembers.FixedBufferAttributeCtor.Resolve (Location); + if (ctor == null) + return; + + encoder = new AttributeEncoder (); + encoder.EncodeTypeName (MemberType); + encoder.Encode (buffer_size); + encoder.EncodeEmptyNamedArguments (); + + FieldBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ()); + } + } + + class FixedFieldSpec : FieldSpec + { + readonly FieldSpec element; + + public FixedFieldSpec (TypeSpec declaringType, IMemberDefinition definition, FieldInfo info, FieldSpec element, Modifiers modifiers) + : base (declaringType, definition, element.MemberType, info, modifiers) + { + this.element = element; + + // It's never CLS-Compliant + state &= ~StateFlags.CLSCompliant_Undetected; + } + + public FieldSpec Element { + get { + return element; + } + } + + public TypeSpec ElementType { + get { + return MemberType; + } + } + } + + // + // The Field class is used to represents class/struct fields during parsing. + // + public class Field : FieldBase { + // + // Modifiers allowed in a class declaration + // + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.STATIC | + Modifiers.VOLATILE | + Modifiers.UNSAFE | + Modifiers.READONLY; + + public Field (DeclSpace parent, FullNamedExpression type, Modifiers mod, MemberName name, + Attributes attrs) + : base (parent, type, mod, AllowedModifiers, name, attrs) + { + } + + bool CanBeVolatile () + { + switch (MemberType.BuiltinType) { + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.UIntPtr: + case BuiltinTypeSpec.Type.IntPtr: + return true; + } + + if (TypeSpec.IsReferenceType (MemberType)) + return true; + + if (MemberType.IsEnum) + return true; + + return false; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + MetaType[] required_modifier = null; + if ((ModFlags & Modifiers.VOLATILE) != 0) { + var mod = Module.PredefinedTypes.IsVolatile.Resolve (); + if (mod != null) + required_modifier = new MetaType[] { mod.GetMetaInfo () }; + } + + FieldBuilder = Parent.TypeBuilder.DefineField ( + Name, member_type.GetMetaInfo (), required_modifier, null, ModifiersExtensions.FieldAttr (ModFlags)); + + spec = new FieldSpec (Parent.Definition, this, MemberType, FieldBuilder, ModFlags); + + // Don't cache inaccessible fields + if ((ModFlags & Modifiers.BACKING_FIELD) == 0) { + Parent.MemberCache.AddMember (spec); + } + + if (initializer != null) { + ((TypeContainer) Parent).RegisterFieldForInitialization (this, + new FieldInitializer (spec, initializer, this)); + } + + if (declarators != null) { + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Fields.IndexOf (this); + foreach (var d in declarators) { + var f = new Field (Parent, t, ModFlags, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + if (d.Initializer != null) + f.initializer = d.Initializer; + + Parent.PartialContainer.Fields.Insert (++index, f); + } + } + +/* + if ((ModFlags & (Modifiers.STATIC | Modifiers.READONLY | Modifiers.COMPILER_GENERATED)) == Modifiers.STATIC) + Console.WriteLine ("{0}: {1}", Location.ToString (), GetSignatureForError ()); +*/ + return true; + } + + protected override void DoMemberTypeDependentChecks () + { + if ((ModFlags & Modifiers.BACKING_FIELD) != 0) + return; + + base.DoMemberTypeDependentChecks (); + + if ((ModFlags & Modifiers.VOLATILE) != 0) { + if (!CanBeVolatile ()) { + Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'", + GetSignatureForError (), TypeManager.CSharpName (MemberType)); + } + + if ((ModFlags & Modifiers.READONLY) != 0) { + Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly", + GetSignatureForError ()); + } + } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if ((ModFlags & Modifiers.VOLATILE) != 0) { + Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ()); + } + + return true; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs new file mode 100644 index 0000000000..d864dc875e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs @@ -0,0 +1,1765 @@ +// +// flowanalyis.cs: The control flow analysis code +// +// Author: +// Martin Baulig (martin@ximian.com) +// Raja R Harinath (rharinath@novell.com) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Text; +using System.Collections.Generic; + +namespace Mono.CSharp +{ + // + // A new instance of this class is created every time a new block is resolved + // and if there's branching in the block's control flow. + // + public abstract class FlowBranching + { + // + // The type of a FlowBranching. + // + public enum BranchingType : byte { + // Normal (conditional or toplevel) block. + Block, + + // Conditional. + Conditional, + + // A loop block. + Loop, + + // The statement embedded inside a loop + Embedded, + + // part of a block headed by a jump target + Labeled, + + // TryCatch block. + TryCatch, + + // TryFinally, Using, Lock, CollectionForeach + Exception, + + // Switch block. + Switch, + + // The toplevel block of a function + Toplevel, + + // An iterator block + Iterator + } + + // + // The type of one sibling of a branching. + // + public enum SiblingType : byte { + Block, + Conditional, + SwitchSection, + Try, + Catch, + Finally + } + + public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc) + { + switch (type) { + case BranchingType.Exception: + case BranchingType.Labeled: + case BranchingType.Toplevel: + case BranchingType.TryCatch: + throw new InvalidOperationException (); + + case BranchingType.Switch: + return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc); + + case BranchingType.Block: + return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc); + + case BranchingType.Loop: + return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc); + + case BranchingType.Embedded: + return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc); + + default: + return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc); + } + } + + // + // The type of this flow branching. + // + public readonly BranchingType Type; + + // + // The block this branching is contained in. This may be null if it's not + // a top-level block and it doesn't declare any local variables. + // + public readonly Block Block; + + // + // The parent of this branching or null if this is the top-block. + // + public readonly FlowBranching Parent; + + // + // Start-Location of this flow branching. + // + public readonly Location Location; + + static int next_id = 0; + int id; + + // + // The vector contains a BitArray with information about which local variables + // and parameters are already initialized at the current code position. + // + public class UsageVector { + // + // The type of this branching. + // + public readonly SiblingType Type; + + // + // Start location of this branching. + // + public Location Location; + + // + // This is only valid for SwitchSection, Try, Catch and Finally. + // + public readonly Block Block; + + // + // The number of locals in this block. + // + public readonly int CountLocals; + + // + // If not null, then we inherit our state from this vector and do a + // copy-on-write. If null, then we're the first sibling in a top-level + // block and inherit from the empty vector. + // + public readonly UsageVector InheritsFrom; + + // + // This is used to construct a list of UsageVector's. + // + public UsageVector Next; + + // + // Private. + // + MyBitVector locals; + bool is_unreachable; + + static int next_id = 0; + int id; + + // + // Normally, you should not use any of these constructors. + // + public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals) + { + this.Type = type; + this.Block = block; + this.Location = loc; + this.InheritsFrom = parent; + this.CountLocals = num_locals; + + locals = num_locals == 0 + ? MyBitVector.Empty + : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals); + + if (parent != null) + is_unreachable = parent.is_unreachable; + + id = ++next_id; + + } + + public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc) + : this (type, parent, block, loc, parent.CountLocals) + { } + + private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc) + { + this.Type = SiblingType.Block; + this.Location = loc; + this.Block = block; + + this.is_unreachable = is_unreachable; + + this.locals = locals; + + id = ++next_id; + + } + + // + // This does a deep copy of the usage vector. + // + public UsageVector Clone () + { + UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals); + + retval.locals = locals.Clone (); + retval.is_unreachable = is_unreachable; + + return retval; + } + + public bool IsAssigned (VariableInfo var, bool ignoreReachability) + { + if (!ignoreReachability && !var.IsParameter && IsUnreachable) + return true; + + return var.IsAssigned (locals); + } + + public void SetAssigned (VariableInfo var) + { + if (!var.IsParameter && IsUnreachable) + return; + + var.SetAssigned (locals); + } + + public bool IsFieldAssigned (VariableInfo var, string name) + { + if (!var.IsParameter && IsUnreachable) + return true; + + return var.IsFieldAssigned (locals, name); + } + + public void SetFieldAssigned (VariableInfo var, string name) + { + if (!var.IsParameter && IsUnreachable) + return; + + var.SetFieldAssigned (locals, name); + } + + public bool IsUnreachable { + get { return is_unreachable; } + } + + public void ResetBarrier () + { + is_unreachable = false; + } + + public void Goto () + { + is_unreachable = true; + } + + public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc) + { + if (sibling_list.Next == null) + return sibling_list; + + MyBitVector locals = null; + bool is_unreachable = sibling_list.is_unreachable; + + if (!sibling_list.IsUnreachable) + locals &= sibling_list.locals; + + for (UsageVector child = sibling_list.Next; child != null; child = child.Next) { + is_unreachable &= child.is_unreachable; + + if (!child.IsUnreachable) + locals &= child.locals; + } + + return new UsageVector (locals, is_unreachable, null, loc); + } + + // + // Merges a child branching. + // + public UsageVector MergeChild (UsageVector child, bool overwrite) + { + Report.Debug (2, " MERGING CHILD EFFECTS", this, child, Type); + + bool new_isunr = child.is_unreachable; + + // + // We've now either reached the point after the branching or we will + // never get there since we always return or always throw an exception. + // + // If we can reach the point after the branching, mark all locals and + // parameters as initialized which have been initialized in all branches + // we need to look at (see above). + // + + if ((Type == SiblingType.SwitchSection) && !new_isunr) { + Report.Error (163, Location, + "Control cannot fall through from one " + + "case label to another"); + return child; + } + + locals |= child.locals; + + // throw away un-necessary information about variables in child blocks + if (locals.Count != CountLocals) + locals = new MyBitVector (locals, CountLocals); + + if (overwrite) + is_unreachable = new_isunr; + else + is_unreachable |= new_isunr; + + return child; + } + + public void MergeOrigins (UsageVector o_vectors) + { + Report.Debug (1, " MERGING BREAK ORIGINS", this); + + if (o_vectors == null) + return; + + if (IsUnreachable && locals != null) + locals.SetAll (true); + + for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) { + Report.Debug (1, " MERGING BREAK ORIGIN", vector); + if (vector.IsUnreachable) + continue; + locals &= vector.locals; + is_unreachable &= vector.is_unreachable; + } + + Report.Debug (1, " MERGING BREAK ORIGINS DONE", this); + } + + // + // Debugging stuff. + // + + public override string ToString () + { + return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals); + } + } + + // + // Creates a new flow branching which is contained in `parent'. + // You should only pass non-null for the `block' argument if this block + // introduces any new variables - in this case, we need to create a new + // usage vector with a different size than our parent's one. + // + protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype, + Block block, Location loc) + { + Parent = parent; + Block = block; + Location = loc; + Type = type; + id = ++next_id; + + UsageVector vector; + if (Block != null) { + UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null; + vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots); + } else { + vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc); + } + + AddSibling (vector); + } + + public abstract UsageVector CurrentUsageVector { + get; + } + + // + // Creates a sibling of the current usage vector. + // + public virtual void CreateSibling (Block block, SiblingType type) + { + UsageVector vector = new UsageVector ( + type, Parent.CurrentUsageVector, block, Location); + AddSibling (vector); + + Report.Debug (1, " CREATED SIBLING", CurrentUsageVector); + } + + public void CreateSibling () + { + CreateSibling (null, SiblingType.Conditional); + } + + protected abstract void AddSibling (UsageVector uv); + + protected abstract UsageVector Merge (); + + public UsageVector MergeChild (FlowBranching child) + { + return CurrentUsageVector.MergeChild (child.Merge (), true); + } + + public virtual bool CheckRethrow (Location loc) + { + return Parent.CheckRethrow (loc); + } + + public virtual bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + return Parent.AddResumePoint (stmt, loc, out pc); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddBreakOrigin (UsageVector vector, Location loc) + { + return Parent.AddBreakOrigin (vector, loc); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddContinueOrigin (UsageVector vector, Location loc) + { + return Parent.AddContinueOrigin (vector, loc); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) + { + return Parent.AddReturnOrigin (vector, stmt); + } + + // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) + public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + return Parent.AddGotoOrigin (vector, goto_stmt); + } + + public bool IsAssigned (VariableInfo vi) + { + return CurrentUsageVector.IsAssigned (vi, false); + } + + public bool IsFieldAssigned (VariableInfo vi, string field_name) + { + return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name); + } + + protected static Report Report { + get { return RootContext.ToplevelTypes.Compiler.Report; } + } + + public void SetAssigned (VariableInfo vi) + { + CurrentUsageVector.SetAssigned (vi); + } + + public void SetFieldAssigned (VariableInfo vi, string name) + { + CurrentUsageVector.SetFieldAssigned (vi, name); + } + +#if DEBUG + public override string ToString () + { + StringBuilder sb = new StringBuilder (); + sb.Append (GetType ()); + sb.Append (" ("); + + sb.Append (id); + sb.Append (","); + sb.Append (Type); + if (Block != null) { + sb.Append (" - "); + sb.Append (Block.ID); + sb.Append (" - "); + sb.Append (Block.StartLocation); + } + sb.Append (" - "); + // sb.Append (Siblings.Length); + // sb.Append (" - "); + sb.Append (CurrentUsageVector); + sb.Append (")"); + return sb.ToString (); + } +#endif + + public string Name { + get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); } + } + } + + public class FlowBranchingBlock : FlowBranching + { + UsageVector sibling_list = null; + + public FlowBranchingBlock (FlowBranching parent, BranchingType type, + SiblingType stype, Block block, Location loc) + : base (parent, type, stype, block, loc) + { } + + public override UsageVector CurrentUsageVector { + get { return sibling_list; } + } + + protected override void AddSibling (UsageVector sibling) + { + if (sibling_list != null && sibling_list.Type == SiblingType.Block) + throw new InternalErrorException ("Blocks don't have sibling flow paths"); + sibling.Next = sibling_list; + sibling_list = sibling; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target); + if (stmt == null) + return Parent.AddGotoOrigin (vector, goto_stmt); + + // forward jump + goto_stmt.SetResolvedTarget (stmt); + stmt.AddUsageVector (vector); + return false; + } + + public static void Error_UnknownLabel (Location loc, string label, Report Report) + { + Report.Error(159, loc, "The label `{0}:' could not be found within the scope of the goto statement", + label); + } + + protected override UsageVector Merge () + { + Report.Debug (2, " MERGING SIBLINGS", Name); + UsageVector vector = UsageVector.MergeSiblings (sibling_list, Location); + Report.Debug (2, " MERGING SIBLINGS DONE", Name, vector); + return vector; + } + } + + public class FlowBranchingBreakable : FlowBranchingBlock + { + UsageVector break_origins; + + public FlowBranchingBreakable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) + : base (parent, type, stype, block, loc) + { } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + vector = vector.Clone (); + vector.Next = break_origins; + break_origins = vector; + return false; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + vector.MergeOrigins (break_origins); + return vector; + } + } + + public class FlowBranchingContinuable : FlowBranchingBlock + { + UsageVector continue_origins; + + public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc) + : base (parent, type, stype, block, loc) + { } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + vector = vector.Clone (); + vector.Next = continue_origins; + continue_origins = vector; + return false; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + vector.MergeOrigins (continue_origins); + return vector; + } + } + + public class FlowBranchingLabeled : FlowBranchingBlock + { + LabeledStatement stmt; + UsageVector actual; + + public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt) + : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc) + { + this.stmt = stmt; + CurrentUsageVector.MergeOrigins (stmt.JumpOrigins); + actual = CurrentUsageVector.Clone (); + + // stand-in for backward jumps + CurrentUsageVector.ResetBarrier (); + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + if (goto_stmt.Target != stmt.Name) + return Parent.AddGotoOrigin (vector, goto_stmt); + + // backward jump + goto_stmt.SetResolvedTarget (stmt); + actual.MergeOrigins (vector.Clone ()); + + return false; + } + + protected override UsageVector Merge () + { + UsageVector vector = base.Merge (); + + if (actual.IsUnreachable) + Report.Warning (162, 2, stmt.loc, "Unreachable code detected"); + + actual.MergeChild (vector, false); + return actual; + } + } + + public class FlowBranchingIterator : FlowBranchingBlock + { + readonly StateMachineInitializer iterator; + + public FlowBranchingIterator (FlowBranching parent, StateMachineInitializer iterator) + : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location) + { + this.iterator = iterator; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + pc = iterator.AddResumePoint (stmt); + return false; + } + } + + public class FlowBranchingToplevel : FlowBranchingBlock + { + UsageVector return_origins; + + public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt) + : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc) + { + } + + public override bool CheckRethrow (Location loc) + { + Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause"); + return false; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + throw new InternalErrorException ("A yield in a non-iterator block"); + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + Report.Error (139, loc, "No enclosing loop out of which to break or continue"); + return false; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + Report.Error (139, loc, "No enclosing loop out of which to break or continue"); + return false; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt) + { + vector = vector.Clone (); + vector.Location = stmt.loc; + vector.Next = return_origins; + return_origins = vector; + return false; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + string name = goto_stmt.Target; + LabeledStatement s = Block.LookupLabel (name); + if (s != null) + throw new InternalErrorException ("Shouldn't get here"); + + if (Parent == null) { + Error_UnknownLabel (goto_stmt.loc, name, Report); + return false; + } + + int errors = Report.Errors; + Parent.AddGotoOrigin (vector, goto_stmt); + if (errors == Report.Errors) + Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method"); + return false; + } + + protected override UsageVector Merge () + { + for (UsageVector origin = return_origins; origin != null; origin = origin.Next) + Block.ParametersBlock.CheckOutParameters (origin, origin.Location); + + UsageVector vector = base.Merge (); + Block.ParametersBlock.CheckOutParameters (vector, Block.loc); + // Note: we _do_not_ merge in the return origins + return vector; + } + + public bool End () + { + return Merge ().IsUnreachable; + } + } + + public class FlowBranchingTryCatch : FlowBranchingBlock + { + TryCatch stmt; + public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt) + : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc) + { + this.stmt = stmt; + } + + public override bool CheckRethrow (Location loc) + { + return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc); + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + int errors = Report.Errors; + Parent.AddResumePoint (stmt, loc, out pc); + if (errors == Report.Errors) { + if (CurrentUsageVector.Next == null) + Report.Error (1626, loc, "Cannot yield a value in the body of a try block with a catch clause"); + else + Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause"); + } + return true; + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + Parent.AddBreakOrigin (vector, loc); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + Parent.AddContinueOrigin (vector, loc); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) + { + Parent.AddReturnOrigin (vector, exit_stmt); + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + Parent.AddGotoOrigin (vector, goto_stmt); + return true; + } + } + + public class FlowBranchingException : FlowBranching + { + ExceptionStatement stmt; + UsageVector current_vector; + UsageVector try_vector; + UsageVector finally_vector; + + abstract class SavedOrigin { + public readonly SavedOrigin Next; + public readonly UsageVector Vector; + + protected SavedOrigin (SavedOrigin next, UsageVector vector) + { + Next = next; + Vector = vector.Clone (); + } + + protected abstract void DoPropagateFinally (FlowBranching parent); + public void PropagateFinally (UsageVector finally_vector, FlowBranching parent) + { + if (finally_vector != null) + Vector.MergeChild (finally_vector, false); + DoPropagateFinally (parent); + } + } + + class BreakOrigin : SavedOrigin { + Location Loc; + public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc) + : base (next, vector) + { + Loc = loc; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddBreakOrigin (Vector, Loc); + } + } + + class ContinueOrigin : SavedOrigin { + Location Loc; + public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc) + : base (next, vector) + { + Loc = loc; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddContinueOrigin (Vector, Loc); + } + } + + class ReturnOrigin : SavedOrigin { + public ExitStatement Stmt; + + public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt) + : base (next, vector) + { + Stmt = stmt; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddReturnOrigin (Vector, Stmt); + } + } + + class GotoOrigin : SavedOrigin { + public Goto Stmt; + + public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt) + : base (next, vector) + { + Stmt = stmt; + } + + protected override void DoPropagateFinally (FlowBranching parent) + { + parent.AddGotoOrigin (Vector, Stmt); + } + } + + SavedOrigin saved_origins; + + public FlowBranchingException (FlowBranching parent, + ExceptionStatement stmt) + : base (parent, BranchingType.Exception, SiblingType.Try, + null, stmt.loc) + { + this.stmt = stmt; + } + + protected override void AddSibling (UsageVector sibling) + { + switch (sibling.Type) { + case SiblingType.Try: + try_vector = sibling; + break; + case SiblingType.Finally: + finally_vector = sibling; + break; + default: + throw new InvalidOperationException (); + } + current_vector = sibling; + } + + public override UsageVector CurrentUsageVector { + get { return current_vector; } + } + + public override bool CheckRethrow (Location loc) + { + if (!Parent.CheckRethrow (loc)) + return false; + if (finally_vector == null) + return true; + Report.Error (724, loc, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause"); + return false; + } + + public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + { + int errors = Report.Errors; + Parent.AddResumePoint (this.stmt, loc, out pc); + if (errors == Report.Errors) { + if (finally_vector == null) + this.stmt.AddResumePoint (stmt, pc); + else + Report.Error (1625, loc, "Cannot yield in the body of a finally clause"); + } + return true; + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddBreakOrigin (vector, loc); + if (errors == Report.Errors) + Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + } else { + saved_origins = new BreakOrigin (saved_origins, vector, loc); + } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddContinueOrigin (vector, loc); + if (errors == Report.Errors) + Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + } else { + saved_origins = new ContinueOrigin (saved_origins, vector, loc); + } + + // either the loop test or a back jump will follow code + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) + { + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddReturnOrigin (vector, exit_stmt); + if (errors == Report.Errors) + exit_stmt.Error_FinallyClause (Report); + } else { + saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt); + } + + // sets ec.NeedReturnLabel() + stmt.SomeCodeFollows (); + return true; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + LabeledStatement s = current_vector.Block == null ? null : current_vector.Block.LookupLabel (goto_stmt.Target); + if (s != null) + throw new InternalErrorException ("Shouldn't get here"); + + if (finally_vector != null) { + int errors = Report.Errors; + Parent.AddGotoOrigin (vector, goto_stmt); + if (errors == Report.Errors) + Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause"); + } else { + saved_origins = new GotoOrigin (saved_origins, vector, goto_stmt); + } + return true; + } + + protected override UsageVector Merge () + { + UsageVector vector = try_vector.Clone (); + + if (finally_vector != null) + vector.MergeChild (finally_vector, false); + + for (SavedOrigin origin = saved_origins; origin != null; origin = origin.Next) + origin.PropagateFinally (finally_vector, Parent); + + return vector; + } + } + + // + // This is used by the flow analysis code to keep track of the type of local variables + // and 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 + // you can only assign the whole variable as such. + // + // For structs, we also need to keep track of all its fields. To do this, we allocate one + // bit for the struct itself (it's used if you assign/access the whole struct) followed by + // one bit for each of its fields. + // + // This class computes this `layout' for each type. + // + public class TypeInfo + { + public readonly TypeSpec Type; + + // + // Total number of bits a variable of this type consumes in the flow vector. + // + public readonly int TotalLength; + + // + // Number of bits the simple fields of a variable of this type consume + // in the flow vector. + // + public readonly int Length; + + // + // This is only used by sub-structs. + // + public readonly int Offset; + + // + // If this is a struct. + // + public readonly bool IsStruct; + + // + // If this is a struct, all fields which are structs theirselves. + // + public TypeInfo[] SubStructInfo; + + readonly StructInfo struct_info; + private static Dictionary type_hash; + + static TypeInfo () + { + Reset (); + } + + public static void Reset () + { + type_hash = new Dictionary (); + StructInfo.field_type_hash = new Dictionary (); + } + + public static TypeInfo GetTypeInfo (TypeSpec type) + { + 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; + } + } + + TypeInfo (StructInfo struct_info, int offset) + { + this.struct_info = struct_info; + this.Offset = offset; + 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) + return 0; + + return struct_info [name]; + } + + public TypeInfo GetSubStruct (string name) + { + if (struct_info == null) + return null; + + return struct_info.GetStructField (name); + } + + // + // A struct's constructor must always assign all fields. + // This method checks whether it actually does so. + // + public bool IsFullyInitialized (BlockContext ec, VariableInfo vi, Location loc) + { + if (struct_info == null) + return true; + + bool ok = true; + FlowBranching branching = ec.CurrentBranching; + 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 (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", + field.GetSignatureForError ()); + } else { + ec.Report.Error (171, loc, + "Field `{0}' must be fully assigned before control leaves the constructor", + field.GetSignatureForError ()); + } + ok = false; + } + } + + return ok; + } + + public override string ToString () + { + return String.Format ("TypeInfo ({0}:{1}:{2}:{3})", + Type, Offset, Length, TotalLength); + } + + class StructInfo { + public readonly TypeSpec Type; + public readonly 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 field_type_hash; + private Dictionary struct_field_hash; + private Dictionary field_hash; + + protected bool InTransit = false; + + // Private constructor. To save memory usage, we only need to create one instance + // of this class per struct type. + private StructInfo (TypeSpec type) + { + this.Type = type; + + field_type_hash.Add (type, this); + + TypeContainer tc = type.MemberDefinition as TypeContainer; + + var public_fields = new List (); + var non_public_fields = new List (); + + 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); + + struct_field_hash = new Dictionary (); + field_hash = new Dictionary (); + + Length = 0; + StructFields = new TypeInfo [Count]; + StructInfo[] sinfo = new StructInfo [Count]; + + InTransit = true; + + for (int i = 0; i < Count; i++) { + var field = Fields [i]; + + sinfo [i] = GetStructInfo (field.MemberType); + if (sinfo [i] == null) + field_hash.Add (field.Name, ++Length); + else if (sinfo [i].InTransit) { + sinfo [i] = null; + return; + } + } + + InTransit = false; + + TotalLength = Length + 1; + for (int i = 0; i < 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 this [string name] { + get { + int val; + if (!field_hash.TryGetValue (name, out val)) + return 0; + + return val; + } + } + + public TypeInfo GetStructField (string name) + { + TypeInfo ti; + if (struct_field_hash.TryGetValue (name, out ti)) + return ti; + + return null; + } + + public static StructInfo GetStructInfo (TypeSpec type) + { + if (!type.IsStruct || type.BuiltinType > 0) + return null; + + StructInfo info; + if (field_type_hash.TryGetValue (type, out info)) + return info; + + return new StructInfo (type); + } + } + } + + // + // This is used by the flow analysis code to store information about a single local variable + // or parameter. Depending on the variable's type, we need to allocate one or more elements + // in the BitVector - if it's a fundamental or reference type, we just need to know whether + // it has been assigned or not, but for structs, we need this information for each of its fields. + // + public class VariableInfo { + public readonly string Name; + public readonly TypeInfo TypeInfo; + + // + // The bit offset of this variable in the flow vector. + // + public readonly int Offset; + + // + // The number of bits this variable needs in the flow vector. + // The first bit always specifies whether the variable as such has been assigned while + // the remaining bits contain this information for each of a struct's fields. + // + public readonly int Length; + + // + // If this is a parameter of local variable. + // + 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; + this.Offset = offset; + this.TypeInfo = TypeInfo.GetTypeInfo (type); + + Length = TypeInfo.TotalLength; + + Initialize (); + } + + protected VariableInfo (VariableInfo parent, TypeInfo type) + { + 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 (); + } + + protected void Initialize () + { + TypeInfo[] sub_fields = TypeInfo.SubStructInfo; + if (sub_fields != null) { + sub_info = new VariableInfo [sub_fields.Length]; + for (int i = 0; i < sub_fields.Length; i++) { + if (sub_fields [i] != null) + sub_info [i] = new VariableInfo (this, sub_fields [i]); + } + } else + sub_info = new VariableInfo [0]; + } + + public VariableInfo (LocalVariable local_info, int offset) + : this (local_info.Name, local_info.Type, offset) + { + this.LocalInfo = local_info; + this.IsParameter = false; + } + + public VariableInfo (ParametersCompiled ip, int i, int offset) + : this (ip.FixedParameters [i].Name, ip.Types [i], offset) + { + this.IsParameter = true; + } + + 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; + } + + public bool IsAssigned (MyBitVector vector) + { + if (vector == null) + return true; + + 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. + 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]) + return false; + } + + // Ok, now check all fields which are structs. + for (int i = 0; i < sub_info.Length; 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 void SetAssigned (MyBitVector vector) + { + if (Length == 1) + vector [Offset] = true; + else + vector.SetRange (Offset, Length); + is_ever_assigned = true; + } + + 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) + { + int field_idx = TypeInfo.GetFieldIndex (field_name); + + if (field_idx == 0) + return true; + + return vector [Offset + field_idx]; + } + + public void SetFieldAssigned (ResolveContext ec, string name) + { + if (ec.DoFlowAnalysis) + ec.CurrentBranching.SetFieldAssigned (this, name); + } + + public void SetFieldAssigned (MyBitVector vector, string field_name) + { + int field_idx = TypeInfo.GetFieldIndex (field_name); + + if (field_idx == 0) + return; + + vector [Offset + field_idx] = true; + is_ever_assigned = true; + } + + public VariableInfo GetSubStruct (string name) + { + TypeInfo type = TypeInfo.GetSubStruct (name); + + if (type == null) + return null; + + return new VariableInfo (this, type); + } + + public override string ToString () + { + return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})", + Name, TypeInfo, Offset, Length, IsParameter); + } + } + + // + // This is a special bit vector which can inherit from another bit vector doing a + // copy-on-write strategy. The inherited vector may have a smaller size than the + // current one. + // + public class MyBitVector { + public readonly int Count; + public static readonly MyBitVector Empty = new MyBitVector (); + + // Invariant: vector != null => vector.Count == Count + // Invariant: vector == null || shared == null + // i.e., at most one of 'vector' and 'shared' can be non-null. They can both be null -- that means all-ones + // The object in 'shared' cannot be modified, while 'vector' can be freely modified + System.Collections.BitArray vector, shared; + + MyBitVector () + { + shared = new System.Collections.BitArray (0, false); + } + + public MyBitVector (MyBitVector InheritsFrom, int Count) + { + if (InheritsFrom != null) + shared = InheritsFrom.MakeShared (Count); + + this.Count = Count; + } + + System.Collections.BitArray MakeShared (int new_count) + { + // Post-condition: vector == null + + // ensure we don't leak out dirty bits from the BitVector we inherited from + if (new_count > Count && + ((shared != null && shared.Count > Count) || + (shared == null && vector == null))) + initialize_vector (); + + if (vector != null) { + shared = vector; + vector = null; + } + + return shared; + } + + // + // Get/set bit `index' in the bit vector. + // + public bool this [int index] { + get { + if (index >= Count) + // FIXME: Disabled due to missing anonymous method flow analysis + // throw new ArgumentOutOfRangeException (); + return true; + + if (vector != null) + return vector [index]; + if (shared == null) + return true; + if (index < shared.Count) + return shared [index]; + return false; + } + + set { + // Only copy the vector if we're actually modifying it. + if (this [index] != value) { + if (vector == null) + initialize_vector (); + vector [index] = value; + } + } + } + + // + // Performs an `or' operation on the bit vector. The `new_vector' may have a + // different size than the current one. + // + private MyBitVector Or (MyBitVector new_vector) + { + if (Count == 0 || new_vector.Count == 0) + return this; + + var o = new_vector.vector != null ? new_vector.vector : new_vector.shared; + + if (o == null) { + int n = new_vector.Count; + if (n < Count) { + for (int i = 0; i < n; ++i) + this [i] = true; + } else { + SetAll (true); + } + return this; + } + + if (Count == o.Count) { + if (vector == null) { + if (shared == null) + return this; + initialize_vector (); + } + vector.Or (o); + return this; + } + + int min = o.Count; + if (Count < min) + min = Count; + + for (int i = 0; i < min; i++) { + if (o [i]) + this [i] = true; + } + + return this; + } + + // + // Performs an `and' operation on the bit vector. The `new_vector' may have + // a different size than the current one. + // + private MyBitVector And (MyBitVector new_vector) + { + if (Count == 0) + return this; + + var o = new_vector.vector != null ? new_vector.vector : new_vector.shared; + + if (o == null) { + for (int i = new_vector.Count; i < Count; ++i) + this [i] = false; + return this; + } + + if (o.Count == 0) { + SetAll (false); + return this; + } + + if (Count == o.Count) { + if (vector == null) { + if (shared == null) { + shared = new_vector.MakeShared (Count); + return this; + } + initialize_vector (); + } + vector.And (o); + return this; + } + + int min = o.Count; + if (Count < min) + min = Count; + + for (int i = 0; i < min; i++) { + if (! o [i]) + this [i] = false; + } + + for (int i = min; i < Count; i++) + this [i] = false; + + return this; + } + + public static MyBitVector operator & (MyBitVector a, MyBitVector b) + { + if (a == b) + return a; + if (a == null) + return b.Clone (); + if (b == null) + return a.Clone (); + if (a.Count > b.Count) + return a.Clone ().And (b); + else + return b.Clone ().And (a); + } + + public static MyBitVector operator | (MyBitVector a, MyBitVector b) + { + if (a == b) + return a; + if (a == null) + return new MyBitVector (null, b.Count); + if (b == null) + return new MyBitVector (null, a.Count); + if (a.Count > b.Count) + return a.Clone ().Or (b); + else + return b.Clone ().Or (a); + } + + public MyBitVector Clone () + { + return Count == 0 ? Empty : new MyBitVector (this, Count); + } + + public void SetRange (int offset, int length) + { + if (offset > Count || offset + length > Count) + throw new ArgumentOutOfRangeException ("flow-analysis"); + + if (shared == null && vector == null) + return; + + int i = 0; + if (shared != null) { + if (offset + length <= shared.Count) { + for (; i < length; ++i) + if (!shared [i+offset]) + break; + if (i == length) + return; + } + initialize_vector (); + } + for (; i < length; ++i) + vector [i+offset] = true; + + } + + public void SetAll (bool value) + { + // Don't clobber Empty + if (Count == 0) + return; + shared = value ? null : Empty.MakeShared (Count); + vector = null; + } + + void initialize_vector () + { + // Post-condition: vector != null + if (shared == null) { + vector = new System.Collections.BitArray (Count, true); + return; + } + + vector = new System.Collections.BitArray (shared); + if (Count != vector.Count) + vector.Length = Count; + shared = null; + } + + StringBuilder Dump (StringBuilder sb) + { + var dump = vector == null ? shared : vector; + if (dump == null) + return sb.Append ("/"); + if (dump == shared) + sb.Append ("="); + for (int i = 0; i < dump.Count; i++) + sb.Append (dump [i] ? "1" : "0"); + return sb; + } + + public override string ToString () + { + return Dump (new StringBuilder ("{")).Append ("}").ToString (); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs new file mode 100644 index 0000000000..1975704777 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs @@ -0,0 +1,3407 @@ +// +// generic.cs: Generics support +// +// Authors: Martin Baulig (martin@ximian.com) +// Miguel de Icaza (miguel@ximian.com) +// 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 +// +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + public enum Variance + { + // + // Don't add or modify internal values, they are used as -/+ calculation signs + // + None = 0, + Covariant = 1, + Contravariant = -1 + } + + [Flags] + public enum SpecialConstraint + { + None = 0, + Constructor = 1 << 2, + Class = 1 << 3, + Struct = 1 << 4 + } + + public class SpecialContraintExpr : FullNamedExpression + { + public SpecialContraintExpr (SpecialConstraint constraint, Location loc) + { + this.loc = loc; + this.Constraint = constraint; + } + + public SpecialConstraint Constraint { get; private set; } + + protected override Expression DoResolve (ResolveContext rc) + { + throw new NotImplementedException (); + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext ec) + { + throw new NotImplementedException (); + } + } + + // + // A set of parsed constraints for a type parameter + // + public class Constraints + { + SimpleMemberName tparam; + List constraints; + Location loc; + bool resolved; + bool resolving; + + public IEnumerable ConstraintExpressions { + get { + return constraints; + } + } + + public Constraints (SimpleMemberName tparam, List constraints, Location loc) + { + this.tparam = tparam; + this.constraints = constraints; + this.loc = loc; + } + + #region Properties + + public Location Location { + get { + return loc; + } + } + + public SimpleMemberName TypeParameter { + get { + return tparam; + } + } + + #endregion + + public static bool CheckConflictingInheritedConstraint (TypeParameterSpec spec, TypeSpec bb, IMemberContext context, Location loc) + { + if (spec.HasSpecialClass && bb.IsStruct) { + context.Module.Compiler.Report.Error (455, loc, + "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'", + spec.Name, "class", bb.GetSignatureForError ()); + + return false; + } + + return CheckConflictingInheritedConstraint (spec, spec.BaseType, bb, context, loc); + } + + static bool CheckConflictingInheritedConstraint (TypeParameterSpec spec, TypeSpec ba, TypeSpec bb, IMemberContext context, Location loc) + { + if (ba == bb) + return true; + + if (TypeSpec.IsBaseClass (ba, bb, false) || TypeSpec.IsBaseClass (bb, ba, false)) + return true; + + context.Module.Compiler.Report.Error (455, loc, + "Type parameter `{0}' inherits conflicting constraints `{1}' and `{2}'", + spec.Name, ba.GetSignatureForError (), bb.GetSignatureForError ()); + return false; + } + + public void CheckGenericConstraints (IMemberContext context, bool obsoleteCheck) + { + foreach (var c in constraints) { + if (c == null) + continue; + + var t = c.Type; + if (t == null) + continue; + + if (obsoleteCheck) { + ObsoleteAttribute obsolete_attr = t.GetAttributeObsolete (); + if (obsolete_attr != null) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, t.GetSignatureForError (), c.Location, context.Module.Compiler.Report); + } + + ConstraintChecker.Check (context, t, c.Location); + } + } + + // + // Resolve the constraints types with only possible early checks, return + // value `false' is reserved for recursive failure + // + public bool Resolve (IMemberContext context, TypeParameter tp) + { + if (resolved) + return true; + + if (resolving) + return false; + + resolving = true; + var spec = tp.Type; + List tparam_types = null; + bool iface_found = false; + + spec.BaseType = context.Module.Compiler.BuiltinTypes.Object; + + for (int i = 0; i < constraints.Count; ++i) { + var constraint = constraints[i]; + + if (constraint is SpecialContraintExpr) { + spec.SpecialConstraint |= ((SpecialContraintExpr) constraint).Constraint; + if (spec.HasSpecialStruct) + spec.BaseType = context.Module.Compiler.BuiltinTypes.ValueType; + + // Set to null as it does not have a type + constraints[i] = null; + continue; + } + + var type = constraint.ResolveAsType (context); + if (type == null) + continue; + + if (type.Arity > 0 && ((InflatedTypeSpec) type).HasDynamicArgument ()) { + context.Module.Compiler.Report.Error (1968, constraint.Location, + "A constraint cannot be the dynamic type `{0}'", type.GetSignatureForError ()); + continue; + } + + if (!context.CurrentMemberDefinition.IsAccessibleAs (type)) { + context.Module.Compiler.Report.SymbolRelatedToPreviousError (type); + context.Module.Compiler.Report.Error (703, loc, + "Inconsistent accessibility: constraint type `{0}' is less accessible than `{1}'", + type.GetSignatureForError (), context.GetSignatureForError ()); + } + + if (type.IsInterface) { + if (!spec.AddInterface (type)) { + context.Module.Compiler.Report.Error (405, constraint.Location, + "Duplicate constraint `{0}' for type parameter `{1}'", type.GetSignatureForError (), tparam.Value); + } + + iface_found = true; + continue; + } + + + var constraint_tp = type as TypeParameterSpec; + if (constraint_tp != null) { + if (tparam_types == null) { + tparam_types = new List (2); + } else if (tparam_types.Contains (constraint_tp)) { + context.Module.Compiler.Report.Error (405, constraint.Location, + "Duplicate constraint `{0}' for type parameter `{1}'", type.GetSignatureForError (), tparam.Value); + continue; + } + + // + // Checks whether each generic method parameter constraint type + // is valid with respect to T + // + if (tp.IsMethodTypeParameter) { + TypeManager.CheckTypeVariance (type, Variance.Contravariant, context); + } + + var tp_def = constraint_tp.MemberDefinition as TypeParameter; + if (tp_def != null && !tp_def.ResolveConstraints (context)) { + context.Module.Compiler.Report.Error (454, constraint.Location, + "Circular constraint dependency involving `{0}' and `{1}'", + constraint_tp.GetSignatureForError (), tp.GetSignatureForError ()); + continue; + } + + // + // Checks whether there are no conflicts between type parameter constraints + // + // class Foo + // where T : A + // where U : B, T + // + // A and B are not convertible and only 1 class constraint is allowed + // + if (constraint_tp.HasTypeConstraint) { + if (spec.HasTypeConstraint || spec.HasSpecialStruct) { + if (!CheckConflictingInheritedConstraint (spec, constraint_tp.BaseType, context, constraint.Location)) + continue; + } else { + for (int ii = 0; ii < tparam_types.Count; ++ii) { + if (!tparam_types[ii].HasTypeConstraint) + continue; + + if (!CheckConflictingInheritedConstraint (spec, tparam_types[ii].BaseType, constraint_tp.BaseType, context, constraint.Location)) + break; + } + } + } + + if (constraint_tp.HasSpecialStruct) { + context.Module.Compiler.Report.Error (456, constraint.Location, + "Type parameter `{0}' has the `struct' constraint, so it cannot be used as a constraint for `{1}'", + constraint_tp.GetSignatureForError (), tp.GetSignatureForError ()); + continue; + } + + tparam_types.Add (constraint_tp); + continue; + } + + if (iface_found || spec.HasTypeConstraint) { + context.Module.Compiler.Report.Error (406, constraint.Location, + "The class type constraint `{0}' must be listed before any other constraints. Consider moving type constraint to the beginning of the constraint list", + type.GetSignatureForError ()); + } + + if (spec.HasSpecialStruct || spec.HasSpecialClass) { + context.Module.Compiler.Report.Error (450, constraint.Location, + "`{0}': cannot specify both a constraint class and the `class' or `struct' constraint", + type.GetSignatureForError ()); + } + + switch (type.BuiltinType) { + case BuiltinTypeSpec.Type.Array: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + case BuiltinTypeSpec.Type.Enum: + case BuiltinTypeSpec.Type.ValueType: + case BuiltinTypeSpec.Type.Object: + context.Module.Compiler.Report.Error (702, constraint.Location, + "A constraint cannot be special class `{0}'", type.GetSignatureForError ()); + continue; + case BuiltinTypeSpec.Type.Dynamic: + context.Module.Compiler.Report.Error (1967, constraint.Location, + "A constraint cannot be the dynamic type"); + continue; + } + + if (type.IsSealed || !type.IsClass) { + context.Module.Compiler.Report.Error (701, loc, + "`{0}' is not a valid constraint. A constraint must be an interface, a non-sealed class or a type parameter", + TypeManager.CSharpName (type)); + continue; + } + + if (type.IsStatic) { + context.Module.Compiler.Report.Error (717, constraint.Location, + "`{0}' is not a valid constraint. Static classes cannot be used as constraints", + type.GetSignatureForError ()); + } + + spec.BaseType = type; + } + + if (tparam_types != null) + spec.TypeArguments = tparam_types.ToArray (); + + resolving = false; + resolved = true; + return true; + } + + public void VerifyClsCompliance (Report report) + { + foreach (var c in constraints) + { + if (c == null) + continue; + + if (!c.Type.IsCLSCompliant ()) { + report.SymbolRelatedToPreviousError (c.Type); + report.Warning (3024, 1, loc, "Constraint type `{0}' is not CLS-compliant", + c.Type.GetSignatureForError ()); + } + } + } + } + + // + // A type parameter for a generic type or generic method definition + // + public class TypeParameter : MemberCore, ITypeDefinition + { + static readonly string[] attribute_target = new string [] { "type parameter" }; + + Constraints constraints; + GenericTypeParameterBuilder builder; + TypeParameterSpec spec; + + public TypeParameter (DeclSpace parent, int index, MemberName name, Constraints constraints, Attributes attrs, Variance variance) + : base (parent, name, attrs) + { + this.constraints = constraints; + this.spec = new TypeParameterSpec (null, index, this, SpecialConstraint.None, variance, null); + } + + public TypeParameter (TypeParameterSpec spec, DeclSpace parent, TypeSpec parentSpec, MemberName name, Attributes attrs) + : base (parent, name, attrs) + { + this.spec = new TypeParameterSpec (parentSpec, spec.DeclaredPosition, spec.MemberDefinition, spec.SpecialConstraint, spec.Variance, null) { + BaseType = spec.BaseType, + InterfacesDefined = spec.InterfacesDefined, + TypeArguments = spec.TypeArguments + }; + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.GenericParameter; + } + } + + public IAssemblyDefinition DeclaringAssembly { + get { + return Module.DeclaringAssembly; + } + } + + public override string DocCommentHeader { + get { + throw new InvalidOperationException ( + "Unexpected attempt to get doc comment from " + this.GetType ()); + } + } + + public bool IsMethodTypeParameter { + get { + return spec.IsMethodOwned; + } + } + + public string Namespace { + get { + return null; + } + } + + public TypeParameterSpec Type { + get { + return spec; + } + } + + public int TypeParametersCount { + get { + return 0; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + return null; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_target; + } + } + + public Variance Variance { + get { + return spec.Variance; + } + } + + public Constraints Constraints { + get { + return this.constraints; + } + } + + #endregion + + // + // This is called for each part of a partial generic type definition. + // + // If partial type parameters constraints are not null and we don't + // already have constraints they become our constraints. If we already + // have constraints, we must check that they're the same. + // + public bool AddPartialConstraints (TypeContainer part, TypeParameter tp) + { + if (builder == null) + throw new InvalidOperationException (); + + var new_constraints = tp.constraints; + if (new_constraints == null) + return true; + + // TODO: could create spec only + //tp.Define (null, -1, part.Definition); + tp.spec.DeclaringType = part.Definition; + if (!tp.ResolveConstraints (part)) + return false; + + if (constraints != null) + return spec.HasSameConstraintsDefinition (tp.Type); + + // Copy constraint from resolved part to partial container + spec.SpecialConstraint = tp.spec.SpecialConstraint; + spec.InterfacesDefined = tp.spec.InterfacesDefined; + spec.TypeArguments = tp.spec.TypeArguments; + spec.BaseType = tp.spec.BaseType; + + return true; + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public void CheckGenericConstraints (bool obsoleteCheck) + { + if (constraints != null) + constraints.CheckGenericConstraints (this, obsoleteCheck); + } + + public TypeParameter CreateHoistedCopy (TypeContainer declaringType, TypeSpec declaringSpec) + { + return new TypeParameter (spec, declaringType, declaringSpec, MemberName, null); + } + + public override bool Define () + { + return true; + } + + // + // This is the first method which is called during the resolving + // process; we're called immediately after creating the type parameters + // with SRE (by calling `DefineGenericParameters()' on the TypeBuilder / + // MethodBuilder). + // + public void Define (GenericTypeParameterBuilder type, TypeSpec declaringType) + { + if (builder != null) + throw new InternalErrorException (); + + this.builder = type; + spec.DeclaringType = declaringType; + spec.SetMetaInfo (type); + } + + public void EmitConstraints (GenericTypeParameterBuilder builder) + { + var attr = GenericParameterAttributes.None; + if (spec.Variance == Variance.Contravariant) + attr |= GenericParameterAttributes.Contravariant; + else if (spec.Variance == Variance.Covariant) + attr |= GenericParameterAttributes.Covariant; + + if (spec.HasSpecialClass) + attr |= GenericParameterAttributes.ReferenceTypeConstraint; + else if (spec.HasSpecialStruct) + attr |= GenericParameterAttributes.NotNullableValueTypeConstraint | GenericParameterAttributes.DefaultConstructorConstraint; + + if (spec.HasSpecialConstructor) + attr |= GenericParameterAttributes.DefaultConstructorConstraint; + + if (spec.BaseType.BuiltinType != BuiltinTypeSpec.Type.Object) + builder.SetBaseTypeConstraint (spec.BaseType.GetMetaInfo ()); + + if (spec.InterfacesDefined != null) + builder.SetInterfaceConstraints (spec.InterfacesDefined.Select (l => l.GetMetaInfo ()).ToArray ()); + + if (spec.TypeArguments != null) + builder.SetInterfaceConstraints (spec.TypeArguments.Select (l => l.GetMetaInfo ()).ToArray ()); + + builder.SetGenericParameterAttributes (attr); + } + + public override void Emit () + { + EmitConstraints (builder); + + if (OptAttributes != null) + OptAttributes.Emit (); + + base.Emit (); + } + + public void ErrorInvalidVariance (IMemberContext mc, Variance expected) + { + Report.SymbolRelatedToPreviousError (mc.CurrentMemberDefinition); + string input_variance = Variance == Variance.Contravariant ? "contravariant" : "covariant"; + string gtype_variance; + switch (expected) { + case Variance.Contravariant: gtype_variance = "contravariantly"; break; + case Variance.Covariant: gtype_variance = "covariantly"; break; + default: gtype_variance = "invariantly"; break; + } + + Delegate d = mc as Delegate; + string parameters = d != null ? d.Parameters.GetSignatureForError () : ""; + + Report.Error (1961, Location, + "The {2} type parameter `{0}' must be {3} valid on `{1}{4}'", + GetSignatureForError (), mc.GetSignatureForError (), input_variance, gtype_variance, parameters); + } + + public TypeSpec GetAttributeCoClass () + { + return null; + } + + public string GetAttributeDefaultMember () + { + throw new NotSupportedException (); + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + throw new NotSupportedException (); + } + + public override string GetSignatureForDocumentation () + { + throw new NotImplementedException (); + } + + public override string GetSignatureForError () + { + return MemberName.Name; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + return spec.MemberDefinition.DeclaringAssembly == assembly; + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotSupportedException ("Not supported for compiled definition"); + } + + // + // Resolves all type parameter constraints + // + public bool ResolveConstraints (IMemberContext context) + { + if (constraints != null) + return constraints.Resolve (context, this); + + if (spec.BaseType == null) + spec.BaseType = context.Module.Compiler.BuiltinTypes.Object; + + return true; + } + + public static TypeParameter FindTypeParameter (TypeParameter[] tparams, string name) + { + foreach (var tp in tparams) { + if (tp.Name == name) + return tp; + } + + return null; + } + + public override bool IsClsComplianceRequired () + { + return false; + } + + public new void VerifyClsCompliance () + { + if (constraints != null) + constraints.VerifyClsCompliance (Report); + } + } + + [System.Diagnostics.DebuggerDisplay ("{DisplayDebugInfo()}")] + public class TypeParameterSpec : TypeSpec + { + public static readonly new TypeParameterSpec[] EmptyTypes = new TypeParameterSpec[0]; + + Variance variance; + SpecialConstraint spec; + readonly int tp_pos; + TypeSpec[] targs; + TypeSpec[] ifaces_defined; + + // + // Creates type owned type parameter + // + public TypeParameterSpec (TypeSpec declaringType, int index, ITypeDefinition definition, SpecialConstraint spec, Variance variance, MetaType info) + : base (MemberKind.TypeParameter, declaringType, definition, info, Modifiers.PUBLIC) + { + this.variance = variance; + this.spec = spec; + state &= ~StateFlags.Obsolete_Undetected; + tp_pos = index; + } + + // + // Creates method owned type parameter + // + public TypeParameterSpec (int index, ITypeDefinition definition, SpecialConstraint spec, Variance variance, MetaType info) + : this (null, index, definition, spec, variance, info) + { + } + + #region Properties + + public int DeclaredPosition { + get { + return tp_pos; + } + } + + public bool HasSpecialConstructor { + get { + return (spec & SpecialConstraint.Constructor) != 0; + } + } + + public bool HasSpecialClass { + get { + return (spec & SpecialConstraint.Class) != 0; + } + } + + public bool HasSpecialStruct { + get { + return (spec & SpecialConstraint.Struct) != 0; + } + } + + public bool HasTypeConstraint { + get { + var bt = BaseType.BuiltinType; + return bt != BuiltinTypeSpec.Type.Object && bt != BuiltinTypeSpec.Type.ValueType; + } + } + + public override IList Interfaces { + get { + if ((state & StateFlags.InterfacesExpanded) == 0) { + if (ifaces != null) { + for (int i = 0; i < ifaces.Count; ++i ) { + var iface_type = ifaces[i]; + if (iface_type.Interfaces != null) { + if (ifaces_defined == null) + ifaces_defined = ifaces.ToArray (); + + for (int ii = 0; ii < iface_type.Interfaces.Count; ++ii) { + var ii_iface_type = iface_type.Interfaces [ii]; + + AddInterface (ii_iface_type); + } + } + } + } + + if (ifaces_defined == null && ifaces != null) + ifaces_defined = ifaces.ToArray (); + + state |= StateFlags.InterfacesExpanded; + } + + return ifaces; + } + } + + // + // Unexpanded interfaces list + // + public TypeSpec[] InterfacesDefined { + get { + if (ifaces_defined == null && ifaces != null) + ifaces_defined = ifaces.ToArray (); + + return ifaces_defined; + } + set { + ifaces = ifaces_defined = value; + } + } + + public bool IsConstrained { + get { + return spec != SpecialConstraint.None || ifaces != null || targs != null || HasTypeConstraint; + } + } + + // + // Returns whether the type parameter is known to be a reference type + // + public new bool IsReferenceType { + get { + if ((spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) + return (spec & SpecialConstraint.Class) != 0; + + // + // Full check is needed (see IsValueType for details) + // + if (HasTypeConstraint && TypeSpec.IsReferenceType (BaseType)) + return true; + + if (targs != null) { + foreach (var ta in targs) { + // + // Secondary special constraints are ignored (I am not sure why) + // + var tp = ta as TypeParameterSpec; + if (tp != null && (tp.spec & (SpecialConstraint.Class | SpecialConstraint.Struct)) != 0) + continue; + + if (TypeSpec.IsReferenceType (ta)) + return true; + } + } + + return false; + } + } + + // + // Returns whether the type parameter is known to be a value type + // + public new bool IsValueType { + get { + // + // Even if structs/enums cannot be used directly as constraints + // they can apear as constraint type when inheriting base constraint + // which has dependant type parameter constraint which has been + // inflated using value type + // + // class A : B { override void Foo () {} } + // class B { virtual void Foo () where U : T {} } + // + return HasSpecialStruct || TypeSpec.IsValueType (BaseType); + } + } + + public override string Name { + get { + return definition.Name; + } + } + + public bool IsMethodOwned { + get { + return DeclaringType == null; + } + } + + public SpecialConstraint SpecialConstraint { + get { + return spec; + } + set { + spec = value; + } + } + + // + // Types used to inflate the generic type + // + public new TypeSpec[] TypeArguments { + get { + return targs; + } + set { + targs = value; + } + } + + public Variance Variance { + get { + return variance; + } + } + + #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 (); + return IsMethodOwned ? s + "!!" : s + "!"; + } + + // + // Finds effective base class. The effective base class is always a class-type + // + public TypeSpec GetEffectiveBase () + { + if (HasSpecialStruct) + return BaseType; + + // + // If T has a class-type constraint C but no type-parameter constraints, its effective base class is C + // + if (BaseType != null && targs == null) { + // + // If T has a constraint V that is a value-type, use instead the most specific base type of V that is a class-type. + // + // LAMESPEC: Is System.ValueType always the most specific base type in this case? + // + // Note: This can never happen in an explicitly given constraint, but may occur when the constraints of a generic method + // are implicitly inherited by an overriding method declaration or an explicit implementation of an interface method. + // + return BaseType.IsStruct ? BaseType.BaseType : BaseType; + } + + var types = targs; + if (HasTypeConstraint) { + Array.Resize (ref types, types.Length + 1); + types[types.Length - 1] = BaseType; + } + + if (types != null) + return Convert.FindMostEncompassedType (types.Select (l => l.BaseType)); + + return BaseType; + } + + public override string GetSignatureForDocumentation () + { + int c = 0; + var type = DeclaringType; + while (type != null && type.DeclaringType != null) { + type = type.DeclaringType; + c += type.MemberDefinition.TypeParametersCount; + } + + var prefix = IsMethodOwned ? "``" : "`"; + return prefix + (c + DeclaredPosition); + } + + public override string GetSignatureForError () + { + return Name; + } + + // + // Constraints have to match by definition but not position, used by + // partial classes or methods + // + public bool HasSameConstraintsDefinition (TypeParameterSpec other) + { + if (spec != other.spec) + return false; + + if (BaseType != other.BaseType) + return false; + + if (!TypeSpecComparer.Override.IsSame (InterfacesDefined, other.InterfacesDefined)) + return false; + + if (!TypeSpecComparer.Override.IsSame (targs, other.targs)) + return false; + + return true; + } + + // + // Constraints have to match by using same set of types, used by + // implicit interface implementation + // + public bool HasSameConstraintsImplementation (TypeParameterSpec other) + { + if (spec != other.spec) + return false; + + // + // It can be same base type or inflated type parameter + // + // interface I { void Foo where U : T; } + // class A : I { void Foo where X : int {} } + // + bool found; + if (!TypeSpecComparer.Override.IsEqual (BaseType, other.BaseType)) { + if (other.targs == null) + return false; + + found = false; + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) { + found = true; + break; + } + } + + if (!found) + return false; + } + + // Check interfaces implementation -> definition + if (InterfacesDefined != null) { + foreach (var iface in InterfacesDefined) { + found = false; + if (other.InterfacesDefined != null) { + foreach (var oiface in other.InterfacesDefined) { + if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { + found = true; + break; + } + } + } + + if (found) + continue; + + if (other.targs != null) { + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (BaseType, otarg)) { + found = true; + break; + } + } + } + + if (!found) + return false; + } + } + + // Check interfaces implementation <- definition + if (other.InterfacesDefined != null) { + if (InterfacesDefined == null) + return false; + + foreach (var oiface in other.InterfacesDefined) { + found = false; + foreach (var iface in InterfacesDefined) { + if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { + found = true; + break; + } + } + + if (!found) + return false; + } + } + + // Check type parameters implementation -> definition + if (targs != null) { + if (other.targs == null) + return false; + + foreach (var targ in targs) { + found = false; + foreach (var otarg in other.targs) { + if (TypeSpecComparer.Override.IsEqual (targ, otarg)) { + found = true; + break; + } + } + + if (!found) + return false; + } + } + + // Check type parameters implementation <- definition + if (other.targs != null) { + foreach (var otarg in other.targs) { + // Ignore inflated type arguments, were checked above + if (!otarg.IsGenericParameter) + continue; + + if (targs == null) + return false; + + found = false; + foreach (var targ in targs) { + if (TypeSpecComparer.Override.IsEqual (targ, otarg)) { + found = true; + break; + } + } + + if (!found) + return false; + } + } + + return true; + } + + public static TypeParameterSpec[] InflateConstraints (TypeParameterInflator inflator, TypeParameterSpec[] tparams) + { + return InflateConstraints (tparams, l => l, inflator); + } + + public static TypeParameterSpec[] InflateConstraints (TypeParameterSpec[] tparams, Func inflatorFactory, T arg) + { + TypeParameterSpec[] constraints = null; + TypeParameterInflator? inflator = null; + + for (int i = 0; i < tparams.Length; ++i) { + var tp = tparams[i]; + if (tp.HasTypeConstraint || tp.InterfacesDefined != null || tp.TypeArguments != null) { + if (constraints == null) { + constraints = new TypeParameterSpec[tparams.Length]; + Array.Copy (tparams, constraints, constraints.Length); + } + + // + // Using a factory to avoid possibly expensive inflator build up + // + if (inflator == null) + inflator = inflatorFactory (arg); + + constraints[i] = (TypeParameterSpec) constraints[i].InflateMember (inflator.Value); + } + } + + if (constraints == null) + constraints = tparams; + + return constraints; + } + + public void InflateConstraints (TypeParameterInflator inflator, TypeParameterSpec tps) + { + tps.BaseType = inflator.Inflate (BaseType); + if (ifaces != null) { + tps.ifaces = new List (ifaces.Count); + for (int i = 0; i < ifaces.Count; ++i) + tps.ifaces.Add (inflator.Inflate (ifaces[i])); + } + + if (targs != null) { + tps.targs = new TypeSpec[targs.Length]; + for (int i = 0; i < targs.Length; ++i) + tps.targs[i] = inflator.Inflate (targs[i]); + } + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var tps = (TypeParameterSpec) MemberwiseClone (); + InflateConstraints (inflator, tps); + return tps; + } + + // + // Populates type parameter members using type parameter constraints + // The trick here is to be called late enough but not too late to + // populate member cache with all members from other types + // + protected override void InitializeMemberCache (bool onlyTypes) + { + cache = new MemberCache (); + + // + // For a type parameter the membercache is the union of the sets of members of the types + // specified as a primary constraint or secondary constraint + // + if (BaseType.BuiltinType != BuiltinTypeSpec.Type.Object && BaseType.BuiltinType != BuiltinTypeSpec.Type.ValueType) + cache.AddBaseType (BaseType); + + if (ifaces != null) { + foreach (var iface_type in Interfaces) { + cache.AddInterface (iface_type); + } + } + + if (targs != null) { + foreach (var ta in targs) { + var b_type = ta.BaseType; + if (b_type.BuiltinType != BuiltinTypeSpec.Type.Object && b_type.BuiltinType != BuiltinTypeSpec.Type.ValueType) + cache.AddBaseType (b_type); + + if (ta.Interfaces != null) { + foreach (var iface_type in ta.Interfaces) { + cache.AddInterface (iface_type); + } + } + } + } + } + + public bool IsConvertibleToInterface (TypeSpec iface) + { + if (Interfaces != null) { + foreach (var t in Interfaces) { + if (t == iface) + return true; + } + } + + if (TypeArguments != null) { + foreach (var t in TypeArguments) { + if (((TypeParameterSpec) t).IsConvertibleToInterface (iface)) + return true; + } + } + + return false; + } + + public override TypeSpec Mutate (TypeParameterMutator mutator) + { + return mutator.Mutate (this); + } + } + + public struct TypeParameterInflator + { + readonly TypeSpec type; + readonly TypeParameterSpec[] tparams; + readonly TypeSpec[] targs; + readonly IModuleContext context; + + public TypeParameterInflator (TypeParameterInflator nested, TypeSpec type) + : this (nested.context, type, nested.tparams, nested.targs) + { + } + + public TypeParameterInflator (IModuleContext context, TypeSpec type, TypeParameterSpec[] tparams, TypeSpec[] targs) + { + if (tparams.Length != targs.Length) + throw new ArgumentException ("Invalid arguments"); + + this.context = context; + this.tparams = tparams; + this.targs = targs; + this.type = type; + } + + #region Properties + + public IModuleContext Context { + get { + return context; + } + } + + public TypeSpec TypeInstance { + get { + return type; + } + } + + // + // Type parameters to inflate + // + public TypeParameterSpec[] TypeParameters { + get { + return tparams; + } + } + + #endregion + + public TypeSpec Inflate (TypeSpec type) + { + var tp = type as TypeParameterSpec; + if (tp != null) + return Inflate (tp); + + var ac = type as ArrayContainer; + if (ac != null) { + var et = Inflate (ac.Element); + if (et != ac.Element) + return ArrayContainer.MakeType (context.Module, et, ac.Rank); + + return ac; + } + + // + // When inflating a nested type, inflate its parent first + // in case it's using same type parameters (was inflated within the type) + // + TypeSpec[] targs; + int i = 0; + if (type.IsNested) { + var parent = Inflate (type.DeclaringType); + + // + // Keep the inflated type arguments + // + targs = type.TypeArguments; + + // + // When inflating imported nested type used inside same declaring type, we get TypeSpec + // because the import cache helps us to catch it. However, that means we have to look at + // type definition to get type argument (they are in fact type parameter in this case) + // + if (targs.Length == 0 && type.Arity > 0) + targs = type.MemberDefinition.TypeParameters; + + // + // Parent was inflated, find the same type on inflated type + // to use same cache for nested types on same generic parent + // + type = MemberCache.FindNestedType (parent, type.Name, type.Arity); + + // + // Handle the tricky case where parent shares local type arguments + // which means inflating inflated type + // + // class Test { + // public static Nested Foo () { return null; } + // + // public class Nested {} + // } + // + // return type of Test.Foo() has to be Test.Nested + // + if (targs.Length > 0) { + var inflated_targs = new TypeSpec[targs.Length]; + for (; i < targs.Length; ++i) + inflated_targs[i] = Inflate (targs[i]); + + type = type.MakeGenericType (context, inflated_targs); + } + + return type; + } + + // Nothing to do for non-generic type + if (type.Arity == 0) + return type; + + targs = new TypeSpec[type.Arity]; + + // + // Inflating using outside type arguments, var v = new Foo (), class Foo {} + // + if (type is InflatedTypeSpec) { + for (; i < targs.Length; ++i) + targs[i] = Inflate (type.TypeArguments[i]); + + type = type.GetDefinition (); + } else { + // + // Inflating parent using inside type arguments, class Foo { ITest foo; } + // + var args = type.MemberDefinition.TypeParameters; + foreach (var ds_tp in args) + targs[i++] = Inflate (ds_tp); + } + + return type.MakeGenericType (context, targs); + } + + public TypeSpec Inflate (TypeParameterSpec tp) + { + for (int i = 0; i < tparams.Length; ++i) + if (tparams [i] == tp) + return targs[i]; + + // This can happen when inflating nested types + // without type arguments specified + return tp; + } + } + + // + // Before emitting any code we have to change all MVAR references to VAR + // when the method is of generic type and has hoisted variables + // + public class TypeParameterMutator + { + readonly TypeParameter[] mvar; + readonly TypeParameter[] var; + Dictionary mutated_typespec; + + public TypeParameterMutator (TypeParameter[] mvar, TypeParameter[] var) + { + if (mvar.Length != var.Length) + throw new ArgumentException (); + + this.mvar = mvar; + this.var = var; + } + + #region Properties + + public TypeParameter[] MethodTypeParameters { + get { + return mvar; + } + } + + #endregion + + public static TypeSpec GetMemberDeclaringType (TypeSpec type) + { + if (type is InflatedTypeSpec) { + if (type.DeclaringType == null) + return type.GetDefinition (); + + var parent = GetMemberDeclaringType (type.DeclaringType); + type = MemberCache.GetMember (parent, type); + } + + return type; + } + + public TypeSpec Mutate (TypeSpec ts) + { + TypeSpec value; + if (mutated_typespec != null && mutated_typespec.TryGetValue (ts, out value)) + return value; + + value = ts.Mutate (this); + if (mutated_typespec == null) + mutated_typespec = new Dictionary (); + + mutated_typespec.Add (ts, value); + return value; + } + + public TypeParameterSpec Mutate (TypeParameterSpec tp) + { + for (int i = 0; i < mvar.Length; ++i) { + if (mvar[i].Type == tp) + return var[i].Type; + } + + return tp; + } + + public TypeSpec[] Mutate (TypeSpec[] targs) + { + TypeSpec[] mutated = new TypeSpec[targs.Length]; + bool changed = false; + for (int i = 0; i < targs.Length; ++i) { + mutated[i] = Mutate (targs[i]); + changed |= targs[i] != mutated[i]; + } + + return changed ? mutated : targs; + } + } + + /// + /// A TypeExpr which already resolved to a type parameter. + /// + public class TypeParameterExpr : TypeExpression + { + public TypeParameterExpr (TypeParameter type_parameter, Location loc) + : base (type_parameter.Type, loc) + { + this.eclass = ExprClass.TypeParameter; + } + } + + public class InflatedTypeSpec : TypeSpec + { + TypeSpec[] targs; + TypeParameterSpec[] constraints; + readonly TypeSpec open_type; + readonly IModuleContext context; + + public InflatedTypeSpec (IModuleContext context, TypeSpec openType, TypeSpec declaringType, TypeSpec[] targs) + : base (openType.Kind, declaringType, openType.MemberDefinition, null, openType.Modifiers) + { + if (targs == null) + throw new ArgumentNullException ("targs"); + +// this.state = openType.state; + this.context = context; + this.open_type = openType; + this.targs = targs; + + foreach (var arg in targs) { + if (arg.HasDynamicElement || arg.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + state |= StateFlags.HasDynamicElement; + break; + } + } + + if (open_type.Kind == MemberKind.MissingType) + MemberCache = MemberCache.Empty; + + if ((open_type.Modifiers & Modifiers.COMPILER_GENERATED) != 0) + state |= StateFlags.ConstraintsChecked; + } + + #region Properties + + public override TypeSpec BaseType { + get { + if (cache == null || (state & StateFlags.PendingBaseTypeInflate) != 0) + InitializeMemberCache (true); + + return base.BaseType; + } + } + + // + // Inflated type parameters with constraints array, mapping with type arguments is based on index + // + public TypeParameterSpec[] Constraints { + get { + if (constraints == null) { + constraints = TypeParameterSpec.InflateConstraints (MemberDefinition.TypeParameters, l => l.CreateLocalInflator (context), this); + } + + return constraints; + } + } + + // + // Used to cache expensive constraints validation on constructed types + // + public bool HasConstraintsChecked { + get { + return (state & StateFlags.ConstraintsChecked) != 0; + } + set { + state = value ? state | StateFlags.ConstraintsChecked : state & ~StateFlags.ConstraintsChecked; + } + } + + public override IList Interfaces { + get { + if (cache == null) + InitializeMemberCache (true); + + return base.Interfaces; + } + } + + public override bool IsExpressionTreeType { + get { + return (open_type.state & StateFlags.InflatedExpressionType) != 0; + } + } + + public override bool IsGenericIterateInterface { + get { + return (open_type.state & StateFlags.GenericIterateInterface) != 0; + } + } + + public override bool IsGenericTask { + get { + return (open_type.state & StateFlags.GenericTask) != 0; + } + } + + public override bool IsNullableType { + get { + return (open_type.state & StateFlags.InflatedNullableType) != 0; + } + } + + // + // Types used to inflate the generic type + // + public override TypeSpec[] TypeArguments { + get { + return targs; + } + } + + #endregion + + public static bool ContainsTypeParameter (TypeSpec type) + { + if (type.Kind == MemberKind.TypeParameter) + return true; + + var element_container = type as ElementTypeSpec; + if (element_container != null) + return ContainsTypeParameter (element_container.Element); + + foreach (var t in type.TypeArguments) { + if (ContainsTypeParameter (t)) { + return true; + } + } + + return false; + } + + TypeParameterInflator CreateLocalInflator (IModuleContext context) + { + TypeParameterSpec[] tparams_full; + TypeSpec[] targs_full = targs; + if (IsNested) { + // + // Special case is needed when we are inflating an open type (nested type definition) + // on inflated parent. Consider following case + // + // Foo.Bar => Foo.Bar + // + // Any later inflation of Foo.Bar has to also inflate T if used inside Bar + // + List merged_targs = null; + List merged_tparams = null; + + var type = DeclaringType; + + do { + if (type.TypeArguments.Length > 0) { + if (merged_targs == null) { + merged_targs = new List (); + merged_tparams = new List (); + if (targs.Length > 0) { + merged_targs.AddRange (targs); + merged_tparams.AddRange (open_type.MemberDefinition.TypeParameters); + } + } + merged_tparams.AddRange (type.MemberDefinition.TypeParameters); + merged_targs.AddRange (type.TypeArguments); + } + type = type.DeclaringType; + } while (type != null); + + if (merged_targs != null) { + // Type arguments are not in the right order but it should not matter in this case + targs_full = merged_targs.ToArray (); + tparams_full = merged_tparams.ToArray (); + } else if (targs.Length == 0) { + tparams_full = TypeParameterSpec.EmptyTypes; + } else { + tparams_full = open_type.MemberDefinition.TypeParameters; + } + } else if (targs.Length == 0) { + tparams_full = TypeParameterSpec.EmptyTypes; + } else { + tparams_full = open_type.MemberDefinition.TypeParameters; + } + + return new TypeParameterInflator (context, this, tparams_full, targs_full); + } + + MetaType CreateMetaInfo (TypeParameterMutator mutator) + { + // + // Converts nested type arguments into right order + // Foo.Bar => string, bool, int + // + var all = new List (); + TypeSpec type = this; + TypeSpec definition = type; + do { + if (type.GetDefinition().IsGeneric) { + all.InsertRange (0, + type.TypeArguments != TypeSpec.EmptyTypes ? + type.TypeArguments.Select (l => l.GetMetaInfo ()) : + type.MemberDefinition.TypeParameters.Select (l => l.GetMetaInfo ())); + } + + definition = definition.GetDefinition (); + type = type.DeclaringType; + } while (type != null); + + return definition.GetMetaInfo ().MakeGenericType (all.ToArray ()); + } + + public override ObsoleteAttribute GetAttributeObsolete () + { + return open_type.GetAttributeObsolete (); + } + + protected override bool IsNotCLSCompliant (out bool attrValue) + { + if (base.IsNotCLSCompliant (out attrValue)) + return true; + + foreach (var ta in TypeArguments) { + if (ta.MemberDefinition.CLSAttributeValue == false) + return true; + } + + return false; + } + + public override TypeSpec GetDefinition () + { + return open_type; + } + + public override MetaType GetMetaInfo () + { + if (info == null) + info = CreateMetaInfo (null); + + return info; + } + + public override string GetSignatureForError () + { + if (IsNullableType) + return targs[0].GetSignatureForError () + "?"; + + return base.GetSignatureForError (); + } + + protected override string GetTypeNameSignature () + { + if (targs.Length == 0 || MemberDefinition is AnonymousTypeClass) + return null; + + return "<" + TypeManager.CSharpName (targs) + ">"; + } + + public bool HasDynamicArgument () + { + for (int i = 0; i < targs.Length; ++i) { + var item = targs[i]; + + if (item.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + if (item is InflatedTypeSpec) { + if (((InflatedTypeSpec) item).HasDynamicArgument ()) + return true; + + continue; + } + + if (item.IsArray) { + while (item.IsArray) { + item = ((ArrayContainer) item).Element; + } + + if (item.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + } + } + + return false; + } + + protected override void InitializeMemberCache (bool onlyTypes) + { + if (cache == null) { + var open_cache = onlyTypes ? open_type.MemberCacheTypes : open_type.MemberCache; + + // Surprisingly, calling MemberCache on open type could meantime create cache on this type + // for imported type parameter constraints referencing nested type of this declaration + if (cache == null) + cache = new MemberCache (open_cache); + } + + var inflator = CreateLocalInflator (context); + + // + // Two stage inflate due to possible nested types recursive + // references + // + // class A { + // B b; + // class B { + // T Value; + // } + // } + // + // When resolving type of `b' members of `B' cannot be + // inflated because are not yet available in membercache + // + if ((state & StateFlags.PendingMemberCacheMembers) == 0) { + open_type.MemberCacheTypes.InflateTypes (cache, inflator); + + // + // Inflate any implemented interfaces + // + if (open_type.Interfaces != null) { + ifaces = new List (open_type.Interfaces.Count); + foreach (var iface in open_type.Interfaces) { + var iface_inflated = inflator.Inflate (iface); + if (iface_inflated == null) + continue; + + AddInterface (iface_inflated); + } + } + + // + // Handles the tricky case of recursive nested base generic type + // + // class A : Base.Nested> { + // class Nested {} + // } + // + // When inflating A. base type is not yet known, secondary + // inflation is required (not common case) once base scope + // is known + // + if (open_type.BaseType == null) { + if (IsClass) + state |= StateFlags.PendingBaseTypeInflate; + } else { + BaseType = inflator.Inflate (open_type.BaseType); + } + } else if ((state & StateFlags.PendingBaseTypeInflate) != 0) { + BaseType = inflator.Inflate (open_type.BaseType); + state &= ~StateFlags.PendingBaseTypeInflate; + } + + if (onlyTypes) { + state |= StateFlags.PendingMemberCacheMembers; + return; + } + + var tc = open_type.MemberDefinition as TypeContainer; + if (tc != null && !tc.HasMembersDefined) + throw new InternalErrorException ("Inflating MemberCache with undefined members"); + + if ((state & StateFlags.PendingBaseTypeInflate) != 0) { + BaseType = inflator.Inflate (open_type.BaseType); + state &= ~StateFlags.PendingBaseTypeInflate; + } + + state &= ~StateFlags.PendingMemberCacheMembers; + open_type.MemberCache.InflateMembers (cache, open_type, inflator); + } + + public override TypeSpec Mutate (TypeParameterMutator mutator) + { + var targs = TypeArguments; + if (targs != null) + targs = mutator.Mutate (targs); + + var decl = DeclaringType; + if (IsNested && DeclaringType.IsGenericOrParentIsGeneric) + decl = mutator.Mutate (decl); + + if (targs == TypeArguments && decl == DeclaringType) + return this; + + var mutated = (InflatedTypeSpec) MemberwiseClone (); + if (decl != DeclaringType) { + // Gets back MethodInfo in case of metaInfo was inflated + //mutated.info = MemberCache.GetMember (DeclaringType.GetDefinition (), this).info; + + mutated.declaringType = decl; + mutated.state |= StateFlags.PendingMetaInflate; + } + + if (targs != null) { + mutated.targs = targs; + mutated.info = null; + } + + return mutated; + } + } + + + // + // Tracks the type arguments when instantiating a generic type. It's used + // by both type arguments and type parameters + // + public class TypeArguments + { + List args; + TypeSpec[] atypes; + + public List Args { + get { return this.args; } + } + + public TypeArguments (params FullNamedExpression[] types) + { + this.args = new List (types); + } + + public void Add (FullNamedExpression type) + { + args.Add (type); + } + + // TODO: Kill this monster + public TypeParameterName[] GetDeclarations () + { + return args.ConvertAll (i => (TypeParameterName) i).ToArray (); + } + + /// + /// We may only be used after Resolve() is called and return the fully + /// resolved types. + /// + // TODO: Not needed, just return type from resolve + public TypeSpec[] Arguments { + get { + return atypes; + } + set { + atypes = value; + } + } + + public int Count { + get { + return args.Count; + } + } + + public virtual bool IsEmpty { + get { + return false; + } + } + + public string GetSignatureForError() + { + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < Count; ++i) { + var expr = args[i]; + if (expr != null) + sb.Append (expr.GetSignatureForError ()); + + if (i + 1 < Count) + sb.Append (','); + } + + return sb.ToString (); + } + + /// + /// Resolve the type arguments. + /// + public virtual bool Resolve (IMemberContext ec) + { + if (atypes != null) + return atypes.Length != 0; + + int count = args.Count; + bool ok = true; + + atypes = new TypeSpec [count]; + + for (int i = 0; i < count; i++){ + var te = args[i].ResolveAsType (ec); + if (te == null) { + ok = false; + continue; + } + + atypes[i] = te; + + if (te.IsStatic) { + ec.Module.Compiler.Report.Error (718, args[i].Location, "`{0}': static classes cannot be used as generic arguments", + te.GetSignatureForError ()); + ok = false; + } + + if (te.IsPointer || te.IsSpecialRuntimeType) { + ec.Module.Compiler.Report.Error (306, args[i].Location, + "The type `{0}' may not be used as a type argument", + te.GetSignatureForError ()); + ok = false; + } + } + + if (!ok) + atypes = TypeSpec.EmptyTypes; + + return ok; + } + + public TypeArguments Clone () + { + TypeArguments copy = new TypeArguments (); + foreach (var ta in args) + copy.args.Add (ta); + + return copy; + } + } + + public class UnboundTypeArguments : TypeArguments + { + public UnboundTypeArguments (int arity) + : base (new FullNamedExpression[arity]) + { + } + + public override bool IsEmpty { + get { + return true; + } + } + + public override bool Resolve (IMemberContext ec) + { + // Nothing to be resolved + return true; + } + } + + public class TypeParameterName : SimpleName + { + Attributes attributes; + Variance variance; + + public TypeParameterName (string name, Attributes attrs, Location loc) + : this (name, attrs, Variance.None, loc) + { + } + + public TypeParameterName (string name, Attributes attrs, Variance variance, Location loc) + : base (name, loc) + { + attributes = attrs; + this.variance = variance; + } + + public Attributes OptAttributes { + get { + return attributes; + } + } + + public Variance Variance { + get { + return variance; + } + } + } + + // + // A type expression of generic type with type arguments + // + class GenericTypeExpr : TypeExpr + { + TypeArguments args; + TypeSpec open_type; + + /// + /// Instantiate the generic type `t' with the type arguments `args'. + /// Use this constructor if you already know the fully resolved + /// generic type. + /// + public GenericTypeExpr (TypeSpec open_type, TypeArguments args, Location l) + { + this.open_type = open_type; + loc = l; + this.args = args; + } + + public TypeArguments TypeArguments { + get { return args; } + } + + public override string GetSignatureForError () + { + return TypeManager.CSharpName (type); + } + + public override TypeSpec ResolveAsType (IMemberContext mc) + { + if (eclass != ExprClass.Unresolved) + return type; + + if (!args.Resolve (mc)) + return null; + + TypeSpec[] atypes = args.Arguments; + + // + // Now bind the parameters + // + var inflated = open_type.MakeGenericType (mc, atypes); + type = inflated; + eclass = ExprClass.Type; + + // + // The constraints can be checked only when full type hierarchy is known + // + if (!inflated.HasConstraintsChecked && mc.Module.HasTypesFullyDefined) { + var constraints = inflated.Constraints; + if (constraints != null) { + var cc = new ConstraintChecker (mc); + if (cc.CheckAll (open_type, atypes, constraints, loc)) { + inflated.HasConstraintsChecked = true; + } + } + } + + return type; + } + + public override bool Equals (object obj) + { + GenericTypeExpr cobj = obj as GenericTypeExpr; + if (cobj == null) + return false; + + if ((type == null) || (cobj.type == null)) + return false; + + return type == cobj.type; + } + + public override int GetHashCode () + { + return base.GetHashCode (); + } + } + + // + // Generic type with unbound type arguments, used for typeof (G<,,>) + // + class GenericOpenTypeExpr : TypeExpression + { + public GenericOpenTypeExpr (TypeSpec type, /*UnboundTypeArguments args,*/ Location loc) + : base (type.GetDefinition (), loc) + { + } + } + + struct ConstraintChecker + { + IMemberContext mc; + bool ignore_inferred_dynamic; + bool recursive_checks; + + public ConstraintChecker (IMemberContext ctx) + { + this.mc = ctx; + ignore_inferred_dynamic = false; + recursive_checks = false; + } + + #region Properties + + public bool IgnoreInferredDynamic { + get { + return ignore_inferred_dynamic; + } + set { + ignore_inferred_dynamic = value; + } + } + + #endregion + + // + // Checks the constraints of open generic type against type + // arguments. This version is used for types which could not be + // checked immediatelly during construction because the type + // hierarchy was not yet fully setup (before Emit phase) + // + public static bool Check (IMemberContext mc, TypeSpec type, Location loc) + { + // + // Check declaring type first if there is any + // + if (type.DeclaringType != null && !Check (mc, type.DeclaringType, loc)) + return false; + + while (type is ElementTypeSpec) + type = ((ElementTypeSpec) type).Element; + + if (type.Arity == 0) + return true; + + var gtype = type as InflatedTypeSpec; + if (gtype == null) + return true; + + var constraints = gtype.Constraints; + if (constraints == null) + return true; + + if (gtype.HasConstraintsChecked) + return true; + + var cc = new ConstraintChecker (mc); + cc.recursive_checks = true; + + if (cc.CheckAll (gtype.GetDefinition (), type.TypeArguments, constraints, loc)) { + gtype.HasConstraintsChecked = true; + return true; + } + + return false; + } + + // + // Checks all type arguments againts type parameters constraints + // NOTE: It can run in probing mode when `mc' is null + // + public bool CheckAll (MemberSpec context, TypeSpec[] targs, TypeParameterSpec[] tparams, Location loc) + { + for (int i = 0; i < tparams.Length; i++) { + if (ignore_inferred_dynamic && targs[i].BuiltinType == BuiltinTypeSpec.Type.Dynamic) + continue; + + var targ = targs[i]; + if (!CheckConstraint (context, targ, tparams [i], loc)) + return false; + + if (!recursive_checks) + continue; + + if (!Check (mc, targ, loc)) + return false; + } + + return true; + } + + bool CheckConstraint (MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, Location loc) + { + // + // First, check the `class' and `struct' constraints. + // + if (tparam.HasSpecialClass && !TypeSpec.IsReferenceType (atype)) { + if (mc != null) { + mc.Module.Compiler.Report.Error (452, loc, + "The type `{0}' must be a reference type in order to use it as type parameter `{1}' in the generic type or method `{2}'", + TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); + } + + return false; + } + + if (tparam.HasSpecialStruct && (!TypeSpec.IsValueType (atype) || atype.IsNullableType)) { + if (mc != null) { + mc.Module.Compiler.Report.Error (453, loc, + "The type `{0}' must be a non-nullable value type in order to use it as type parameter `{1}' in the generic type or method `{2}'", + TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); + } + + return false; + } + + bool ok = true; + + // + // Check the class constraint + // + if (tparam.HasTypeConstraint) { + var dep = tparam.BaseType.GetMissingDependencies (); + if (dep != null) { + if (mc == null) + return false; + + ImportedTypeDefinition.Error_MissingDependency (mc, dep, loc); + ok = false; + } + + if (!CheckConversion (mc, context, atype, tparam, tparam.BaseType, loc)) { + if (mc == null) + return false; + + ok = false; + } + } + + // + // Check the interfaces constraints + // + if (tparam.Interfaces != null) { + if (atype.IsNullableType) { + 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; + + // return immediately to avoid duplicate errors because we are scanning + // expanded interface list + return false; + } + + if (!CheckConversion (mc, context, atype, tparam, iface, loc)) { + if (mc == null) + return false; + + ok = false; + } + } + } + } + + // + // Check the type parameter constraint + // + if (tparam.TypeArguments != null) { + foreach (var ta in tparam.TypeArguments) { + if (!CheckConversion (mc, context, atype, tparam, ta, loc)) { + if (mc == null) + return false; + + ok = false; + } + } + } + + // + // Finally, check the constructor constraint. + // + if (!tparam.HasSpecialConstructor) + return ok; + + if (!HasDefaultConstructor (atype)) { + if (mc != null) { + mc.Module.Compiler.Report.SymbolRelatedToPreviousError (atype); + mc.Module.Compiler.Report.Error (310, loc, + "The type `{0}' must have a public parameterless constructor in order to use it as parameter `{1}' in the generic type or method `{2}'", + TypeManager.CSharpName (atype), tparam.GetSignatureForError (), context.GetSignatureForError ()); + } + return false; + } + + return ok; + } + + static bool HasDynamicTypeArgument (TypeSpec[] targs) + { + for (int i = 0; i < targs.Length; ++i) { + var targ = targs [i]; + if (targ.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return true; + + if (HasDynamicTypeArgument (targ.TypeArguments)) + return true; + } + + return false; + } + + bool CheckConversion (IMemberContext mc, MemberSpec context, TypeSpec atype, TypeParameterSpec tparam, TypeSpec ttype, Location loc) + { + if (atype == ttype) + return true; + + if (atype.IsGenericParameter) { + var tps = (TypeParameterSpec) atype; + if (Convert.ImplicitTypeParameterConversion (null, tps, ttype) != null) + 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) + return true; + + } else if (TypeSpec.IsValueType (atype)) { + if (Convert.ImplicitBoxingConversion (null, atype, ttype) != null) + return true; + } else { + var expr = new EmptyExpression (atype); + if (Convert.ImplicitStandardConversionExists (expr, ttype)) + return true; + } + + // + // When partial/full type inference finds a dynamic type argument delay + // the constraint check to runtime, it can succeed for real underlying + // dynamic type + // + if (ignore_inferred_dynamic && HasDynamicTypeArgument (ttype.TypeArguments)) + return true; + + if (mc != null) { + mc.Module.Compiler.Report.SymbolRelatedToPreviousError (tparam); + if (atype.IsGenericParameter) { + mc.Module.Compiler.Report.Error (314, loc, + "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 ()); + } 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}'", + atype.GetSignatureForError (), tparam.GetSignatureForError (), context.GetSignatureForError (), ttype.GetSignatureForError ()); + } + } + + return false; + } + + bool HasDefaultConstructor (TypeSpec atype) + { + var tp = atype as TypeParameterSpec; + if (tp != null) { + return tp.HasSpecialConstructor || tp.HasSpecialStruct; + } + + if (atype.IsStruct || atype.IsEnum) + return true; + + if (atype.IsAbstract) + return false; + + var tdef = atype.GetDefinition (); + + var found = MemberCache.FindMember (tdef, + MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), + BindingRestriction.DeclaredOnly | BindingRestriction.InstanceOnly); + + return found != null && (found.Modifiers & Modifiers.PUBLIC) != 0; + } + } + + /// + /// A generic method definition. + /// + public class GenericMethod : DeclSpace + { + ParametersCompiled parameters; + + public GenericMethod (NamespaceContainer ns, DeclSpace parent, MemberName name, + FullNamedExpression return_type, ParametersCompiled parameters) + : base (ns, parent, name, null) + { + this.parameters = parameters; + } + + public GenericMethod (NamespaceContainer ns, DeclSpace parent, MemberName name, TypeParameter[] tparams, + FullNamedExpression return_type, ParametersCompiled parameters) + : this (ns, parent, name, return_type, parameters) + { + this.type_params = tparams; + } + + public override TypeParameter[] CurrentTypeParameters { + get { + return base.type_params; + } + } + + protected override TypeAttributes TypeAttr { + get { + throw new NotSupportedException (); + } + } + + public override void DefineType () + { + throw new Exception (); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + throw new NotSupportedException (); + } + + public override bool Define () + { + throw new NotSupportedException (); + } + + /// + /// Define and resolve the type parameters. + /// We're called from Method.Define(). + /// + public bool Define (MethodOrOperator m) + { + TypeParameterName[] names = MemberName.TypeArguments.GetDeclarations (); + string[] snames = new string [names.Length]; + var block = m.Block; + for (int i = 0; i < names.Length; i++) { + string type_argument_name = names[i].Name; + + if (block == null) { + int idx = parameters.GetParameterIndexByName (type_argument_name); + if (idx >= 0) { + var b = m.Block; + if (b == null) + b = new ToplevelBlock (Compiler, Location); + + b.Error_AlreadyDeclaredTypeParameter (type_argument_name, parameters[i].Location); + } + } else { + INamedBlockVariable variable = null; + block.GetLocalName (type_argument_name, m.Block, ref variable); + if (variable != null) + variable.Block.Error_AlreadyDeclaredTypeParameter (type_argument_name, variable.Location); + } + + snames[i] = type_argument_name; + } + + GenericTypeParameterBuilder[] gen_params = m.MethodBuilder.DefineGenericParameters (snames); + for (int i = 0; i < TypeParameters.Length; i++) + TypeParameters [i].Define (gen_params [i], null); + + return true; + } + + public void EmitAttributes () + { + if (OptAttributes != null) + OptAttributes.Emit (); + } + + public override string GetSignatureForError () + { + return base.GetSignatureForError () + parameters.GetSignatureForError (); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method | AttributeTargets.ReturnValue; + } + } + + public override string DocCommentHeader { + get { return "M:"; } + } + + public new void VerifyClsCompliance () + { + foreach (TypeParameter tp in TypeParameters) { + tp.VerifyClsCompliance (); + } + } + } + + public partial class TypeManager + { + public static Variance CheckTypeVariance (TypeSpec t, Variance expected, IMemberContext member) + { + var tp = t as TypeParameterSpec; + if (tp != null) { + Variance v = tp.Variance; + if (expected == Variance.None && v != expected || + expected == Variance.Covariant && v == Variance.Contravariant || + expected == Variance.Contravariant && v == Variance.Covariant) { + ((TypeParameter)tp.MemberDefinition).ErrorInvalidVariance (member, expected); + } + + return expected; + } + + if (t.TypeArguments.Length > 0) { + var targs_definition = t.MemberDefinition.TypeParameters; + TypeSpec[] targs = GetTypeArguments (t); + for (int i = 0; i < targs.Length; ++i) { + Variance v = targs_definition[i].Variance; + CheckTypeVariance (targs[i], (Variance) ((int)v * (int)expected), member); + } + + return expected; + } + + if (t.IsArray) + return CheckTypeVariance (GetElementType (t), expected, member); + + return Variance.None; + } + } + + // + // Implements C# type inference + // + class TypeInference + { + // + // Tracks successful rate of type inference + // + int score = int.MaxValue; + readonly Arguments arguments; + readonly int arg_count; + + public TypeInference (Arguments arguments) + { + this.arguments = arguments; + if (arguments != null) + arg_count = arguments.Count; + } + + public int InferenceScore { + get { + return score; + } + } + + public TypeSpec[] InferMethodArguments (ResolveContext ec, MethodSpec method) + { + var method_generic_args = method.GenericDefinition.TypeParameters; + TypeInferenceContext context = new TypeInferenceContext (method_generic_args); + if (!context.UnfixedVariableExists) + return TypeSpec.EmptyTypes; + + AParametersCollection pd = method.Parameters; + if (!InferInPhases (ec, context, pd)) + return null; + + return context.InferredTypeArguments; + } + + // + // Implements method type arguments inference + // + bool InferInPhases (ResolveContext ec, TypeInferenceContext tic, AParametersCollection methodParameters) + { + int params_arguments_start; + if (methodParameters.HasParams) { + params_arguments_start = methodParameters.Count - 1; + } else { + params_arguments_start = arg_count; + } + + TypeSpec [] ptypes = methodParameters.Types; + + // + // The first inference phase + // + TypeSpec method_parameter = null; + for (int i = 0; i < arg_count; i++) { + Argument a = arguments [i]; + if (a == null) + continue; + + if (i < params_arguments_start) { + method_parameter = methodParameters.Types [i]; + } else if (i == params_arguments_start) { + if (arg_count == params_arguments_start + 1 && TypeManager.HasElementType (a.Type)) + method_parameter = methodParameters.Types [params_arguments_start]; + else + method_parameter = TypeManager.GetElementType (methodParameters.Types [params_arguments_start]); + + ptypes = (TypeSpec[]) ptypes.Clone (); + ptypes [i] = method_parameter; + } + + // + // When a lambda expression, an anonymous method + // is used an explicit argument type inference takes a place + // + AnonymousMethodExpression am = a.Expr as AnonymousMethodExpression; + if (am != null) { + if (am.ExplicitTypeInference (ec, tic, method_parameter)) + --score; + continue; + } + + if (a.IsByRef) { + score -= tic.ExactInference (a.Type, method_parameter); + continue; + } + + if (a.Expr.Type == InternalType.NullLiteral) + continue; + + if (TypeSpec.IsValueType (method_parameter)) { + score -= tic.LowerBoundInference (a.Type, method_parameter); + continue; + } + + // + // Otherwise an output type inference is made + // + score -= tic.OutputTypeInference (ec, a.Expr, method_parameter); + } + + // + // Part of the second phase but because it happens only once + // we don't need to call it in cycle + // + bool fixed_any = false; + if (!tic.FixIndependentTypeArguments (ec, ptypes, ref fixed_any)) + return false; + + return DoSecondPhase (ec, tic, ptypes, !fixed_any); + } + + bool DoSecondPhase (ResolveContext ec, TypeInferenceContext tic, TypeSpec[] methodParameters, bool fixDependent) + { + bool fixed_any = false; + if (fixDependent && !tic.FixDependentTypes (ec, ref fixed_any)) + return false; + + // If no further unfixed type variables exist, type inference succeeds + if (!tic.UnfixedVariableExists) + return true; + + if (!fixed_any && fixDependent) + return false; + + // For all arguments where the corresponding argument output types + // contain unfixed type variables but the input types do not, + // an output type inference is made + for (int i = 0; i < arg_count; i++) { + + // Align params arguments + TypeSpec t_i = methodParameters [i >= methodParameters.Length ? methodParameters.Length - 1: i]; + + if (!TypeManager.IsDelegateType (t_i)) { + if (!t_i.IsExpressionTreeType) + continue; + + t_i = TypeManager.GetTypeArguments (t_i) [0]; + } + + 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); + } + + + return DoSecondPhase (ec, tic, methodParameters, true); + } + } + + public class TypeInferenceContext + { + protected enum BoundKind + { + Exact = 0, + Lower = 1, + Upper = 2 + } + + protected class BoundInfo : IEquatable + { + public readonly TypeSpec Type; + public readonly BoundKind Kind; + + public BoundInfo (TypeSpec type, BoundKind kind) + { + this.Type = type; + this.Kind = kind; + } + + public override int GetHashCode () + { + return Type.GetHashCode (); + } + + public virtual Expression GetTypeExpression () + { + return new TypeExpression (Type, Location.Null); + } + + #region IEquatable Members + + public virtual bool Equals (BoundInfo other) + { + return Type == other.Type && Kind == other.Kind; + } + + #endregion + } + + readonly TypeSpec[] tp_args; + readonly TypeSpec[] fixed_types; + readonly List[] bounds; + bool failed; + + // TODO MemberCache: Could it be TypeParameterSpec[] ?? + public TypeInferenceContext (TypeSpec[] typeArguments) + { + if (typeArguments.Length == 0) + throw new ArgumentException ("Empty generic arguments"); + + fixed_types = new TypeSpec [typeArguments.Length]; + for (int i = 0; i < typeArguments.Length; ++i) { + if (typeArguments [i].IsGenericParameter) { + if (bounds == null) { + bounds = new List [typeArguments.Length]; + tp_args = new TypeSpec [typeArguments.Length]; + } + tp_args [i] = typeArguments [i]; + } else { + fixed_types [i] = typeArguments [i]; + } + } + } + + // + // Used together with AddCommonTypeBound fo implement + // 7.4.2.13 Finding the best common type of a set of expressions + // + public TypeInferenceContext () + { + fixed_types = new TypeSpec [1]; + tp_args = new TypeSpec [1]; + tp_args[0] = InternalType.Arglist; // it can be any internal type + bounds = new List [1]; + } + + public TypeSpec[] InferredTypeArguments { + get { + return fixed_types; + } + } + + public void AddCommonTypeBound (TypeSpec type) + { + AddToBounds (new BoundInfo (type, BoundKind.Lower), 0); + } + + protected void AddToBounds (BoundInfo bound, int index) + { + // + // Some types cannot be used as type arguments + // + if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType || + bound.Type == InternalType.MethodGroup) + return; + + var a = bounds [index]; + if (a == null) { + a = new List (2); + a.Add (bound); + bounds [index] = a; + return; + } + + if (a.Contains (bound)) + return; + + a.Add (bound); + } + + bool AllTypesAreFixed (TypeSpec[] types) + { + foreach (TypeSpec t in types) { + if (t.IsGenericParameter) { + if (!IsFixed (t)) + return false; + continue; + } + + if (TypeManager.IsGenericType (t)) + return AllTypesAreFixed (TypeManager.GetTypeArguments (t)); + } + + return true; + } + + // + // 26.3.3.8 Exact Inference + // + public int ExactInference (TypeSpec u, TypeSpec v) + { + // If V is an array type + if (v.IsArray) { + if (!u.IsArray) + return 0; + + // TODO MemberCache: GetMetaInfo () + if (u.GetMetaInfo ().GetArrayRank () != v.GetMetaInfo ().GetArrayRank ()) + return 0; + + return ExactInference (TypeManager.GetElementType (u), TypeManager.GetElementType (v)); + } + + // If V is constructed type and U is constructed type + if (TypeManager.IsGenericType (v)) { + if (!TypeManager.IsGenericType (u)) + return 0; + + TypeSpec [] ga_u = TypeManager.GetTypeArguments (u); + TypeSpec [] ga_v = TypeManager.GetTypeArguments (v); + if (ga_u.Length != ga_v.Length) + return 0; + + int score = 0; + for (int i = 0; i < ga_u.Length; ++i) + score += ExactInference (ga_u [i], ga_v [i]); + + return score > 0 ? 1 : 0; + } + + // If V is one of the unfixed type arguments + int pos = IsUnfixed (v); + if (pos == -1) + return 0; + + AddToBounds (new BoundInfo (u, BoundKind.Exact), pos); + return 1; + } + + public bool FixAllTypes (ResolveContext ec) + { + for (int i = 0; i < tp_args.Length; ++i) { + if (!FixType (ec, i)) + return false; + } + return true; + } + + // + // All unfixed type variables Xi are fixed for which all of the following hold: + // a, There is at least one type variable Xj that depends on Xi + // b, Xi has a non-empty set of bounds + // + public bool FixDependentTypes (ResolveContext ec, ref bool fixed_any) + { + for (int i = 0; i < tp_args.Length; ++i) { + if (fixed_types[i] != null) + continue; + + if (bounds[i] == null) + continue; + + if (!FixType (ec, i)) + return false; + + fixed_any = true; + } + + return true; + } + + // + // All unfixed type variables Xi which depend on no Xj are fixed + // + public bool FixIndependentTypeArguments (ResolveContext ec, TypeSpec[] methodParameters, ref bool fixed_any) + { + var types_to_fix = new List (tp_args); + for (int i = 0; i < methodParameters.Length; ++i) { + TypeSpec t = methodParameters[i]; + + if (!TypeManager.IsDelegateType (t)) { + if (!t.IsExpressionTreeType) + continue; + + t = TypeManager.GetTypeArguments (t) [0]; + } + + if (t.IsGenericParameter) + continue; + + var invoke = Delegate.GetInvokeMethod (t); + TypeSpec rtype = invoke.ReturnType; + while (rtype.IsArray) + rtype = ((ArrayContainer) rtype).Element; + + if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype)) + continue; + + // Remove dependent types, they cannot be fixed yet + RemoveDependentTypes (types_to_fix, rtype); + } + + foreach (TypeSpec t in types_to_fix) { + if (t == null) + continue; + + int idx = IsUnfixed (t); + if (idx >= 0 && !FixType (ec, idx)) { + return false; + } + } + + fixed_any = types_to_fix.Count > 0; + return true; + } + + // + // 26.3.3.10 Fixing + // + public bool FixType (ResolveContext ec, int i) + { + // It's already fixed + if (fixed_types[i] != null) + throw new InternalErrorException ("Type argument has been already fixed"); + + if (failed) + return false; + + var candidates = bounds [i]; + if (candidates == null) + return false; + + if (candidates.Count == 1) { + TypeSpec t = candidates[0].Type; + if (t == InternalType.NullLiteral) + return false; + + fixed_types [i] = t; + return true; + } + + // + // Determines a unique type from which there is + // a standard implicit conversion to all the other + // candidate types. + // + TypeSpec best_candidate = null; + int cii; + int candidates_count = candidates.Count; + for (int ci = 0; ci < candidates_count; ++ci) { + BoundInfo bound = candidates [ci]; + for (cii = 0; cii < candidates_count; ++cii) { + if (cii == ci) + continue; + + BoundInfo cbound = candidates[cii]; + + // Same type parameters with different bounds + if (cbound.Type == bound.Type) { + if (bound.Kind != BoundKind.Exact) + bound = cbound; + + continue; + } + + if (bound.Kind == BoundKind.Exact || cbound.Kind == BoundKind.Exact) { + if (cbound.Kind == BoundKind.Lower) { + if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) { + break; + } + + continue; + } + if (cbound.Kind == BoundKind.Upper) { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + + continue; + } + + if (bound.Kind != BoundKind.Exact) { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + + bound = cbound; + continue; + } + + break; + } + + if (bound.Kind == BoundKind.Lower) { + if (cbound.Kind == BoundKind.Lower) { + if (!Convert.ImplicitConversionExists (ec, cbound.GetTypeExpression (), bound.Type)) { + break; + } + } else { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + + bound = cbound; + } + + continue; + } + + if (bound.Kind == BoundKind.Upper) { + if (!Convert.ImplicitConversionExists (ec, bound.GetTypeExpression (), cbound.Type)) { + break; + } + } else { + throw new NotImplementedException ("variance conversion"); + } + } + + if (cii != candidates_count) + continue; + + // + // We already have the best candidate, break if thet are different + // + // Dynamic is never ambiguous as we prefer dynamic over other best candidate types + // + if (best_candidate != null) { + + if (best_candidate.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + continue; + + if (bound.Type.BuiltinType != BuiltinTypeSpec.Type.Dynamic && best_candidate != bound.Type) + return false; + } + + best_candidate = bound.Type; + } + + if (best_candidate == null) + return false; + + 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 + // null when type parameter has not been fixed + // + public TypeSpec InflateGenericArgument (IModuleContext context, TypeSpec parameter) + { + var tp = parameter as TypeParameterSpec; + if (tp != null) { + // + // Type inference works on generic arguments (MVAR) only + // + if (!tp.IsMethodOwned) + return parameter; + + // + // Ensure the type parameter belongs to same container + // + if (tp.DeclaredPosition < tp_args.Length && tp_args[tp.DeclaredPosition] == parameter) + return fixed_types[tp.DeclaredPosition] ?? parameter; + + return parameter; + } + + var gt = parameter as InflatedTypeSpec; + if (gt != null) { + var inflated_targs = new TypeSpec [gt.TypeArguments.Length]; + for (int ii = 0; ii < inflated_targs.Length; ++ii) { + var inflated = InflateGenericArgument (context, gt.TypeArguments [ii]); + if (inflated == null) + return null; + + inflated_targs[ii] = inflated; + } + + return gt.GetDefinition ().MakeGenericType (context, inflated_targs); + } + + return parameter; + } + + // + // Tests whether all delegate input arguments are fixed and generic output type + // requires output type inference + // + public bool IsReturnTypeNonDependent (ResolveContext ec, MethodSpec invoke, TypeSpec returnType) + { + while (returnType.IsArray) + returnType = ((ArrayContainer) returnType).Element; + + if (returnType.IsGenericParameter) { + if (IsFixed (returnType)) + return false; + } else if (TypeManager.IsGenericType (returnType)) { + if (TypeManager.IsDelegateType (returnType)) { + invoke = Delegate.GetInvokeMethod (returnType); + return IsReturnTypeNonDependent (ec, invoke, invoke.ReturnType); + } + + TypeSpec[] g_args = TypeManager.GetTypeArguments (returnType); + + // At least one unfixed return type has to exist + if (AllTypesAreFixed (g_args)) + return false; + } else { + return false; + } + + // All generic input arguments have to be fixed + AParametersCollection d_parameters = invoke.Parameters; + return AllTypesAreFixed (d_parameters.Types); + } + + bool IsFixed (TypeSpec type) + { + return IsUnfixed (type) == -1; + } + + int IsUnfixed (TypeSpec type) + { + if (!type.IsGenericParameter) + return -1; + + for (int i = 0; i < tp_args.Length; ++i) { + if (tp_args[i] == type) { + if (fixed_types[i] != null) + break; + + return i; + } + } + + return -1; + } + + // + // 26.3.3.9 Lower-bound Inference + // + public int LowerBoundInference (TypeSpec u, TypeSpec v) + { + return LowerBoundInference (u, v, false); + } + + // + // Lower-bound (false) or Upper-bound (true) inference based on inversed argument + // + int LowerBoundInference (TypeSpec u, TypeSpec v, bool inversed) + { + // If V is one of the unfixed type arguments + int pos = IsUnfixed (v); + if (pos != -1) { + AddToBounds (new BoundInfo (u, inversed ? BoundKind.Upper : BoundKind.Lower), pos); + return 1; + } + + // If U is an array type + var u_ac = u as ArrayContainer; + if (u_ac != null) { + var v_ac = v as ArrayContainer; + if (v_ac != null) { + if (u_ac.Rank != v_ac.Rank) + return 0; + + if (TypeSpec.IsValueType (u_ac.Element)) + return ExactInference (u_ac.Element, v_ac.Element); + + return LowerBoundInference (u_ac.Element, v_ac.Element, inversed); + } + + if (u_ac.Rank != 1 || !v.IsGenericIterateInterface) + return 0; + + var v_i = TypeManager.GetTypeArguments (v) [0]; + if (TypeSpec.IsValueType (u_ac.Element)) + return ExactInference (u_ac.Element, v_i); + + return LowerBoundInference (u_ac.Element, v_i); + } + + if (TypeManager.IsGenericType (v)) { + // + // if V is a constructed type C and there is a unique type C + // such that U is identical to, inherits from (directly or indirectly), + // or implements (directly or indirectly) C + // + var u_candidates = new List (); + var open_v = v.MemberDefinition; + + for (TypeSpec t = u; t != null; t = t.BaseType) { + if (open_v == t.MemberDefinition) + u_candidates.Add (t); + + // + // Using this trick for dynamic type inference, the spec says the type arguments are "unknown" but + // that would complicate the process a lot, instead I treat them as dynamic + // + if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + u_candidates.Add (t); + + if (t.Interfaces != null) { + foreach (var iface in t.Interfaces) { + if (open_v == iface.MemberDefinition) + u_candidates.Add (iface); + } + } + } + + TypeSpec [] unique_candidate_targs = null; + TypeSpec[] ga_v = TypeManager.GetTypeArguments (v); + foreach (TypeSpec u_candidate in u_candidates) { + // + // The unique set of types U1..Uk means that if we have an interface I, + // class U : I, I then no type inference is made when inferring + // type I by applying type U because T could be int or long + // + if (unique_candidate_targs != null) { + TypeSpec[] second_unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate); + if (TypeSpecComparer.Equals (unique_candidate_targs, second_unique_candidate_targs)) { + unique_candidate_targs = second_unique_candidate_targs; + continue; + } + + // + // This should always cause type inference failure + // + failed = true; + return 1; + } + + // + // A candidate is dynamic type expression, to simplify things use dynamic + // for all type parameter of this type. For methods like this one + // + // void M (IList, IList) + // + // dynamic becomes both T and U when the arguments are of dynamic type + // + if (u_candidate.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + unique_candidate_targs = new TypeSpec[ga_v.Length]; + for (int i = 0; i < unique_candidate_targs.Length; ++i) + unique_candidate_targs[i] = u_candidate; + } else { + unique_candidate_targs = TypeManager.GetTypeArguments (u_candidate); + } + } + + if (unique_candidate_targs != null) { + var ga_open_v = open_v.TypeParameters; + int score = 0; + for (int i = 0; i < unique_candidate_targs.Length; ++i) { + Variance variance = ga_open_v [i].Variance; + + TypeSpec u_i = unique_candidate_targs [i]; + if (variance == Variance.None || TypeSpec.IsValueType (u_i)) { + if (ExactInference (u_i, ga_v [i]) == 0) + ++score; + } else { + bool upper_bound = (variance == Variance.Contravariant && !inversed) || + (variance == Variance.Covariant && inversed); + + if (LowerBoundInference (u_i, ga_v [i], upper_bound) == 0) + ++score; + } + } + return score; + } + } + + return 0; + } + + // + // 26.3.3.6 Output Type Inference + // + public int OutputTypeInference (ResolveContext ec, Expression e, TypeSpec t) + { + // If e is a lambda or anonymous method with inferred return type + AnonymousMethodExpression ame = e as AnonymousMethodExpression; + if (ame != null) { + TypeSpec rt = ame.InferReturnType (ec, this, t); + var invoke = Delegate.GetInvokeMethod (t); + + if (rt == null) { + AParametersCollection pd = invoke.Parameters; + return ame.Parameters.Count == pd.Count ? 1 : 0; + } + + TypeSpec rtype = invoke.ReturnType; + return LowerBoundInference (rt, rtype) + 1; + } + + // + // if E is a method group and T is a delegate type or expression tree type + // return type Tb with parameter types T1..Tk and return type Tb, and overload + // resolution of E with the types T1..Tk yields a single method with return type U, + // then a lower-bound inference is made from U for Tb. + // + if (e is MethodGroupExpr) { + if (!TypeManager.IsDelegateType (t)) { + if (!t.IsExpressionTreeType) + return 0; + + t = TypeManager.GetTypeArguments (t)[0]; + } + + var invoke = Delegate.GetInvokeMethod (t); + TypeSpec rtype = invoke.ReturnType; + + if (!rtype.IsGenericParameter && !TypeManager.IsGenericType (rtype)) + return 0; + + // LAMESPEC: Standard does not specify that all methodgroup arguments + // has to be fixed but it does not specify how to do recursive type inference + // either. We choose the simple option and infer return type only + // if all delegate generic arguments are fixed. + TypeSpec[] param_types = new TypeSpec [invoke.Parameters.Count]; + for (int i = 0; i < param_types.Length; ++i) { + var inflated = InflateGenericArgument (ec, invoke.Parameters.Types[i]); + if (inflated == null) + return 0; + + if (IsUnfixed (inflated) >= 0) + return 0; + + param_types[i] = inflated; + } + + MethodGroupExpr mg = (MethodGroupExpr) e; + Arguments args = DelegateCreation.CreateDelegateMethodArguments (invoke.Parameters, param_types, e.Location); + mg = mg.OverloadResolve (ec, ref args, null, OverloadResolver.Restrictions.CovariantDelegate | OverloadResolver.Restrictions.ProbingOnly); + if (mg == null) + return 0; + + return LowerBoundInference (mg.BestCandidateReturnType, rtype) + 1; + } + + // + // if e is an expression with type U, then + // a lower-bound inference is made from U for T + // + return LowerBoundInference (e.Type, t) * 2; + } + + void RemoveDependentTypes (List types, TypeSpec returnType) + { + int idx = IsUnfixed (returnType); + if (idx >= 0) { + types [idx] = null; + return; + } + + if (TypeManager.IsGenericType (returnType)) { + foreach (TypeSpec t in TypeManager.GetTypeArguments (returnType)) { + RemoveDependentTypes (types, t); + } + } + } + + public bool UnfixedVariableExists { + get { + foreach (TypeSpec ut in fixed_types) { + if (ut == null) + return true; + } + + return false; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj new file mode 100644 index 0000000000..4d9953b31c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj @@ -0,0 +1,111 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56} + Library + Properties + gmcs + gmcs + v3.5 + 512 + + + true + full + false + ..\..\..\monodevelop\main\build\bin + TRACE;DEBUG;NET_2_0;MS_COMPATIBLE;FULL_AST;BOOTSTRAP_BASIC + prompt + 4 + false + + + pdbonly + true + TRACE;NET_2_0;MS_COMPATIBLE + prompt + TRACE;NET_2_0;MS_COMPATIBLE + prompt + 4 + ..\..\..\monodevelop\main\build\bin + + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config new file mode 100644 index 0000000000..fe1df560aa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources new file mode 100644 index 0000000000..03738c5032 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources @@ -0,0 +1,56 @@ +AssemblyInfo.cs +anonymous.cs +argument.cs +assign.cs +attribute.cs +cs-tokenizer.cs +cfold.cs +class.cs +codegen.cs +complete.cs +const.cs +constant.cs +convert.cs +context.cs +decl.cs +delegate.cs +doc.cs +doc-bootstrap.cs +driver.cs +dynamic.cs +ecore.cs +enum.cs +eval.cs +expression.cs +field.cs +flowanalysis.cs +generic.cs +import.cs +iterators.cs +lambda.cs +linq.cs +literal.cs +location.cs +membercache.cs +method.cs +modifiers.cs +namespace.cs +nullable.cs +parameter.cs +pending.cs +property.cs +report.cs +rootcontext.cs +roottypes.cs +statement.cs +support.cs +typemanager.cs +typespec.cs +visit.cs +symbolwriter.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs +../build/common/Consts.cs +../tools/monop/outline.cs diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln new file mode 100644 index 0000000000..7fe59487e1 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual C# Express 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gmcs", "gmcs.csproj", "{D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4A01C5B-A1B5-48F5-BB5B-D2E1BD236E56}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs new file mode 100644 index 0000000000..1231ec7060 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj new file mode 100644 index 0000000000..26a8030e8d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj @@ -0,0 +1,29 @@ + + + + Exe + gmcs + v3.5 + gmcs.exe.sources + 65001 + ..\class\lib\basic\ + false + + + BOOTSTRAP_BASIC,NET_1_1,NET_2_0 + + + NET_1_1,NET_2_0 + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs new file mode 100644 index 0000000000..137c5ccb38 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs @@ -0,0 +1,2096 @@ +// +// import.cs: System.Reflection conversions +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2009, 2010 Novell, Inc +// + +using System; +using System.Runtime.CompilerServices; +using System.Linq; +using System.Collections.Generic; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public abstract class MetadataImporter + { + // + // Dynamic types reader with additional logic to reconstruct a dynamic + // type using DynamicAttribute values + // + struct DynamicTypeReader + { + static readonly bool[] single_attribute = { true }; + + public int Position; + bool[] flags; + + // There is no common type for CustomAttributeData and we cannot + // use ICustomAttributeProvider + object provider; + + // + // A member provider which can be used to get CustomAttributeData + // + public DynamicTypeReader (object provider) + { + Position = 0; + flags = null; + this.provider = provider; + } + + // + // Returns true when object at local position has dynamic attribute flag + // + public bool IsDynamicObject (MetadataImporter importer) + { + if (provider != null) + ReadAttribute (importer); + + return flags != null && Position < flags.Length && flags[Position]; + } + + // + // Returns true when DynamicAttribute exists + // + public bool HasDynamicAttribute (MetadataImporter importer) + { + if (provider != null) + ReadAttribute (importer); + + return flags != null; + } + + void ReadAttribute (MetadataImporter importer) + { + IList cad; + if (provider is MemberInfo) { + cad = CustomAttributeData.GetCustomAttributes ((MemberInfo) provider); + } else if (provider is ParameterInfo) { + cad = CustomAttributeData.GetCustomAttributes ((ParameterInfo) provider); + } else { + provider = null; + return; + } + + if (cad.Count > 0) { + foreach (var ca in cad) { + var dt = ca.Constructor.DeclaringType; + if (dt.Name != "DynamicAttribute" && dt.Namespace != CompilerServicesNamespace) + continue; + + if (ca.ConstructorArguments.Count == 0) { + flags = single_attribute; + break; + } + + var arg_type = ca.ConstructorArguments[0].ArgumentType; + + if (arg_type.IsArray && MetaType.GetTypeCode (arg_type.GetElementType ()) == TypeCode.Boolean) { + var carg = (IList) ca.ConstructorArguments[0].Value; + flags = new bool[carg.Count]; + for (int i = 0; i < flags.Length; ++i) { + if (MetaType.GetTypeCode (carg[i].ArgumentType) == TypeCode.Boolean) + flags[i] = (bool) carg[i].Value; + } + + break; + } + } + } + + provider = null; + } + } + + protected readonly Dictionary import_cache; + protected readonly Dictionary compiled_types; + protected readonly Dictionary assembly_2_definition; + readonly ModuleContainer module; + + public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices"; + + protected MetadataImporter (ModuleContainer module) + { + this.module = module; + + import_cache = new Dictionary (1024, ReferenceEquality.Default); + compiled_types = new Dictionary (40, ReferenceEquality.Default); + assembly_2_definition = new Dictionary (ReferenceEquality.Default); + IgnorePrivateMembers = true; + } + + #region Properties + + public ICollection Assemblies { + get { + return assembly_2_definition.Values; + } + } + + public bool IgnorePrivateMembers { get; set; } + + #endregion + + public abstract void AddCompiledType (TypeBuilder builder, TypeSpec spec); + protected abstract MemberKind DetermineKindFromBaseType (MetaType baseType); + protected abstract bool HasVolatileModifier (MetaType[] modifiers); + + public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType) + { + Modifiers mod = 0; + var fa = fi.Attributes; + switch (fa & FieldAttributes.FieldAccessMask) { + case FieldAttributes.Public: + mod = Modifiers.PUBLIC; + break; + case FieldAttributes.Assembly: + mod = Modifiers.INTERNAL; + break; + case FieldAttributes.Family: + mod = Modifiers.PROTECTED; + break; + case FieldAttributes.FamORAssem: + mod = Modifiers.PROTECTED | Modifiers.INTERNAL; + break; + default: + // Ignore private fields (even for error reporting) to not require extra dependencies + if (IgnorePrivateMembers || HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "CompilerGeneratedAttribute", CompilerServicesNamespace)) + return null; + + mod = Modifiers.PRIVATE; + break; + } + + TypeSpec field_type; + + try { + field_type = ImportType (fi.FieldType, new DynamicTypeReader (fi)); + } catch (Exception e) { + // TODO: I should construct fake TypeSpec based on TypeRef signature + // but there is no way to do it with System.Reflection + throw new InternalErrorException (e, "Cannot import field `{0}.{1}' referenced in assembly `{2}'", + declaringType.GetSignatureForError (), fi.Name, declaringType.MemberDefinition.DeclaringAssembly); + } + + var definition = new ImportedMemberDefinition (fi, field_type, this); + + if ((fa & FieldAttributes.Literal) != 0) { + var c = Constant.CreateConstantFromValue (field_type, fi.GetRawConstantValue (), Location.Null); + return new ConstSpec (declaringType, definition, field_type, fi, mod, c); + } + + if ((fa & FieldAttributes.InitOnly) != 0) { + if (field_type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + var dc = ReadDecimalConstant (CustomAttributeData.GetCustomAttributes (fi)); + if (dc != null) + return new ConstSpec (declaringType, definition, field_type, fi, mod, dc); + } + + mod |= Modifiers.READONLY; + } else { + var req_mod = fi.GetRequiredCustomModifiers (); + if (req_mod.Length > 0 && HasVolatileModifier (req_mod)) + mod |= Modifiers.VOLATILE; + } + + if ((fa & FieldAttributes.Static) != 0) { + mod |= Modifiers.STATIC; + } else { + // Fixed buffers cannot be static + if (declaringType.IsStruct && field_type.IsStruct && field_type.IsNested && + HasAttribute (CustomAttributeData.GetCustomAttributes (fi), "FixedBufferAttribute", CompilerServicesNamespace)) { + + // TODO: Sanity check on field_type (only few types are allowed) + var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType); + return new FixedFieldSpec (declaringType, definition, fi, element_field, mod); + } + } + + return new FieldSpec (declaringType, definition, field_type, fi, mod); + } + + public EventSpec CreateEvent (EventInfo ei, TypeSpec declaringType, MethodSpec add, MethodSpec remove) + { + add.IsAccessor = true; + remove.IsAccessor = true; + + if (add.Modifiers != remove.Modifiers) + throw new NotImplementedException ("Different accessor modifiers " + ei.Name); + + var event_type = ImportType (ei.EventHandlerType, new DynamicTypeReader (ei)); + var definition = new ImportedMemberDefinition (ei, event_type, this); + return new EventSpec (declaringType, definition, event_type, add.Modifiers, add, remove); + } + + TypeParameterSpec[] CreateGenericParameters (MetaType type, TypeSpec declaringType) + { + var tparams = type.GetGenericArguments (); + + int parent_owned_count; + if (type.IsNested) { + parent_owned_count = type.DeclaringType.GetGenericArguments ().Length; + + // + // System.Reflection duplicates parent type parameters for each + // nested type with slightly modified properties (eg. different owner) + // This just makes things more complicated (think of cloned constraints) + // therefore we remap any nested type owned by parent using `type_cache' + // to the single TypeParameterSpec + // + if (declaringType != null && parent_owned_count > 0) { + int read_count = 0; + while (read_count != parent_owned_count) { + var tparams_count = declaringType.Arity; + if (tparams_count != 0) { + var parent_tp = declaringType.MemberDefinition.TypeParameters; + read_count += tparams_count; + for (int i = 0; i < tparams_count; i++) { + import_cache.Add (tparams[parent_owned_count - read_count + i], parent_tp[i]); + } + } + + declaringType = declaringType.DeclaringType; + } + } + } else { + parent_owned_count = 0; + } + + if (tparams.Length - parent_owned_count == 0) + return null; + + return CreateGenericParameters (parent_owned_count, tparams); + } + + TypeParameterSpec[] CreateGenericParameters (int first, MetaType[] tparams) + { + var tspec = new TypeParameterSpec[tparams.Length - first]; + for (int pos = first; pos < tparams.Length; ++pos) { + var type = tparams[pos]; + int index = pos - first; + + tspec[index] = (TypeParameterSpec) CreateType (type, new DynamicTypeReader (), false); + } + + return tspec; + } + + TypeSpec[] CreateGenericArguments (int first, MetaType[] tparams, DynamicTypeReader dtype) + { + ++dtype.Position; + + var tspec = new TypeSpec [tparams.Length - first]; + for (int pos = first; pos < tparams.Length; ++pos) { + var type = tparams[pos]; + int index = pos - first; + + TypeSpec spec; + if (type.HasElementType) { + var element = type.GetElementType (); + ++dtype.Position; + spec = ImportType (element, dtype); + + if (!type.IsArray) { + throw new NotImplementedException ("Unknown element type " + type.ToString ()); + } + + spec = ArrayContainer.MakeType (module, spec, type.GetArrayRank ()); + } else { + spec = CreateType (type, dtype, true); + + // + // We treat nested generic types as inflated internally where + // reflection uses type definition + // + // class A { + // IFoo> foo; // A is definition in this case + // } + // + // TODO: Is full logic from CreateType needed here as well? + // + if (!IsMissingType (type) && type.IsGenericTypeDefinition) { + var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); + spec = spec.MakeGenericType (module, targs); + } + } + + ++dtype.Position; + tspec[index] = spec; + } + + return tspec; + } + + public MethodSpec CreateMethod (MethodBase mb, TypeSpec declaringType) + { + Modifiers mod = ReadMethodModifiers (mb, declaringType); + TypeParameterSpec[] tparams; + + var parameters = CreateParameters (declaringType, mb.GetParameters (), mb); + + if (mb.IsGenericMethod) { + if (!mb.IsGenericMethodDefinition) + throw new NotSupportedException ("assert"); + + tparams = CreateGenericParameters (0, mb.GetGenericArguments ()); + } else { + tparams = null; + } + + MemberKind kind; + TypeSpec returnType; + if (mb.MemberType == MemberTypes.Constructor) { + kind = MemberKind.Constructor; + returnType = module.Compiler.BuiltinTypes.Void; + } else { + // + // Detect operators and destructors + // + string name = mb.Name; + kind = MemberKind.Method; + if (tparams == null && !mb.DeclaringType.IsInterface && name.Length > 6) { + if ((mod & (Modifiers.STATIC | Modifiers.PUBLIC)) == (Modifiers.STATIC | Modifiers.PUBLIC)) { + if (name[2] == '_' && name[1] == 'p' && name[0] == 'o') { + var op_type = Operator.GetType (name); + if (op_type.HasValue && parameters.Count > 0 && parameters.Count < 3) { + kind = MemberKind.Operator; + } + } + } else if (parameters.IsEmpty && name == Destructor.MetadataName) { + kind = MemberKind.Destructor; + if (declaringType.BuiltinType == BuiltinTypeSpec.Type.Object) { + mod &= ~Modifiers.OVERRIDE; + mod |= Modifiers.VIRTUAL; + } + } + } + + var mi = (MethodInfo) mb; + returnType = ImportType (mi.ReturnType, new DynamicTypeReader (mi.ReturnParameter)); + + // Cannot set to OVERRIDE without full hierarchy checks + // this flag indicates that the method could be override + // but further validation is needed + if ((mod & Modifiers.OVERRIDE) != 0) { + bool is_real_override = false; + if (kind == MemberKind.Method && declaringType.BaseType != null) { + var filter = MemberFilter.Method (name, tparams != null ? tparams.Length : 0, parameters, null); + var candidate = MemberCache.FindMember (declaringType.BaseType, filter, BindingRestriction.None); + + // + // For imported class method do additional validation to be sure that metadata + // override flag was correct + // + // Difference between protected internal and protected is ok + // + const Modifiers conflict_mask = Modifiers.AccessibilityMask & ~Modifiers.INTERNAL; + if (candidate != null && (candidate.Modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) { + is_real_override = true; + } + } + + if (!is_real_override) { + mod &= ~Modifiers.OVERRIDE; + if ((mod & Modifiers.SEALED) != 0) + mod &= ~Modifiers.SEALED; + else + mod |= Modifiers.VIRTUAL; + } + } + } + + IMemberDefinition definition; + if (tparams != null) { + var gmd = new ImportedGenericMethodDefinition ((MethodInfo) mb, returnType, parameters, tparams, this); + foreach (var tp in gmd.TypeParameters) { + ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ()); + } + + definition = gmd; + } else { + definition = new ImportedParameterMemberDefinition (mb, returnType, parameters, this); + } + + MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod); + if (tparams != null) + ms.IsGeneric = true; + + return ms; + } + + // + // Imports System.Reflection parameters + // + AParametersCollection CreateParameters (TypeSpec parent, ParameterInfo[] pi, MethodBase method) + { + int varargs = method != null && (method.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0; + + if (pi.Length == 0 && varargs == 0) + return ParametersCompiled.EmptyReadOnlyParameters; + + TypeSpec[] types = new TypeSpec[pi.Length + varargs]; + IParameterData[] par = new IParameterData[pi.Length + varargs]; + bool is_params = false; + for (int i = 0; i < pi.Length; i++) { + ParameterInfo p = pi[i]; + Parameter.Modifier mod = 0; + Expression default_value = null; + if (p.ParameterType.IsByRef) { + if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out) + mod = Parameter.Modifier.OUT; + else + mod = Parameter.Modifier.REF; + + // + // Strip reference wrapping + // + var el = p.ParameterType.GetElementType (); + types[i] = ImportType (el, new DynamicTypeReader (p)); // TODO: 1-based positio to be csc compatible + } else if (i == 0 && method.IsStatic && parent.IsStatic && parent.MemberDefinition.DeclaringAssembly.HasExtensionMethod && + HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) { + mod = Parameter.Modifier.This; + types[i] = ImportType (p.ParameterType); + } else { + types[i] = ImportType (p.ParameterType, new DynamicTypeReader (p)); + + if (i >= pi.Length - 2 && types[i] is ArrayContainer) { + if (HasAttribute (CustomAttributeData.GetCustomAttributes (p), "ParamArrayAttribute", "System")) { + mod = Parameter.Modifier.PARAMS; + is_params = true; + } + } + + if (!is_params && p.IsOptional) { + object value = p.RawDefaultValue; + var ptype = types[i]; + if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeSpec.IsReferenceType (ptype))) { + if (value == null) { + default_value = Constant.CreateConstant (ptype, null, Location.Null); + } else { + default_value = ImportParameterConstant (value); + + if (ptype.IsEnum) { + default_value = new EnumConstant ((Constant) default_value, ptype); + } + } + } else if (value == Missing.Value) { + default_value = EmptyExpression.MissingValue; + } else if (value == null) { + default_value = new DefaultValueExpression (new TypeExpression (ptype, Location.Null), Location.Null); + } else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + default_value = ImportParameterConstant (value); + } + } + } + + par[i] = new ParameterData (p.Name, mod, default_value); + } + + if (varargs != 0) { + par[par.Length - 1] = new ArglistParameter (Location.Null); + types[types.Length - 1] = InternalType.Arglist; + } + + return method != null ? + new ParametersImported (par, types, varargs != 0, is_params) : + new ParametersImported (par, types, is_params); + } + + // + // Returns null when the property is not valid C# property + // + public PropertySpec CreateProperty (PropertyInfo pi, TypeSpec declaringType, MethodSpec get, MethodSpec set) + { + Modifiers mod = 0; + AParametersCollection param = null; + TypeSpec type = null; + if (get != null) { + mod = get.Modifiers; + param = get.Parameters; + type = get.ReturnType; + } + + bool is_valid_property = true; + if (set != null) { + if (set.ReturnType.Kind != MemberKind.Void) + is_valid_property = false; + + var set_param_count = set.Parameters.Count - 1; + + if (set_param_count < 0) { + set_param_count = 0; + is_valid_property = false; + } + + var set_type = set.Parameters.Types[set_param_count]; + + if (mod == 0) { + AParametersCollection set_based_param; + + if (set_param_count == 0) { + set_based_param = ParametersCompiled.EmptyReadOnlyParameters; + } else { + // + // Create indexer parameters based on setter method parameters (the last parameter has to be removed) + // + var data = new IParameterData[set_param_count]; + var types = new TypeSpec[set_param_count]; + Array.Copy (set.Parameters.FixedParameters, data, set_param_count); + Array.Copy (set.Parameters.Types, types, set_param_count); + set_based_param = new ParametersImported (data, types, set.Parameters.HasParams); + } + + mod = set.Modifiers; + param = set_based_param; + type = set_type; + } else { + if (set_param_count != get.Parameters.Count) + is_valid_property = false; + + if (get.ReturnType != set_type) + is_valid_property = false; + + // Possible custom accessor modifiers + if ((mod & Modifiers.AccessibilityMask) != (set.Modifiers & Modifiers.AccessibilityMask)) { + var get_acc = mod & Modifiers.AccessibilityMask; + if (get_acc != Modifiers.PUBLIC) { + var set_acc = set.Modifiers & Modifiers.AccessibilityMask; + // If the accessor modifiers are not same, do extra restriction checks + if (get_acc != set_acc) { + var get_restr = ModifiersExtensions.IsRestrictedModifier (get_acc, set_acc); + var set_restr = ModifiersExtensions.IsRestrictedModifier (set_acc, get_acc); + if (get_restr && set_restr) { + is_valid_property = false; // Neither is more restrictive + } + + if (get_restr) { + mod &= ~Modifiers.AccessibilityMask; + mod |= set_acc; + } + } + } + } + } + } + + PropertySpec spec = null; + if (!param.IsEmpty) { + var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember (); + if (index_name == null) { + is_valid_property = false; + } else { + if (get != null) { + if (get.IsStatic) + is_valid_property = false; + if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) + is_valid_property = false; + } + if (set != null) { + if (set.IsStatic) + is_valid_property = false; + if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) + is_valid_property = false; + } + } + + if (is_valid_property) + spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod); + } + + if (spec == null) + spec = new PropertySpec (MemberKind.Property, declaringType, new ImportedMemberDefinition (pi, type, this), type, pi, mod); + + if (!is_valid_property) { + spec.IsNotCSharpCompatible = true; + return spec; + } + + if (set != null) + spec.Set = set; + if (get != null) + spec.Get = get; + + return spec; + } + + public TypeSpec CreateType (MetaType type) + { + return CreateType (type, new DynamicTypeReader (), true); + } + + public TypeSpec CreateNestedType (MetaType type, TypeSpec declaringType) + { + return CreateType (type, declaringType, new DynamicTypeReader (type), false); + } + + TypeSpec CreateType (MetaType type, DynamicTypeReader dtype, bool canImportBaseType) + { + TypeSpec declaring_type; + if (type.IsNested && !type.IsGenericParameter) + declaring_type = CreateType (type.DeclaringType, new DynamicTypeReader (type.DeclaringType), true); + else + declaring_type = null; + + return CreateType (type, declaring_type, dtype, canImportBaseType); + } + + TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType) + { + TypeSpec spec; + if (import_cache.TryGetValue (type, out spec)) { + if (spec.BuiltinType == BuiltinTypeSpec.Type.Object) { + if (dtype.IsDynamicObject (this)) + return module.Compiler.BuiltinTypes.Dynamic; + + return spec; + } + + if (!spec.IsGeneric || type.IsGenericTypeDefinition) + return spec; + + if (!dtype.HasDynamicAttribute (this)) + return spec; + + // We've found same object in the cache but this one has a dynamic custom attribute + // and it's most likely dynamic version of same type IFoo agains IFoo + // Do type resolve process again in that case + + // TODO: Handle cases where they still unify + } + + if (IsMissingType (type)) { + spec = new TypeSpec (MemberKind.MissingType, declaringType, new ImportedTypeDefinition (type, this), type, Modifiers.PUBLIC); + spec.MemberCache = MemberCache.Empty; + import_cache.Add (type, spec); + return spec; + } + + if (type.IsGenericType && !type.IsGenericTypeDefinition) { + var type_def = type.GetGenericTypeDefinition (); + + // Generic type definition can also be forwarded + if (compiled_types.TryGetValue (type_def, out spec)) + return spec; + + var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); + if (declaringType == null) { + // Simple case, no nesting + spec = CreateType (type_def, null, new DynamicTypeReader (), canImportBaseType); + spec = spec.MakeGenericType (module, targs); + } else { + // + // Nested type case, converting .NET types like + // A`1.B`1.C`1 to typespec like + // A.B.C + // + var nested_hierarchy = new List (); + while (declaringType.IsNested) { + nested_hierarchy.Add (declaringType); + declaringType = declaringType.DeclaringType; + } + + int targs_pos = 0; + if (declaringType.Arity > 0) { + spec = declaringType.MakeGenericType (module, targs.Skip (targs_pos).Take (declaringType.Arity).ToArray ()); + targs_pos = spec.Arity; + } else { + spec = declaringType; + } + + for (int i = nested_hierarchy.Count; i != 0; --i) { + var t = nested_hierarchy [i - 1]; + spec = MemberCache.FindNestedType (spec, t.Name, t.Arity); + if (t.Arity > 0) { + spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ()); + targs_pos += t.Arity; + } + } + + string name = type.Name; + int index = name.IndexOf ('`'); + if (index > 0) + name = name.Substring (0, index); + + spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos); + if (spec == null) + return null; + + if (spec.Arity > 0) { + spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ()); + } + } + + // Don't add generic type with dynamic arguments, they can interfere with same type + // using object type arguments + if (!spec.HasDynamicElement) { + + // Add to reading cache to speed up reading + if (!import_cache.ContainsKey (type)) + import_cache.Add (type, spec); + } + + return spec; + } + + Modifiers mod; + MemberKind kind; + + var ma = type.Attributes; + switch (ma & TypeAttributes.VisibilityMask) { + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + mod = Modifiers.PUBLIC; + break; + case TypeAttributes.NestedPrivate: + mod = Modifiers.PRIVATE; + break; + case TypeAttributes.NestedFamily: + mod = Modifiers.PROTECTED; + break; + case TypeAttributes.NestedFamORAssem: + mod = Modifiers.PROTECTED | Modifiers.INTERNAL; + break; + default: + mod = Modifiers.INTERNAL; + break; + } + + if ((ma & TypeAttributes.Interface) != 0) { + kind = MemberKind.Interface; + } else if (type.IsGenericParameter) { + kind = MemberKind.TypeParameter; + } else { + var base_type = type.BaseType; + if (base_type == null || (ma & TypeAttributes.Abstract) != 0) { + kind = MemberKind.Class; + } else { + kind = DetermineKindFromBaseType (base_type); + if (kind == MemberKind.Struct || kind == MemberKind.Delegate) { + mod |= Modifiers.SEALED; + } + } + + if (kind == MemberKind.Class) { + if ((ma & TypeAttributes.Sealed) != 0) { + mod |= Modifiers.SEALED; + if ((ma & TypeAttributes.Abstract) != 0) + mod |= Modifiers.STATIC; + } else if ((ma & TypeAttributes.Abstract) != 0) { + mod |= Modifiers.ABSTRACT; + } + } + } + + var definition = new ImportedTypeDefinition (type, this); + TypeSpec pt; + + if (kind == MemberKind.Enum) { + const BindingFlags underlying_member = BindingFlags.DeclaredOnly | + BindingFlags.Instance | + BindingFlags.Public | BindingFlags.NonPublic; + + var type_members = type.GetFields (underlying_member); + foreach (var type_member in type_members) { + spec = new EnumSpec (declaringType, definition, CreateType (type_member.FieldType), type, mod); + break; + } + + if (spec == null) + kind = MemberKind.Class; + + } else if (kind == MemberKind.TypeParameter) { + spec = CreateTypeParameter (type, declaringType); + } else if (type.IsGenericTypeDefinition) { + definition.TypeParameters = CreateGenericParameters (type, declaringType); + } else if (compiled_types.TryGetValue (type, out pt)) { + // + // Same type was found in inside compiled types. It's + // either build-in type or forward referenced typed + // which point into just compiled assembly. + // + spec = pt; + BuiltinTypeSpec bts = pt as BuiltinTypeSpec; + if (bts != null) + bts.SetDefinition (definition, type, mod); + } + + if (spec == null) + spec = new TypeSpec (kind, declaringType, definition, type, mod); + + import_cache.Add (type, spec); + + // + // Two stage setup as the base type can be inflated declaring type or + // another nested type inside same declaring type which has not been + // loaded, therefore we can import a base type of nested types once + // the types have been imported + // + if (canImportBaseType) + ImportTypeBase (spec, type); + + return spec; + } + + public IAssemblyDefinition GetAssemblyDefinition (Assembly assembly) + { + IAssemblyDefinition found; + if (!assembly_2_definition.TryGetValue (assembly, out found)) { + + // This can happen in dynamic context only + var def = new ImportedAssemblyDefinition (assembly); + assembly_2_definition.Add (assembly, def); + def.ReadAttributes (); + found = def; + } + + return found; + } + + public void ImportTypeBase (MetaType type) + { + TypeSpec spec = import_cache[type]; + if (spec != null) + ImportTypeBase (spec, type); + } + + TypeParameterSpec CreateTypeParameter (MetaType type, TypeSpec declaringType) + { + Variance variance; + switch (type.GenericParameterAttributes & GenericParameterAttributes.VarianceMask) { + case GenericParameterAttributes.Covariant: + variance = Variance.Covariant; + break; + case GenericParameterAttributes.Contravariant: + variance = Variance.Contravariant; + break; + default: + variance = Variance.None; + break; + } + + SpecialConstraint special = SpecialConstraint.None; + var import_special = type.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; + + if ((import_special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0) { + special |= SpecialConstraint.Struct; + } else if ((import_special & GenericParameterAttributes.DefaultConstructorConstraint) != 0) { + special = SpecialConstraint.Constructor; + } + + if ((import_special & GenericParameterAttributes.ReferenceTypeConstraint) != 0) { + special |= SpecialConstraint.Class; + } + + TypeParameterSpec spec; + var def = new ImportedTypeParameterDefinition (type, this); + if (type.DeclaringMethod != null) { + spec = new TypeParameterSpec (type.GenericParameterPosition, def, special, variance, type); + } else { + spec = new TypeParameterSpec (declaringType, type.GenericParameterPosition, def, special, variance, type); + } + + return spec; + } + + // + // Test for a custom attribute type match. Custom attributes are not really predefined globaly + // they can be assembly specific therefore we do check based on names only + // + public bool HasAttribute (IList attributesData, string attrName, string attrNamespace) + { + if (attributesData.Count == 0) + return false; + + foreach (var attr in attributesData) { + var dt = attr.Constructor.DeclaringType; + if (dt.Name == attrName && dt.Namespace == attrNamespace) + return true; + } + + return false; + } + + void ImportTypeBase (TypeSpec spec, MetaType type) + { + if (spec.Kind == MemberKind.Interface) + spec.BaseType = module.Compiler.BuiltinTypes.Object; + else if (type.BaseType != null) { + TypeSpec base_type; + if (!IsMissingType (type.BaseType) && type.BaseType.IsGenericType) + base_type = CreateType (type.BaseType, new DynamicTypeReader (type), true); + else + base_type = CreateType (type.BaseType); + + spec.BaseType = base_type; + } + + MetaType[] ifaces; +#if STATIC + ifaces = type.__GetDeclaredInterfaces (); + if (ifaces.Length != 0) { + foreach (var iface in ifaces) { + var it = CreateType (iface); + if (it == null) + continue; + + spec.AddInterface (it); + + // Unfortunately not all languages expand inherited interfaces + var bifaces = it.Interfaces; + if (bifaces != null) { + foreach (var biface in bifaces) { + spec.AddInterface (biface); + } + } + } + } + + if (spec.BaseType != null) { + var bifaces = spec.BaseType.Interfaces; + if (bifaces != null) { + foreach (var iface in bifaces) + spec.AddInterface (iface); + } + } +#else + ifaces = type.GetInterfaces (); + + if (ifaces.Length > 0) { + foreach (var iface in ifaces) { + spec.AddInterface (CreateType (iface)); + } + } +#endif + + if (spec.MemberDefinition.TypeParametersCount > 0) { + foreach (var tp in spec.MemberDefinition.TypeParameters) { + ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ()); + } + } + + } + + protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool hasExtensionTypes) + { + Namespace ns = targetNamespace; + string prev_namespace = null; + foreach (var t in types) { + if (t == null) + continue; + + // Be careful not to trigger full parent type loading + if (t.MemberType == MemberTypes.NestedType) + continue; + + if (t.Name[0] == '<') + continue; + + var it = CreateType (t, null, new DynamicTypeReader (t), true); + if (it == null) + continue; + + if (prev_namespace != t.Namespace) { + ns = t.Namespace == null ? targetNamespace : targetNamespace.GetNamespace (t.Namespace, true); + prev_namespace = t.Namespace; + } + + ns.AddType (module, it); + + if (it.IsStatic && hasExtensionTypes && + HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) { + it.SetExtensionMethodContainer (); + } + } + } + + void ImportTypeParameterTypeConstraints (TypeParameterSpec spec, MetaType type) + { + var constraints = type.GetGenericParameterConstraints (); + List tparams = null; + foreach (var ct in constraints) { + if (ct.IsGenericParameter) { + if (tparams == null) + tparams = new List (); + + tparams.Add (CreateType (ct)); + continue; + } + + if (!IsMissingType (ct) && ct.IsClass) { + spec.BaseType = CreateType (ct); + continue; + } + + spec.AddInterface (CreateType (ct)); + } + + if (spec.BaseType == null) + spec.BaseType = module.Compiler.BuiltinTypes.Object; + + if (tparams != null) + spec.TypeArguments = tparams.ToArray (); + } + + Constant ImportParameterConstant (object value) + { + // + // Get type of underlying value as int constant can be used for object + // parameter type. This is not allowed in C# but other languages can do that + // + var types = module.Compiler.BuiltinTypes; + switch (System.Type.GetTypeCode (value.GetType ())) { + case TypeCode.Boolean: + return new BoolConstant (types, (bool) value, Location.Null); + case TypeCode.Byte: + return new ByteConstant (types, (byte) value, Location.Null); + case TypeCode.Char: + return new CharConstant (types, (char) value, Location.Null); + case TypeCode.Decimal: + return new DecimalConstant (types, (decimal) value, Location.Null); + case TypeCode.Double: + return new DoubleConstant (types, (double) value, Location.Null); + case TypeCode.Int16: + return new ShortConstant (types, (short) value, Location.Null); + case TypeCode.Int32: + return new IntConstant (types, (int) value, Location.Null); + case TypeCode.Int64: + return new LongConstant (types, (long) value, Location.Null); + case TypeCode.SByte: + return new SByteConstant (types, (sbyte) value, Location.Null); + case TypeCode.Single: + return new FloatConstant (types, (float) value, Location.Null); + case TypeCode.String: + return new StringConstant (types, (string) value, Location.Null); + case TypeCode.UInt16: + return new UShortConstant (types, (ushort) value, Location.Null); + case TypeCode.UInt32: + return new UIntConstant (types, (uint) value, Location.Null); + case TypeCode.UInt64: + return new ULongConstant (types, (ulong) value, Location.Null); + } + + throw new NotImplementedException (value.GetType ().ToString ()); + } + + public TypeSpec ImportType (MetaType type) + { + return ImportType (type, new DynamicTypeReader (type)); + } + + TypeSpec ImportType (MetaType type, DynamicTypeReader dtype) + { + if (type.HasElementType) { + var element = type.GetElementType (); + ++dtype.Position; + var spec = ImportType (element, dtype); + + if (type.IsArray) + return ArrayContainer.MakeType (module, spec, type.GetArrayRank ()); + if (type.IsByRef) + return ReferenceContainer.MakeType (module, spec); + if (type.IsPointer) + return PointerContainer.MakeType (module, spec); + + throw new NotImplementedException ("Unknown element type " + type.ToString ()); + } + + return CreateType (type, dtype, true); + } + + static bool IsMissingType (MetaType type) + { +#if STATIC + return type.__IsMissing; +#else + return false; +#endif + } + + // + // Decimal constants cannot be encoded in the constant blob, and thus are marked + // as IsInitOnly ('readonly' in C# parlance). We get its value from the + // DecimalConstantAttribute metadata. + // + Constant ReadDecimalConstant (IList attrs) + { + if (attrs.Count == 0) + return null; + + foreach (var ca in attrs) { + var dt = ca.Constructor.DeclaringType; + if (dt.Name != "DecimalConstantAttribute" || dt.Namespace != CompilerServicesNamespace) + continue; + + var value = new decimal ( + (int) (uint) ca.ConstructorArguments[4].Value, + (int) (uint) ca.ConstructorArguments[3].Value, + (int) (uint) ca.ConstructorArguments[2].Value, + (byte) ca.ConstructorArguments[1].Value != 0, + (byte) ca.ConstructorArguments[0].Value); + + return new DecimalConstant (module.Compiler.BuiltinTypes, value, Location.Null); + } + + return null; + } + + static Modifiers ReadMethodModifiers (MethodBase mb, TypeSpec declaringType) + { + Modifiers mod; + var ma = mb.Attributes; + switch (ma & MethodAttributes.MemberAccessMask) { + case MethodAttributes.Public: + mod = Modifiers.PUBLIC; + break; + case MethodAttributes.Assembly: + mod = Modifiers.INTERNAL; + break; + case MethodAttributes.Family: + mod = Modifiers.PROTECTED; + break; + case MethodAttributes.FamORAssem: + mod = Modifiers.PROTECTED | Modifiers.INTERNAL; + break; + default: + mod = Modifiers.PRIVATE; + break; + } + + if ((ma & MethodAttributes.Static) != 0) { + mod |= Modifiers.STATIC; + return mod; + } + if ((ma & MethodAttributes.Abstract) != 0 && declaringType.IsClass) { + mod |= Modifiers.ABSTRACT; + return mod; + } + + // It can be sealed and override + if ((ma & MethodAttributes.Final) != 0) + mod |= Modifiers.SEALED; + + if ((ma & MethodAttributes.Virtual) != 0) { + // Not every member can be detected based on MethodAttribute, we + // set virtual or non-virtual only when we are certain. Further checks + // to really find out what `virtual' means for this member are done + // later + if ((ma & MethodAttributes.NewSlot) != 0) { + if ((mod & Modifiers.SEALED) != 0) { + mod &= ~Modifiers.SEALED; + } else { + mod |= Modifiers.VIRTUAL; + } + } else { + mod |= Modifiers.OVERRIDE; + } + } + + return mod; + } + } + + abstract class ImportedDefinition : IMemberDefinition + { + protected class AttributesBag + { + public static readonly AttributesBag Default = new AttributesBag (); + + public AttributeUsageAttribute AttributeUsage; + public ObsoleteAttribute Obsolete; + public string[] Conditionals; + public string DefaultIndexerName; + public bool? CLSAttributeValue; + public TypeSpec CoClass; + + public static AttributesBag Read (MemberInfo mi, MetadataImporter importer) + { + AttributesBag bag = null; + List conditionals = null; + + // It should not throw any loading exception + IList attrs = CustomAttributeData.GetCustomAttributes (mi); + + foreach (var a in attrs) { + var dt = a.Constructor.DeclaringType; + string name = dt.Name; + if (name == "ObsoleteAttribute") { + if (dt.Namespace != "System") + continue; + + if (bag == null) + bag = new AttributesBag (); + + var args = a.ConstructorArguments; + + if (args.Count == 1) { + bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value); + } else if (args.Count == 2) { + bag.Obsolete = new ObsoleteAttribute ((string) args[0].Value, (bool) args[1].Value); + } else { + bag.Obsolete = new ObsoleteAttribute (); + } + + continue; + } + + if (name == "ConditionalAttribute") { + if (dt.Namespace != "System.Diagnostics") + continue; + + if (bag == null) + bag = new AttributesBag (); + + if (conditionals == null) + conditionals = new List (2); + + conditionals.Add ((string) a.ConstructorArguments[0].Value); + continue; + } + + if (name == "CLSCompliantAttribute") { + if (dt.Namespace != "System") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.CLSAttributeValue = (bool) a.ConstructorArguments[0].Value; + continue; + } + + // Type only attributes + if (mi.MemberType == MemberTypes.TypeInfo || mi.MemberType == MemberTypes.NestedType) { + if (name == "DefaultMemberAttribute") { + if (dt.Namespace != "System.Reflection") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.DefaultIndexerName = (string) a.ConstructorArguments[0].Value; + continue; + } + + if (name == "AttributeUsageAttribute") { + if (dt.Namespace != "System") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.AttributeUsage = new AttributeUsageAttribute ((AttributeTargets) a.ConstructorArguments[0].Value); + foreach (var named in a.NamedArguments) { + if (named.MemberInfo.Name == "AllowMultiple") + bag.AttributeUsage.AllowMultiple = (bool) named.TypedValue.Value; + else if (named.MemberInfo.Name == "Inherited") + bag.AttributeUsage.Inherited = (bool) named.TypedValue.Value; + } + continue; + } + + // Interface only attribute + if (name == "CoClassAttribute") { + if (dt.Namespace != "System.Runtime.InteropServices") + continue; + + if (bag == null) + bag = new AttributesBag (); + + bag.CoClass = importer.ImportType ((MetaType) a.ConstructorArguments[0].Value); + continue; + } + } + } + + if (bag == null) + return Default; + + if (conditionals != null) + bag.Conditionals = conditionals.ToArray (); + + return bag; + } + } + + protected readonly MemberInfo provider; + protected AttributesBag cattrs; + protected readonly MetadataImporter importer; + + public ImportedDefinition (MemberInfo provider, MetadataImporter importer) + { + this.provider = provider; + this.importer = importer; + } + + #region Properties + + public bool IsImported { + get { + return true; + } + } + + public virtual string Name { + get { + return provider.Name; + } + } + + #endregion + + public string[] ConditionalConditions () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.Conditionals; + } + + public ObsoleteAttribute GetAttributeObsolete () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.Obsolete; + } + + public bool? CLSAttributeValue { + get { + if (cattrs == null) + ReadAttributes (); + + return cattrs.CLSAttributeValue; + } + } + + protected void ReadAttributes () + { + cattrs = AttributesBag.Read (provider, importer); + } + + public void SetIsAssigned () + { + // Unused for imported members + } + + public void SetIsUsed () + { + // Unused for imported members + } + } + + public class ImportedModuleDefinition + { + readonly Module module; + bool cls_compliant; + + public ImportedModuleDefinition (Module module) + { + this.module = module; + } + + #region Properties + + public bool IsCLSCompliant { + get { + return cls_compliant; + } + } + + public string Name { + get { + return module.Name; + } + } + + #endregion + + public void ReadAttributes () + { + IList attrs = CustomAttributeData.GetCustomAttributes (module); + + foreach (var a in attrs) { + var dt = a.Constructor.DeclaringType; + if (dt.Name == "CLSCompliantAttribute") { + if (dt.Namespace != "System") + continue; + + cls_compliant = (bool) a.ConstructorArguments[0].Value; + continue; + } + } + } + + // + // Reads assembly attributes which where attached to a special type because + // module does have assembly manifest + // + public List ReadAssemblyAttributes () + { + var t = module.GetType (AssemblyAttributesPlaceholder.GetGeneratedName (Name)); + if (t == null) + return null; + + var field = t.GetField (AssemblyAttributesPlaceholder.AssemblyFieldName, BindingFlags.NonPublic | BindingFlags.Static); + if (field == null) + return null; + + // TODO: implement, the idea is to fabricate specil Attribute class and + // add it to OptAttributes before resolving the source code attributes + // Need to build module location as well for correct error reporting + + //var assembly_attributes = CustomAttributeData.GetCustomAttributes (field); + //var attrs = new List (assembly_attributes.Count); + //foreach (var a in assembly_attributes) + //{ + // var type = metaImporter.ImportType (a.Constructor.DeclaringType); + // var ctor = metaImporter.CreateMethod (a.Constructor, type); + + // foreach (var carg in a.ConstructorArguments) { + // carg.Value + // } + + // attrs.Add (new Attribute ("assembly", ctor, null, Location.Null, true)); + //} + + return null; + } + } + + public class ImportedAssemblyDefinition : IAssemblyDefinition + { + readonly Assembly assembly; + readonly AssemblyName aname; + bool cls_compliant; + bool contains_extension_methods; + + List internals_visible_to; + Dictionary internals_visible_to_cache; + + public ImportedAssemblyDefinition (Assembly assembly) + { + this.assembly = assembly; + this.aname = assembly.GetName (); + } + + #region Properties + + public Assembly Assembly { + get { + return assembly; + } + } + + public string FullName { + get { + return aname.FullName; + } + } + + public bool HasExtensionMethod { + get { + return contains_extension_methods; + } + } + + public bool HasStrongName { + get { + return aname.GetPublicKey ().Length != 0; + } + } + + public bool IsMissing { + get { +#if STATIC + return assembly.__IsMissing; +#else + return false; +#endif + } + } + + public bool IsCLSCompliant { + get { + return cls_compliant; + } + } + + public string Location { + get { + return assembly.Location; + } + } + + public string Name { + get { + return aname.Name; + } + } + + #endregion + + public byte[] GetPublicKeyToken () + { + return aname.GetPublicKeyToken (); + } + + public AssemblyName GetAssemblyVisibleToName (IAssemblyDefinition assembly) + { + return internals_visible_to_cache [assembly]; + } + + public bool IsFriendAssemblyTo (IAssemblyDefinition assembly) + { + if (internals_visible_to == null) + return false; + + AssemblyName is_visible = null; + if (internals_visible_to_cache == null) { + internals_visible_to_cache = new Dictionary (); + } else { + if (internals_visible_to_cache.TryGetValue (assembly, out is_visible)) + return is_visible != null; + } + + var token = assembly.GetPublicKeyToken (); + if (token != null && token.Length == 0) + token = null; + + foreach (var internals in internals_visible_to) { + if (internals.Name != assembly.Name) + continue; + + if (token == null && assembly is AssemblyDefinition) { + is_visible = internals; + break; + } + + if (!ArrayComparer.IsEqual (token, internals.GetPublicKeyToken ())) + continue; + + is_visible = internals; + break; + } + + internals_visible_to_cache.Add (assembly, is_visible); + return is_visible != null; + } + + public void ReadAttributes () + { +#if STATIC + if (assembly.__IsMissing) + return; +#endif + + IList attrs = CustomAttributeData.GetCustomAttributes (assembly); + + foreach (var a in attrs) { + var dt = a.Constructor.DeclaringType; + var name = dt.Name; + if (name == "CLSCompliantAttribute") { + if (dt.Namespace == "System") { + cls_compliant = (bool) a.ConstructorArguments[0].Value; + } + continue; + } + + if (name == "InternalsVisibleToAttribute") { + if (dt.Namespace != MetadataImporter.CompilerServicesNamespace) + continue; + + string s = a.ConstructorArguments[0].Value as string; + if (s == null) + continue; + + var an = new AssemblyName (s); + if (internals_visible_to == null) + internals_visible_to = new List (); + + internals_visible_to.Add (an); + continue; + } + + if (name == "ExtensionAttribute") { + if (dt.Namespace == MetadataImporter.CompilerServicesNamespace) + contains_extension_methods = true; + + continue; + } + } + } + + public override string ToString () + { + return FullName; + } + } + + class ImportedMemberDefinition : ImportedDefinition + { + readonly TypeSpec type; + + public ImportedMemberDefinition (MemberInfo member, TypeSpec type, MetadataImporter importer) + : base (member, importer) + { + this.type = type; + } + + #region Properties + + public TypeSpec MemberType { + get { + return type; + } + } + + #endregion + } + + class ImportedParameterMemberDefinition : ImportedMemberDefinition, IParametersMember + { + readonly AParametersCollection parameters; + + public ImportedParameterMemberDefinition (MethodBase provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) + : base (provider, type, importer) + { + this.parameters = parameters; + } + + public ImportedParameterMemberDefinition (PropertyInfo provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) + : base (provider, type, importer) + { + this.parameters = parameters; + } + + #region Properties + + public AParametersCollection Parameters { + get { + return parameters; + } + } + + #endregion + } + + class ImportedGenericMethodDefinition : ImportedParameterMemberDefinition, IGenericMethodDefinition + { + readonly TypeParameterSpec[] tparams; + + public ImportedGenericMethodDefinition (MethodInfo provider, TypeSpec type, AParametersCollection parameters, TypeParameterSpec[] tparams, MetadataImporter importer) + : base (provider, type, parameters, importer) + { + this.tparams = tparams; + } + + #region Properties + + public TypeParameterSpec[] TypeParameters { + get { + return tparams; + } + } + + public int TypeParametersCount { + get { + return tparams.Length; + } + } + + #endregion + } + + class ImportedTypeDefinition : ImportedDefinition, ITypeDefinition + { + TypeParameterSpec[] tparams; + string name; + + public ImportedTypeDefinition (MetaType type, MetadataImporter importer) + : base (type, importer) + { + } + + #region Properties + + public IAssemblyDefinition DeclaringAssembly { + get { + return importer.GetAssemblyDefinition (provider.Module.Assembly); + } + } + + public override string Name { + get { + if (name == null) { + name = base.Name; + if (tparams != null) { + int arity_start = name.IndexOf ('`'); + if (arity_start > 0) + name = name.Substring (0, arity_start); + } + } + + return name; + } + } + + public string Namespace { + get { + return ((MetaType) provider).Namespace; + } + } + + public int TypeParametersCount { + get { + return tparams == null ? 0 : tparams.Length; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + return tparams; + } + set { + tparams = value; + } + } + + #endregion + + public static void Error_MissingDependency (IMemberContext ctx, List types, Location loc) + { + // + // Report details about missing type and most likely cause of the problem. + // csc reports 1683, 1684 as warnings but we report them only when used + // or referenced from the user core in which case compilation error has to + // be reported because compiler cannot continue anyway + // + foreach (var t in types) { + string name = t.GetSignatureForError (); + + if (t.MemberDefinition.DeclaringAssembly == ctx.Module.DeclaringAssembly) { + ctx.Module.Compiler.Report.Error (1683, loc, + "Reference to type `{0}' claims it is defined in this assembly, but it is not defined in source or any added modules", + name); + } else if (t.MemberDefinition.DeclaringAssembly.IsMissing) { + ctx.Module.Compiler.Report.Error (12, loc, + "The type `{0}' is defined in an assembly that is not referenced. Consider adding a reference to assembly `{1}'", + name, t.MemberDefinition.DeclaringAssembly.FullName); + } else { + ctx.Module.Compiler.Report.Error (1684, loc, + "Reference to type `{0}' claims it is defined assembly `{1}', but it could not be found", + name, t.MemberDefinition.DeclaringAssembly.FullName); + } + } + } + + public TypeSpec GetAttributeCoClass () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.CoClass; + } + + public string GetAttributeDefaultMember () + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.DefaultIndexerName; + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + if (cattrs == null) + ReadAttributes (); + + return cattrs.AttributeUsage; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + var a = importer.GetAssemblyDefinition (provider.Module.Assembly); + return a == assembly || a.IsFriendAssemblyTo (assembly); + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + // + // Not interested in members of nested private types unless the importer needs them + // + if (declaringType.IsPrivate && importer.IgnorePrivateMembers) { + cache = MemberCache.Empty; + return; + } + + var loading_type = (MetaType) provider; + const BindingFlags all_members = BindingFlags.DeclaredOnly | + BindingFlags.Static | BindingFlags.Instance | + BindingFlags.Public | BindingFlags.NonPublic; + + const MethodAttributes explicit_impl = MethodAttributes.NewSlot | + MethodAttributes.Virtual | MethodAttributes.HideBySig | + MethodAttributes.Final; + + Dictionary possible_accessors = null; + List imported_events = null; + EventSpec event_spec; + MemberSpec imported; + MethodInfo m; + MemberInfo[] all; + try { + all = loading_type.GetMembers (all_members); + } catch (Exception e) { + throw new InternalErrorException (e, "Could not import type `{0}' from `{1}'", + declaringType.GetSignatureForError (), declaringType.MemberDefinition.DeclaringAssembly.FullName); + } + + if (cache == null) { + cache = new MemberCache (all.Length); + + // + // Do the types first as they can be referenced by the members before + // they are found or inflated + // + foreach (var member in all) { + if (member.MemberType != MemberTypes.NestedType) + continue; + + var t = (MetaType) member; + + // Ignore compiler generated types, mostly lambda containers + if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers) + continue; + + imported = importer.CreateNestedType (t, declaringType); + cache.AddMemberImported (imported); + } + + foreach (var member in all) { + if (member.MemberType != MemberTypes.NestedType) + continue; + + var t = (MetaType) member; + + if ((t.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && importer.IgnorePrivateMembers) + continue; + + importer.ImportTypeBase (t); + } + } + + if (!onlyTypes) { + // + // The logic here requires methods to be returned first which seems to work for both Mono and .NET + // + foreach (var member in all) { + switch (member.MemberType) { + case MemberTypes.Constructor: + case MemberTypes.Method: + MethodBase mb = (MethodBase) member; + var attrs = mb.Attributes; + + if ((attrs & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) { + if (importer.IgnorePrivateMembers) + continue; + + // Ignore explicitly implemented members + if ((attrs & explicit_impl) == explicit_impl) + continue; + + // Ignore compiler generated methods + if (importer.HasAttribute (CustomAttributeData.GetCustomAttributes (mb), "CompilerGeneratedAttribute", MetadataImporter.CompilerServicesNamespace)) + continue; + } + + imported = importer.CreateMethod (mb, declaringType); + if (imported.Kind == MemberKind.Method && !imported.IsGeneric) { + if (possible_accessors == null) + possible_accessors = new Dictionary (ReferenceEquality.Default); + + // There are no metadata rules for accessors, we have to consider any method as possible candidate + possible_accessors.Add (mb, (MethodSpec) imported); + } + + break; + case MemberTypes.Property: + if (possible_accessors == null) + continue; + + var p = (PropertyInfo) member; + // + // Links possible accessors with property + // + MethodSpec get, set; + m = p.GetGetMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out get)) + get = null; + + m = p.GetSetMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out set)) + set = null; + + // No accessors registered (e.g. explicit implementation) + if (get == null && set == null) + continue; + + imported = importer.CreateProperty (p, declaringType, get, set); + if (imported == null) + continue; + + break; + case MemberTypes.Event: + if (possible_accessors == null) + continue; + + var e = (EventInfo) member; + // + // Links accessors with event + // + MethodSpec add, remove; + m = e.GetAddMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out add)) + add = null; + + m = e.GetRemoveMethod (true); + if (m == null || !possible_accessors.TryGetValue (m, out remove)) + remove = null; + + // Both accessors are required + if (add == null || remove == null) + continue; + + event_spec = importer.CreateEvent (e, declaringType, add, remove); + if (!importer.IgnorePrivateMembers) { + if (imported_events == null) + imported_events = new List (); + + imported_events.Add (event_spec); + } + + imported = event_spec; + break; + case MemberTypes.Field: + var fi = (FieldInfo) member; + + imported = importer.CreateField (fi, declaringType); + if (imported == null) + continue; + + // + // For dynamic binder event has to be fully restored to allow operations + // within the type container to work correctly + // + if (imported_events != null) { + // The backing event field should be private but it may not + int i; + for (i = 0; i < imported_events.Count; ++i) { + var ev = imported_events[i]; + if (ev.Name == fi.Name) { + ev.BackingField = (FieldSpec) imported; + imported_events.RemoveAt (i); + i = -1; + break; + } + } + + if (i < 0) + continue; + } + + break; + case MemberTypes.NestedType: + // Already in the cache from the first pass + continue; + default: + throw new NotImplementedException (member.ToString ()); + } + + cache.AddMemberImported (imported); + } + } + + if (declaringType.IsInterface && declaringType.Interfaces != null) { + foreach (var iface in declaringType.Interfaces) { + cache.AddInterface (iface); + } + } + } + } + + class ImportedTypeParameterDefinition : ImportedDefinition, ITypeDefinition + { + public ImportedTypeParameterDefinition (MetaType type, MetadataImporter importer) + : base (type, importer) + { + } + + #region Properties + + public IAssemblyDefinition DeclaringAssembly { + get { + throw new NotImplementedException (); + } + } + + public string Namespace { + get { + return null; + } + } + + public int TypeParametersCount { + get { + return 0; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + return null; + } + } + + #endregion + + public TypeSpec GetAttributeCoClass () + { + return null; + } + + public string GetAttributeDefaultMember () + { + throw new NotSupportedException (); + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + throw new NotSupportedException (); + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + throw new NotImplementedException (); + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotImplementedException (); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs new file mode 100644 index 0000000000..9a256de68c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs @@ -0,0 +1,1057 @@ +// +// iterators.cs: Support for implementing iterators +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// Copyright 2003 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// + +// TODO: +// Flow analysis for Yield. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public abstract class YieldStatement : ResumableStatement where T : StateMachineInitializer + { + protected Expression expr; + bool unwind_protect; + protected T machine_initializer; + int resume_pc; + + public Expression Expr { + get { return this.expr; } + } + + protected YieldStatement (Expression expr, Location l) + { + this.expr = expr; + loc = l; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + var target = (YieldStatement) t; + target.expr = expr.Clone (clonectx); + } + + protected override void DoEmit (EmitContext ec) + { + machine_initializer.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + } + + public override bool Resolve (BlockContext bc) + { + expr = expr.Resolve (bc); + if (expr == null) + return false; + + machine_initializer = bc.CurrentAnonymousMethod as T; + + if (!bc.CurrentBranching.CurrentUsageVector.IsUnreachable) + unwind_protect = bc.CurrentBranching.AddResumePoint (this, loc, out resume_pc); + + return true; + } + } + + public class Yield : YieldStatement + { + public Yield (Expression expr, Location loc) + : base (expr, loc) + { + } + + public static bool CheckContext (ResolveContext ec, Location loc) + { + if (!ec.CurrentAnonymousMethod.IsIterator) { + ec.Report.Error (1621, loc, + "The yield statement cannot be used inside anonymous method blocks"); + return false; + } + + return true; + } + + public override bool Resolve (BlockContext bc) + { + if (!CheckContext (bc, loc)) + return false; + + if (!base.Resolve (bc)) + return false; + + var otype = bc.CurrentIterator.OriginalIteratorType; + if (expr.Type != otype) { + expr = Convert.ImplicitConversionRequired (bc, expr, otype, loc); + if (expr == null) + return false; + } + + return true; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class YieldBreak : ExitStatement + { + Iterator iterator; + + public YieldBreak (Location l) + { + loc = l; + } + + public override void Error_FinallyClause (Report Report) + { + Report.Error (1625, loc, "Cannot yield in the body of a finally clause"); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + protected override bool DoResolve (BlockContext ec) + { + iterator = ec.CurrentIterator; + return Yield.CheckContext (ec, loc); + } + + protected override void DoEmit (EmitContext ec) + { + iterator.EmitYieldBreak (ec, unwind_protect); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public abstract class StateMachine : AnonymousMethodStorey + { + public enum State + { + Running = -3, // Used only in CurrentPC, never stored into $PC + Uninitialized = -2, + After = -1, + Start = 0 + } + + Field disposing_field; + Field pc_field; + int local_name_idx; + StateMachineMethod method; + + protected StateMachine (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name) + : base (block, parent, host, tparams, name) + { + } + + #region Properties + + public Field DisposingField { + get { + return disposing_field; + } + } + + public StateMachineMethod StateMachineMethod { + get { + return method; + } + } + + public Field PC { + get { + return pc_field; + } + } + + #endregion + + public void AddEntryMethod (StateMachineMethod method) + { + if (this.method != null) + throw new InternalErrorException (); + + this.method = method; + AddMethod (method); + } + + protected override bool DoDefineMembers () + { + pc_field = AddCompilerGeneratedField ("$PC", new TypeExpression (Compiler.BuiltinTypes.Int, Location)); + disposing_field = AddCompilerGeneratedField ("$disposing", new TypeExpression (Compiler.BuiltinTypes.Bool, Location)); + + return base.DoDefineMembers (); + } + + protected override string GetVariableMangledName (LocalVariable local_info) + { + return "<" + local_info.Name + ">__" + local_name_idx++.ToString (); + } + } + + class IteratorStorey : StateMachine + { + class GetEnumeratorMethod : StateMachineMethod + { + sealed class GetEnumeratorStatement : Statement + { + readonly IteratorStorey host; + readonly StateMachineMethod host_method; + + Expression new_storey; + + public GetEnumeratorStatement (IteratorStorey host, StateMachineMethod host_method) + { + this.host = host; + this.host_method = host_method; + loc = host_method.Location; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + public override bool Resolve (BlockContext ec) + { + TypeExpression storey_type_expr = new TypeExpression (host.Definition, loc); + List init = null; + if (host.hoisted_this != null) { + init = new List (host.hoisted_params == null ? 1 : host.HoistedParameters.Count + 1); + HoistedThis ht = host.hoisted_this; + FieldExpr from = new FieldExpr (ht.Field, loc); + from.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + init.Add (new ElementInitializer (ht.Field.Name, from, loc)); + } + + if (host.hoisted_params != null) { + if (init == null) + init = new List (host.HoistedParameters.Count); + + for (int i = 0; i < host.hoisted_params.Count; ++i) { + HoistedParameter hp = host.hoisted_params [i]; + HoistedParameter hp_cp = host.hoisted_params_copy [i]; + + FieldExpr from = new FieldExpr (hp_cp.Field, loc); + from.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); + + init.Add (new ElementInitializer (hp.Field.Name, from, loc)); + } + } + + if (init != null) { + new_storey = new NewInitialize (storey_type_expr, null, + new CollectionOrObjectInitializers (init, loc), loc); + } else { + new_storey = new New (storey_type_expr, null, loc); + } + + new_storey = new_storey.Resolve (ec); + if (new_storey != null) + new_storey = Convert.ImplicitConversionRequired (ec, new_storey, host_method.MemberType, loc); + + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + Label label_init = ec.DefineLabel (); + + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldflda, host.PC.Spec); + ec.EmitInt ((int) State.Start); + ec.EmitInt ((int) State.Uninitialized); + + var m = ec.Module.PredefinedMembers.InterlockedCompareExchange.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + + ec.EmitInt ((int) State.Uninitialized); + ec.Emit (OpCodes.Bne_Un_S, label_init); + + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ret); + + ec.MarkLabel (label_init); + + new_storey.Emit (ec); + ec.Emit (OpCodes.Ret); + } + } + + public GetEnumeratorMethod (IteratorStorey host, FullNamedExpression returnType, MemberName name) + : base (host, null, returnType, Modifiers.DEBUGGER_HIDDEN, name) + { + Block.AddStatement (new GetEnumeratorStatement (host, this)); + } + } + + class DisposeMethod : StateMachineMethod + { + sealed class DisposeMethodStatement : Statement + { + Iterator iterator; + + public DisposeMethodStatement (Iterator iterator) + { + this.iterator = iterator; + this.loc = iterator.Location; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + public override bool Resolve (BlockContext ec) + { + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.CurrentAnonymousMethod = iterator; + iterator.EmitDispose (ec); + } + } + + public DisposeMethod (IteratorStorey host) + : base (host, null, new TypeExpression (host.Compiler.BuiltinTypes.Void, host.Location), Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, + new MemberName ("Dispose", host.Location)) + { + host.AddMethod (this); + + Block.AddStatement (new DisposeMethodStatement (host.Iterator)); + } + } + + // + // Uses Method as method info + // + class DynamicMethodGroupExpr : MethodGroupExpr + { + readonly Method method; + + public DynamicMethodGroupExpr (Method method, Location loc) + : base ((IList) null, null, loc) + { + this.method = method; + eclass = ExprClass.Unresolved; + } + + protected override Expression DoResolve (ResolveContext ec) + { + Methods = new List (1) { method.Spec }; + type = method.Parent.Definition; + InstanceExpression = new CompilerGeneratedThis (type, Location); + return base.DoResolve (ec); + } + } + + class DynamicFieldExpr : FieldExpr + { + readonly Field field; + + public DynamicFieldExpr (Field field, Location loc) + : base (loc) + { + this.field = field; + } + + protected override Expression DoResolve (ResolveContext ec) + { + spec = field.Spec; + type = spec.MemberType; + InstanceExpression = new CompilerGeneratedThis (type, Location); + return base.DoResolve (ec); + } + } + + public readonly Iterator Iterator; + + List hoisted_params_copy; + + TypeExpr iterator_type_expr; + Field current_field; + + TypeExpr enumerator_type; + TypeExpr enumerable_type; + TypeArguments generic_args; + TypeExpr generic_enumerator_type; + TypeExpr generic_enumerable_type; + + public IteratorStorey (Iterator iterator) + : base (iterator.Container.ParametersBlock, iterator.Host, + iterator.OriginalMethod as MemberBase, iterator.GenericMethod == null ? null : iterator.GenericMethod.CurrentTypeParameters, "Iterator") + { + this.Iterator = iterator; + } + + public Field CurrentField { + get { return current_field; } + } + + public IList HoistedParameters { + get { return hoisted_params; } + } + + protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class) + { + var mtype = Iterator.OriginalIteratorType; + if (Mutator != null) + mtype = Mutator.Mutate (mtype); + + iterator_type_expr = new TypeExpression (mtype, Location); + generic_args = new TypeArguments (iterator_type_expr); + + var list = new List (); + if (Iterator.IsEnumerable) { + enumerable_type = new TypeExpression (Compiler.BuiltinTypes.IEnumerable, Location); + list.Add (enumerable_type); + + if (Module.PredefinedTypes.IEnumerableGeneric.Define ()) { + generic_enumerable_type = new GenericTypeExpr (Module.PredefinedTypes.IEnumerableGeneric.TypeSpec, generic_args, Location); + list.Add (generic_enumerable_type); + } + } + + enumerator_type = new TypeExpression (Compiler.BuiltinTypes.IEnumerator, Location); + list.Add (enumerator_type); + + list.Add (new TypeExpression (Compiler.BuiltinTypes.IDisposable, Location)); + + var ienumerator_generic = Module.PredefinedTypes.IEnumeratorGeneric; + if (ienumerator_generic.Define ()) { + generic_enumerator_type = new GenericTypeExpr (ienumerator_generic.TypeSpec, generic_args, Location); + list.Add (generic_enumerator_type); + } + + type_bases = list; + + return base.ResolveBaseTypes (out base_class); + } + + protected override bool DoDefineMembers () + { + current_field = AddCompilerGeneratedField ("$current", iterator_type_expr); + + if (hoisted_params != null) { + // + // Iterators are independent, each GetEnumerator call has to + // create same enumerator therefore we have to keep original values + // around for re-initialization + // + // TODO: Do it for assigned/modified parameters only + // + hoisted_params_copy = new List (hoisted_params.Count); + foreach (HoistedParameter hp in hoisted_params) { + hoisted_params_copy.Add (new HoistedParameter (hp, "<$>" + hp.Field.Name)); + } + } + + if (generic_enumerator_type != null) + Define_Current (true); + + Define_Current (false); + new DisposeMethod (this); + Define_Reset (); + + if (Iterator.IsEnumerable) { + MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location); + name = new MemberName (name, "Collections", Location); + name = new MemberName (name, "IEnumerable", Location); + name = new MemberName (name, "GetEnumerator", Location); + + if (generic_enumerator_type != null) { + Method get_enumerator = new StateMachineMethod (this, null, enumerator_type, 0, name); + + name = new MemberName (name.Left.Left, "Generic", Location); + name = new MemberName (name, "IEnumerable", generic_args, Location); + name = new MemberName (name, "GetEnumerator", Location); + Method gget_enumerator = new GetEnumeratorMethod (this, generic_enumerator_type, name); + + // + // Just call generic GetEnumerator implementation + // + get_enumerator.Block.AddStatement ( + new Return (new Invocation (new DynamicMethodGroupExpr (gget_enumerator, Location), null), Location)); + + AddMethod (get_enumerator); + AddMethod (gget_enumerator); + } else { + AddMethod (new GetEnumeratorMethod (this, enumerator_type, name)); + } + } + + return base.DoDefineMembers (); + } + + void Define_Current (bool is_generic) + { + TypeExpr type; + + MemberName name = new MemberName (QualifiedAliasMember.GlobalAlias, "System", null, Location); + name = new MemberName (name, "Collections", Location); + + if (is_generic) { + name = new MemberName (name, "Generic", Location); + name = new MemberName (name, "IEnumerator", generic_args, Location); + type = iterator_type_expr; + } else { + name = new MemberName (name, "IEnumerator"); + type = new TypeExpression (Compiler.BuiltinTypes.Object, Location); + } + + name = new MemberName (name, "Current", Location); + + ToplevelBlock get_block = new ToplevelBlock (Compiler, Location); + get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location)); + + Property current = new Property (this, type, Modifiers.DEBUGGER_HIDDEN, name, null); + current.Get = new Property.GetMethod (current, 0, null, Location); + current.Get.Block = get_block; + + AddProperty (current); + } + + void Define_Reset () + { + Method reset = new Method ( + this, null, new TypeExpression (Compiler.BuiltinTypes.Void, Location), + Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN, + new MemberName ("Reset", Location), + ParametersCompiled.EmptyReadOnlyParameters, null); + AddMethod (reset); + + reset.Block = new ToplevelBlock (Compiler, Location); + + TypeSpec ex_type = Module.PredefinedTypes.NotSupportedException.Resolve (); + if (ex_type == null) + return; + + reset.Block.AddStatement (new Throw (new New (new TypeExpression (ex_type, Location), null, Location), Location)); + } + + protected override void EmitHoistedParameters (EmitContext ec, IList hoisted) + { + base.EmitHoistedParameters (ec, hoisted); + base.EmitHoistedParameters (ec, hoisted_params_copy); + } + } + + public class StateMachineMethod : Method + { + readonly StateMachineInitializer expr; + + public StateMachineMethod (StateMachine host, StateMachineInitializer expr, FullNamedExpression returnType, Modifiers mod, MemberName name) + : base (host, null, returnType, mod | Modifiers.COMPILER_GENERATED, + name, ParametersCompiled.EmptyReadOnlyParameters, null) + { + this.expr = expr; + Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location); + } + + public override EmitContext CreateEmitContext (ILGenerator ig) + { + EmitContext ec = new EmitContext (this, ig, MemberType); + ec.CurrentAnonymousMethod = expr; + return ec; + } + } + + public abstract class StateMachineInitializer : AnonymousExpression + { + sealed class MoveNextBodyStatement : Statement + { + readonly StateMachineInitializer state_machine; + + public MoveNextBodyStatement (StateMachineInitializer stateMachine) + { + this.state_machine = stateMachine; + this.loc = stateMachine.Location; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotSupportedException (); + } + + public override bool Resolve (BlockContext ec) + { + return true; + } + + protected override void DoEmit (EmitContext ec) + { + state_machine.EmitMoveNext (ec); + } + } + + public readonly TypeContainer Host; + protected StateMachine storey; + + // + // The state as we generate the machine + // + Label move_next_ok; + protected Label move_next_error; + protected LocalBuilder skip_finally, current_pc; + List resume_points; + + protected StateMachineInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType) + : base (block, returnType, block.StartLocation) + { + this.Host = host; + } + + public override AnonymousMethodStorey Storey { + get { + return storey; + } + } + + public int AddResumePoint (ResumableStatement stmt) + { + if (resume_points == null) + resume_points = new List (); + + resume_points.Add (stmt); + return resume_points.Count; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + 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; + + var ctx = CreateBlockContext (ec); + + ctx.StartFlowBranching (this, ec.CurrentBranching); + Block.Resolve (ctx); + + // + // Explicit return is required for Task state machine + // + var task_storey = storey as AsyncTaskStorey; + if (task_storey == null || (task_storey.ReturnType != null && !task_storey.ReturnType.IsGenericTask)) + ctx.CurrentBranching.CurrentUsageVector.Goto (); + + ctx.EndFlowBranching (); + + 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; + } + + public override void Emit (EmitContext ec) + { + // + // Load Iterator storey instance + // + storey.Instance.Emit (ec); + } + + public void EmitDispose (EmitContext ec) + { + Label end = ec.DefineLabel (); + + Label[] labels = null; + int n_resume_points = resume_points == null ? 0 : resume_points.Count; + for (int i = 0; i < n_resume_points; ++i) { + ResumableStatement s = resume_points[i]; + Label ret = s.PrepareForDispose (ec, end); + if (ret.Equals (end) && labels == null) + continue; + if (labels == null) { + labels = new Label[resume_points.Count + 1]; + for (int j = 0; j <= i; ++j) + labels[j] = end; + } + + labels[i + 1] = ret; + } + + if (labels != null) { + current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + ec.Emit (OpCodes.Stloc, current_pc); + } + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt (1); + ec.Emit (OpCodes.Stfld, storey.DisposingField.Spec); + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + if (labels != null) { + //SymbolWriter.StartIteratorDispatcher (ec.ig); + ec.Emit (OpCodes.Ldloc, current_pc); + ec.Emit (OpCodes.Switch, labels); + //SymbolWriter.EndIteratorDispatcher (ec.ig); + + foreach (ResumableStatement s in resume_points) + s.EmitForDispose (ec, current_pc, end, true); + } + + ec.MarkLabel (end); + } + + void EmitMoveNext_NoResumePoints (EmitContext ec, Block original_block) + { + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + // We only care if the PC is zero (start executing) or non-zero (don't do anything) + ec.Emit (OpCodes.Brtrue, move_next_error); + + SymbolWriter.StartIteratorBody (ec); + original_block.Emit (ec); + SymbolWriter.EndIteratorBody (ec); + + EmitMoveNextEpilogue (ec); + + ec.MarkLabel (move_next_error); + + if (ReturnType.Kind != MemberKind.Void) { + ec.EmitInt (0); + ec.Emit (OpCodes.Ret); + } + } + + void EmitMoveNext (EmitContext ec) + { + move_next_ok = ec.DefineLabel (); + move_next_error = ec.DefineLabel (); + + if (resume_points == null) { + EmitMoveNext_NoResumePoints (ec, block); + return; + } + + current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + ec.Emit (OpCodes.Stloc, current_pc); + + // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + Label[] labels = new Label[1 + resume_points.Count]; + labels[0] = ec.DefineLabel (); + + bool need_skip_finally = false; + for (int i = 0; i < resume_points.Count; ++i) { + ResumableStatement s = resume_points[i]; + need_skip_finally |= s is ExceptionStatement; + labels[i + 1] = s.PrepareForEmit (ec); + } + + if (need_skip_finally) { + skip_finally = ec.GetTemporaryLocal (ec.BuiltinTypes.Bool); + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Stloc, skip_finally); + } + + SymbolWriter.StartIteratorDispatcher (ec); + ec.Emit (OpCodes.Ldloc, current_pc); + ec.Emit (OpCodes.Switch, labels); + + ec.Emit (OpCodes.Br, move_next_error); + SymbolWriter.EndIteratorDispatcher (ec); + + ec.MarkLabel (labels[0]); + + SymbolWriter.StartIteratorBody (ec); + block.Emit (ec); + SymbolWriter.EndIteratorBody (ec); + + 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); + + if (ReturnType.Kind != MemberKind.Void) { + ec.EmitInt (0); + ec.Emit (OpCodes.Ret); + } + + ec.MarkLabel (move_next_ok); + + if (ReturnType.Kind != MemberKind.Void) { + ec.EmitInt (1); + ec.Emit (OpCodes.Ret); + } + + SymbolWriter.EndIteratorDispatcher (ec); + } + + protected virtual void EmitMoveNextEpilogue (EmitContext ec) + { + } + + // + // Called back from YieldStatement + // + public virtual void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) + { + // + // Guard against being disposed meantime + // + Label disposed = ec.DefineLabel (); + ec.Emit (OpCodes.Ldarg_0); + ec.Emit (OpCodes.Ldfld, storey.DisposingField.Spec); + ec.Emit (OpCodes.Brtrue_S, disposed); + + // + // store resume program-counter + // + ec.Emit (OpCodes.Ldarg_0); + ec.EmitInt (resume_pc); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + ec.MarkLabel (disposed); + + // mark finally blocks as disabled + if (unwind_protect && skip_finally != null) { + ec.EmitInt (1); + ec.Emit (OpCodes.Stloc, skip_finally); + } + + // Return ok + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); + + ec.MarkLabel (resume_point); + } + } + + // + // Iterators are implemented as hidden anonymous block + // + public class Iterator : StateMachineInitializer + { + public readonly IMethodData OriginalMethod; + public readonly bool IsEnumerable; + public readonly TypeSpec OriginalIteratorType; + + public Iterator (ParametersBlock block, IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable) + : base (block, host, host.Compiler.BuiltinTypes.Bool) + { + this.OriginalMethod = method; + this.OriginalIteratorType = iterator_type; + this.IsEnumerable = is_enumerable; + this.type = method.ReturnType; + } + + public LocalBuilder SkipFinally { + get { return skip_finally; } + } + + public LocalBuilder CurrentPC { + get { return current_pc; } + } + + public Block Container { + get { return OriginalMethod.Block; } + } + + public GenericMethod GenericMethod { + get { return OriginalMethod.GenericMethod; } + } + + public override string ContainerType { + get { return "iterator"; } + } + + public override bool IsIterator { + get { return true; } + } + + public void EmitYieldBreak (EmitContext ec, bool unwind_protect) + { + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_error); + } + + public override string GetSignatureForError () + { + return OriginalMethod.GetSignatureForError (); + } + + public override void Emit (EmitContext ec) + { + // + // Load Iterator storey instance + // + storey.Instance.Emit (ec); + + // + // Initialize iterator PC when it's unitialized + // + if (IsEnumerable) { + ec.Emit (OpCodes.Dup); + ec.EmitInt ((int)IteratorStorey.State.Uninitialized); + + var field = storey.PC.Spec; + if (storey.MemberName.IsGeneric) { + field = MemberCache.GetMember (Storey.Instance.Type, field); + } + + ec.Emit (OpCodes.Stfld, field); + } + } + + public override void EmitStatement (EmitContext ec) + { + throw new NotImplementedException (); + } + + public override void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) + { + // Store the new value into current + var fe = new FieldExpr (((IteratorStorey) storey).CurrentField, loc); + fe.InstanceExpression = new CompilerGeneratedThis (storey.CurrentType, loc); + fe.EmitAssign (ec, expr, false, false); + + base.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + } + + public static void CreateIterator (IMethodData method, TypeContainer parent, Modifiers modifiers) + { + bool is_enumerable; + TypeSpec iterator_type; + + TypeSpec ret = method.ReturnType; + if (ret == null) + return; + + if (!CheckType (ret, parent, out iterator_type, out is_enumerable)) { + parent.Compiler.Report.Error (1624, method.Location, + "The body of `{0}' cannot be an iterator block " + + "because `{1}' is not an iterator interface type", + method.GetSignatureForError (), + TypeManager.CSharpName (ret)); + return; + } + + ParametersCompiled parameters = method.ParameterInfo; + for (int i = 0; i < parameters.Count; i++) { + Parameter p = parameters [i]; + Parameter.Modifier mod = p.ModFlags; + if ((mod & Parameter.Modifier.ISBYREF) != 0) { + parent.Compiler.Report.Error (1623, p.Location, + "Iterators cannot have ref or out parameters"); + return; + } + + if (p is ArglistParameter) { + parent.Compiler.Report.Error (1636, method.Location, + "__arglist is not allowed in parameter list of iterators"); + return; + } + + if (parameters.Types [i].IsPointer) { + parent.Compiler.Report.Error (1637, p.Location, + "Iterators cannot have unsafe parameters or yield types"); + return; + } + } + + if ((modifiers & Modifiers.UNSAFE) != 0) { + parent.Compiler.Report.Error (1629, method.Location, "Unsafe code may not appear in iterators"); + } + + method.Block.WrapIntoIterator (method, parent, iterator_type, is_enumerable); + } + + static bool CheckType (TypeSpec ret, TypeContainer parent, out TypeSpec original_iterator_type, out bool is_enumerable) + { + original_iterator_type = null; + is_enumerable = false; + + if (ret.BuiltinType == BuiltinTypeSpec.Type.IEnumerable) { + original_iterator_type = parent.Compiler.BuiltinTypes.Object; + is_enumerable = true; + return true; + } + if (ret.BuiltinType == BuiltinTypeSpec.Type.IEnumerator) { + original_iterator_type = parent.Compiler.BuiltinTypes.Object; + is_enumerable = false; + return true; + } + + InflatedTypeSpec inflated = ret as InflatedTypeSpec; + if (inflated == null) + return false; + + var member_definition = inflated.MemberDefinition; + PredefinedType ptype = parent.Module.PredefinedTypes.IEnumerableGeneric; + + if (ptype.Define () && ptype.TypeSpec.MemberDefinition == member_definition) { + original_iterator_type = inflated.TypeArguments[0]; + is_enumerable = true; + return true; + } + + ptype = parent.Module.PredefinedTypes.IEnumeratorGeneric; + if (ptype.Define () && ptype.TypeSpec.MemberDefinition == member_definition) { + original_iterator_type = inflated.TypeArguments[0]; + is_enumerable = false; + return true; + } + + return false; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs new file mode 100644 index 0000000000..3cad50ce49 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs @@ -0,0 +1,229 @@ +// +// lambda.cs: support for lambda expressions +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2007-2008 Novell, Inc +// + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + public class LambdaExpression : AnonymousMethodExpression + { + // + // The parameters can either be: + // A list of Parameters (explicitly typed parameters) + // An ImplicitLambdaParameter + // + public LambdaExpression (bool isAsync, Location loc) + : base (isAsync, loc) + { + } + + public LambdaExpression (Location loc) + : this (false, loc) + { + } + + protected override Expression CreateExpressionTree (ResolveContext ec, TypeSpec delegate_type) + { + if (ec.IsInProbingMode) + return this; + + BlockContext bc = new BlockContext (ec.MemberContext, ec.ConstructorBlock, ec.BuiltinTypes.Void) { + CurrentAnonymousMethod = ec.CurrentAnonymousMethod + }; + + Expression args = Parameters.CreateExpressionTree (bc, loc); + Expression expr = Block.CreateExpressionTree (ec); + if (expr == null) + return null; + + Arguments arguments = new Arguments (2); + arguments.Add (new Argument (expr)); + arguments.Add (new Argument (args)); + return CreateExpressionFactoryCall (ec, "Lambda", + new TypeArguments (new TypeExpression (delegate_type, loc)), + arguments); + } + + public override bool HasExplicitParameters { + get { + return Parameters.Count > 0 && !(Parameters.FixedParameters [0] is ImplicitLambdaParameter); + } + } + + protected override ParametersCompiled ResolveParameters (ResolveContext ec, TypeInferenceContext tic, TypeSpec delegateType) + { + if (!delegateType.IsDelegate) + return null; + + AParametersCollection d_params = Delegate.GetParameters (delegateType); + + if (HasExplicitParameters) { + if (!VerifyExplicitParameters (ec, delegateType, d_params)) + return null; + + return Parameters; + } + + // + // If L has an implicitly typed parameter list we make implicit parameters explicit + // Set each parameter of L is given the type of the corresponding parameter in D + // + if (!VerifyParameterCompatibility (ec, delegateType, d_params, ec.IsInProbingMode)) + return null; + + TypeSpec [] ptypes = new TypeSpec [Parameters.Count]; + for (int i = 0; i < d_params.Count; i++) { + // D has no ref or out parameters + if ((d_params.FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) != 0) + return null; + + TypeSpec d_param = d_params.Types [i]; + + // + // When type inference context exists try to apply inferred type arguments + // + if (tic != null) { + d_param = tic.InflateGenericArgument (ec, d_param); + } + + ptypes [i] = d_param; + ImplicitLambdaParameter ilp = (ImplicitLambdaParameter) Parameters.FixedParameters [i]; + ilp.SetParameterType (d_param); + ilp.Resolve (null, i); + } + + Parameters.Types = ptypes; + return Parameters; + } + + protected override AnonymousMethodBody CompatibleMethodFactory (TypeSpec returnType, TypeSpec delegateType, ParametersCompiled p, ParametersBlock b) + { + return new LambdaMethod (p, b, returnType, delegateType, loc); + } + + protected override bool DoResolveParameters (ResolveContext rc) + { + // + // Only explicit parameters can be resolved at this point + // + if (HasExplicitParameters) { + return Parameters.Resolve (rc); + } + + return true; + } + + public override string GetSignatureForError () + { + return "lambda expression"; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + class LambdaMethod : AnonymousMethodBody + { + public LambdaMethod (ParametersCompiled parameters, + ParametersBlock block, TypeSpec return_type, TypeSpec delegate_type, + Location loc) + : base (parameters, block, return_type, delegate_type, loc) + { + } + + #region Properties + + public override string ContainerType { + get { + return "lambda expression"; + } + } + + #endregion + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // TODO: nothing ?? + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + BlockContext bc = new BlockContext (ec.MemberContext, Block, ReturnType); + Expression args = parameters.CreateExpressionTree (bc, loc); + Expression expr = Block.CreateExpressionTree (ec); + if (expr == null) + return null; + + Arguments arguments = new Arguments (2); + arguments.Add (new Argument (expr)); + arguments.Add (new Argument (args)); + return CreateExpressionFactoryCall (ec, "Lambda", + new TypeArguments (new TypeExpression (type, loc)), + arguments); + } + } + + // + // This is a return statement that is prepended lambda expression bodies that happen + // to be expressions. Depending on the return type of the delegate this will behave + // as either { expr (); return (); } or { return expr (); } + // + public class ContextualReturn : Return + { + ExpressionStatement statement; + + public ContextualReturn (Expression expr) + : base (expr, expr.Location) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return Expr.CreateExpressionTree (ec); + } + + public override void Emit (EmitContext ec) + { + if (statement != null) { + statement.EmitStatement (ec); + ec.Emit (OpCodes.Ret); + return; + } + + base.Emit (ec); + } + + protected override bool DoResolve (BlockContext ec) + { + // + // When delegate returns void, only expression statements can be used + // + if (ec.ReturnType.Kind == MemberKind.Void) { + Expr = Expr.Resolve (ec); + if (Expr == null) + return false; + + statement = Expr as ExpressionStatement; + if (statement == null) + Expr.Error_InvalidExpressionStatement (ec); + + return true; + } + + return base.DoResolve (ec); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo new file mode 100644 index 0000000000..e3a8a184cd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo @@ -0,0 +1,24 @@ +Tasks for completing Lambda support: + +* Port the grammar to mcs + +* Everywhere where we use Arguments, we need to clone them. + +* We need a "CloneContext" that would keep track of mappings between +the old blocks and the new blocks, so that expression that keep +pointers to blocks can get the proper block on cloning, something like: + + CloneTo (CloneContext cc, Expression t) + { + MyClass target = (MyClass) t; + target.Block = cc.RemapBlock (Block); + } + +* Generics section support. + +* Fix the bug in the modified l1.cs that introduces two rets instead + of a single one. + +* Complete CloneTo for Statements. + +* Write an extensive test suite to exercise CloneTo \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs new file mode 100644 index 0000000000..070b6df10c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs @@ -0,0 +1,892 @@ +// +// linq.cs: support for query expressions +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2007-2008 Novell, Inc +// + +using System; +using System.Collections.Generic; + +namespace Mono.CSharp.Linq +{ + public class QueryExpression : AQueryClause + { + public QueryExpression (AQueryClause start) + : base (null, null, start.Location) + { + this.next = start; + } + + public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parentParameter) + { + return next.BuildQueryClause (ec, lSide, parentParameter); + } + + protected override Expression DoResolve (ResolveContext ec) + { + int counter = QueryBlock.TransparentParameter.Counter; + + Expression e = BuildQueryClause (ec, null, null); + if (e != null) + e = e.Resolve (ec); + + // + // Reset counter in probing mode to ensure that all transparent + // identifier anonymous types are created only once + // + if (ec.IsInProbingMode) + QueryBlock.TransparentParameter.Counter = counter; + + return e; + } + + protected override string MethodName { + get { throw new NotSupportedException (); } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public abstract class AQueryClause : ShimExpression + { + protected class QueryExpressionAccess : MemberAccess + { + public QueryExpressionAccess (Expression expr, string methodName, Location loc) + : base (expr, methodName, loc) + { + } + + public QueryExpressionAccess (Expression expr, string methodName, TypeArguments typeArguments, Location loc) + : base (expr, methodName, typeArguments, loc) + { + } + + protected override void Error_TypeDoesNotContainDefinition (ResolveContext ec, TypeSpec type, string name) + { + ec.Report.Error (1935, loc, "An implementation of `{0}' query expression pattern could not be found. " + + "Are you missing `System.Linq' using directive or `System.Core.dll' assembly reference?", + name); + } + } + + protected class QueryExpressionInvocation : Invocation, OverloadResolver.IErrorHandler + { + public QueryExpressionInvocation (QueryExpressionAccess expr, Arguments arguments) + : base (expr, arguments) + { + } + + protected override MethodGroupExpr DoResolveOverload (ResolveContext ec) + { + MethodGroupExpr rmg = mg.OverloadResolve (ec, ref arguments, this, OverloadResolver.Restrictions.None); + return rmg; + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) + { + ec.Report.SymbolRelatedToPreviousError (best); + ec.Report.SymbolRelatedToPreviousError (ambiguous); + ec.Report.Error (1940, loc, "Ambiguous implementation of the query pattern `{0}' for source type `{1}'", + best.Name, mg.InstanceExpression.GetSignatureForError ()); + return true; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + return false; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + return false; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + var ms = (MethodSpec) best; + TypeSpec source_type = ms.Parameters.ExtensionMethodType; + if (source_type != null) { + Argument a = arguments[0]; + + if (TypeManager.IsGenericType (source_type) && InflatedTypeSpec.ContainsTypeParameter (source_type)) { + TypeInferenceContext tic = new TypeInferenceContext (source_type.TypeArguments); + tic.OutputTypeInference (rc, a.Expr, source_type); + if (tic.FixAllTypes (rc)) { + source_type = source_type.GetDefinition ().MakeGenericType (rc, tic.InferredTypeArguments); + } + } + + if (!Convert.ImplicitConversionExists (rc, a.Expr, source_type)) { + rc.Report.Error (1936, loc, "An implementation of `{0}' query expression pattern for source type `{1}' could not be found", + best.Name, TypeManager.CSharpName (a.Type)); + return true; + } + } + + if (best.Name == "SelectMany") { + rc.Report.Error (1943, loc, + "An expression type is incorrect in a subsequent `from' clause in a query expression with source type `{0}'", + arguments[0].GetSignatureForError ()); + } else { + rc.Report.Error (1942, loc, + "An expression type in `{0}' clause is incorrect. Type inference failed in the call to `{1}'", + best.Name.ToLowerInvariant (), best.Name); + } + + return true; + } + + #endregion + } + + public AQueryClause next; + public QueryBlock block; + + protected AQueryClause (QueryBlock block, Expression expr, Location loc) + : base (expr) + { + this.block = block; + this.loc = loc; + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + base.CloneTo (clonectx, target); + + AQueryClause t = (AQueryClause) target; + + if (block != null) + t.block = (QueryBlock) clonectx.LookupBlock (block); + + if (next != null) + t.next = (AQueryClause) next.Clone (clonectx); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return expr.Resolve (ec); + } + + public virtual Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter) + { + Arguments args = null; + CreateArguments (ec, parameter, ref args); + lSide = CreateQueryExpression (lSide, args); + if (next != null) { + parameter = CreateChildrenParameters (parameter); + + Select s = next as Select; + if (s == null || s.IsRequired (parameter)) + return next.BuildQueryClause (ec, lSide, parameter); + + // Skip transparent select clause if any clause follows + if (next.next != null) + return next.next.BuildQueryClause (ec, lSide, parameter); + } + + return lSide; + } + + protected virtual Parameter CreateChildrenParameters (Parameter parameter) + { + // Have to clone the parameter for any children use, it carries block sensitive data + return parameter.Clone (); + } + + protected virtual void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + args = new Arguments (2); + + LambdaExpression selector = new LambdaExpression (loc); + + block.SetParameter (parameter); + selector.Block = block; + selector.Block.AddStatement (new ContextualReturn (expr)); + + args.Add (new Argument (selector)); + } + + protected Invocation CreateQueryExpression (Expression lSide, Arguments arguments) + { + return new QueryExpressionInvocation ( + new QueryExpressionAccess (lSide, MethodName, loc), arguments); + } + + protected abstract string MethodName { get; } + + public AQueryClause Next { + set { + next = value; + } + } + + public AQueryClause Tail { + get { + return next == null ? this : next.Tail; + } + } + } + + // + // A query clause with an identifier (range variable) + // + public abstract class ARangeVariableQueryClause : AQueryClause + { + sealed class RangeAnonymousTypeParameter : AnonymousTypeParameter + { + public RangeAnonymousTypeParameter (Expression initializer, RangeVariable parameter) + : base (initializer, parameter.Name, parameter.Location) + { + } + + protected override void Error_InvalidInitializer (ResolveContext ec, string initializer) + { + ec.Report.Error (1932, loc, "A range variable `{0}' cannot be initialized with `{1}'", + Name, initializer); + } + } + + class RangeParameterReference : ParameterReference + { + Parameter parameter; + + public RangeParameterReference (Parameter p) + : base (null, p.Location) + { + this.parameter = p; + } + + protected override Expression DoResolve (ResolveContext ec) + { + pi = ec.CurrentBlock.ParametersBlock.GetParameterInfo (parameter); + return base.DoResolve (ec); + } + } + + protected RangeVariable identifier; + + public RangeVariable IntoVariable { + get { + return identifier; + } + } + + protected ARangeVariableQueryClause (QueryBlock block, RangeVariable identifier, Expression expr, Location loc) + : base (block, expr, loc) + { + this.identifier = identifier; + } + + public FullNamedExpression IdentifierType { get; set; } + + protected Invocation CreateCastExpression (Expression lSide) + { + return new QueryExpressionInvocation ( + new QueryExpressionAccess (lSide, "Cast", new TypeArguments (IdentifierType), loc), null); + } + + protected override Parameter CreateChildrenParameters (Parameter parameter) + { + return new QueryBlock.TransparentParameter (parameter.Clone (), GetIntoVariable ()); + } + + protected static Expression CreateRangeVariableType (ResolveContext rc, Parameter parameter, RangeVariable name, Expression init) + { + var args = new List (2); + + // + // The first argument is the reference to the parameter + // + args.Add (new AnonymousTypeParameter (new RangeParameterReference (parameter), parameter.Name, parameter.Location)); + + // + // The second argument is the linq expression + // + args.Add (new RangeAnonymousTypeParameter (init, name)); + + // + // Create unique anonymous type + // + return new NewAnonymousType (args, rc.MemberContext.CurrentMemberDefinition.Parent, name.Location); + } + + protected virtual RangeVariable GetIntoVariable () + { + return identifier; + } + } + + public sealed class RangeVariable : INamedBlockVariable + { + Block block; + + public RangeVariable (string name, Location loc) + { + Name = name; + Location = loc; + } + + #region Properties + + public Block Block { + get { + return block; + } + set { + block = value; + } + } + + public bool IsDeclared { + get { + return true; + } + } + + public Location Location { get; private set; } + + public string Name { get; private set; } + + #endregion + + public Expression CreateReferenceExpression (ResolveContext rc, Location loc) + { + // + // We know the variable name is somewhere in the scope. This generates + // an access expression from current block + // + var pb = rc.CurrentBlock.ParametersBlock; + while (true) { + if (pb is QueryBlock) { + for (int i = pb.Parameters.Count - 1; i >= 0; --i) { + var p = pb.Parameters[i]; + if (p.Name == Name) + return pb.GetParameterReference (i, loc); + + Expression expr = null; + var tp = p as QueryBlock.TransparentParameter; + while (tp != null) { + if (expr == null) + expr = pb.GetParameterReference (i, loc); + else + expr = new TransparentMemberAccess (expr, tp.Name); + + if (tp.Identifier == Name) + return new TransparentMemberAccess (expr, Name); + + if (tp.Parent.Name == Name) + return new TransparentMemberAccess (expr, Name); + + tp = tp.Parent as QueryBlock.TransparentParameter; + } + } + } + + if (pb == block) + return null; + + pb = pb.Parent.ParametersBlock; + } + } + } + + public class QueryStartClause : ARangeVariableQueryClause + { + public QueryStartClause (QueryBlock block, Expression expr, RangeVariable identifier, Location loc) + : base (block, identifier, expr, loc) + { + block.AddRangeVariable (identifier); + } + + public override Expression BuildQueryClause (ResolveContext ec, Expression lSide, Parameter parameter) + { +/* + expr = expr.Resolve (ec); + if (expr == null) + return null; + + if (expr.Type == InternalType.Dynamic || expr.Type == TypeManager.void_type) { + ec.Report.Error (1979, expr.Location, + "Query expression with a source or join sequence of type `{0}' is not allowed", + TypeManager.CSharpName (expr.Type)); + return null; + } +*/ + + if (IdentifierType != null) + expr = CreateCastExpression (expr); + + if (parameter == null) + lSide = expr; + + return next.BuildQueryClause (ec, lSide, new ImplicitLambdaParameter (identifier.Name, identifier.Location)); + } + + protected override Expression DoResolve (ResolveContext ec) + { + Expression e = BuildQueryClause (ec, null, null); + return e.Resolve (ec); + } + + protected override string MethodName { + get { throw new NotSupportedException (); } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + + public class GroupBy : AQueryClause + { + Expression element_selector; + QueryBlock element_block; + + public Expression ElementSelector { + get { return this.element_selector; } + } + + public GroupBy (QueryBlock block, Expression elementSelector, QueryBlock elementBlock, Expression keySelector, Location loc) + : base (block, keySelector, loc) + { + // + // Optimizes clauses like `group A by A' + // + if (!elementSelector.Equals (keySelector)) { + this.element_selector = elementSelector; + this.element_block = elementBlock; + } + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + base.CreateArguments (ec, parameter, ref args); + + if (element_selector != null) { + LambdaExpression lambda = new LambdaExpression (element_selector.Location); + + element_block.SetParameter (parameter.Clone ()); + lambda.Block = element_block; + lambda.Block.AddStatement (new ContextualReturn (element_selector)); + args.Add (new Argument (lambda)); + } + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + GroupBy t = (GroupBy) target; + if (element_selector != null) { + t.element_selector = element_selector.Clone (clonectx); + t.element_block = (QueryBlock) element_block.Clone (clonectx); + } + + base.CloneTo (clonectx, t); + } + + protected override string MethodName { + get { return "GroupBy"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Join : SelectMany + { + QueryBlock inner_selector, outer_selector; + + public RangeVariable JoinVariable { + get { return this.GetIntoVariable (); } + } + + public QueryBlock InnerSelector { + get { + return inner_selector; + } + } + + public QueryBlock OuterSelector { + get { + return outer_selector; + } + } + + public Join (QueryBlock block, RangeVariable lt, Expression inner, QueryBlock outerSelector, QueryBlock innerSelector, Location loc) + : base (block, lt, inner, loc) + { + this.outer_selector = outerSelector; + this.inner_selector = innerSelector; + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + args = new Arguments (4); + + if (IdentifierType != null) + expr = CreateCastExpression (expr); + + args.Add (new Argument (expr)); + + outer_selector.SetParameter (parameter.Clone ()); + var lambda = new LambdaExpression (outer_selector.StartLocation); + lambda.Block = outer_selector; + args.Add (new Argument (lambda)); + + inner_selector.SetParameter (new ImplicitLambdaParameter (identifier.Name, identifier.Location)); + lambda = new LambdaExpression (inner_selector.StartLocation); + lambda.Block = inner_selector; + args.Add (new Argument (lambda)); + + base.CreateArguments (ec, parameter, ref args); + } + + protected override void CloneTo (CloneContext clonectx, Expression target) + { + Join t = (Join) target; + t.inner_selector = (QueryBlock) inner_selector.Clone (clonectx); + t.outer_selector = (QueryBlock) outer_selector.Clone (clonectx); + base.CloneTo (clonectx, t); + } + + protected override string MethodName { + get { return "Join"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class GroupJoin : Join + { + readonly RangeVariable into; + + public GroupJoin (QueryBlock block, RangeVariable lt, Expression inner, + QueryBlock outerSelector, QueryBlock innerSelector, RangeVariable into, Location loc) + : base (block, lt, inner, outerSelector, innerSelector, loc) + { + this.into = into; + } + + protected override RangeVariable GetIntoVariable () + { + return into; + } + + protected override string MethodName { + get { return "GroupJoin"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Let : ARangeVariableQueryClause + { + public Let (QueryBlock block, RangeVariable identifier, Expression expr, Location loc) + : base (block, identifier, expr, loc) + { + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + expr = CreateRangeVariableType (ec, parameter, identifier, expr); + base.CreateArguments (ec, parameter, ref args); + } + + protected override string MethodName { + get { return "Select"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Select : AQueryClause + { + public Select (QueryBlock block, Expression expr, Location loc) + : base (block, expr, loc) + { + } + + // + // For queries like `from a orderby a select a' + // the projection is transparent and select clause can be safely removed + // + public bool IsRequired (Parameter parameter) + { + SimpleName sn = expr as SimpleName; + if (sn == null) + return true; + + return sn.Name != parameter.Name; + } + + protected override string MethodName { + get { return "Select"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + public class SelectMany : ARangeVariableQueryClause + { + public SelectMany (QueryBlock block, RangeVariable identifier, Expression expr, Location loc) + : base (block, identifier, expr, loc) + { + } + + protected override void CreateArguments (ResolveContext ec, Parameter parameter, ref Arguments args) + { + if (args == null) { + if (IdentifierType != null) + expr = CreateCastExpression (expr); + + base.CreateArguments (ec, parameter.Clone (), ref args); + } + + Expression result_selector_expr; + QueryBlock result_block; + + var target = GetIntoVariable (); + var target_param = new ImplicitLambdaParameter (target.Name, target.Location); + + // + // When select follows use it as a result selector + // + if (next is Select) { + result_selector_expr = next.Expr; + + result_block = next.block; + result_block.SetParameters (parameter, target_param); + + next = next.next; + } else { + result_selector_expr = CreateRangeVariableType (ec, parameter, target, new SimpleName (target.Name, target.Location)); + + result_block = new QueryBlock (block.Parent, block.StartLocation); + result_block.SetParameters (parameter, target_param); + } + + LambdaExpression result_selector = new LambdaExpression (Location); + result_selector.Block = result_block; + result_selector.Block.AddStatement (new ContextualReturn (result_selector_expr)); + + args.Add (new Argument (result_selector)); + } + + protected override string MethodName { + get { return "SelectMany"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Where : AQueryClause + { + public Where (QueryBlock block, Expression expr, Location loc) + : base (block, expr, loc) + { + } + + protected override string MethodName { + get { return "Where"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class OrderByAscending : AQueryClause + { + public OrderByAscending (QueryBlock block, Expression expr) + : base (block, expr, expr.Location) + { + } + + protected override string MethodName { + get { return "OrderBy"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class OrderByDescending : AQueryClause + { + public OrderByDescending (QueryBlock block, Expression expr) + : base (block, expr, expr.Location) + { + } + + protected override string MethodName { + get { return "OrderByDescending"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ThenByAscending : OrderByAscending + { + public ThenByAscending (QueryBlock block, Expression expr) + : base (block, expr) + { + } + + protected override string MethodName { + get { return "ThenBy"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ThenByDescending : OrderByDescending + { + public ThenByDescending (QueryBlock block, Expression expr) + : base (block, expr) + { + } + + protected override string MethodName { + get { return "ThenByDescending"; } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Implicit query block + // + public class QueryBlock : ParametersBlock + { + // + // Transparent parameters are used to package up the intermediate results + // and pass them onto next clause + // + public sealed class TransparentParameter : ImplicitLambdaParameter + { + public static int Counter; + const string ParameterNamePrefix = "<>__TranspIdent"; + + public readonly Parameter Parent; + public readonly string Identifier; + + public TransparentParameter (Parameter parent, RangeVariable identifier) + : base (ParameterNamePrefix + Counter++, identifier.Location) + { + Parent = parent; + Identifier = identifier.Name; + } + + public static void Reset () + { + Counter = 0; + } + } + + public QueryBlock (Block parent, Location start) + : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start) + { + flags |= Flags.CompilerGenerated; + } + + public void AddRangeVariable (RangeVariable variable) + { + variable.Block = this; + AddLocalName (variable.Name, variable); + } + + public override void Error_AlreadyDeclared (string name, INamedBlockVariable variable, string reason) + { + TopBlock.Report.Error (1931, variable.Location, + "A range variable `{0}' conflicts with a previous declaration of `{0}'", + name); + } + + public override void Error_AlreadyDeclared (string name, INamedBlockVariable variable) + { + TopBlock.Report.Error (1930, variable.Location, + "A range variable `{0}' has already been declared in this scope", + name); + } + + public override void Error_AlreadyDeclaredTypeParameter (string name, Location loc) + { + TopBlock.Report.Error (1948, loc, + "A range variable `{0}' conflicts with a method type parameter", + name); + } + + public void SetParameter (Parameter parameter) + { + base.parameters = new ParametersCompiled (parameter); + base.parameter_info = new ParameterInfo[] { + new ParameterInfo (this, 0) + }; + } + + public void SetParameters (Parameter first, Parameter second) + { + base.parameters = new ParametersCompiled (first, second); + base.parameter_info = new ParameterInfo[] { + new ParameterInfo (this, 0), + new ParameterInfo (this, 1) + }; + } + } + + sealed class TransparentMemberAccess : MemberAccess + { + public TransparentMemberAccess (Expression expr, string name) + : base (expr, name) + { + } + + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) + { + rc.Report.Error (1947, loc, + "A range variable `{0}' cannot be assigned to. Consider using `let' clause to store the value", + Name); + + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs new file mode 100644 index 0000000000..b2efb35c1a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs @@ -0,0 +1,282 @@ +// +// literal.cs: Literal representation for the IL tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001 Ximian, Inc. +// +// +// Notice that during parsing we create objects of type Literal, but the +// types are not loaded (thats why the Resolve method has to assign the +// type at that point). +// +// Literals differ from the constants in that we know we encountered them +// as a literal in the source code (and some extra rules apply there) and +// they have to be resolved (since during parsing we have not loaded the +// types yet) while constants are created only after types have been loaded +// and are fully resolved when born. +// + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + public interface ILiteralConstant + { +#if FULL_AST + char[] ParsedValue { get; set; } +#endif + } + + // + // The null literal + // + // Note: C# specification null-literal is NullLiteral of NullType type + // + public class NullLiteral : NullConstant + { + // + // Default type of null is an object + // + public NullLiteral (Location loc) + : base (InternalType.NullLiteral, loc) + { + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec t, bool expl) + { + if (t.IsGenericParameter) { + ec.Report.Error(403, loc, + "Cannot convert null to the type parameter `{0}' because it could be a value " + + "type. Consider using `default ({0})' instead", t.Name); + return; + } + + if (TypeSpec.IsValueType (t)) { + ec.Report.Error(37, loc, "Cannot convert null to `{0}' because it is a value type", + TypeManager.CSharpName(t)); + return; + } + + base.Error_ValueCannotBeConverted (ec, loc, t, expl); + } + + public override string GetValueAsLiteral () + { + return "null"; + } + + public override bool IsLiteral { + get { return true; } + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + return System.Linq.Expressions.Expression.Constant (null); + } + } + + public class BoolLiteral : BoolConstant, ILiteralConstant + { + public BoolLiteral (BuiltinTypes types, bool val, Location loc) + : base (types, val, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class CharLiteral : CharConstant, ILiteralConstant + { + public CharLiteral (BuiltinTypes types, char c, Location loc) + : base (types, c, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class IntLiteral : IntConstant, ILiteralConstant + { + public IntLiteral (BuiltinTypes types, int l, Location loc) + : base (types, l, loc) + { + } + + public override Constant ConvertImplicitly (TypeSpec type) + { + // + // The 0 literal can be converted to an enum value + // + if (Value == 0 && TypeManager.IsEnumType (type)) { + Constant c = ConvertImplicitly (EnumSpec.GetUnderlyingType (type)); + if (c == null) + return null; + + return new EnumConstant (c, type); + } + + return base.ConvertImplicitly (type); + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class UIntLiteral : UIntConstant, ILiteralConstant + { + public UIntLiteral (BuiltinTypes types, uint l, Location loc) + : base (types, l, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class LongLiteral : LongConstant, ILiteralConstant + { + public LongLiteral (BuiltinTypes types, long l, Location loc) + : base (types, l, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class ULongLiteral : ULongConstant, ILiteralConstant + { + public ULongLiteral (BuiltinTypes types, ulong l, Location loc) + : base (types, l, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class FloatLiteral : FloatConstant, ILiteralConstant + { + public FloatLiteral (BuiltinTypes types, float f, Location loc) + : base (types, f, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class DoubleLiteral : DoubleConstant, ILiteralConstant + { + public DoubleLiteral (BuiltinTypes types, double d, Location loc) + : base (types, d, loc) + { + } + + public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) + { + if (target.BuiltinType == BuiltinTypeSpec.Type.Float) { + Error_664 (ec, loc, "float", "f"); + return; + } + + if (target.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + Error_664 (ec, loc, "decimal", "m"); + return; + } + + base.Error_ValueCannotBeConverted (ec, loc, target, expl); + } + + static void Error_664 (ResolveContext ec, Location loc, string type, string suffix) + { + ec.Report.Error (664, loc, + "Literal of type double cannot be implicitly converted to type `{0}'. Add suffix `{1}' to create a literal of this type", + type, suffix); + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class DecimalLiteral : DecimalConstant, ILiteralConstant + { + public DecimalLiteral (BuiltinTypes types, decimal d, Location loc) + : base (types, d, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } + + public class StringLiteral : StringConstant, ILiteralConstant + { + public StringLiteral (BuiltinTypes types, string s, Location loc) + : base (types, s, loc) + { + } + + public override bool IsLiteral { + get { return true; } + } + +#if FULL_AST + char[] ILiteralConstant.ParsedValue { get; set; } +#endif + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs new file mode 100644 index 0000000000..fd3fe3aaa3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs @@ -0,0 +1,912 @@ +// +// location.cs: Keeps track of the location of source code entity +// +// Author: +// Miguel de Icaza +// Atsushi Enomoto +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001 Ximian, Inc. +// Copyright 2005 Novell, Inc. +// + +using System; +using System.IO; +using System.Collections.Generic; +using Mono.CompilerServices.SymbolWriter; +using System.Diagnostics; +using System.Linq; + +namespace Mono.CSharp { + /// + /// This is one single source file. + /// + /// + /// This is intentionally a class and not a struct since we need + /// to pass this by reference. + /// + public class SourceFile : ISourceFile, IEquatable + { + public readonly string Name; + public readonly string FullPathName; + public readonly int Index; + public bool AutoGenerated; + + SourceFileEntry file; + byte[] guid, checksum; + + public SourceFile (string name, string path, int index) + { + this.Index = index; + this.Name = name; + this.FullPathName = path; + } + + public SourceFileEntry SourceFileEntry { + get { return file; } + } + + SourceFileEntry ISourceFile.Entry { + get { return file; } + } + + public void SetChecksum (byte[] guid, byte[] checksum) + { + this.guid = guid; + this.checksum = checksum; + } + + public virtual void DefineSymbolInfo (MonoSymbolWriter symwriter) + { + if (guid != null) + file = symwriter.DefineDocument (FullPathName, guid, checksum); + else { + file = symwriter.DefineDocument (FullPathName); + if (AutoGenerated) + file.SetAutoGenerated (); + } + } + + public bool Equals (SourceFile other) + { + return FullPathName == other.FullPathName; + } + + public override string ToString () + { + return String.Format ("SourceFile ({0}:{1}:{2}:{3})", + Name, FullPathName, Index, SourceFileEntry); + } + } + + public class CompilationSourceFile : SourceFile, ICompileUnit + { + CompileUnitEntry comp_unit; + Dictionary include_files; + Dictionary conditionals; + NamespaceContainer ns_container; + + public CompilationSourceFile (string name, string fullPathName, int index) + : base (name, fullPathName, index) + { + } + + CompileUnitEntry ICompileUnit.Entry { + get { return comp_unit; } + } + + public CompileUnitEntry CompileUnitEntry { + get { return comp_unit; } + } + + public NamespaceContainer NamespaceContainer { + get { + return ns_container; + } + set { + ns_container = value; + } + } + + public void AddIncludeFile (SourceFile file) + { + if (file == this) + return; + + if (include_files == null) + include_files = new Dictionary (); + + if (!include_files.ContainsKey (file.FullPathName)) + include_files.Add (file.FullPathName, file); + } + + public void AddDefine (string value) + { + if (conditionals == null) + conditionals = new Dictionary (2); + + conditionals [value] = true; + } + + public void AddUndefine (string value) + { + if (conditionals == null) + conditionals = new Dictionary (2); + + conditionals [value] = false; + } + + public override void DefineSymbolInfo (MonoSymbolWriter symwriter) + { + base.DefineSymbolInfo (symwriter); + + comp_unit = symwriter.DefineCompilationUnit (SourceFileEntry); + + if (include_files != null) { + foreach (SourceFile include in include_files.Values) { + include.DefineSymbolInfo (symwriter); + comp_unit.AddFile (include.SourceFileEntry); + } + } + } + + public bool IsConditionalDefined (CompilerContext ctx, string value) + { + if (conditionals != null) { + bool res; + if (conditionals.TryGetValue (value, out res)) + return res; + + // When conditional was undefined + if (conditionals.ContainsKey (value)) + return false; + } + + return ctx.Settings.IsConditionalSymbolDefined (value); + } + } + + /// + /// Keeps track of the location in the program + /// + /// + /// + /// This uses a compact representation and a couple of auxiliary + /// structures to keep track of tokens to (file,line and column) + /// mappings. The usage of the bits is: + /// + /// - 16 bits for "checkpoint" which is a mixed concept of + /// file and "line segment" + /// - 8 bits for line delta (offset) from the line segment + /// - 8 bits for column number. + /// + /// http://lists.ximian.com/pipermail/mono-devel-list/2004-December/009508.html + /// + public struct Location : IEquatable + { + struct Checkpoint { + public readonly int LineOffset; + public readonly int CompilationUnit; + public readonly int File; + + public Checkpoint (int compile_unit, int file, int line) + { + File = file; + CompilationUnit = compile_unit; + LineOffset = line - (int) (line % (1 << line_delta_bits)); + } + } + +#if FULL_AST + long token; + + const int column_bits = 24; + const int line_delta_bits = 24; +#else + int token; + + const int column_bits = 8; + const int line_delta_bits = 8; +#endif + const int checkpoint_bits = 16; + + // -2 because the last one is used for hidden + const int max_column = (1 << column_bits) - 2; + const int column_mask = (1 << column_bits) - 1; + + static List source_list; + static int current_source; + static int current_compile_unit; + static Checkpoint [] checkpoints; + static int checkpoint_index; + + public readonly static Location Null = new Location (-1); + public static bool InEmacs; + + static Location () + { + Reset (); + } + + public static void Reset () + { + source_list = new List (); + current_source = 0; + current_compile_unit = 0; + checkpoint_index = 0; + } + + public static SourceFile AddFile (string name, string fullName) + { + var source = new SourceFile (name, fullName, source_list.Count + 1); + source_list.Add (source); + return source; + } + + // + // After adding all source files we want to compile with AddFile(), this method + // must be called to `reserve' an appropriate number of bits in the token for the + // source file. We reserve some extra space for files we encounter via #line + // directives while parsing. + // + static public void Initialize (List files) + { +#if NET_4_0 + source_list.AddRange (files); +#else + source_list.AddRange (files.ToArray ()); +#endif + + checkpoints = new Checkpoint [source_list.Count * 2]; + if (checkpoints.Length > 0) + checkpoints [0] = new Checkpoint (0, 0, 0); + } + + static public void Push (CompilationSourceFile compile_unit, SourceFile file) + { + current_source = file != null ? file.Index : -1; + current_compile_unit = compile_unit != null ? compile_unit.Index : -1; + // File is always pushed before being changed. + } + + public Location (int row) + : this (row, 0) + { + } + + public Location (int row, int column) + { + if (row <= 0) + token = 0; + else { + if (column > max_column) + column = max_column; + else if (column < 0) + column = max_column + 1; + + long target = -1; + long delta = 0; + + // FIXME: This value is certainly wrong but what was the intension + int max = checkpoint_index < 10 ? + checkpoint_index : 10; + for (int i = 0; i < max; i++) { + int offset = checkpoints [checkpoint_index - i].LineOffset; + delta = row - offset; + if (delta >= 0 && + delta < (1 << line_delta_bits) && + checkpoints [checkpoint_index - i].File == current_source) { + target = checkpoint_index - i; + break; + } + } + if (target == -1) { + AddCheckpoint (current_compile_unit, current_source, row); + target = checkpoint_index; + delta = row % (1 << line_delta_bits); + } + + long l = column + + (delta << column_bits) + + (target << (line_delta_bits + column_bits)); +#if FULL_AST + token = l; +#else + token = l > 0xFFFFFFFF ? 0 : (int) l; +#endif + } + } + + public static Location operator - (Location loc, int columns) + { + return new Location (loc.Row, loc.Column - columns); + } + + static void AddCheckpoint (int compile_unit, int file, int row) + { + if (checkpoints.Length == ++checkpoint_index) { + Array.Resize (ref checkpoints, checkpoint_index * 2); + } + checkpoints [checkpoint_index] = new Checkpoint (compile_unit, file, row); + } + + string FormatLocation (string fileName) + { + if (column_bits == 0 || InEmacs) + return fileName + "(" + Row.ToString () + "):"; + + return fileName + "(" + Row.ToString () + "," + Column.ToString () + + (Column == max_column ? "+):" : "):"); + } + + public override string ToString () + { + return FormatLocation (Name); + } + + public string ToStringFullName () + { + return FormatLocation (NameFullPath); + } + + /// + /// Whether the Location is Null + /// + public bool IsNull { + get { return token == 0; } + } + + public string Name { + get { + int index = File; + if (token == 0 || index == 0) + return "Internal"; + if (source_list == null || index - 1 >= source_list.Count) + return "unknown_file"; + + SourceFile file = source_list [index - 1]; + return file.Name; + } + } + + public string NameFullPath { + get { + int index = File; + if (token == 0 || index == 0) + return "Internal"; + + return source_list[index - 1].FullPathName; + } + } + + int CheckpointIndex { + get { + const int checkpoint_mask = (1 << checkpoint_bits) - 1; + return ((int) (token >> (line_delta_bits + column_bits))) & checkpoint_mask; + } + } + + public int Row { + get { + if (token == 0) + return 1; + + int offset = checkpoints[CheckpointIndex].LineOffset; + + const int line_delta_mask = (1 << column_bits) - 1; + return offset + (((int)(token >> column_bits)) & line_delta_mask); + } + } + + public int Column { + get { + if (token == 0) + return 1; + int col = (int) (token & column_mask); + return col > max_column ? 1 : col; + } + } + + public bool Hidden { + get { + return (int) (token & column_mask) == max_column + 1; + } + } + + public int CompilationUnitIndex { + get { + if (token == 0) + return 0; +if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("Should not happen. Token is {0:X04}, checkpoints are {1}, index is {2}", token, checkpoints.Length, CheckpointIndex)); + return checkpoints [CheckpointIndex].CompilationUnit; + } + } + + public int File { + get { + if (token == 0) + return 0; +if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format ("Should not happen. Token is {0:X04}, checkpoints are {1}, index is {2}", token, checkpoints.Length, CheckpointIndex)); + return checkpoints [CheckpointIndex].File; + } + } + + // The ISymbolDocumentWriter interface is used by the symbol writer to + // describe a single source file - for each source file there's exactly + // one corresponding ISymbolDocumentWriter instance. + // + // This class has an internal hash table mapping source document names + // to such ISymbolDocumentWriter instances - so there's exactly one + // instance per document. + // + // This property returns the ISymbolDocumentWriter instance which belongs + // to the location's source file. + // + // If we don't have a symbol writer, this property is always null. + public SourceFile SourceFile { + get { + int index = File; + if (index == 0) + return null; + return (SourceFile) source_list [index - 1]; + } + } + + public CompilationSourceFile CompilationUnit { + get { + int index = CompilationUnitIndex; + if (index == 0) + return null; + return (CompilationSourceFile) source_list [index - 1]; + } + } + + #region IEquatable Members + + public bool Equals (Location other) + { + return this.token == other.token; + } + + #endregion + } + + public class SpecialsBag + { + public enum CommentType + { + Single, + Multi, + Documentation + } + + public class Comment + { + public readonly CommentType CommentType; + public readonly bool StartsLine; + public readonly int Line; + public readonly int Col; + public readonly int EndLine; + public readonly int EndCol; + public readonly string Content; + + public Comment (CommentType commentType, bool startsLine, int line, int col, int endLine, int endCol, string content) + { + this.CommentType = commentType; + this.StartsLine = startsLine; + this.Line = line; + this.Col = col; + this.EndLine = endLine; + this.EndCol = endCol; + this.Content = content; + } + + public override string ToString () + { + return string.Format ("[Comment: CommentType={0}, Line={1}, Col={2}, EndLine={3}, EndCol={4}, Content={5}]", CommentType, Line, Col, EndLine, EndCol, Content); + } + } + + public class PreProcessorDirective + { + public readonly int Line; + public readonly int Col; + public readonly int EndLine; + public readonly int EndCol; + + public readonly Tokenizer.PreprocessorDirective Cmd; + public readonly string Arg; + + public PreProcessorDirective (int line, int col, int endLine, int endCol, Tokenizer.PreprocessorDirective cmd, string arg) + { + this.Line = line; + this.Col = col; + this.EndLine = endLine; + this.EndCol = endCol; + this.Cmd = cmd; + this.Arg = arg; + } + + public override string ToString () + { + return string.Format ("[PreProcessorDirective: Line={0}, Col={1}, EndLine={2}, EndCol={3}, Cmd={4}, Arg={5}]", Line, Col, EndLine, EndCol, Cmd, Arg); + } + } + + public readonly List Specials = new List (); + + CommentType curComment; + bool startsLine; + int startLine, startCol; + System.Text.StringBuilder contentBuilder = new System.Text.StringBuilder (); + + [Conditional ("FULL_AST")] + public void StartComment (CommentType type, bool startsLine, int startLine, int startCol) + { + curComment = type; + this.startsLine = startsLine; + this.startLine = startLine; + this.startCol = startCol; + contentBuilder.Length = 0; + } + + [Conditional ("FULL_AST")] + public void PushCommentChar (int ch) + { + if (ch < 0) + return; + contentBuilder.Append ((char)ch); + } + [Conditional ("FULL_AST")] + public void PushCommentString (string str) + { + contentBuilder.Append (str); + } + + [Conditional ("FULL_AST")] + public void EndComment (int endLine, int endColumn) + { + 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) + { + Specials.Add (new PreProcessorDirective (startLine, startCol, endLine, endColumn, cmd, arg)); + } + } + + // + // A bag of additional locations to support full ast tree + // + public class LocationsBag + { + public class MemberLocations + { + public IList> Modifiers { get; internal set; } + List locations; + + public MemberLocations (IList> mods, IEnumerable locs) + { + Modifiers = mods; + locations = locs != null ? new List (locs) : null; + } + + #region Properties + + public Location this [int index] { + get { + return locations [index]; + } + } + + public int Count { + get { + return locations != null ? locations.Count : 0; + } + } + + #endregion + + public void AddLocations (params Location[] additional) + + { + + AddLocations ((IEnumerable)additional); + + } + public void AddLocations (IEnumerable additional) + { + if (additional == null) + return; + if (locations == null) { + locations = new List(additional); + } else { + locations.AddRange (additional); + } + } + } + + public MemberCore LastMember { + get; + private set; + } + + Dictionary> simple_locs = new Dictionary> (ReferenceEquality.Default); + Dictionary member_locs = new Dictionary (ReferenceEquality.Default); + + [Conditional ("FULL_AST")] + public void AddLocation (object element, params Location[] locations) + { + AddLocation (element, (IEnumerable)locations); + } + + [Conditional ("FULL_AST")] + public void AddLocation (object element, IEnumerable locations) + { + if (element == null || locations == null) + return; + simple_locs.Add (element, new List (locations)); + } + + [Conditional ("FULL_AST")] + public void AddStatement (object element, params Location[] locations) + { + if (element == null) + return; + if (locations.Length == 0) + throw new ArgumentException ("Statement is missing semicolon location"); + simple_locs.Add (element, new List(locations)); + } + + [Conditional ("FULL_AST")] + public void AddMember (MemberCore member, IList> modLocations, params Location[] locations) + { + LastMember = member; + if (member == null) + return; + + MemberLocations existing; + if (member_locs.TryGetValue (member, out existing)) { + existing.Modifiers = modLocations; + existing.AddLocations (locations); + return; + } + member_locs.Add (member, new MemberLocations (modLocations, locations)); + } + [Conditional ("FULL_AST")] + public void AddMember (MemberCore member, IList> modLocations, IEnumerable locations) + { + LastMember = member; + if (member == null) + return; + + MemberLocations existing; + if (member_locs.TryGetValue (member, out existing)) { + existing.Modifiers = modLocations; + existing.AddLocations (locations); + return; + } + member_locs.Add (member, new MemberLocations (modLocations, locations)); + } + + [Conditional ("FULL_AST")] + public void AppendTo (object existing, params Location[] locations) + { + AppendTo (existing, (IEnumerable)locations); + + } + + [Conditional ("FULL_AST")] + public void AppendTo (object existing, IEnumerable locations) + { + if (existing == null) + return; + List locs; + if (simple_locs.TryGetValue (existing, out locs)) { + simple_locs [existing].AddRange (locations); + return; + } + AddLocation (existing, locations); + } + + [Conditional ("FULL_AST")] + public void AppendToMember (MemberCore existing, params Location[] locations) + { + AppendToMember (existing, (IEnumerable)locations); + + } + + [Conditional ("FULL_AST")] + public void AppendToMember (MemberCore existing, IEnumerable locations) + { + if (existing == null) + return; + MemberLocations member; + if (member_locs.TryGetValue (existing, out member)) { + member.AddLocations (locations); + return; + } + member_locs.Add (existing, new MemberLocations (null, locations)); + } + + public List GetLocations (object element) + { + if (element == null) + return null; + List found; + simple_locs.TryGetValue (element, out found); + return found; + } + + public MemberLocations GetMemberLocation (MemberCore element) + { + MemberLocations found; + member_locs.TryGetValue (element, out found); + return found; + } + } + + public class UsingsBag + { + public class Namespace { + public Location NamespaceLocation { get; set; } + public MemberName Name { get; set; } + + public Location OpenBrace { get; set; } + public Location CloseBrace { get; set; } + public Location OptSemicolon { get; set; } + + public List usings = new List (); + public List members = new List (); + + public Namespace () + { + // in case of missing close brace, set it to the highest value. + CloseBrace = new Location (int.MaxValue, int.MaxValue); + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class AliasUsing + { + public readonly Location UsingLocation; + public readonly Tokenizer.LocatedToken Identifier; + public readonly Location AssignLocation; + public readonly MemberName Nspace; + public readonly Location SemicolonLocation; + + public AliasUsing (Location usingLocation, Tokenizer.LocatedToken identifier, Location assignLocation, MemberName nspace, Location semicolonLocation) + { + this.UsingLocation = usingLocation; + this.Identifier = identifier; + this.AssignLocation = assignLocation; + this.Nspace = nspace; + this.SemicolonLocation = semicolonLocation; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class Using + { + public readonly Location UsingLocation; + public readonly MemberName NSpace; + public readonly Location SemicolonLocation; + + public Using (Location usingLocation, MemberName nSpace, Location semicolonLocation) + { + this.UsingLocation = usingLocation; + this.NSpace = nSpace; + this.SemicolonLocation = semicolonLocation; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public class ExternAlias + { + public readonly Location ExternLocation; + public readonly Location AliasLocation; + public readonly Tokenizer.LocatedToken Identifier; + public readonly Location SemicolonLocation; + + public ExternAlias (Location externLocation, Location aliasLocation, Tokenizer.LocatedToken identifier, Location semicolonLocation) + { + this.ExternLocation = externLocation; + this.AliasLocation = aliasLocation; + this.Identifier = identifier; + this.SemicolonLocation = semicolonLocation; + } + + public virtual void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public Namespace Global { + get; + set; + } + Stack curNamespace = new Stack (); + + public UsingsBag () + { + Global = new Namespace (); + Global.OpenBrace = new Location (1, 1); + Global.CloseBrace = new Location (int.MaxValue, int.MaxValue); + curNamespace.Push (Global); + } + + [Conditional ("FULL_AST")] + public void AddUsingAlias (Location usingLocation, Tokenizer.LocatedToken identifier, Location assignLocation, MemberName nspace, Location semicolonLocation) + { + curNamespace.Peek ().usings.Add (new AliasUsing (usingLocation, identifier, assignLocation, nspace, semicolonLocation)); + } + + [Conditional ("FULL_AST")] + public void AddUsing (Location usingLocation, MemberName nspace, Location semicolonLocation) + { + curNamespace.Peek ().usings.Add (new Using (usingLocation, nspace, semicolonLocation)); + } + + [Conditional ("FULL_AST")] + public void AddExternAlias (Location externLocation, Location aliasLocation, Tokenizer.LocatedToken identifier, Location semicolonLocation) + { + curNamespace.Peek ().usings.Add (new ExternAlias (externLocation, aliasLocation, identifier, semicolonLocation)); + } + + [Conditional ("FULL_AST")] + public void DeclareNamespace (Location namespaceLocation, MemberName nspace) + { + var newNamespace = new Namespace () { NamespaceLocation = namespaceLocation, Name = nspace }; + curNamespace.Peek ().members.Add (newNamespace); + curNamespace.Push (newNamespace); + } + + int typeLevel = 0; + [Conditional ("FULL_AST")] + public void PushTypeDeclaration (object type) + { + if (typeLevel == 0) + curNamespace.Peek ().members.Add (type); + typeLevel++; + } + + [Conditional ("FULL_AST")] + public void PopTypeDeclaration () + { + typeLevel--; + } + + [Conditional ("FULL_AST")] + public void EndNamespace (Location optSemicolon) + { + curNamespace.Peek ().OptSemicolon = optSemicolon; + curNamespace.Pop (); + } + + [Conditional ("FULL_AST")] + public void OpenNamespace (Location bracketLocation) + { + curNamespace.Peek ().OpenBrace = bracketLocation; + } + + [Conditional ("FULL_AST")] + public void CloseNamespace (Location bracketLocation) + { + curNamespace.Peek ().CloseBrace = bracketLocation; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs new file mode 100644 index 0000000000..a01100c25f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs @@ -0,0 +1,1409 @@ +// +// membercache.cs: A container for all member lookups +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2010 Novell, Inc +// +// + +using System; +using System.Collections.Generic; + +namespace Mono.CSharp { + + [Flags] + public enum MemberKind + { + Constructor = 1, + Event = 1 << 1, + Field = 1 << 2, + Method = 1 << 3, + Property = 1 << 4, + Indexer = 1 << 5, + Operator = 1 << 6, + Destructor = 1 << 7, + + Class = 1 << 11, + Struct = 1 << 12, + Delegate = 1 << 13, + Enum = 1 << 14, + Interface = 1 << 15, + TypeParameter = 1 << 16, + + ArrayType = 1 << 19, + PointerType = 1 << 20, + InternalCompilerType = 1 << 21, + MissingType = 1 << 22, + Void = 1 << 23, + + NestedMask = Class | Struct | Delegate | Enum | Interface, + GenericMask = Method | Class | Struct | Delegate | Interface, + MaskType = Constructor | Event | Field | Method | Property | Indexer | Operator | Destructor | NestedMask + } + + [Flags] + public enum BindingRestriction + { + None = 0, + + // Inspect only queried type members + DeclaredOnly = 1 << 1, + + // Exclude static + InstanceOnly = 1 << 2, + + NoAccessors = 1 << 3, + + // Member has to be override + OverrideOnly = 1 << 4 + } + + public struct MemberFilter : IEquatable + { + public readonly string Name; + public readonly MemberKind Kind; + public readonly AParametersCollection Parameters; + public readonly TypeSpec MemberType; + public readonly int Arity; // -1 to ignore the check + + private MemberFilter (string name, MemberKind kind) + { + Name = name; + Kind = kind; + Parameters = null; + MemberType = null; + Arity = -1; + } + + public MemberFilter (MethodSpec m) + { + Name = m.Name; + Kind = MemberKind.Method; + Parameters = m.Parameters; + MemberType = m.ReturnType; + Arity = m.Arity; + } + + public MemberFilter (string name, int arity, MemberKind kind, AParametersCollection param, TypeSpec type) + { + Name = name; + Kind = kind; + Parameters = param; + MemberType = type; + this.Arity = arity; + } + + public static MemberFilter Constructor (AParametersCollection param) + { + return new MemberFilter (Mono.CSharp.Constructor.ConstructorName, 0, MemberKind.Constructor, param, null); + } + + public static MemberFilter Property (string name, TypeSpec type) + { + return new MemberFilter (name, 0, MemberKind.Property, null, type); + } + + public static MemberFilter Field (string name, TypeSpec type) + { + return new MemberFilter (name, 0, MemberKind.Field, null, type); + } + + public static MemberFilter Method (string name, int arity, AParametersCollection param, TypeSpec type) + { + return new MemberFilter (name, arity, MemberKind.Method, param, type); + } + + #region IEquatable Members + + public bool Equals (MemberSpec other) + { + // Is the member of the correct type ? + // TODO: Isn't this redundant ? + if ((other.Kind & Kind & MemberKind.MaskType) == 0) + return false; + + // Check arity when not disabled + if (Arity >= 0 && Arity != other.Arity) + return false; + + if (Parameters != null) { + if (other is IParametersMember) { + var other_param = ((IParametersMember) other).Parameters; + if (!TypeSpecComparer.Override.IsEqual (Parameters, other_param)) + return false; + } else { + return false; + } + } + + if (MemberType != null) { + if (other is IInterfaceMemberSpec) { + var other_type = ((IInterfaceMemberSpec) other).MemberType; + if (!TypeSpecComparer.Override.IsEqual (other_type, MemberType)) + return false; + } else { + return false; + } + } + + return true; + } + + #endregion + } + + // + // The MemberCache is the main members container used by compiler. It contains + // all members imported or defined during compilation using on demand filling + // process. Inflated containers are also using MemberCache to make inflated + // members look like normal definition. + // + // All of the methods are performance and memory sensitive as the MemberCache + // is the underlying engine of all member based operations. + // + public class MemberCache + { + [Flags] + enum StateFlags + { + HasConversionOperator = 1 << 1, + HasUserOperator = 1 << 2 + } + + readonly Dictionary> member_hash; + Dictionary locase_members; + IList missing_abstract; + StateFlags state; // TODO: Move to TypeSpec or ITypeDefinition + + public static readonly string IndexerNameAlias = ""; + + public static readonly MemberCache Empty = new MemberCache (0); + + public MemberCache () + : this (16) + { + } + + public MemberCache (int capacity) + { + member_hash = new Dictionary> (capacity); + } + + public MemberCache (MemberCache cache) + : this (cache.member_hash.Count) + { + this.state = cache.state; + } + + // + // Creates a new MemberCache for the given `container'. + // + public MemberCache (TypeContainer container) + : this () // TODO: Optimize the size + { + } + + // + // For cases where we need to union cache members + // + public void AddBaseType (TypeSpec baseType) + { + var cache = baseType.MemberCache; + + IList list; + foreach (var entry in cache.member_hash) { + if (!member_hash.TryGetValue (entry.Key, out list)) { + if (entry.Value.Count == 1) { + list = entry.Value; + } else { + list = new List (entry.Value); + } + + member_hash.Add (entry.Key, list); + continue; + } + + foreach (var ce in entry.Value) { + if (list.Contains (ce)) + continue; + + if (list is MemberSpec[]) { + list = new List () { list [0] }; + member_hash[entry.Key] = list; + } + + list.Add (ce); + } + } + } + + // + // Member-cache does not contain base members but it does + // contain all base interface members, so the Lookup code + // can use simple inheritance rules. + // + public void AddInterface (TypeSpec iface) + { + var cache = iface.MemberCache; + + IList list; + foreach (var entry in cache.member_hash) { + if (!member_hash.TryGetValue (entry.Key, out list)) { + if (entry.Value.Count == 1) { + list = entry.Value; + } else { + list = new List (entry.Value); + } + + member_hash.Add (entry.Key, list); + continue; + } + + foreach (var ce in entry.Value) { + if (list.Contains (ce)) + continue; + + if (AddInterfaceMember (ce, ref list)) + member_hash[entry.Key] = list; + } + } + + // Add also all base interfaces + if (iface.Interfaces != null) { + foreach (var base_iface in iface.Interfaces) + AddInterface (base_iface); + } + } + + public void AddMember (InterfaceMemberBase imb, string exlicitName, MemberSpec ms) + { + // Explicit names cannot be looked-up but can be used for + // collision checking (no name mangling needed) + if (imb.IsExplicitImpl) + AddMember (exlicitName, ms, false); + else + AddMember (ms); + } + + // + // Add non-explicit member to member cache + // + public void AddMember (MemberSpec ms) + { + AddMember (GetLookupName (ms), ms, false); + } + + void AddMember (string name, MemberSpec member, bool removeHiddenMembers) + { + if (member.Kind == MemberKind.Operator) { + var dt = member.DeclaringType; + switch (dt.BuiltinType) { + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Delegate: + case BuiltinTypeSpec.Type.MulticastDelegate: + // Some core types have user operators but they cannot be used as normal + // user operators as they are predefined and therefore having different + // rules (e.g. binary operators) by not setting the flag we hide them for + // user conversions + // TODO: Should I do this for all core types ? + break; + default: + if (name == Operator.GetMetadataName (Operator.OpType.Implicit) || name == Operator.GetMetadataName (Operator.OpType.Explicit)) { + state |= StateFlags.HasConversionOperator; + } else { + state |= StateFlags.HasUserOperator; + } + + break; + } + } + + IList list; + if (!member_hash.TryGetValue (name, out list)) { + member_hash.Add (name, new MemberSpec[] { member }); + return; + } + + if (removeHiddenMembers && member.DeclaringType.IsInterface) { + if (AddInterfaceMember (member, ref list)) + member_hash[name] = list; + } else { + if (list.Count == 1) { + list = new List () { list[0] }; + member_hash[name] = list; + } + + list.Add (member); + } + } + + public void AddMemberImported (MemberSpec ms) + { + AddMember (GetLookupName (ms), ms, true); + } + + // + // Ignores any base interface member which can be hidden + // by this interface + // + static bool AddInterfaceMember (MemberSpec member, ref IList existing) + { + var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : ParametersCompiled.EmptyReadOnlyParameters; + + // + // interface IA : IB { int Prop { set; } } + // interface IB { bool Prop { get; } } + // + // IB.Prop is never accessible from IA interface + // + for (int i = 0; i < existing.Count; ++i) { + var entry = existing[i]; + + if (entry.Arity != member.Arity) + continue; + + if (entry is IParametersMember) { + var entry_param = ((IParametersMember) entry).Parameters; + if (!TypeSpecComparer.Override.IsEqual (entry_param, member_param)) + continue; + } + + if (member.DeclaringType.ImplementsInterface (entry.DeclaringType, false)) { + if (existing.Count == 1) { + existing = new MemberSpec[] { member }; + return true; + } + + existing.RemoveAt (i--); + continue; + } + + if ((entry.DeclaringType == member.DeclaringType && entry.IsAccessor == member.IsAccessor) || + entry.DeclaringType.ImplementsInterface (member.DeclaringType, false)) + return false; + } + + if (existing.Count == 1) { + existing = new List () { existing[0], member }; + return true; + } + + existing.Add (member); + return false; + } + + public static MemberSpec FindMember (TypeSpec container, MemberFilter filter, BindingRestriction restrictions) + { + do { + IList applicable; + if (container.MemberCache.member_hash.TryGetValue (filter.Name, out applicable)) { + // Start from the end because interface members are in reverse order + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable [i]; + + if ((restrictions & BindingRestriction.InstanceOnly) != 0 && entry.IsStatic) + continue; + + if ((restrictions & BindingRestriction.NoAccessors) != 0 && entry.IsAccessor) + continue; + + if ((restrictions & BindingRestriction.OverrideOnly) != 0 && (entry.Modifiers & Modifiers.OVERRIDE) == 0) + continue; + + if (!filter.Equals (entry)) + continue; + + if ((restrictions & BindingRestriction.DeclaredOnly) != 0 && container.IsInterface && entry.DeclaringType != container) + continue; + + return entry; + } + } + + if ((restrictions & BindingRestriction.DeclaredOnly) != 0) + break; + + container = container.BaseType; + } while (container != null); + + return null; + } + + // + // A special method to work with member lookup only. It returns a list of all members named @name + // starting from @container. It's very performance sensitive + // + public static IList FindMembers (TypeSpec container, string name, bool declaredOnly) + { + IList applicable; + + do { + if (container.MemberCache.member_hash.TryGetValue (name, out applicable) || declaredOnly) + return applicable; + + container = container.BaseType; + } while (container != null); + + return null; + } + + // + // Finds the nested type in container + // + public static TypeSpec FindNestedType (TypeSpec container, string name, int arity) + { + IList applicable; + TypeSpec best_match = null; + do { + // TODO: Don't know how to handle this yet + // When resolving base type of nested type, parent type must have + // base type resolved to scan full hierarchy correctly + // Similarly MemberCacheTypes will inflate BaseType and Interfaces + // based on type definition + var tc = container.MemberDefinition as TypeContainer; + if (tc != null) + tc.DefineType (); + + if (container.MemberCacheTypes.member_hash.TryGetValue (name, out applicable)) { + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable[i]; + if ((entry.Kind & MemberKind.NestedMask) == 0) + continue; + + var ts = (TypeSpec) entry; + if (arity == ts.Arity) + return ts; + + if (arity < 0) { + if (best_match == null) { + best_match = ts; + } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (ts.Arity + arity)) { + best_match = ts; + } + } + } + } + + container = container.BaseType; + } while (container != null); + + return best_match; + } + + // + // Looks for extension methods with defined name and extension type + // + public List FindExtensionMethods (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity) + { + IList entries; + if (!member_hash.TryGetValue (name, out entries)) + return null; + + List candidates = null; + foreach (var entry in entries) { + if (entry.Kind != MemberKind.Method || (arity > 0 && entry.Arity != arity)) + continue; + + var ms = (MethodSpec) entry; + if (!ms.IsExtensionMethod) + continue; + + if (!ms.IsAccessible (invocationContext)) + continue; + + // + // Extension methods cannot be nested hence checking parent is enough + // + if ((ms.DeclaringType.Modifiers & Modifiers.INTERNAL) != 0 && !ms.DeclaringType.MemberDefinition.IsInternalAsPublic (invocationContext.Module.DeclaringAssembly)) + continue; + + if (candidates == null) + candidates = new List (); + candidates.Add (ms); + } + + return candidates; + } + + // + // Returns base members of @member member if no exact match is found @bestCandidate returns + // the best match + // + public static MemberSpec FindBaseMember (MemberCore member, out MemberSpec bestCandidate, ref bool overrides) + { + bestCandidate = null; + var container = member.Parent.PartialContainer.Definition; + if (!container.IsInterface) { + container = container.BaseType; + + // It can happen for a user definition of System.Object + if (container == null) + return null; + } + + string name = GetLookupName (member); + var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : null; + + var mkind = GetMemberCoreKind (member); + bool member_with_accessors = mkind == MemberKind.Indexer || mkind == MemberKind.Property; + + IList applicable; + MemberSpec ambig_candidate = null; + + do { + if (container.MemberCache.member_hash.TryGetValue (name, out applicable)) { + for (int i = 0; i < applicable.Count; ++i) { + var entry = applicable [i]; + + if ((entry.Modifiers & Modifiers.PRIVATE) != 0) + continue; + + if ((entry.Modifiers & Modifiers.AccessibilityMask) == Modifiers.INTERNAL && + !entry.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly)) + continue; + + // + // Isn't the member of same kind ? + // + if ((entry.Kind & ~MemberKind.Destructor & mkind & MemberKind.MaskType) == 0) { + // Destructors are ignored as they cannot be overridden by user + if ((entry.Kind & MemberKind.Destructor) != 0) + continue; + + // A method with different arity does not hide base member + if (mkind != MemberKind.Method && member.MemberName.Arity != entry.Arity) + continue; + + bestCandidate = entry; + return null; + } + + // + // Same kind of different arity is valid + // + if (member.MemberName.Arity != entry.Arity) { + continue; + } + + if ((entry.Kind & mkind & (MemberKind.Method | MemberKind.Indexer)) != 0) { + if (entry.IsAccessor != member is AbstractPropertyEventMethod) + continue; + + var pm = entry as IParametersMember; + if (!TypeSpecComparer.Override.IsEqual (pm.Parameters, member_param)) + continue; + } + + // + // Skip override for member with accessors. It may not fully implement the base member + // but keep flag we found an implementation in case the base member is abstract + // + if (member_with_accessors && ((entry.Modifiers & (Modifiers.OVERRIDE | Modifiers.SEALED)) == Modifiers.OVERRIDE)) { + // + // Set candidate to override implementation to flag we found an implementation + // + overrides = true; + continue; + } + + // + // For members with parameters we can encounter an ambiguous candidates (they match exactly) + // because generic type parameters could be inflated into same types + // + if (ambig_candidate == null && (entry.Kind & mkind & (MemberKind.Method | MemberKind.Indexer)) != 0) { + bestCandidate = null; + ambig_candidate = entry; + continue; + } + + bestCandidate = ambig_candidate; + return entry; + } + } + + if (container.IsInterface || ambig_candidate != null) + break; + + container = container.BaseType; + } while (container != null); + + return ambig_candidate; + } + + // + // Returns inflated version of MemberSpec, it works similarly to + // SRE TypeBuilder.GetMethod + // + public static T GetMember (TypeSpec container, T spec) where T : MemberSpec + { + IList applicable; + if (container.MemberCache.member_hash.TryGetValue (GetLookupName (spec), out applicable)) { + for (int i = applicable.Count - 1; i >= 0; i--) { + var entry = applicable[i]; + if (entry.MemberDefinition == spec.MemberDefinition) + return (T) entry; + } + } + + throw new InternalErrorException ("Missing member `{0}' on inflated type `{1}'", + spec.GetSignatureForError (), container.GetSignatureForError ()); + } + + static MemberKind GetMemberCoreKind (MemberCore member) + { + if (member is FieldBase) + return MemberKind.Field; + if (member is Indexer) + return MemberKind.Indexer; + if (member is Class) + return MemberKind.Class; + if (member is Struct) + return MemberKind.Struct; + if (member is Destructor) + return MemberKind.Destructor; + if (member is Method) + return MemberKind.Method; + if (member is Property) + return MemberKind.Property; + if (member is EventField) + return MemberKind.Event; + if (member is Interface) + return MemberKind.Interface; + if (member is EventProperty) + return MemberKind.Event; + if (member is Delegate) + return MemberKind.Delegate; + if (member is Enum) + return MemberKind.Enum; + + throw new NotImplementedException (member.GetType ().ToString ()); + } + + public static IList GetCompletitionMembers (IMemberContext ctx, TypeSpec container, string name) + { + var matches = new List (); + foreach (var entry in container.MemberCache.member_hash) { + foreach (var name_entry in entry.Value) { + if (name_entry.IsAccessor) + continue; + + if ((name_entry.Kind & (MemberKind.Constructor | MemberKind.Destructor | MemberKind.Operator)) != 0) + continue; + + if (!name_entry.IsAccessible (ctx)) + continue; + + if (name == null || name_entry.Name.StartsWith (name)) { + matches.Add (name_entry); + } + } + } + + return matches; + } + + // + // Returns members of @iface only, base members are ignored + // + public static List GetInterfaceMethods (TypeSpec iface) + { + // + // MemberCache flatten interfaces, therefore in cases like this one + // + // interface IA : IB {} + // interface IB { void Foo () } + // + // we would return Foo inside IA which is not expected in this case + // + var methods = new List (); + foreach (var entry in iface.MemberCache.member_hash.Values) { + foreach (var name_entry in entry) { + if (iface == name_entry.DeclaringType) { + if (name_entry.Kind == MemberKind.Method) { + methods.Add ((MethodSpec) name_entry); + } + } + } + } + + return methods; + } + + // + // Returns all not implememted abstract members inside abstract type + // NOTE: Returned list is shared and must not be modified + // + public static IList GetNotImplementedAbstractMethods (TypeSpec type) + { + if (type.MemberCache.missing_abstract != null) + return type.MemberCache.missing_abstract; + + var abstract_methods = new List (); + List hierarchy = null; + + // + // Stage 1: top-to-bottom scan for abstract members + // + var abstract_type = type; + while (true) { + foreach (var entry in abstract_type.MemberCache.member_hash) { + foreach (var name_entry in entry.Value) { + if ((name_entry.Modifiers & Modifiers.ABSTRACT) == 0) + continue; + + if (name_entry.Kind != MemberKind.Method) + continue; + + abstract_methods.Add ((MethodSpec) name_entry); + } + } + + var base_type = abstract_type.BaseType; + if (!base_type.IsAbstract) + break; + + if (hierarchy == null) + hierarchy = new List (); + + hierarchy.Add (abstract_type); + abstract_type = base_type; + } + + int not_implemented_count = abstract_methods.Count; + if (not_implemented_count == 0 || hierarchy == null) { + type.MemberCache.missing_abstract = abstract_methods; + return type.MemberCache.missing_abstract; + } + + // + // Stage 2: Remove already implemented methods + // + foreach (var type_up in hierarchy) { + var members = type_up.MemberCache.member_hash; + if (members.Count == 0) + continue; + + for (int i = 0; i < abstract_methods.Count; ++i) { + var candidate = abstract_methods [i]; + if (candidate == null) + continue; + + IList applicable; + if (!members.TryGetValue (candidate.Name, out applicable)) + continue; + + var filter = new MemberFilter (candidate); + foreach (var item in applicable) { + if ((item.Modifiers & (Modifiers.OVERRIDE | Modifiers.VIRTUAL)) == 0) + continue; + + if (filter.Equals (item)) { + --not_implemented_count; + abstract_methods [i] = null; + break; + } + } + } + } + + if (not_implemented_count == abstract_methods.Count) { + type.MemberCache.missing_abstract = abstract_methods; + return type.MemberCache.missing_abstract; + } + + var not_implemented = new MethodSpec[not_implemented_count]; + int counter = 0; + foreach (var m in abstract_methods) { + if (m == null) + continue; + + not_implemented[counter++] = m; + } + + type.MemberCache.missing_abstract = not_implemented; + return type.MemberCache.missing_abstract; + } + + static string GetLookupName (MemberSpec ms) + { + if (ms.Kind == MemberKind.Indexer) + return IndexerNameAlias; + + if (ms.Kind == MemberKind.Constructor) { + if (ms.IsStatic) + return Constructor.TypeConstructorName; + + return Constructor.ConstructorName; + } + + return ms.Name; + } + + static string GetLookupName (MemberCore mc) + { + if (mc is Indexer) + return IndexerNameAlias; + + if (mc is Constructor) + return Constructor.ConstructorName; + + return mc.MemberName.Name; + } + + // + // Returns all operators declared on container and its base types (until declaredOnly is used) + // + public static IList GetUserOperator (TypeSpec container, Operator.OpType op, bool declaredOnly) + { + IList found = null; + + IList applicable; + do { + var mc = container.MemberCache; + + if (((op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) && (mc.state & StateFlags.HasConversionOperator) != 0) || + (mc.state & StateFlags.HasUserOperator) != 0) { + + if (mc.member_hash.TryGetValue (Operator.GetMetadataName (op), out applicable)) { + int i; + for (i = 0; i < applicable.Count; ++i) { + if (applicable[i].Kind != MemberKind.Operator) { + break; + } + } + + // + // Handles very rare case where a method with same name as operator (op_xxxx) exists + // and we have to resize the applicable list + // + if (i != applicable.Count) { + for (i = 0; i < applicable.Count; ++i) { + if (applicable[i].Kind != MemberKind.Operator) { + continue; + } + + if (found == null) { + found = new List (); + found.Add (applicable[i]); + } else { + var prev = found as List; + if (prev == null) { + prev = new List (found.Count + 1); + prev.AddRange (found); + } + + prev.Add (applicable[i]); + } + } + } else { + if (found == null) { + found = applicable; + } else { + var merged = found as List; + if (merged == null) { + merged = new List (found.Count + applicable.Count); + merged.AddRange (found); + found = merged; + } + + merged.AddRange (applicable); + } + } + } + } + + // BaseType call can be expensive + if (declaredOnly) + break; + + container = container.BaseType; + } while (container != null); + + return found; + } + + // + // Inflates all member cache nested types + // + public void InflateTypes (MemberCache inflated_cache, TypeParameterInflator inflator) + { + foreach (var item in member_hash) { + IList inflated_members = null; + for (int i = 0; i < item.Value.Count; ++i ) { + var member = item.Value[i]; + + // FIXME: When inflating members refering nested types before they are inflated + if (member == null) + continue; + + if ((member.Kind & MemberKind.NestedMask) != 0 && + (member.Modifiers & Modifiers.COMPILER_GENERATED) == 0) { + if (inflated_members == null) { + inflated_members = new MemberSpec[item.Value.Count]; + inflated_cache.member_hash.Add (item.Key, inflated_members); + } + + inflated_members [i] = member.InflateMember (inflator); + } + } + } + } + + // + // Inflates all open type members, requires InflateTypes to be called before + // + public void InflateMembers (MemberCache cacheToInflate, TypeSpec inflatedType, TypeParameterInflator inflator) + { + var inflated_member_hash = cacheToInflate.member_hash; + Dictionary accessor_relation = null; + List accessor_members = null; + + // Copy member specific flags when all members were added + cacheToInflate.state = state; + + foreach (var item in member_hash) { + var members = item.Value; + IList inflated_members = null; + for (int i = 0; i < members.Count; ++i ) { + var member = members[i]; + + // + // All nested types have been inflated earlier except for + // compiler types which are created later and could miss InflateTypes + // + if ((member.Kind & MemberKind.NestedMask) != 0 && + (member.Modifiers & Modifiers.COMPILER_GENERATED) == 0) { + if (inflated_members == null) + inflated_members = inflated_member_hash[item.Key]; + + continue; + } + + // + // Clone the container first + // + if (inflated_members == null) { + inflated_members = new MemberSpec [item.Value.Count]; + inflated_member_hash.Add (item.Key, inflated_members); + } + + var local_inflator = inflator; + + if (member.DeclaringType != inflatedType) { + // + // Don't inflate top-level non-generic interface members + // merged into generic interface + // + if (!member.DeclaringType.IsGeneric && !member.DeclaringType.IsNested) { + inflated_members [i] = member; + continue; + } + + // + // Needed when inflating flatten interfaces. It inflates + // container type only, type parameters are already done + // + // Handles cases like: + // + // interface I {} + // interface I : I {} + // + // class C: I {} + // + var inflated_parent = inflator.Inflate (member.DeclaringType); + if (inflated_parent != inflator.TypeInstance) + local_inflator = new TypeParameterInflator (inflator, inflated_parent); + } + + // + // Inflate every member, its parent is now different + // + var inflated = member.InflateMember (local_inflator); + inflated_members [i] = inflated; + + if (member is PropertySpec || member is EventSpec) { + if (accessor_members == null) + accessor_members = new List (); + + accessor_members.Add (inflated); + continue; + } + + if (member.IsAccessor) { + if (accessor_relation == null) + accessor_relation = new Dictionary (); + accessor_relation.Add (member, (MethodSpec) inflated); + } + } + } + + if (accessor_members != null) { + foreach (var member in accessor_members) { + var prop = member as PropertySpec; + if (prop != null) { + if (prop.Get != null) + prop.Get = accessor_relation[prop.Get]; + if (prop.Set != null) + prop.Set = accessor_relation[prop.Set]; + + continue; + } + + var ev = (EventSpec) member; + ev.AccessorAdd = accessor_relation[ev.AccessorAdd]; + ev.AccessorRemove = accessor_relation[ev.AccessorRemove]; + } + } + } + + // + // Removes hidden base members of an interface. For compiled interfaces we cannot + // do name filtering during Add (as we do for import) because we need all base + // names to be valid during type definition. + // Add replaces hidden base member with current one which means any name collision + // (CS0108) of non-first name would be unnoticed because the name was replaced + // with the one from compiled type + // + public void RemoveHiddenMembers (TypeSpec container) + { + foreach (var entry in member_hash) { + var values = entry.Value; + + int container_members_start_at = 0; + while (values[container_members_start_at].DeclaringType != container && ++container_members_start_at < entry.Value.Count); + + if (container_members_start_at == 0 || container_members_start_at == values.Count) + continue; + + for (int i = 0; i < container_members_start_at; ++i) { + var member = values[i]; + + if (!container.ImplementsInterface (member.DeclaringType, false)) + continue; + + var member_param = member is IParametersMember ? ((IParametersMember) member).Parameters : ParametersCompiled.EmptyReadOnlyParameters; + + for (int ii = container_members_start_at; ii < values.Count; ++ii) { + var container_entry = values[ii]; + + if (container_entry.Arity != member.Arity) + continue; + + if (container_entry is IParametersMember) { + if (!TypeSpecComparer.Override.IsEqual (((IParametersMember) container_entry).Parameters, member_param)) + continue; + } + + values.RemoveAt (i); + --container_members_start_at; + --ii; + --i; + } + } + } + } + + // + // Checks all appropriate container members for CLS compliance + // + public void VerifyClsCompliance (TypeSpec container, Report report) + { + if (locase_members != null) + return; + + if (container.BaseType == null) { + locase_members = new Dictionary (member_hash.Count); // StringComparer.OrdinalIgnoreCase); + } else { + container.BaseType.MemberCache.VerifyClsCompliance (container.BaseType, report); + locase_members = new Dictionary (container.BaseType.MemberCache.locase_members); //, StringComparer.OrdinalIgnoreCase); + } + + var is_imported_type = container.MemberDefinition.IsImported; + foreach (var entry in container.MemberCache.member_hash) { + for (int i = 0; i < entry.Value.Count; ++i ) { + var name_entry = entry.Value[i]; + if ((name_entry.Modifiers & (Modifiers.PUBLIC | Modifiers.PROTECTED)) == 0) + continue; + + if ((name_entry.Modifiers & (Modifiers.OVERRIDE | Modifiers.COMPILER_GENERATED)) != 0) + continue; + + if ((name_entry.Kind & MemberKind.MaskType) == 0) + continue; + + 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) { + var p_a_pd = p_a.Parameters; + for (int ii = i + 1; ii < entry.Value.Count; ++ii) { + var checked_entry = entry.Value[ii]; + IParametersMember p_b = checked_entry as IParametersMember; + if (p_b == null) + continue; + + if (p_a_pd.Count != p_b.Parameters.Count) + continue; + + if (checked_entry.IsAccessor) + continue; + + 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 ()); + } + } + } + } + } + + if (i > 0 || name_entry.Kind == MemberKind.Constructor || name_entry.Kind == MemberKind.Indexer) + continue; + + var name_entry_locase = name_entry.Name.ToLowerInvariant (); + + MemberSpec[] found; + if (!locase_members.TryGetValue (name_entry_locase, out found)) { + found = new MemberSpec[] { name_entry }; + locase_members.Add (name_entry_locase, found); + } else { + bool same_names_only = true; + foreach (var f in found) { + if (f.Name == name_entry.Name) + continue; + +// if (f.IsAccessor && name_entry.IsAccessor) +// continue; + + same_names_only = false; + if (!is_imported_type) { + var last = GetLaterDefinedMember (f, name_entry); + if (last == f.MemberDefinition) { + report.SymbolRelatedToPreviousError (name_entry); + } else { + report.SymbolRelatedToPreviousError (f); + } + + report.Warning (3005, 1, last.Location, + "Identifier `{0}' differing only in case is not CLS-compliant", last.GetSignatureForError ()); + } + } + + if (!same_names_only) { + Array.Resize (ref found, found.Length + 1); + found[found.Length - 1] = name_entry; + locase_members[name_entry_locase] = found; + } + } + } + } + } + + // + // Local report helper to issue correctly ordered members stored in hashtable + // + static MemberCore GetLaterDefinedMember (MemberSpec a, MemberSpec b) + { + var mc_a = a.MemberDefinition as MemberCore; + var mc_b = b.MemberDefinition as MemberCore; + if (mc_a == null) + return mc_b; + + if (mc_b == null) + return mc_a; + + 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; + } + + public bool CheckExistingMembersOverloads (MemberCore member, AParametersCollection parameters) + { + var name = GetLookupName (member); + var imb = member as InterfaceMemberBase; + if (imb != null && imb.IsExplicitImpl) { + name = imb.GetFullName (name); + } + + return CheckExistingMembersOverloads (member, name, parameters); + } + + public bool CheckExistingMembersOverloads (MemberCore member, string name, AParametersCollection parameters) + { + IList entries; + if (!member_hash.TryGetValue (name, out entries)) + return false; + + var Report = member.Compiler.Report; + + int method_param_count = parameters.Count; + for (int i = entries.Count - 1; i >= 0; --i) { + var ce = entries[i]; + var pm = ce as IParametersMember; + var pd = pm == null ? ParametersCompiled.EmptyReadOnlyParameters : pm.Parameters; + if (pd.Count != method_param_count) + continue; + + if (ce.Arity != member.MemberName.Arity) + continue; + + // Ignore merged interface members + if (member.Parent.PartialContainer != ce.DeclaringType.MemberDefinition) + continue; + + var p_types = pd.Types; + if (method_param_count > 0) { + int ii = method_param_count - 1; + TypeSpec type_a, type_b; + do { + type_a = parameters.Types [ii]; + type_b = p_types [ii]; + + if ((pd.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF) != + (parameters.FixedParameters [ii].ModFlags & Parameter.Modifier.ISBYREF)) + break; + + } while (TypeSpecComparer.Override.IsEqual (type_a, type_b) && ii-- != 0); + + if (ii >= 0) + continue; + + // + // Operators can differ in return type only + // + if (member is Operator && ce.Kind == MemberKind.Operator && ((MethodSpec) ce).ReturnType != ((Operator) member).ReturnType) + continue; + + // + // Report difference in parameter modifiers only + // + if (pd != null && member is MethodCore) { + ii = method_param_count; + while (ii-- != 0 && parameters.FixedParameters[ii].ModFlags == pd.FixedParameters[ii].ModFlags && + parameters.ExtensionMethodType == pd.ExtensionMethodType) ; + + if (ii >= 0) { + var mc = ce as MethodSpec; + member.Compiler.Report.SymbolRelatedToPreviousError (ce); + if ((member.ModFlags & Modifiers.PARTIAL) != 0 && (mc.Modifiers & Modifiers.PARTIAL) != 0) { + if (parameters.HasParams || pd.HasParams) { + Report.Error (758, member.Location, + "A partial method declaration and partial method implementation cannot differ on use of `params' modifier"); + } else { + Report.Error (755, member.Location, + "A partial method declaration and partial method implementation must be both an extension method or neither"); + } + } else if (member is Constructor) { + Report.Error (851, member.Location, + "Overloaded contructor `{0}' cannot differ on use of parameter modifiers only", + member.GetSignatureForError ()); + } else { + Report.Error (663, member.Location, + "Overloaded method `{0}' cannot differ on use of parameter modifiers only", + member.GetSignatureForError ()); + } + return false; + } + } + } + + if ((ce.Kind & MemberKind.Method) != 0) { + Method method_a = member as Method; + Method method_b = ce.MemberDefinition as Method; + if (method_a != null && method_b != null && (method_a.ModFlags & method_b.ModFlags & Modifiers.PARTIAL) != 0) { + const Modifiers partial_modifiers = Modifiers.STATIC | Modifiers.UNSAFE; + if (method_a.IsPartialDefinition == method_b.IsPartialImplementation) { + if ((method_a.ModFlags & partial_modifiers) == (method_b.ModFlags & partial_modifiers) || + method_a.Parent.IsUnsafe && method_b.Parent.IsUnsafe) { + if (method_a.IsPartialImplementation) { + method_a.SetPartialDefinition (method_b); + if (entries.Count == 1) + member_hash.Remove (name); + else + entries.RemoveAt (i); + } else { + method_b.SetPartialDefinition (method_a); + method_a.caching_flags |= MemberCore.Flags.PartialDefinitionExists; + } + continue; + } + + if (method_a.IsStatic != method_b.IsStatic) { + Report.SymbolRelatedToPreviousError (ce); + Report.Error (763, member.Location, + "A partial method declaration and partial method implementation must be both `static' or neither"); + } + + Report.SymbolRelatedToPreviousError (ce); + Report.Error (764, member.Location, + "A partial method declaration and partial method implementation must be both `unsafe' or neither"); + return false; + } + + Report.SymbolRelatedToPreviousError (ce); + if (method_a.IsPartialDefinition) { + Report.Error (756, member.Location, "A partial method `{0}' declaration is already defined", + member.GetSignatureForError ()); + } + + Report.Error (757, member.Location, "A partial method `{0}' implementation is already defined", + member.GetSignatureForError ()); + return false; + } + + Report.SymbolRelatedToPreviousError (ce); + + bool is_reserved_a = member is AbstractPropertyEventMethod || member is Operator; + bool is_reserved_b = ((MethodSpec) ce).IsReservedMethod; + + if (is_reserved_a || is_reserved_b) { + Report.Error (82, member.Location, "A member `{0}' is already reserved", + is_reserved_a ? + ce.GetSignatureForError () : + member.GetSignatureForError ()); + return false; + } + } else { + Report.SymbolRelatedToPreviousError (ce); + } + + if (member is Operator && ce.Kind == MemberKind.Operator) { + Report.Error (557, member.Location, "Duplicate user-defined conversion in type `{0}'", + member.Parent.GetSignatureForError ()); + return false; + } + + Report.Error (111, member.Location, + "A member `{0}' is already defined. Rename this member or use different parameter types", + member.GetSignatureForError ()); + return false; + } + + return true; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs new file mode 100644 index 0000000000..75998515ac --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs @@ -0,0 +1,2691 @@ +// +// method.cs: Method based declarations +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// 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 +// + +using System; +using System.Collections.Generic; +using System.Security; +using System.Security.Permissions; +using System.Text; +using System.Linq; + +#if NET_2_1 +using XmlElement = System.Object; +#else +using System.Xml; +#endif + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using SecurityType = System.Collections.Generic.List; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using SecurityType = System.Collections.Generic.Dictionary; +using System.Reflection; +using System.Reflection.Emit; +#endif + +using Mono.CompilerServices.SymbolWriter; + +namespace Mono.CSharp { + + public abstract class MethodCore : InterfaceMemberBase, IParametersMember + { + protected ParametersCompiled parameters; + protected ToplevelBlock block; + protected MethodSpec spec; + + public MethodCore (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, + MemberName name, Attributes attrs, ParametersCompiled parameters) + : base (parent, generic, type, mod, allowed_mod, name, attrs) + { + this.parameters = parameters; + } + + public override Variance ExpectedMemberTypeVariance { + get { + return Variance.Covariant; + } + } + + // + // Returns the System.Type array for the parameters of this method + // + public TypeSpec [] ParameterTypes { + get { + return parameters.Types; + } + } + + public ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + AParametersCollection IParametersMember.Parameters { + get { return parameters; } + } + + public ToplevelBlock Block { + get { + return block; + } + + set { + block = value; + } + } + + public CallingConventions CallingConventions { + get { + CallingConventions cc = parameters.CallingConvention; + if (!IsInterface) + if ((ModFlags & Modifiers.STATIC) == 0) + cc |= CallingConventions.HasThis; + + // FIXME: How is `ExplicitThis' used in C#? + + return cc; + } + } + + protected override bool CheckOverrideAgainstBase (MemberSpec base_member) + { + bool res = base.CheckOverrideAgainstBase (base_member); + + // + // Check that the permissions are not being changed + // + if (!CheckAccessModifiers (this, base_member)) { + Error_CannotChangeAccessModifiers (this, base_member); + res = false; + } + + return res; + } + + protected override bool CheckBase () + { + // Check whether arguments were correct. + if (!DefineParameters (parameters)) + return false; + + return base.CheckBase (); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader + { + get { return "M:"; } + } + + public override void Emit () + { + if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) { + parameters.CheckConstraints (this); + } + + base.Emit (); + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + if (overload is MethodCore) { + caching_flags |= Flags.MethodOverloadsExist; + return true; + } + + if (overload is AbstractPropertyEventMethod) + return true; + + return base.EnableOverloadChecks (overload); + } + + public override string GetSignatureForDocumentation () + { + string s = base.GetSignatureForDocumentation (); + if (MemberName.Arity > 0) + s += "``" + MemberName.Arity.ToString (); + + return s + parameters.GetSignatureForDocumentation (); + } + + public MethodSpec Spec { + get { return spec; } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (parameters.HasArglist) { + Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant"); + } + + if (member_type != null && !member_type.IsCLSCompliant ()) { + Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + + parameters.VerifyClsCompliance (this); + return true; + } + } + + public interface IGenericMethodDefinition : IMemberDefinition + { + TypeParameterSpec[] TypeParameters { get; } + int TypeParametersCount { get; } + +// MethodInfo MakeGenericMethod (TypeSpec[] targs); + } + + public sealed class MethodSpec : MemberSpec, IParametersMember + { + MethodBase metaInfo, inflatedMetaInfo; + AParametersCollection parameters; + TypeSpec returnType; + + TypeSpec[] targs; + TypeParameterSpec[] constraints; + + public MethodSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition details, TypeSpec returnType, + MethodBase info, AParametersCollection parameters, Modifiers modifiers) + : base (kind, declaringType, details, modifiers) + { + this.metaInfo = info; + this.parameters = parameters; + this.returnType = returnType; + } + + #region Properties + + public override int Arity { + get { + return IsGeneric ? GenericDefinition.TypeParametersCount : 0; + } + } + + public TypeParameterSpec[] Constraints { + get { + if (constraints == null && IsGeneric) + constraints = GenericDefinition.TypeParameters; + + return constraints; + } + } + + public bool IsConstructor { + get { + return Kind == MemberKind.Constructor; + } + } + + public IGenericMethodDefinition GenericDefinition { + get { + return (IGenericMethodDefinition) definition; + } + } + + public bool IsExtensionMethod { + get { + return IsStatic && parameters.HasExtensionMethodType; + } + } + + public bool IsSealed { + get { + return (Modifiers & Modifiers.SEALED) != 0; + } + } + + // When is virtual or abstract + public bool IsVirtual { + get { + return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0; + } + } + + public bool IsReservedMethod { + get { + return Kind == MemberKind.Operator || IsAccessor; + } + } + + TypeSpec IInterfaceMemberSpec.MemberType { + get { + return returnType; + } + } + + public AParametersCollection Parameters { + get { + return parameters; + } + } + + public TypeSpec ReturnType { + get { + return returnType; + } + } + + public TypeSpec[] TypeArguments { + get { + return targs; + } + } + + #endregion + + public MethodSpec GetGenericMethodDefinition () + { + if (!IsGeneric && !DeclaringType.IsGeneric) + return this; + + return MemberCache.GetMember (declaringType, this); + } + + public MethodBase GetMetaInfo () + { + // + // inflatedMetaInfo is extra field needed for cases where we + // inflate method but another nested type can later inflate + // again (the cache would be build with inflated metaInfo) and + // TypeBuilder can work with method definitions only + // + if (inflatedMetaInfo == null) { + if ((state & StateFlags.PendingMetaInflate) != 0) { + var dt_meta = DeclaringType.GetMetaInfo (); + + if (DeclaringType.IsTypeBuilder) { + if (IsConstructor) + inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) metaInfo); + else + inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) metaInfo); + } else { +#if STATIC + // it should not be reached + throw new NotImplementedException (); +#else + inflatedMetaInfo = MethodInfo.GetMethodFromHandle (metaInfo.MethodHandle, dt_meta.TypeHandle); +#endif + } + + state &= ~StateFlags.PendingMetaInflate; + } else { + inflatedMetaInfo = metaInfo; + } + } + + if ((state & StateFlags.PendingMakeMethod) != 0) { + var sre_targs = new MetaType[targs.Length]; + for (int i = 0; i < sre_targs.Length; ++i) + sre_targs[i] = targs[i].GetMetaInfo (); + + inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs); + state &= ~StateFlags.PendingMakeMethod; + } + + return inflatedMetaInfo; + } + + public override string GetSignatureForDocumentation () + { + string name; + switch (Kind) { + case MemberKind.Constructor: + name = "#ctor"; + break; + case MemberKind.Method: + if (Arity > 0) + name = Name + "``" + Arity.ToString (); + else + name = Name; + + break; + default: + name = Name; + break; + } + + name = DeclaringType.GetSignatureForDocumentation () + "." + name + parameters.GetSignatureForDocumentation (); + if (Kind == MemberKind.Operator) { + var op = Operator.GetType (Name).Value; + if (op == Operator.OpType.Explicit || op == Operator.OpType.Implicit) { + name += "~" + ReturnType.GetSignatureForDocumentation (); + } + } + + return name; + } + + public override string GetSignatureForError () + { + string name; + if (IsConstructor) { + name = DeclaringType.GetSignatureForError () + "." + DeclaringType.Name; + } else if (Kind == MemberKind.Operator) { + var op = Operator.GetType (Name).Value; + if (op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) { + name = DeclaringType.GetSignatureForError () + "." + Operator.GetName (op) + " operator " + returnType.GetSignatureForError (); + } else { + name = DeclaringType.GetSignatureForError () + ".operator " + Operator.GetName (op); + } + } else if (IsAccessor) { + int split = Name.IndexOf ('_'); + name = Name.Substring (split + 1); + var postfix = Name.Substring (0, split); + if (split == 3) { + var pc = parameters.Count; + if (pc > 0 && postfix == "get") { + name = "this" + parameters.GetSignatureForError ("[", "]", pc); + } else if (pc > 1 && postfix == "set") { + name = "this" + parameters.GetSignatureForError ("[", "]", pc - 1); + } + } + + return DeclaringType.GetSignatureForError () + "." + name + "." + postfix; + } else { + name = base.GetSignatureForError (); + if (targs != null) + name += "<" + TypeManager.CSharpName (targs) + ">"; + else if (IsGeneric) + name += "<" + TypeManager.CSharpName (GenericDefinition.TypeParameters) + ">"; + } + + return name + parameters.GetSignatureForError (); + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var ms = (MethodSpec) base.InflateMember (inflator); + ms.inflatedMetaInfo = null; + ms.returnType = inflator.Inflate (returnType); + ms.parameters = parameters.Inflate (inflator); + if (IsGeneric) + ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints); + + return ms; + } + + public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs) + { + if (targs == null) + throw new ArgumentNullException (); +// TODO MemberCache +// if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance)) +// return ginstance; + + //if (generic_intances == null) + // generic_intances = new Dictionary (TypeSpecArrayComparer.Default); + + var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs); + + var inflated = (MethodSpec) MemberwiseClone (); + inflated.declaringType = inflator.TypeInstance; + inflated.returnType = inflator.Inflate (returnType); + inflated.parameters = parameters.Inflate (inflator); + inflated.targs = targs; + inflated.constraints = TypeParameterSpec.InflateConstraints (inflator, constraints ?? GenericDefinition.TypeParameters); + inflated.state |= StateFlags.PendingMakeMethod; + + // if (inflated.parent == null) + // inflated.parent = parent; + + //generic_intances.Add (targs, inflated); + return inflated; + } + + public MethodSpec Mutate (TypeParameterMutator mutator) + { + var targs = TypeArguments; + if (targs != null) + targs = mutator.Mutate (targs); + + var decl = DeclaringType; + if (DeclaringType.IsGenericOrParentIsGeneric) { + decl = mutator.Mutate (decl); + } + + if (targs == TypeArguments && decl == DeclaringType) + return this; + + var ms = (MethodSpec) MemberwiseClone (); + if (decl != DeclaringType) { + ms.inflatedMetaInfo = null; + ms.declaringType = decl; + ms.state |= StateFlags.PendingMetaInflate; + } + + if (targs != null) { + ms.targs = targs; + ms.state |= StateFlags.PendingMakeMethod; + } + + return ms; + } + + public override List ResolveMissingDependencies () + { + var missing = returnType.ResolveMissingDependencies (); + foreach (var pt in parameters.Types) { + var m = pt.GetMissingDependencies (); + if (m == null) + continue; + + if (missing == null) + missing = new List (); + + missing.AddRange (m); + } + + return missing; + } + + public void SetMetaInfo (MethodInfo info) + { + if (this.metaInfo != null) + throw new InternalErrorException ("MetaInfo reset"); + + this.metaInfo = info; + } + } + + public abstract class MethodOrOperator : MethodCore, IMethodData + { + public MethodBuilder MethodBuilder; + ReturnParameter return_attributes; + SecurityType declarative_security; + protected MethodData MethodData; + + static readonly string[] attribute_targets = new string [] { "method", "return" }; + + protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, Modifiers mod, + Modifiers allowed_mod, MemberName name, + Attributes attrs, ParametersCompiled parameters) + : base (parent, generic, type, mod, allowed_mod, name, + attrs, parameters) + { + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.ReturnValue) { + if (return_attributes == null) + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + if (a.Type == pa.MethodImpl) { + is_external_implementation = a.IsInternalCall (); + } + + if (a.Type == pa.DllImport) { + const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC; + if ((ModFlags & extern_static) != extern_static) { + Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'"); + } + is_external_implementation = true; + } + + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (MethodBuilder != null) + MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method; + } + } + + protected override bool CheckForDuplications () + { + return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); + } + + public virtual EmitContext CreateEmitContext (ILGenerator ig) + { + return new EmitContext (this, ig, MemberType); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!CheckBase ()) + return false; + + MemberKind kind; + if (this is Operator) + kind = MemberKind.Operator; + else if (this is Destructor) + kind = MemberKind.Destructor; + else + kind = MemberKind.Method; + + if (IsPartialDefinition) { + caching_flags &= ~Flags.Excluded_Undetected; + caching_flags |= Flags.Excluded; + + // Add to member cache only when a partial method implementation has not been found yet + if ((caching_flags & Flags.PartialDefinitionExists) == 0) { +// MethodBase mb = new PartialMethodDefinitionInfo (this); + + spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, null, parameters, ModFlags); + if (MemberName.Arity > 0) { + spec.IsGeneric = true; + + // TODO: Have to move DefineMethod after Define (ideally to Emit) + throw new NotImplementedException ("Generic partial methods"); + } + + Parent.MemberCache.AddMember (spec); + } + + return true; + } + + MethodData = new MethodData ( + this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method); + + if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report)) + return false; + + MethodBuilder = MethodData.MethodBuilder; + + spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, MethodBuilder, parameters, ModFlags); + if (MemberName.Arity > 0) + spec.IsGeneric = true; + + Parent.MemberCache.AddMember (this, MethodBuilder.Name, spec); + + return true; + } + + protected override void DoMemberTypeIndependentChecks () + { + base.DoMemberTypeIndependentChecks (); + + CheckAbstractAndExtern (block != null); + + if ((ModFlags & Modifiers.PARTIAL) != 0) { + for (int i = 0; i < parameters.Count; ++i) { + IParameterData p = parameters.FixedParameters [i]; + if (p.ModFlags == Parameter.Modifier.OUT) { + Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier", + GetSignatureForError ()); + } + + if (p.HasDefaultValue && IsPartialImplementation) + ((Parameter) p).Warning_UselessOptionalParameter (Report); + } + } + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + if (MemberType.IsStatic) { + Error_StaticReturnType (); + } + } + + public override void Emit () + { + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder); + if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder); + + if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.HasDynamicElement) { + return_attributes = new ReturnParameter (this, MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location); + } + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + MethodBuilder.__AddDeclarativeSecurity (de); +#else + MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + + if (type_expr != null) + ConstraintChecker.Check (this, member_type, type_expr.Location); + + base.Emit (); + + if (MethodData != null) + MethodData.Emit (Parent); + + Block = null; + MethodData = null; + } + + protected void Error_ConditionalAttributeIsNotValid () + { + Report.Error (577, Location, + "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation", + GetSignatureForError ()); + } + + public bool IsPartialDefinition { + get { + return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null; + } + } + + public bool IsPartialImplementation { + get { + return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #region IMethodData Members + + bool IMethodData.IsAccessor { + get { + return false; + } + } + + public TypeSpec ReturnType { + get { + return MemberType; + } + } + + public MemberName MethodName { + get { + return MemberName; + } + } + + /// + /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded). + /// + public override string[] ConditionalConditions () + { + if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0) + return null; + + if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.Excluded) != 0) + return new string [0]; + + caching_flags &= ~Flags.Excluded_Undetected; + string[] conditions; + + if (base_method == null) { + if (OptAttributes == null) + return null; + + Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional); + if (attrs == null) + return null; + + conditions = new string[attrs.Length]; + for (int i = 0; i < conditions.Length; ++i) + conditions[i] = attrs[i].GetConditionalAttributeValue (); + } else { + conditions = base_method.MemberDefinition.ConditionalConditions(); + } + + if (conditions != null) + caching_flags |= Flags.Excluded; + + return conditions; + } + + GenericMethod IMethodData.GenericMethod { + get { + return GenericMethod; + } + } + + public virtual void EmitExtraSymbolInfo (SourceMethod source) + { } + + #endregion + + } + + public class SourceMethod : IMethodDef + { + MethodBase method; + SourceMethodBuilder builder; + + protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file) + { + this.method = method; + + builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this); + } + + public string Name { + get { return method.Name; } + } + + public int Token { + get { + MethodToken token; + var mb = method as MethodBuilder; + if (mb != null) + token = mb.GetToken (); + else + token = ((ConstructorBuilder) method).GetToken (); +#if STATIC + if (token.IsPseudoToken) + return ((ModuleBuilder) method.Module).ResolvePseudoToken (token.Token); +#endif + return token.Token; + } + } + + public void CloseMethod () + { + SymbolWriter.CloseMethod (); + } + + public void SetRealMethodName (string name) + { + if (builder != null) + builder.SetRealMethodName (name); + } + + public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block) + { + if (!SymbolWriter.HasSymbolWriter) + return null; + if (block == null) + return null; + + Location start_loc = block.StartLocation; + if (start_loc.IsNull) + return null; + + ICompileUnit compile_unit = start_loc.CompilationUnit; + if (compile_unit == null) + return null; + + return new SourceMethod (parent, method, compile_unit); + } + } + + public class Method : MethodOrOperator, IGenericMethodDefinition + { + Method partialMethodImplementation; + + public Method (DeclSpace parent, GenericMethod generic, + FullNamedExpression return_type, Modifiers mod, + MemberName name, ParametersCompiled parameters, Attributes attrs) + : base (parent, generic, return_type, mod, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct | Modifiers.ASYNC : + AllowedModifiersClass | Modifiers.ASYNC, + name, attrs, parameters) + { + } + + protected Method (DeclSpace parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod, + MemberName name, ParametersCompiled parameters, Attributes attrs) + : base (parent, null, return_type, mod, amod, name, attrs, parameters) + { + } + + #region Properties + + public override TypeParameter[] CurrentTypeParameters { + get { + if (GenericMethod != null) + return GenericMethod.CurrentTypeParameters; + + return null; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + // TODO: Cache this + return CurrentTypeParameters.Select (l => l.Type).ToArray (); + } + } + + public int TypeParametersCount { + get { + return CurrentTypeParameters == null ? 0 : CurrentTypeParameters.Length; + } + } + +#endregion + + public override string GetSignatureForError() + { + return base.GetSignatureForError () + parameters.GetSignatureForError (); + } + + void Error_DuplicateEntryPoint (Method b) + { + Report.Error (17, b.Location, + "Program `{0}' has more than one entry point defined: `{1}'", + b.Module.Builder.ScopeName, b.GetSignatureForError ()); + } + + bool IsEntryPoint () + { + if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int) + return false; + + if (parameters.IsEmpty) + return true; + + if (parameters.Count > 1) + return false; + + var ac = parameters.Types [0] as ArrayContainer; + return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String && + (parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE; + } + + public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + if (arity == 0) { + TypeParameter[] tp = CurrentTypeParameters; + if (tp != null) { + TypeParameter t = TypeParameter.FindTypeParameter (tp, name); + if (t != null) + return new TypeParameterExpr (t, loc); + } + } + + return base.LookupNamespaceOrType (name, arity, mode, loc); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.Conditional) { + if (IsExplicitImpl) { + Error_ConditionalAttributeIsNotValid (); + return; + } + + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ()); + return; + } + + if (ReturnType.Kind != MemberKind.Void) { + Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ()); + return; + } + + if (IsInterface) { + Report.Error (582, Location, "Conditional not valid on interface members"); + return; + } + + if (MethodData.implementing != null) { + Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType); + Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'", + GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing)); + return; + } + + for (int i = 0; i < parameters.Count; ++i) { + if (parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) { + Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ()); + return; + } + } + } + + if (a.Type == pa.Extension) { + a.Error_MisusedExtensionAttribute (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected virtual void DefineTypeParameters () + { + var tparams = CurrentTypeParameters; + + TypeParameterSpec[] base_tparams = null; + TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes; + TypeSpec[] base_targs = TypeSpec.EmptyTypes; + if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) { + if (base_method != null) { + base_tparams = base_method.GenericDefinition.TypeParameters; + + if (base_method.DeclaringType.IsGeneric) { + base_decl_tparams = base_method.DeclaringType.MemberDefinition.TypeParameters; + + var base_type_parent = CurrentType; + while (base_type_parent.BaseType != base_method.DeclaringType) { + base_type_parent = base_type_parent.BaseType; + } + + base_targs = base_type_parent.BaseType.TypeArguments; + } + + if (base_method.IsGeneric) { + ObsoleteAttribute oa; + foreach (var base_tp in base_tparams) { + oa = base_tp.BaseType.GetAttributeObsolete (); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, base_tp.BaseType.GetSignatureForError (), Location, Report); + } + + if (base_tp.InterfacesDefined != null) { + foreach (var iface in base_tp.InterfacesDefined) { + oa = iface.GetAttributeObsolete (); + if (oa != null) { + AttributeTester.Report_ObsoleteMessage (oa, iface.GetSignatureForError (), Location, Report); + } + } + } + } + + if (base_decl_tparams.Length != 0) { + base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray (); + base_targs = base_targs.Concat (tparams.Select (l => l.Type)).ToArray (); + } else { + base_decl_tparams = base_tparams; + base_targs = tparams.Select (l => l.Type).ToArray (); + } + } + } else if (MethodData.implementing != null) { + base_tparams = MethodData.implementing.GenericDefinition.TypeParameters; + if (MethodData.implementing.DeclaringType.IsGeneric) { + base_decl_tparams = MethodData.implementing.DeclaringType.MemberDefinition.TypeParameters; + foreach (var iface in Parent.CurrentType.Interfaces) { + if (iface == MethodData.implementing.DeclaringType) { + base_targs = iface.TypeArguments; + break; + } + } + } + } + } + + for (int i = 0; i < tparams.Length; ++i) { + var tp = tparams[i]; + + if (!tp.ResolveConstraints (this)) + continue; + + // + // Copy base constraints for override/explicit methods + // + if (base_tparams != null) { + var base_tparam = base_tparams[i]; + var local_tparam = tp.Type; + local_tparam.SpecialConstraint = base_tparam.SpecialConstraint; + + var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs); + base_tparam.InflateConstraints (inflator, local_tparam); + + // + // Check all type argument constraints for possible collision + // introduced by inflating inherited constraints in this context + // + // Conflict example: + // + // class A { virtual void Foo () where U : class, T {} } + // class B : A { override void Foo {} } + // + var local_tparam_targs = local_tparam.TypeArguments; + 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); + } + } + } + + 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 ()); + } + } + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + // + // Creates the type + // + public override bool Define () + { + if (!base.Define ()) + return false; + + if (member_type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) { + Report.Warning (465, 1, Location, + "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?"); + } + + if (partialMethodImplementation != null && IsPartialDefinition) + MethodBuilder = partialMethodImplementation.MethodBuilder; + + if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) { + Error1599 (Location, ReturnType, Report); + return false; + } + + if (CurrentTypeParameters == null) { + if (base_method != null) { + if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && Name == "Equals") + Parent.PartialContainer.Mark_HasEquals (); + else if (parameters.IsEmpty && Name == "GetHashCode") + Parent.PartialContainer.Mark_HasGetHashCode (); + } + + } else { + DefineTypeParameters (); + } + + if (block != null) { + if (block.IsIterator) { + // + // Current method is turned into automatically generated + // wrapper which creates an instance of iterator + // + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + ModFlags |= Modifiers.DEBUGGER_HIDDEN; + } + + if ((ModFlags & Modifiers.ASYNC) != 0) { + AsyncInitializer.Create (block, parameters, Parent.PartialContainer, ReturnType, Location); + } + } + + if ((ModFlags & Modifiers.STATIC) == 0) + return true; + + if (parameters.HasExtensionMethodType) { + if (Parent.PartialContainer.IsStatic && !Parent.IsGeneric) { + if (!Parent.IsTopLevel) + Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class", + GetSignatureForError ()); + + 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", + GetSignatureForError ()); + } + + ModFlags |= Modifiers.METHOD_EXTENSION; + Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION; + Spec.DeclaringType.SetExtensionMethodContainer (); + Parent.Module.HasExtensionMethod = true; + } else { + Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class", + GetSignatureForError ()); + } + } + + // + // This is used to track the Entry Point, + // + var settings = Compiler.Settings; + if (settings.NeedsEntryPoint && Name == "Main" && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) { + if (IsEntryPoint ()) { + if (Parent.DeclaringAssembly.EntryPoint == null) { + if (Parent.IsGeneric || MemberName.IsGeneric) { + Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type", + GetSignatureForError ()); + } else { + SetIsUsed (); + Parent.DeclaringAssembly.EntryPoint = this; + } + } else { + Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint); + Error_DuplicateEntryPoint (this); + } + } else { + Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point", + GetSignatureForError ()); + } + } + + return true; + } + + // + // Emits the code + // + public override void Emit () + { + try { + if (IsPartialDefinition) { + // + // Use partial method implementation builder for partial method declaration attributes + // + if (partialMethodImplementation != null) { + MethodBuilder = partialMethodImplementation.MethodBuilder; + } + + return; + } + + if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) { + Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration", + GetSignatureForError ()); + } + + if (CurrentTypeParameters != null) { + for (int i = 0; i < CurrentTypeParameters.Length; ++i) { + var tp = CurrentTypeParameters [i]; + tp.CheckGenericConstraints (false); + tp.Emit (); + } + } + + base.Emit (); + + if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0) + Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder); + } catch { + Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}", + Location, MethodBuilder); + throw; + } + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + // TODO: It can be deleted when members will be defined in correct order + if (overload is Operator) + return overload.EnableOverloadChecks (this); + + if (overload is Indexer) + return false; + + return base.EnableOverloadChecks (overload); + } + + public static void Error1599 (Location loc, TypeSpec t, Report Report) + { + Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t)); + } + + protected override bool ResolveMemberType () + { + if (GenericMethod != null) { + MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags); + if (!GenericMethod.Define (this)) + return false; + } + + return base.ResolveMemberType (); + } + + public void SetPartialDefinition (Method methodDefinition) + { + caching_flags |= Flags.PartialDefinitionExists; + methodDefinition.partialMethodImplementation = this; + + // Ensure we are always using method declaration parameters + for (int i = 0; i < methodDefinition.parameters.Count; ++i ) { + parameters [i].Name = methodDefinition.parameters [i].Name; + parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue; + } + + if (methodDefinition.attributes == null) + return; + + if (attributes == null) { + attributes = methodDefinition.attributes; + } else { + attributes.Attrs.AddRange (methodDefinition.attributes.Attrs); + } + } + } + + public abstract class ConstructorInitializer : ExpressionStatement + { + Arguments argument_list; + MethodSpec base_ctor; + + public ConstructorInitializer (Arguments argument_list, Location loc) + { + this.argument_list = argument_list; + this.loc = loc; + } + + public Arguments Arguments { + get { + return argument_list; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + eclass = ExprClass.Value; + + // FIXME: Hack + var caller_builder = (Constructor) ec.MemberContext; + + // + // Spec mandates that constructor initializer will not have `this' access + // + using (ec.Set (ResolveContext.Options.BaseInitializer)) { + if (argument_list != null) { + bool dynamic; + argument_list.Resolve (ec, out dynamic); + + if (dynamic) { + ec.Report.Error (1975, loc, + "The constructor call cannot be dynamically dispatched within constructor initializer"); + + return null; + } + } + + type = ec.CurrentType; + if (this is ConstructorBaseInitializer) { + if (ec.CurrentType.BaseType == null) + return this; + + type = ec.CurrentType.BaseType; + if (ec.CurrentType.IsStruct) { + ec.Report.Error (522, loc, + "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ()); + return this; + } + } else { + // + // It is legal to have "this" initializers that take no arguments + // in structs, they are just no-ops. + // + // struct D { public D (int a) : this () {} + // + if (ec.CurrentType.IsStruct && argument_list == null) + return this; + } + + base_ctor = ConstructorLookup (ec, type, ref argument_list, loc); + } + + // TODO MemberCache: Does it work for inflated types ? + if (base_ctor == caller_builder.Spec){ + ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself", + caller_builder.GetSignatureForError ()); + } + + return this; + } + + public override void Emit (EmitContext ec) + { + // It can be null for static initializers + if (base_ctor == null) + return; + + ec.Mark (loc); + + Invocation.EmitCall (ec, new CompilerGeneratedThis (type, loc), base_ctor, argument_list, loc); + } + + public override void EmitStatement (EmitContext ec) + { + Emit (ec); + } + } + + public class ConstructorBaseInitializer : ConstructorInitializer { + public ConstructorBaseInitializer (Arguments argument_list, Location l) : + base (argument_list, l) + { + } + } + + class GeneratedBaseInitializer: ConstructorBaseInitializer { + public GeneratedBaseInitializer (Location loc): + base (null, loc) + { + } + } + + public class ConstructorThisInitializer : ConstructorInitializer { + public ConstructorThisInitializer (Arguments argument_list, Location l) : + base (argument_list, l) + { + } + } + + public class Constructor : MethodCore, IMethodData { + public ConstructorBuilder ConstructorBuilder; + public ConstructorInitializer Initializer; + SecurityType declarative_security; + bool has_compliant_args; + + // + // Modifiers allowed for a constructor. + // + public const Modifiers AllowedModifiers = + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.STATIC | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.PRIVATE; + + static readonly string[] attribute_targets = new string [] { "method" }; + + public static readonly string ConstructorName = ".ctor"; + public static readonly string TypeConstructorName = ".cctor"; + + // + // The spec claims that static is not permitted, but + // my very own code has static constructors. + // + public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, + ConstructorInitializer init, Location loc) + : base (parent, null, null, mod, AllowedModifiers, + new MemberName (name, loc), attrs, args) + { + Initializer = init; + } + + public bool HasCompliantArgs { + get { return has_compliant_args; } + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Constructor; + } + } + + bool IMethodData.IsAccessor { + get { + return false; + } + } + + // + // Returns true if this is a default constructor + // + public bool IsDefault () + { + if ((ModFlags & Modifiers.STATIC) != 0) + return parameters.IsEmpty; + + return parameters.IsEmpty && + (Initializer is ConstructorBaseInitializer) && + (Initializer.Arguments == null); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Type == pa.MethodImpl) { + is_external_implementation = a.IsInternalCall (); + } + + ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + protected override bool CheckBase () + { + if ((ModFlags & Modifiers.STATIC) != 0) { + if (!parameters.IsEmpty) { + Report.Error (132, Location, "`{0}': The static constructor must be parameterless", + GetSignatureForError ()); + return false; + } + + // the rest can be ignored + return true; + } + + // Check whether arguments were correct. + if (!DefineParameters (parameters)) + return false; + + if ((caching_flags & Flags.MethodOverloadsExist) != 0) + Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); + + if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) { + Report.Error (568, Location, + "Structs cannot contain explicit parameterless constructors"); + return false; + } + + CheckProtectedModifier (); + + return true; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + // + // Creates the ConstructorBuilder + // + public override bool Define () + { + if (ConstructorBuilder != null) + return true; + + var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName; + + if ((ModFlags & Modifiers.STATIC) != 0) { + ca |= MethodAttributes.Static | MethodAttributes.Private; + } else { + ca |= ModifiersExtensions.MethodAttr (ModFlags); + } + + if (!CheckAbstractAndExtern (block != null)) + return false; + + // Check if arguments were correct. + if (!CheckBase ()) + return false; + + ConstructorBuilder = Parent.TypeBuilder.DefineConstructor ( + ca, CallingConventions, + parameters.GetMetaInfo ()); + + spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, ConstructorBuilder, parameters, ModFlags); + + Parent.MemberCache.AddMember (spec); + + // It's here only to report an error + if (block != null && block.IsIterator) { + member_type = Compiler.BuiltinTypes.Void; + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + } + + return true; + } + + // + // Emits the code + // + public override void Emit () + { + if (Parent.PartialContainer.IsComImport) { + if (!IsDefault ()) { + Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor", + Parent.GetSignatureForError ()); + } + + // Set as internal implementation and reset block data + // to ensure no IL is generated + ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall); + block = null; + } + + if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0) + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder); + + if (OptAttributes != null) + OptAttributes.Emit (); + + base.Emit (); + parameters.ApplyAttributes (this, ConstructorBuilder); + + // + // If we use a "this (...)" constructor initializer, then + // do not emit field initializers, they are initialized in the other constructor + // + bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) || + !(Initializer is ConstructorThisInitializer); + + BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void); + bc.Set (ResolveContext.Options.ConstructorScope); + + if (emit_field_initializers) + Parent.PartialContainer.ResolveFieldInitializers (bc); + + if (block != null) { + // If this is a non-static `struct' constructor and doesn't have any + // 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); + + if (block != null && (ModFlags & Modifiers.STATIC) == 0){ + if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null) + Initializer = new GeneratedBaseInitializer (Location); + + if (Initializer != null) { + block.AddScopeStatement (new StatementExpression (Initializer)); + } + } + } + + SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block); + + if (block != null) { + if (block.Resolve (null, bc, this)) { + EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType); + ec.With (EmitContext.Options.ConstructorScope, true); + + if (!ec.HasReturnLabel && bc.HasReturnLabel) { + ec.ReturnLabel = bc.ReturnLabel; + ec.HasReturnLabel = true; + } + + block.Emit (ec); + } + } + + if (source != null) + source.CloseMethod (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + ConstructorBuilder.__AddDeclarativeSecurity (de); +#else + ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + + block = null; + } + + protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) + { + // Is never override + bestCandidate = null; + return null; + } + + public override string GetSignatureForDocumentation () + { + return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation (); + } + + public override string GetSignatureForError() + { + return base.GetSignatureForError () + parameters.GetSignatureForError (); + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) { + return false; + } + + if (!parameters.IsEmpty && Parent.Definition.IsAttribute) { + foreach (TypeSpec param in parameters.Types) { + if (param.IsArray) { + return true; + } + } + } + + has_compliant_args = true; + return true; + } + + #region IMethodData Members + + public MemberName MethodName { + get { + return MemberName; + } + } + + public TypeSpec ReturnType { + get { + return MemberType; + } + } + + public EmitContext CreateEmitContext (ILGenerator ig) + { + throw new NotImplementedException (); + } + + public bool IsExcluded() + { + return false; + } + + GenericMethod IMethodData.GenericMethod { + get { + return null; + } + } + + void IMethodData.EmitExtraSymbolInfo (SourceMethod source) + { } + + #endregion + } + + /// + /// Interface for MethodData class. Holds links to parent members to avoid member duplication. + /// + public interface IMethodData : IMemberContext + { + CallingConventions CallingConventions { get; } + Location Location { get; } + MemberName MethodName { get; } + TypeSpec ReturnType { get; } + GenericMethod GenericMethod { get; } + ParametersCompiled ParameterInfo { get; } + MethodSpec Spec { get; } + bool IsAccessor { get; } + + Attributes OptAttributes { get; } + ToplevelBlock Block { get; set; } + + EmitContext CreateEmitContext (ILGenerator ig); + void EmitExtraSymbolInfo (SourceMethod source); + } + + // + // Encapsulates most of the Method's state + // + public class MethodData + { +#if !STATIC + static FieldInfo methodbuilder_attrs_field; +#endif + + public readonly IMethodData method; + + public readonly GenericMethod GenericMethod; + + // + // Are we implementing an interface ? + // + public MethodSpec implementing; + + // + // Protected data. + // + protected InterfaceMemberBase member; + protected Modifiers modifiers; + protected MethodAttributes flags; + protected TypeSpec declaring_type; + protected MethodSpec parent_method; + + MethodBuilder builder; + public MethodBuilder MethodBuilder { + get { + return builder; + } + } + + public TypeSpec DeclaringType { + get { + return declaring_type; + } + } + + public MethodData (InterfaceMemberBase member, + Modifiers modifiers, MethodAttributes flags, IMethodData method) + { + this.member = member; + this.modifiers = modifiers; + this.flags = flags; + + this.method = method; + } + + public MethodData (InterfaceMemberBase member, + Modifiers modifiers, MethodAttributes flags, + IMethodData method, MethodBuilder builder, + GenericMethod generic, MethodSpec parent_method) + : this (member, modifiers, flags, method) + { + this.builder = builder; + this.GenericMethod = generic; + this.parent_method = parent_method; + } + + public bool Define (DeclSpace parent, string method_full_name, Report Report) + { + TypeContainer container = parent.PartialContainer; + + PendingImplementation pending = container.PendingImplementations; + MethodSpec ambig_iface_method; + if (pending != null) { + implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method); + + if (member.InterfaceType != null) { + if (implementing == null) { + if (member is PropertyBase) { + Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'", + method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType), + member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); + + } else { + Report.Error (539, method.Location, + "`{0}.{1}' in explicit interface declaration is not a member of interface", + TypeManager.CSharpName (member.InterfaceType), member.ShortName); + } + return false; + } + if (implementing.IsAccessor && !method.IsAccessor) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", + member.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); + return false; + } + } else { + if (implementing != null) { + if (!method.IsAccessor) { + if (implementing.IsAccessor) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'", + method.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); + } + } else if (implementing.DeclaringType.IsInterface) { + if (!implementing.IsAccessor) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", + method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ()); + } else { + PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod; + if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'", + method.GetSignatureForError (), implementing.GetSignatureForError ()); + } + } + } + } + } + } else { + ambig_iface_method = null; + } + + // + // For implicit implementations, make sure we are public, for + // explicit implementations, make sure we are private. + // + if (implementing != null){ + // + // Setting null inside this block will trigger a more + // verbose error reporting for missing interface implementations + // + // The "candidate" function has been flagged already + // but it wont get cleared + // + if (member.IsExplicitImpl){ + if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) { + Report.SymbolRelatedToPreviousError (implementing); + Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier", + method.GetSignatureForError ()); + } + + if (ambig_iface_method != null) { + Report.SymbolRelatedToPreviousError (ambig_iface_method); + Report.SymbolRelatedToPreviousError (implementing); + Report.Warning (473, 2, method.Location, + "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead", + method.GetSignatureForError ()); + } + + } else { + if (implementing.DeclaringType.IsInterface) { + // + // If this is an interface method implementation, + // check for public accessibility + // + if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) + { + implementing = null; + } + } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){ + // We may never be private. + implementing = null; + + } else if ((modifiers & Modifiers.OVERRIDE) == 0){ + // + // We may be protected if we're overriding something. + // + implementing = null; + } + } + + // + // Static is not allowed + // + if ((modifiers & Modifiers.STATIC) != 0){ + implementing = null; + } + } + + // + // If implementing is still valid, set flags + // + if (implementing != null){ + // + // When implementing interface methods, set NewSlot + // unless, we are overwriting a method. + // + if (implementing.DeclaringType.IsInterface){ + if ((modifiers & Modifiers.OVERRIDE) == 0) + flags |= MethodAttributes.NewSlot; + } + + flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig; + + // Set Final unless we're virtual, abstract or already overriding a method. + if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0) + flags |= MethodAttributes.Final; + + // + // clear the pending implementation flag (requires explicit methods to be defined first) + // + parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName, + member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method); + + // + // Update indexer accessor name to match implementing abstract accessor + // + if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor) + method_full_name = implementing.MemberDefinition.Name; + } + + DefineMethodBuilder (container, method_full_name, method.ParameterInfo); + + if (builder == null) + return false; + +// if (container.CurrentType != null) +// declaring_type = container.CurrentType; +// else + declaring_type = container.Definition; + + if (implementing != null && member.IsExplicitImpl) { + container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ()); + } + + return true; + } + + + /// + /// Create the MethodBuilder for the method + /// + void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param) + { + var return_type = method.ReturnType.GetMetaInfo (); + var p_types = param.GetMetaInfo (); + + if (builder == null) { + builder = container.TypeBuilder.DefineMethod ( + method_name, flags, method.CallingConventions, + return_type, p_types); + return; + } + + // + // Generic method has been already defined to resolve method parameters + // correctly when they use type parameters + // + builder.SetParameters (p_types); + builder.SetReturnType (return_type); + if (builder.Attributes != flags) { +#if STATIC + builder.__SetAttributes (flags); +#else + try { + if (methodbuilder_attrs_field == null) + methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance); + methodbuilder_attrs_field.SetValue (builder, flags); + } catch { + container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes"); + } +#endif + } + } + + // + // Emits the code + // + public void Emit (DeclSpace parent) + { + if (GenericMethod != null) + GenericMethod.EmitAttributes (); + + var mc = (IMemberContext) method; + + method.ParameterInfo.ApplyAttributes (mc, MethodBuilder); + + SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block); + + ToplevelBlock block = method.Block; + if (block != null) { + BlockContext bc = new BlockContext (mc, block, method.ReturnType); + if (block.Resolve (null, bc, method)) { + EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ()); + if (!ec.HasReturnLabel && bc.HasReturnLabel) { + ec.ReturnLabel = bc.ReturnLabel; + ec.HasReturnLabel = true; + } + + block.Emit (ec); + } + } + + if (source != null) { + method.EmitExtraSymbolInfo (source); + source.CloseMethod (); + } + } + } + + public class Destructor : MethodOrOperator + { + const Modifiers AllowedModifiers = + Modifiers.UNSAFE | + Modifiers.EXTERN; + + static readonly string[] attribute_targets = new string [] { "method" }; + + public static readonly string MetadataName = "Finalize"; + + public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l) + : base (parent, null, null, mod, AllowedModifiers, + new MemberName (MetadataName, l), attrs, parameters) + { + ModFlags &= ~Modifiers.PRIVATE; + ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE; + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.Conditional) { + Error_ConditionalAttributeIsNotValid (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + protected override bool CheckBase () + { + // Don't check base, destructors have special syntax + return true; + } + + public override void Emit() + { + var base_type = Parent.PartialContainer.BaseType; + if (base_type != null && Block != null) { + var base_dtor = MemberCache.FindMember (base_type, + new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec; + + if (base_dtor == null) + throw new NotImplementedException (); + + MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location); + method_expr.InstanceExpression = new BaseThis (base_type, Location); + + var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation); + var finaly_block = new ExplicitBlock (block, Location, Location); + + // + // 0-size arguments to avoid CS0250 error + // TODO: Should use AddScopeStatement or something else which emits correct + // debugger scope + // + finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0)))); + + var tf = new TryFinally (try_block, finaly_block, Location); + block.WrapIntoDestructor (tf, try_block); + } + + base.Emit (); + } + + public override string GetSignatureForError () + { + return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()"; + } + + protected override bool ResolveMemberType () + { + member_type = Compiler.BuiltinTypes.Void; + return true; + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + + // Ooouh Martin, templates are missing here. + // When it will be possible move here a lot of child code and template method type. + public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData { + protected MethodData method_data; + protected ToplevelBlock block; + protected SecurityType declarative_security; + + protected readonly string prefix; + + ReturnParameter return_attributes; + + public AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc) + : base (member.Parent, SetupName (prefix, member, loc), attrs) + { + this.prefix = prefix; + } + + static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc) + { + return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc); + } + + public void UpdateName (InterfaceMemberBase member) + { + SetMemberName (SetupName (prefix, member, Location)); + } + + #region IMethodData Members + + public ToplevelBlock Block { + get { + return block; + } + + set { + block = value; + } + } + + public CallingConventions CallingConventions { + get { + return CallingConventions.Standard; + } + } + + public EmitContext CreateEmitContext (ILGenerator ig) + { + return new EmitContext (this, ig, ReturnType); + } + + public bool IsAccessor { + get { + return true; + } + } + + public bool IsExcluded () + { + return false; + } + + GenericMethod IMethodData.GenericMethod { + get { + return null; + } + } + + public MemberName MethodName { + get { + return MemberName; + } + } + + public TypeSpec[] ParameterTypes { + get { + return ParameterInfo.Types; + } + } + + public abstract ParametersCompiled ParameterInfo { get ; } + public abstract TypeSpec ReturnType { get; } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) { + Report.Error (1667, a.Location, + "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only", + TypeManager.CSharpName (a.Type), a.GetValidTargets ()); + return; + } + + if (a.IsValidSecurityAttribute ()) { + a.ExtractSecurityPermissionSet (ctor, ref declarative_security); + return; + } + + if (a.Target == AttributeTargets.Method) { + method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + return; + } + + if (a.Target == AttributeTargets.ReturnValue) { + if (return_attributes == null) + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + + return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + ApplyToExtraTarget (a, ctor, cdata, pa); + } + + protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + throw new NotSupportedException ("You forgot to define special attribute target handling"); + } + + // It is not supported for the accessors + public sealed override bool Define() + { + throw new NotSupportedException (); + } + + public virtual void Emit (DeclSpace parent) + { + method_data.Emit (parent); + + if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated) + Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder); + if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)) + Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder); + + if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder); + } else if (ReturnType.HasDynamicElement) { + return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location); + Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location); + } + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (declarative_security != null) { + foreach (var de in declarative_security) { +#if STATIC + method_data.MethodBuilder.__AddDeclarativeSecurity (de); +#else + method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value); +#endif + } + } + + block = null; + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + if (overload is MethodCore) { + caching_flags |= Flags.MethodOverloadsExist; + return true; + } + + // This can only happen with indexers and it will + // be catched as indexer difference + if (overload is AbstractPropertyEventMethod) + return true; + + return false; + } + + public override string GetSignatureForDocumentation () + { + // should not be called + throw new NotSupportedException (); + } + + public override bool IsClsComplianceRequired() + { + return false; + } + + public MethodSpec Spec { get; protected set; } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); } + } + + void IMethodData.EmitExtraSymbolInfo (SourceMethod source) + { } + } + + public class Operator : MethodOrOperator { + + const Modifiers AllowedModifiers = + Modifiers.PUBLIC | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.STATIC; + + public enum OpType : byte { + + // Unary operators + LogicalNot, + OnesComplement, + Increment, + Decrement, + True, + False, + + // Unary and Binary operators + Addition, + Subtraction, + + UnaryPlus, + UnaryNegation, + + // Binary operators + Multiply, + Division, + Modulus, + BitwiseAnd, + BitwiseOr, + ExclusiveOr, + LeftShift, + RightShift, + Equality, + Inequality, + GreaterThan, + LessThan, + GreaterThanOrEqual, + LessThanOrEqual, + + // Implicit and Explicit + Implicit, + Explicit, + + // Just because of enum + TOP + }; + + public readonly OpType OperatorType; + + static readonly string [] [] names; + + static Operator () + { + names = new string[(int)OpType.TOP][]; + names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" }; + names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" }; + names [(int) OpType.Increment] = new string [] { "++", "op_Increment" }; + names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" }; + names [(int) OpType.True] = new string [] { "true", "op_True" }; + names [(int) OpType.False] = new string [] { "false", "op_False" }; + names [(int) OpType.Addition] = new string [] { "+", "op_Addition" }; + names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" }; + names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" }; + names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" }; + names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" }; + names [(int) OpType.Division] = new string [] { "/", "op_Division" }; + names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" }; + names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" }; + names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" }; + names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" }; + names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" }; + names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" }; + names [(int) OpType.Equality] = new string [] { "==", "op_Equality" }; + names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" }; + names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" }; + names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" }; + names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" }; + names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" }; + names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" }; + names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" }; + } + + public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type, + Modifiers mod_flags, ParametersCompiled parameters, + ToplevelBlock block, Attributes attrs, Location loc) + : base (parent, null, ret_type, mod_flags, AllowedModifiers, + new MemberName (GetMetadataName (type), loc), attrs, parameters) + { + OperatorType = type; + Block = block; + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.Conditional) { + Error_ConditionalAttributeIsNotValid (); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC; + if ((ModFlags & RequiredModifiers) != RequiredModifiers){ + Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ()); + } + + if (!base.Define ()) + return false; + + if (block != null && block.IsIterator) { + // + // Current method is turned into automatically generated + // wrapper which creates an instance of iterator + // + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + ModFlags |= Modifiers.DEBUGGER_HIDDEN; + } + + // imlicit and explicit operator of same types are not allowed + if (OperatorType == OpType.Explicit) + Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters); + else if (OperatorType == OpType.Implicit) + Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters); + + TypeSpec declaring_type = Parent.CurrentType; + TypeSpec return_type = MemberType; + TypeSpec first_arg_type = ParameterTypes [0]; + + TypeSpec first_arg_type_unwrap = first_arg_type; + if (first_arg_type.IsNullableType) + first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type); + + TypeSpec return_type_unwrap = return_type; + if (return_type.IsNullableType) + return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type); + + // + // Rules for conversion operators + // + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) { + Report.Error (555, Location, + "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type"); + return false; + } + + TypeSpec conv_type; + if (declaring_type == return_type || declaring_type == return_type_unwrap) { + conv_type = first_arg_type; + } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) { + conv_type = return_type; + } else { + Report.Error (556, Location, + "User-defined conversion must convert to or from the enclosing type"); + return false; + } + + if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Report.Error (1964, Location, + "User-defined conversion `{0}' cannot convert to or from the dynamic type", + GetSignatureForError ()); + + return false; + } + + if (conv_type.IsInterface) { + Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type", + GetSignatureForError ()); + return false; + } + + if (conv_type.IsClass) { + if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) { + Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class", + GetSignatureForError ()); + return false; + } + + if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) { + Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class", + GetSignatureForError ()); + return false; + } + } + } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) { + if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) { + Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int"); + return false; + } + } else if (parameters.Count == 1) { + // Checks for Unary operators + + if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) { + if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) { + Report.Error (448, Location, + "The return type for ++ or -- operator must be the containing type or derived from the containing type"); + return false; + } + if (first_arg_type != declaring_type) { + Report.Error ( + 559, Location, "The parameter type for ++ or -- operator must be the containing type"); + return false; + } + } + + if (first_arg_type_unwrap != declaring_type) { + Report.Error (562, Location, + "The parameter type of a unary operator must be the containing type"); + return false; + } + + if (OperatorType == OpType.True || OperatorType == OpType.False) { + if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) { + Report.Error ( + 215, Location, + "The return type of operator True or False " + + "must be bool"); + return false; + } + } + + } else if (first_arg_type_unwrap != declaring_type) { + // Checks for Binary operators + + var second_arg_type = ParameterTypes[1]; + if (second_arg_type.IsNullableType) + second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type); + + if (second_arg_type != declaring_type) { + Report.Error (563, Location, + "One of the parameters of a binary operator must be the containing type"); + return false; + } + } + + return true; + } + + protected override bool ResolveMemberType () + { + if (!base.ResolveMemberType ()) + return false; + + flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig; + return true; + } + + protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides) + { + // Operator cannot be override + bestCandidate = null; + return null; + } + + public static string GetName (OpType ot) + { + return names [(int) ot] [0]; + } + + public static string GetName (string metadata_name) + { + for (int i = 0; i < names.Length; ++i) { + if (names [i] [1] == metadata_name) + return names [i] [0]; + } + return null; + } + + public static string GetMetadataName (OpType ot) + { + return names [(int) ot] [1]; + } + + public static string GetMetadataName (string name) + { + for (int i = 0; i < names.Length; ++i) { + if (names [i] [0] == name) + return names [i] [1]; + } + return null; + } + + public static OpType? GetType (string metadata_name) + { + for (int i = 0; i < names.Length; ++i) { + if (names[i][1] == metadata_name) + return (OpType) i; + } + + return null; + } + + public OpType GetMatchingOperator () + { + switch (OperatorType) { + case OpType.Equality: + return OpType.Inequality; + case OpType.Inequality: + return OpType.Equality; + case OpType.True: + return OpType.False; + case OpType.False: + return OpType.True; + case OpType.GreaterThan: + return OpType.LessThan; + case OpType.LessThan: + return OpType.GreaterThan; + case OpType.GreaterThanOrEqual: + return OpType.LessThanOrEqual; + case OpType.LessThanOrEqual: + return OpType.GreaterThanOrEqual; + default: + return OpType.TOP; + } + } + + public override string GetSignatureForDocumentation () + { + string s = base.GetSignatureForDocumentation (); + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + s = s + "~" + ReturnType.GetSignatureForDocumentation (); + } + + return s; + } + + public override string GetSignatureForError () + { + StringBuilder sb = new StringBuilder (); + if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) { + sb.AppendFormat ("{0}.{1} operator {2}", + Parent.GetSignatureForError (), GetName (OperatorType), + member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ()); + } + else { + sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType)); + } + + sb.Append (parameters.GetSignatureForError ()); + return sb.ToString (); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs new file mode 100644 index 0000000000..3edbed6ba8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs @@ -0,0 +1,281 @@ +// +// modifiers.cs: Modifiers handling +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// 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-2010 Novell, Inc +// + +using System; + +#if STATIC +using IKVM.Reflection; +#else +using System.Reflection; +#endif + +namespace Mono.CSharp +{ + [Flags] + public enum Modifiers + { + PROTECTED = 0x0001, + PUBLIC = 0x0002, + PRIVATE = 0x0004, + INTERNAL = 0x0008, + NEW = 0x0010, + ABSTRACT = 0x0020, + SEALED = 0x0040, + STATIC = 0x0080, + READONLY = 0x0100, + VIRTUAL = 0x0200, + OVERRIDE = 0x0400, + EXTERN = 0x0800, + VOLATILE = 0x1000, + UNSAFE = 0x2000, + ASYNC = 0x4000, + TOP = 0x8000, + + // + // Compiler specific flags + // + PROPERTY_CUSTOM = 0x10000, + + PARTIAL = 0x20000, + DEFAULT_ACCESS_MODIFER = 0x40000, + METHOD_EXTENSION = 0x80000, + COMPILER_GENERATED = 0x100000, + BACKING_FIELD = 0x200000, + DEBUGGER_HIDDEN = 0x400000, + + AccessibilityMask = PUBLIC | PROTECTED | INTERNAL | PRIVATE, + AllowedExplicitImplFlags = UNSAFE | EXTERN, + } + + static class ModifiersExtensions + { + public static string AccessibilityName (Modifiers mod) + { + switch (mod & Modifiers.AccessibilityMask) { + case Modifiers.PUBLIC: + return "public"; + case Modifiers.PROTECTED: + return "protected"; + case Modifiers.PROTECTED | Modifiers.INTERNAL: + return "protected internal"; + case Modifiers.INTERNAL: + return "internal"; + case Modifiers.PRIVATE: + return "private"; + default: + throw new NotImplementedException (mod.ToString ()); + } + } + + static public string Name (Modifiers i) + { + string s = ""; + + switch (i) { + case Modifiers.NEW: + s = "new"; break; + case Modifiers.PUBLIC: + s = "public"; break; + case Modifiers.PROTECTED: + s = "protected"; break; + case Modifiers.INTERNAL: + s = "internal"; break; + case Modifiers.PRIVATE: + s = "private"; break; + case Modifiers.ABSTRACT: + s = "abstract"; break; + case Modifiers.SEALED: + s = "sealed"; break; + case Modifiers.STATIC: + s = "static"; break; + case Modifiers.READONLY: + s = "readonly"; break; + case Modifiers.VIRTUAL: + s = "virtual"; break; + case Modifiers.OVERRIDE: + s = "override"; break; + case Modifiers.EXTERN: + s = "extern"; break; + case Modifiers.VOLATILE: + s = "volatile"; break; + case Modifiers.UNSAFE: + s = "unsafe"; break; + case Modifiers.ASYNC: + s = "async"; break; + } + + return s; + } + + // + // Used by custom property accessors to check whether @modA is more restrictive than @modB + // + public static bool IsRestrictedModifier (Modifiers modA, Modifiers modB) + { + Modifiers flags = 0; + + if ((modB & Modifiers.PUBLIC) != 0) { + flags = Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE; + } else if ((modB & Modifiers.PROTECTED) != 0) { + if ((modB & Modifiers.INTERNAL) != 0) + flags = Modifiers.PROTECTED | Modifiers.INTERNAL; + + flags |= Modifiers.PRIVATE; + } else if ((modB & Modifiers.INTERNAL) != 0) + flags = Modifiers.PRIVATE; + + return modB != modA && (modA & (~flags)) == 0; + } + + public static TypeAttributes TypeAttr (Modifiers mod_flags, bool is_toplevel) + { + TypeAttributes t = 0; + + if (is_toplevel){ + if ((mod_flags & Modifiers.PUBLIC) != 0) + t = TypeAttributes.Public; + else if ((mod_flags & Modifiers.PRIVATE) != 0) + t = TypeAttributes.NotPublic; + } else { + if ((mod_flags & Modifiers.PUBLIC) != 0) + t = TypeAttributes.NestedPublic; + else if ((mod_flags & Modifiers.PRIVATE) != 0) + t = TypeAttributes.NestedPrivate; + else if ((mod_flags & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) + t = TypeAttributes.NestedFamORAssem; + else if ((mod_flags & Modifiers.PROTECTED) != 0) + t = TypeAttributes.NestedFamily; + else if ((mod_flags & Modifiers.INTERNAL) != 0) + t = TypeAttributes.NestedAssembly; + } + + if ((mod_flags & Modifiers.SEALED) != 0) + t |= TypeAttributes.Sealed; + if ((mod_flags & Modifiers.ABSTRACT) != 0) + t |= TypeAttributes.Abstract; + + return t; + } + + public static FieldAttributes FieldAttr (Modifiers mod_flags) + { + FieldAttributes fa = 0; + + if ((mod_flags & Modifiers.PUBLIC) != 0) + fa |= FieldAttributes.Public; + if ((mod_flags & Modifiers.PRIVATE) != 0) + fa |= FieldAttributes.Private; + if ((mod_flags & Modifiers.PROTECTED) != 0) { + if ((mod_flags & Modifiers.INTERNAL) != 0) + fa |= FieldAttributes.FamORAssem; + else + fa |= FieldAttributes.Family; + } else { + if ((mod_flags & Modifiers.INTERNAL) != 0) + fa |= FieldAttributes.Assembly; + } + + if ((mod_flags & Modifiers.STATIC) != 0) + fa |= FieldAttributes.Static; + if ((mod_flags & Modifiers.READONLY) != 0) + fa |= FieldAttributes.InitOnly; + + return fa; + } + + public static MethodAttributes MethodAttr (Modifiers mod_flags) + { + MethodAttributes ma = MethodAttributes.HideBySig; + + switch (mod_flags & Modifiers.AccessibilityMask) { + case Modifiers.PUBLIC: + ma |= MethodAttributes.Public; + break; + case Modifiers.PRIVATE: + ma |= MethodAttributes.Private; + break; + case Modifiers.PROTECTED | Modifiers.INTERNAL: + ma |= MethodAttributes.FamORAssem; + break; + case Modifiers.PROTECTED: + ma |= MethodAttributes.Family; + break; + case Modifiers.INTERNAL: + ma |= MethodAttributes.Assembly; + break; + default: + throw new NotImplementedException (mod_flags.ToString ()); + } + + if ((mod_flags & Modifiers.STATIC) != 0) + ma |= MethodAttributes.Static; + if ((mod_flags & Modifiers.ABSTRACT) != 0) { + ma |= MethodAttributes.Abstract | MethodAttributes.Virtual; + } + if ((mod_flags & Modifiers.SEALED) != 0) + ma |= MethodAttributes.Final; + + if ((mod_flags & Modifiers.VIRTUAL) != 0) + ma |= MethodAttributes.Virtual; + + if ((mod_flags & Modifiers.OVERRIDE) != 0) { + ma |= MethodAttributes.Virtual; + } else { + if ((ma & MethodAttributes.Virtual) != 0) + ma |= MethodAttributes.NewSlot; + } + + return ma; + } + + // + // Checks the object @mod modifiers to be in @allowed. + // Returns the new mask. Side effect: reports any + // incorrect attributes. + // + public static Modifiers Check (Modifiers allowed, Modifiers mod, Modifiers def_access, Location l, Report Report) + { + int invalid_flags = (~(int) allowed) & ((int) mod & ((int) Modifiers.TOP - 1)); + int i; + + if (invalid_flags == 0){ + // + // If no accessibility bits provided + // then provide the defaults. + // + if ((mod & Modifiers.AccessibilityMask) == 0) { + mod |= def_access; + if (def_access != 0) + mod |= Modifiers.DEFAULT_ACCESS_MODIFER; + return mod; + } + + return mod; + } + + for (i = 1; i <= (int) Modifiers.TOP; i <<= 1) { + if ((i & invalid_flags) == 0) + continue; + + Error_InvalidModifier ((Modifiers)i, l, Report); + } + + return allowed & mod; + } + + static void Error_InvalidModifier (Modifiers mod, Location l, Report Report) + { + Report.Error (106, l, "The modifier `{0}' is not valid for this item", + Name (mod)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs new file mode 100644 index 0000000000..fdafbee39f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs @@ -0,0 +1,1227 @@ +// +// namespace.cs: Tracks namespaces +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001 Ximian, Inc. +// Copyright 2003-2008 Novell, Inc. +// +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Mono.CSharp { + + public class RootNamespace : Namespace { + + readonly string alias_name; + readonly Dictionary all_namespaces; + + public RootNamespace (string alias_name) + : base (null, String.Empty) + { + this.alias_name = alias_name; + + all_namespaces = new Dictionary (); + all_namespaces.Add ("", this); + } + + public string Alias { + get { + return alias_name; + } + } + + public void RegisterNamespace (Namespace child) + { + if (child != this) + all_namespaces.Add (child.Name, child); + } + + public bool IsNamespace (string name) + { + return all_namespaces.ContainsKey (name); + } + + protected void RegisterNamespace (string dotted_name) + { + if (dotted_name != null && dotted_name.Length != 0 && ! IsNamespace (dotted_name)) + GetNamespace (dotted_name, true); + } + + public override string GetSignatureForError () + { + return alias_name + "::"; + } + } + + public class GlobalRootNamespace : RootNamespace + { + public GlobalRootNamespace () + : base ("global") + { + } + } + + // + // Namespace cache for imported and compiled namespaces + // + // This is an Expression to allow it to be referenced in the + // compiler parse/intermediate tree during name resolution. + // + public class Namespace : FullNamedExpression + { + Namespace parent; + string fullname; + protected Dictionary namespaces; + protected Dictionary> types; + Dictionary cached_types; + RootNamespace root; + bool cls_checked; + + public readonly MemberName MemberName; + + /// + /// Constructor Takes the current namespace and the + /// name. This is bootstrapped with parent == null + /// and name = "" + /// + public Namespace (Namespace parent, string name) + { + // Expression members. + this.eclass = ExprClass.Namespace; + this.Type = InternalType.Namespace; + this.loc = Location.Null; + + this.parent = parent; + + if (parent != null) + this.root = parent.root; + else + this.root = this as RootNamespace; + + if (this.root == null) + throw new InternalErrorException ("Root namespaces must be created using RootNamespace"); + + string pname = parent != null ? parent.fullname : ""; + + if (pname == "") + fullname = name; + else + fullname = parent.fullname + "." + name; + + if (fullname == null) + throw new InternalErrorException ("Namespace has a null fullname"); + + if (parent != null && parent.MemberName != MemberName.Null) + MemberName = new MemberName (parent.MemberName, name); + else if (name.Length == 0) + MemberName = MemberName.Null; + else + MemberName = new MemberName (name); + + namespaces = new Dictionary (); + cached_types = new Dictionary (); + + root.RegisterNamespace (this); + } + + #region Properties + + /// + /// The qualified name of the current namespace + /// + public string Name { + get { return fullname; } + } + + /// + /// The parent of this namespace, used by the parser to "Pop" + /// the current namespace declaration + /// + public Namespace Parent { + get { return parent; } + } + + #endregion + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public void Error_NamespaceDoesNotExist (IMemberContext ctx, string name, int arity, Location loc) + { + var retval = LookupType (ctx, name, arity, LookupMode.IgnoreAccessibility, loc); + if (retval != null) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type); + ErrorIsInaccesible (ctx, retval.GetSignatureForError (), loc); + return; + } + + retval = LookupType (ctx, name, -System.Math.Max (1, arity), LookupMode.Probing, loc); + if (retval != null) { + Error_TypeArgumentsCannotBeUsed (ctx, retval.Type, arity, loc); + return; + } + + Namespace ns; + if (arity > 0 && namespaces.TryGetValue (name, out ns)) { + ns.Error_TypeArgumentsCannotBeUsed (ctx, null, arity, loc); + return; + } + + if (this is GlobalRootNamespace) { + ctx.Module.Compiler.Report.Error (400, loc, + "The type or namespace name `{0}' could not be found in the global namespace (are you missing an assembly reference?)", + name); + } else { + ctx.Module.Compiler.Report.Error (234, loc, + "The type or namespace name `{0}' does not exist in the namespace `{1}'. Are you missing an assembly reference?", + name, GetSignatureForError ()); + } + } + + public override string GetSignatureForError () + { + return fullname; + } + + public Namespace GetNamespace (string name, bool create) + { + int pos = name.IndexOf ('.'); + + Namespace ns; + string first; + if (pos >= 0) + first = name.Substring (0, pos); + else + first = name; + + if (!namespaces.TryGetValue (first, out ns)) { + if (!create) + return null; + + ns = new Namespace (this, first); + namespaces.Add (first, ns); + } + + if (pos >= 0) + ns = ns.GetNamespace (name.Substring (pos + 1), create); + + return ns; + } + + public IList GetAllTypes (string name) + { + IList found; + if (types == null || !types.TryGetValue (name, out found)) + return null; + + return found; + } + + public TypeExpr LookupType (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) + { + if (types == null) + return null; + + TypeExpr te; + if (arity == 0 && cached_types.TryGetValue (name, out te)) + return te; + + IList found; + if (!types.TryGetValue (name, out found)) + return null; + + TypeSpec best = null; + foreach (var ts in found) { + if (ts.Arity == arity) { + if (best == null) { + if ((ts.Modifiers & Modifiers.INTERNAL) != 0 && !ts.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly) && mode != LookupMode.IgnoreAccessibility) + continue; + + best = ts; + continue; + } + + if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) { + if (mode == LookupMode.Normal) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best); + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); + ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ()); + } + break; + } + + if (best.MemberDefinition.IsImported) + best = ts; + + if ((best.Modifiers & Modifiers.INTERNAL) != 0 && !best.MemberDefinition.IsInternalAsPublic (ctx.Module.DeclaringAssembly)) + continue; + + if (mode != LookupMode.Normal) + continue; + + if (ts.MemberDefinition.IsImported) + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts); + + ctx.Module.Compiler.Report.Warning (436, 2, loc, + "The type `{0}' conflicts with the imported type of same name'. Ignoring the imported type definition", + best.GetSignatureForError ()); + } + + // + // Lookup for the best candidate with the closest arity match + // + if (arity < 0) { + if (best == null) { + best = ts; + } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) { + best = ts; + } + } + } + + if (best == null) + return null; + + te = new TypeExpression (best, Location.Null); + + // TODO MemberCache: Cache more + if (arity == 0 && mode == LookupMode.Normal) + cached_types.Add (name, te); + + return te; + } + + TypeSpec LookupType (string name, int arity) + { + if (types == null) + return null; + + IList found; + if (types.TryGetValue (name, out found)) { + TypeSpec best = null; + + foreach (var ts in found) { + if (ts.Arity == arity) + return ts; + + // + // Lookup for the best candidate with closest arity match + // + if (arity < 0) { + if (best == null) { + best = ts; + } else if (System.Math.Abs (ts.Arity + arity) < System.Math.Abs (best.Arity + arity)) { + best = ts; + } + } + } + + return best; + } + + return null; + } + + public FullNamedExpression LookupTypeOrNamespace (IMemberContext ctx, string name, int arity, LookupMode mode, Location loc) + { + var texpr = LookupType (ctx, name, arity, mode, loc); + + Namespace ns; + if (arity == 0 && namespaces.TryGetValue (name, out ns)) { + if (texpr == null) + return ns; + + if (mode != LookupMode.Probing) { + ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (texpr.Type); + // ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ns.loc, ""); + ctx.Module.Compiler.Report.Warning (437, 2, loc, + "The type `{0}' conflicts with the imported namespace `{1}'. Using the definition found in the source file", + texpr.GetSignatureForError (), ns.GetSignatureForError ()); + } + + if (texpr.Type.MemberDefinition.IsImported) + return ns; + } + + return texpr; + } + + // + // Completes types with the given `prefix' + // + public IEnumerable CompletionGetTypesStartingWith (string prefix) + { + if (types == null) + return Enumerable.Empty (); + + var res = from item in types + where item.Key.StartsWith (prefix) && item.Value.Any (l => (l.Modifiers & Modifiers.PUBLIC) != 0) + select item.Key; + + if (namespaces != null) + res = res.Concat (from item in namespaces where item.Key.StartsWith (prefix) select item.Key); + + return res; + } + + /// + /// Looks for extension method in this namespace + /// + public List LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity) + { + if (types == null) + return null; + + List found = null; + + // TODO: Add per namespace flag when at least 1 type has extension + + foreach (var tgroup in types.Values) { + foreach (var ts in tgroup) { + if ((ts.Modifiers & Modifiers.METHOD_EXTENSION) == 0) + continue; + + var res = ts.MemberCache.FindExtensionMethods (invocationContext, extensionType, name, arity); + if (res == null) + continue; + + if (found == null) { + found = res; + } else { + found.AddRange (res); + } + } + } + + return found; + } + + public void AddType (ModuleContainer module, TypeSpec ts) + { + if (types == null) { + types = new Dictionary> (64); + } + + var name = ts.Name; + IList existing; + if (types.TryGetValue (name, out existing)) { + TypeSpec better_type; + TypeSpec found; + if (existing.Count == 1) { + found = existing[0]; + if (ts.Arity == found.Arity) { + better_type = IsImportedTypeOverride (module, ts, found); + if (better_type == found) + return; + + if (better_type != null) { + existing [0] = better_type; + return; + } + } + + existing = new List (); + existing.Add (found); + types[name] = existing; + } else { + for (int i = 0; i < existing.Count; ++i) { + found = existing[i]; + if (ts.Arity != found.Arity) + continue; + + better_type = IsImportedTypeOverride (module, ts, found); + if (better_type == found) + return; + + if (better_type != null) { + existing.RemoveAt (i); + --i; + continue; + } + } + } + + existing.Add (ts); + } else { + types.Add (name, new TypeSpec[] { ts }); + } + } + + // + // We import any types but in the situation there are same types + // but one has better visibility (either public or internal with friend) + // the less visible type is removed from the namespace cache + // + public static TypeSpec IsImportedTypeOverride (ModuleContainer module, TypeSpec ts, TypeSpec found) + { + var ts_accessible = (ts.Modifiers & Modifiers.PUBLIC) != 0 || ts.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); + var found_accessible = (found.Modifiers & Modifiers.PUBLIC) != 0 || found.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly); + + if (ts_accessible && !found_accessible) + return ts; + + // found is better always better for accessible or inaccessible ts + if (!ts_accessible) + return found; + + return null; + } + + public void RemoveDeclSpace (string name) + { + types.Remove (name); + cached_types.Remove (name); + } + + public override FullNamedExpression ResolveAsTypeOrNamespace (IMemberContext mc) + { + return this; + } + + public void SetBuiltinType (BuiltinTypeSpec pts) + { + var found = types[pts.Name]; + cached_types.Remove (pts.Name); + if (found.Count == 1) { + types[pts.Name][0] = pts; + } else { + throw new NotImplementedException (); + } + } + + public void VerifyClsCompliance () + { + if (types == null || cls_checked) + return; + + cls_checked = true; + + // TODO: This is quite ugly way to check for CLS compliance at namespace level + + var locase_types = new Dictionary> (StringComparer.OrdinalIgnoreCase); + foreach (var tgroup in types.Values) { + foreach (var tm in tgroup) { + if ((tm.Modifiers & Modifiers.PUBLIC) == 0 || !tm.IsCLSCompliant ()) + continue; + + List found; + if (!locase_types.TryGetValue (tm.Name, out found)) { + found = new List (); + locase_types.Add (tm.Name, found); + } + + found.Add (tm); + } + } + + foreach (var locase in locase_types.Values) { + if (locase.Count < 2) + continue; + + bool all_same = true; + foreach (var notcompliant in locase) { + all_same = notcompliant.Name == locase[0].Name; + if (!all_same) + break; + } + + if (all_same) + continue; + + TypeContainer compiled = null; + foreach (var notcompliant in locase) { + if (!notcompliant.MemberDefinition.IsImported) { + if (compiled != null) + compiled.Compiler.Report.SymbolRelatedToPreviousError (compiled); + + compiled = notcompliant.MemberDefinition as TypeContainer; + } else { + compiled.Compiler.Report.SymbolRelatedToPreviousError (notcompliant); + } + } + + compiled.Compiler.Report.Warning (3005, 1, compiled.Location, + "Identifier `{0}' differing only in case is not CLS-compliant", compiled.GetSignatureForError ()); + } + } + } + + // + // Namespace block as created by the parser + // + public class NamespaceContainer : IMemberContext, ITypesContainer + { + Namespace ns; + + readonly ModuleContainer module; + readonly NamespaceContainer parent; + readonly CompilationSourceFile file; + readonly Location loc; + + NamespaceContainer implicit_parent; + int symfile_id; + + // Namespace using import block + List using_aliases; + List using_clauses; + public bool DeclarationFound; + // End + + bool resolved; + + public readonly bool IsImplicit; + public readonly TypeContainer SlaveDeclSpace; + static readonly Namespace [] empty_namespaces = new Namespace [0]; + static readonly string[] empty_using_list = new string[0]; + + Namespace [] namespace_using_table; + + public NamespaceContainer (MemberName name, ModuleContainer module, NamespaceContainer parent, CompilationSourceFile sourceFile) + { + this.module = module; + this.parent = parent; + this.file = sourceFile; + this.loc = name == null ? Location.Null : name.Location; + + if (parent != null) + ns = parent.NS.GetNamespace (name.GetName (), true); + else if (name != null) + ns = module.GlobalRootNamespace.GetNamespace (name.GetName (), true); + else + ns = module.GlobalRootNamespace; + + SlaveDeclSpace = new RootDeclSpace (module, this); + } + + private NamespaceContainer (ModuleContainer module, NamespaceContainer parent, CompilationSourceFile file, Namespace ns, bool slave) + { + this.module = module; + this.parent = parent; + this.file = file; + this.IsImplicit = true; + this.ns = ns; + this.SlaveDeclSpace = slave ? new RootDeclSpace (module, this) : null; + } + + #region Properties + + public Location Location { + get { + return loc; + } + } + + public MemberName MemberName { + get { + return ns.MemberName; + } + } + + public CompilationSourceFile SourceFile { + get { + return file; + } + } + + public List Usings { + get { + return using_clauses; + } + } + + #endregion + + // + // Extracts the using alises and using clauses into a couple of + // arrays that might already have the same information; Used by the + // C# Eval mode. + // + public void Extract (List out_using_aliases, List out_using_clauses) + { + if (using_aliases != null){ + foreach (NamespaceUsingAlias uae in using_aliases){ + bool replaced = false; + + for (int i = 0; i < out_using_aliases.Count; i++){ + NamespaceUsingAlias out_uea = (NamespaceUsingAlias) out_using_aliases [i]; + + if (out_uea.Alias == uae.Alias){ + out_using_aliases [i] = uae; + replaced = true; + break; + } + } + if (!replaced) + out_using_aliases.Add (uae); + } + } + + if (using_clauses != null){ + foreach (NamespaceUsing ue in using_clauses){ + bool found = false; + + foreach (NamespaceUsing out_ue in out_using_clauses) + if (out_ue.Name == ue.Name){ + found = true; + break; + } + if (!found) + out_using_clauses.Add (ue); + } + } + } + + // + // According to section 16.3.1 (using-alias-directive), the namespace-or-type-name is + // resolved as if the immediately containing namespace body has no using-directives. + // + // Section 16.3.2 says that the same rule is applied when resolving the namespace-name + // in the using-namespace-directive. + // + // To implement these rules, the expressions in the using directives are resolved using + // the "doppelganger" (ghostly bodiless duplicate). + // + NamespaceContainer doppelganger; + NamespaceContainer Doppelganger { + get { + if (!IsImplicit && doppelganger == null) { + doppelganger = new NamespaceContainer (module, ImplicitParent, file, ns, true); + doppelganger.using_aliases = using_aliases; + } + return doppelganger; + } + } + + public Namespace NS { + get { return ns; } + } + + public NamespaceContainer Parent { + get { return parent; } + } + + public NamespaceContainer ImplicitParent { + get { + if (parent == null) + return null; + if (implicit_parent == null) { + implicit_parent = (parent.NS == ns.Parent) + ? parent + : new NamespaceContainer (module, parent, file, ns.Parent, false); + } + return implicit_parent; + } + } + + /// + /// Records a new namespace for resolving name references + /// + public void AddUsing (MemberName name, Location loc) + { + if (DeclarationFound){ + Compiler.Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations"); + } + + if (using_clauses == null) { + using_clauses = new List (); + } else { + foreach (NamespaceUsing old_entry in using_clauses) { + if (name.Equals (old_entry.MemberName)) { + Compiler.Report.SymbolRelatedToPreviousError (old_entry.Location, old_entry.GetSignatureForError ()); + Compiler.Report.Warning (105, 3, loc, "The using directive for `{0}' appeared previously in this namespace", name.GetSignatureForError ()); + return; + } + } + } + + using_clauses.Add (new NamespaceUsing (name)); + } + + public void AddUsingAlias (string alias, MemberName name, Location loc) + { + if (DeclarationFound){ + Compiler.Report.Error (1529, loc, "A using clause must precede all other namespace elements except extern alias declarations"); + } + + AddUsingAlias (new LocalUsingAliasEntry (alias, name, loc)); + } + + public void AddUsingExternalAlias (string alias, Location loc, Report Report) + { + bool not_first = using_clauses != null || DeclarationFound; + if (using_aliases != null && !not_first) { + foreach (NamespaceUsingAlias uae in using_aliases) { + if (uae is LocalUsingAliasEntry) { + not_first = true; + break; + } + } + } + + if (not_first) + Report.Error (439, loc, "An extern alias declaration must precede all other elements"); + + if (alias == "global") { + Error_GlobalNamespaceRedefined (loc, Report); + return; + } + + AddUsingAlias (new NamespaceUsingAlias (alias, loc)); + } + + void AddUsingAlias (NamespaceUsingAlias uae) + { + if (using_aliases == null) { + using_aliases = new List (); + } else { + foreach (NamespaceUsingAlias entry in using_aliases) { + if (uae.Alias == entry.Alias) { + Compiler.Report.SymbolRelatedToPreviousError (uae.Location, uae.Alias); + Compiler.Report.Error (1537, entry.Location, "The using alias `{0}' appeared previously in this namespace", + entry.Alias); + return; + } + } + } + + using_aliases.Add (uae); + } + + // + // Does extension methods look up to find a method which matches name and extensionType. + // Search starts from this namespace and continues hierarchically up to top level. + // + public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + List candidates = null; + foreach (Namespace n in GetUsingTable ()) { + var a = n.LookupExtensionMethod (this, extensionType, name, arity); + if (a == null) + continue; + + if (candidates == null) + candidates = a; + else + candidates.AddRange (a); + } + + scope = parent; + if (candidates != null) + return candidates; + + if (parent == null) + return null; + + // + // Inspect parent namespaces in namespace expression + // + Namespace parent_ns = ns.Parent; + do { + candidates = parent_ns.LookupExtensionMethod (this, extensionType, name, arity); + if (candidates != null) + return candidates; + + parent_ns = parent_ns.Parent; + } while (parent_ns != null); + + // + // Continue in parent scope + // + return parent.LookupExtensionMethod (extensionType, name, arity, ref scope); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + // Precondition: Only simple names (no dots) will be looked up with this function. + FullNamedExpression resolved = null; + for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent) { + if ((resolved = curr_ns.Lookup (name, arity, mode, loc)) != null) + break; + } + + return resolved; + } + + public IList CompletionGetTypesStartingWith (string prefix) + { + IEnumerable all = Enumerable.Empty (); + + for (NamespaceContainer curr_ns = this; curr_ns != null; curr_ns = curr_ns.ImplicitParent){ + foreach (Namespace using_ns in GetUsingTable ()){ + if (prefix.StartsWith (using_ns.Name)){ + int ld = prefix.LastIndexOf ('.'); + if (ld != -1){ + string rest = prefix.Substring (ld+1); + + all = all.Concat (using_ns.CompletionGetTypesStartingWith (rest)); + } + } + all = all.Concat (using_ns.CompletionGetTypesStartingWith (prefix)); + } + } + + return all.Distinct ().ToList (); + } + + // Looks-up a alias named @name in this and surrounding namespace declarations + public FullNamedExpression LookupNamespaceAlias (string name) + { + for (NamespaceContainer n = this; n != null; n = n.ImplicitParent) { + if (n.using_aliases == null) + continue; + + foreach (NamespaceUsingAlias ue in n.using_aliases) { + if (ue.Alias == name) + return ue.Resolve (Doppelganger ?? this, Doppelganger == null); + } + } + + return null; + } + + FullNamedExpression Lookup (string name, int arity, LookupMode mode, Location loc) + { + // + // Check whether it's in the namespace. + // + FullNamedExpression fne = ns.LookupTypeOrNamespace (this, name, arity, mode, loc); + + // + // Check aliases. + // + if (using_aliases != null && arity == 0) { + foreach (NamespaceUsingAlias ue in using_aliases) { + if (ue.Alias == name) { + if (fne != null) { + if (Doppelganger != null) { + if (mode == LookupMode.Normal) { + // TODO: Namespace has broken location + //Report.SymbolRelatedToPreviousError (fne.Location, null); + Compiler.Report.SymbolRelatedToPreviousError (ue.Location, null); + Compiler.Report.Error (576, loc, + "Namespace `{0}' contains a definition with same name as alias `{1}'", + GetSignatureForError (), name); + } + } else { + return fne; + } + } + + return ue.Resolve (Doppelganger ?? this, Doppelganger == null); + } + } + } + + if (fne != null) + return fne; + + if (IsImplicit) + return null; + + // + // Check using entries. + // + FullNamedExpression match = null; + foreach (Namespace using_ns in GetUsingTable ()) { + // A using directive imports only types contained in the namespace, it + // does not import any nested namespaces + fne = using_ns.LookupType (this, name, arity, mode, loc); + if (fne == null) + continue; + + if (match == null) { + match = fne; + continue; + } + + // Prefer types over namespaces + var texpr_fne = fne as TypeExpr; + var texpr_match = match as TypeExpr; + if (texpr_fne != null && texpr_match == null) { + match = fne; + continue; + } else if (texpr_fne == null) { + continue; + } + + // It can be top level accessibility only + var better = Namespace.IsImportedTypeOverride (module, texpr_match.Type, texpr_fne.Type); + if (better == null) { + if (mode == LookupMode.Normal) { + Compiler.Report.SymbolRelatedToPreviousError (texpr_match.Type); + Compiler.Report.SymbolRelatedToPreviousError (texpr_fne.Type); + Compiler.Report.Error (104, loc, "`{0}' is an ambiguous reference between `{1}' and `{2}'", + name, texpr_match.GetSignatureForError (), texpr_fne.GetSignatureForError ()); + } + + return match; + } + + if (better == texpr_fne.Type) + match = texpr_fne; + } + + return match; + } + + Namespace [] GetUsingTable () + { + if (namespace_using_table != null) + return namespace_using_table; + + if (using_clauses == null) { + namespace_using_table = empty_namespaces; + return namespace_using_table; + } + + var list = new List (using_clauses.Count); + + foreach (NamespaceUsing ue in using_clauses) { + Namespace using_ns = ue.Resolve (Doppelganger); + if (using_ns == null) + continue; + + list.Add (using_ns); + } + + namespace_using_table = list.ToArray (); + return namespace_using_table; + } + + public int SymbolFileID { + get { + if (symfile_id == 0 && file.SourceFileEntry != null) { + int parent_id = parent == null ? 0 : parent.SymbolFileID; + + string [] using_list = empty_using_list; + if (using_clauses != null) { + using_list = new string [using_clauses.Count]; + for (int i = 0; i < using_clauses.Count; i++) + using_list [i] = ((NamespaceUsing) using_clauses [i]).MemberName.GetName (); + } + + symfile_id = SymbolWriter.DefineNamespace (ns.Name, file.CompileUnitEntry, using_list, parent_id); + } + return symfile_id; + } + } + + static void MsgtryRef (string s) + { + Console.WriteLine (" Try using -r:" + s); + } + + static void MsgtryPkg (string s) + { + Console.WriteLine (" Try using -pkg:" + s); + } + + public static void Error_GlobalNamespaceRedefined (Location loc, Report Report) + { + Report.Error (1681, loc, "The global extern alias cannot be redefined"); + } + + public static void Error_NamespaceNotFound (Location loc, string name, Report Report) + { + Report.Error (246, loc, "The type or namespace name `{0}' could not be found. Are you missing a using directive or an assembly reference?", + name); + + switch (name) { + case "Gtk": case "GtkSharp": + MsgtryPkg ("gtk-sharp-2.0"); + break; + + case "Gdk": case "GdkSharp": + MsgtryPkg ("gdk-sharp-2.0"); + break; + + case "Glade": case "GladeSharp": + MsgtryPkg ("glade-sharp-2.0"); + break; + + case "System.Drawing": + case "System.Web.Services": + case "System.Web": + case "System.Data": + case "System.Windows.Forms": + MsgtryRef (name); + break; + } + } + + /// + /// Used to validate that all the using clauses are correct + /// after we are finished parsing all the files. + /// + public void Resolve () + { + if (resolved) + return; + + resolved = true; + + if (using_aliases != null) { + foreach (NamespaceUsingAlias ue in using_aliases) + ue.Resolve (Doppelganger, Doppelganger == null); + } + + if (using_clauses != null) { + foreach (NamespaceUsing ue in using_clauses) + ue.Resolve (Doppelganger); + } + + if (parent != null) + parent.Resolve (); + } + + public string GetSignatureForError () + { + return ns.GetSignatureForError (); + } + + #region IMemberContext Members + + CompilerContext Compiler { + get { return module.Compiler; } + } + + public TypeSpec CurrentType { + get { return SlaveDeclSpace.CurrentType; } + } + + public MemberCore CurrentMemberDefinition { + get { return SlaveDeclSpace.CurrentMemberDefinition; } + } + + public TypeParameter[] CurrentTypeParameters { + get { return SlaveDeclSpace.CurrentTypeParameters; } + } + + public bool IsObsolete { + get { return SlaveDeclSpace.IsObsolete; } + } + + public bool IsUnsafe { + get { return SlaveDeclSpace.IsUnsafe; } + } + + public bool IsStatic { + get { return SlaveDeclSpace.IsStatic; } + } + + public ModuleContainer Module { + get { return module; } + } + + #endregion + } + + public class NamespaceUsing + { + readonly MemberName name; + Namespace resolved; + + public NamespaceUsing (MemberName name) + { + this.name = name; + } + + public string GetSignatureForError () + { + return name.GetSignatureForError (); + } + + public Location Location + { + get { return name.Location; } + } + + public MemberName MemberName + { + get { return name; } + } + + public string Name + { + get { return GetSignatureForError (); } + } + + public Namespace Resolve (IMemberContext rc) + { + if (resolved != null) + return resolved; + + FullNamedExpression fne = name.GetTypeExpression ().ResolveAsTypeOrNamespace (rc); + if (fne == null) + return null; + + resolved = fne as Namespace; + if (resolved == null) { + rc.Module.Compiler.Report.SymbolRelatedToPreviousError (fne.Type); + rc.Module.Compiler.Report.Error (138, Location, + "`{0}' is a type not a namespace. A using namespace directive can only be applied to namespaces", + GetSignatureForError ()); + } + return resolved; + } + } + + public class NamespaceUsingAlias + { + public readonly string Alias; + public Location Location; + + public NamespaceUsingAlias (string alias, Location loc) + { + this.Alias = alias; + this.Location = loc; + } + + public virtual FullNamedExpression Resolve (IMemberContext rc, bool local) + { + FullNamedExpression fne = rc.Module.GetRootNamespace (Alias); + if (fne == null) { + rc.Module.Compiler.Report.Error (430, Location, + "The extern alias `{0}' was not specified in -reference option", + Alias); + } + + return fne; + } + } + + class LocalUsingAliasEntry : NamespaceUsingAlias + { + FullNamedExpression resolved; + MemberName value; + + public LocalUsingAliasEntry (string alias, MemberName name, Location loc) + : base (alias, loc) + { + this.value = name; + } + + public override FullNamedExpression Resolve (IMemberContext rc, bool local) + { + if (resolved != null || value == null) + return resolved; + + if (local) + return null; + + resolved = value.GetTypeExpression ().ResolveAsTypeOrNamespace (rc); + if (resolved == null) { + value = null; + return null; + } + + return resolved; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs new file mode 100644 index 0000000000..f6b9abcca9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs @@ -0,0 +1,1292 @@ +// +// nullable.cs: Nullable types support +// +// Authors: Martin Baulig (martin@ximian.com) +// Miguel de Icaza (miguel@ximian.com) +// 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 +// + +using System; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp.Nullable +{ + public class NullableType : TypeExpr + { + readonly TypeSpec underlying; + + public NullableType (TypeSpec type, Location loc) + { + this.underlying = type; + this.loc = loc; + } + + public override TypeSpec ResolveAsType (IMemberContext ec) + { + eclass = ExprClass.Type; + + var otype = ec.Module.PredefinedTypes.Nullable.Resolve (); + if (otype == null) + return null; + + TypeArguments args = new TypeArguments (new TypeExpression (underlying, loc)); + GenericTypeExpr ctype = new GenericTypeExpr (otype, args, loc); + + type = ctype.ResolveAsType (ec); + return type; + } + } + + static class NullableInfo + { + public static MethodSpec GetConstructor (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (GetUnderlyingType (nullableType))), BindingRestriction.DeclaredOnly); + } + + public static MethodSpec GetHasValue (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Method ("get_HasValue", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); + } + + public static MethodSpec GetGetValueOrDefault (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Method ("GetValueOrDefault", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); + } + + public static MethodSpec GetValue (TypeSpec nullableType) + { + return (MethodSpec) MemberCache.FindMember (nullableType, + MemberFilter.Method ("get_Value", 0, ParametersCompiled.EmptyReadOnlyParameters, null), BindingRestriction.None); + } + + public static TypeSpec GetUnderlyingType (TypeSpec nullableType) + { + return ((InflatedTypeSpec) nullableType).TypeArguments[0]; + } + } + + public class Unwrap : Expression, IMemoryLocation, IAssignMethod + { + Expression expr; + + LocalTemporary temp; + readonly bool useDefaultValue; + + Unwrap (Expression expr, bool useDefaultValue) + { + this.expr = expr; + this.loc = expr.Location; + this.useDefaultValue = useDefaultValue; + + type = NullableInfo.GetUnderlyingType (expr.Type); + eclass = expr.eclass; + } + + public static Expression Create (Expression expr) + { + // + // Avoid unwraping and wraping of same type + // + Wrap wrap = expr as Wrap; + if (wrap != null) + return wrap.Child; + + return Create (expr, false); + } + + public static Unwrap Create (Expression expr, bool useDefaultValue) + { + return new Unwrap (expr, useDefaultValue); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) + { + expr = expr.DoResolveLValue (ec, right_side); + return this; + } + + public override void Emit (EmitContext ec) + { + Store (ec); + if (useDefaultValue) + Invocation.EmitCall (ec, this, NullableInfo.GetGetValueOrDefault (expr.Type), null, loc); + else + Invocation.EmitCall (ec, this, NullableInfo.GetValue (expr.Type), null, loc); + } + + public void EmitCheck (EmitContext ec) + { + Store (ec); + Invocation.EmitCall (ec, this, NullableInfo.GetHasValue (expr.Type), null, loc); + } + + public override bool Equals (object obj) + { + Unwrap uw = obj as Unwrap; + return uw != null && expr.Equals (uw.expr); + } + + public Expression Original { + get { + return expr; + } + } + + public override int GetHashCode () + { + return expr.GetHashCode (); + } + + public override bool IsNull { + get { + return expr.IsNull; + } + } + + void Store (EmitContext ec) + { + if (expr is VariableReference) + return; + + if (temp != null) + return; + + expr.Emit (ec); + LocalVariable.Store (ec); + } + + public void Load (EmitContext ec) + { + if (expr is VariableReference) + expr.Emit (ec); + else + LocalVariable.Emit (ec); + } + + public override System.Linq.Expressions.Expression MakeExpression (BuilderContext ctx) + { + return expr.MakeExpression (ctx); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + IMemoryLocation ml = expr as VariableReference; + if (ml != null) + ml.AddressOf (ec, mode); + else + LocalVariable.AddressOf (ec, mode); + } + + // + // Keeps result of non-variable expression + // + LocalTemporary LocalVariable { + get { + if (temp == null) + temp = new LocalTemporary (expr.Type); + return temp; + } + } + + public void Emit (EmitContext ec, bool leave_copy) + { + if (leave_copy) + Load (ec); + + Emit (ec); + } + + public void EmitAssign (EmitContext ec, Expression source, + bool leave_copy, bool prepare_for_load) + { + InternalWrap wrap = new InternalWrap (source, expr.Type, loc); + ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false); + } + + class InternalWrap : Expression + { + public Expression expr; + + public InternalWrap (Expression expr, TypeSpec type, Location loc) + { + this.expr = expr; + this.loc = loc; + this.type = type; + + eclass = ExprClass.Value; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException ("ET"); + } + + protected override Expression DoResolve (ResolveContext ec) + { + return this; + } + + public override void Emit (EmitContext ec) + { + expr.Emit (ec); + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } + } + } + + // + // Calls get_Value method on nullable expression + // + public class UnwrapCall : CompositeExpression + { + public UnwrapCall (Expression expr) + : base (expr) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + base.DoResolve (rc); + + if (type != null) + type = NullableInfo.GetUnderlyingType (type); + + return this; + } + + public override void Emit (EmitContext ec) + { + Invocation.EmitCall (ec, Child, NullableInfo.GetValue (Child.Type), null, loc); + } + } + + public class Wrap : TypeCast + { + private Wrap (Expression expr, TypeSpec type) + : base (expr, type) + { + eclass = ExprClass.Value; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + TypeCast child_cast = child as TypeCast; + if (child_cast != null) { + child.Type = type; + return child_cast.CreateExpressionTree (ec); + } + + return base.CreateExpressionTree (ec); + } + + public static Expression Create (Expression expr, TypeSpec type) + { + // + // Avoid unwraping and wraping of the same type + // + Unwrap unwrap = expr as Unwrap; + if (unwrap != null && expr.Type == NullableInfo.GetUnderlyingType (type)) + return unwrap.Original; + + return new Wrap (expr, type); + } + + public override void Emit (EmitContext ec) + { + child.Emit (ec); + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } + } + + // + // Represents null literal lifted to nullable type + // + public class LiftedNull : NullConstant, IMemoryLocation + { + private LiftedNull (TypeSpec nullable_type, Location loc) + : base (nullable_type, loc) + { + eclass = ExprClass.Value; + } + + public static Constant Create (TypeSpec nullable, Location loc) + { + return new LiftedNull (nullable, loc); + } + + public static Constant CreateFromExpression (ResolveContext ec, Expression e) + { + ec.Report.Warning (458, 2, e.Location, "The result of the expression is always `null' of type `{0}'", + TypeManager.CSharpName (e.Type)); + + return ReducedExpression.Create (Create (e.Type, e.Location), e); + } + + public override void Emit (EmitContext ec) + { + // TODO: generate less temporary variables + LocalTemporary value_target = new LocalTemporary (type); + + value_target.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + value_target.Emit (ec); + } + + public void AddressOf (EmitContext ec, AddressOp Mode) + { + LocalTemporary value_target = new LocalTemporary (type); + + value_target.AddressOf (ec, AddressOp.Store); + ec.Emit (OpCodes.Initobj, type); + ((IMemoryLocation) value_target).AddressOf (ec, Mode); + } + } + + // + // Generic lifting expression, supports all S/S? -> T/T? cases + // + public class Lifted : Expression, IMemoryLocation + { + Expression expr, null_value; + Unwrap unwrap; + + public Lifted (Expression expr, Unwrap unwrap, TypeSpec type) + { + this.expr = expr; + this.unwrap = unwrap; + this.loc = expr.Location; + this.type = type; + } + + public Lifted (Expression expr, Expression unwrap, TypeSpec type) + : this (expr, unwrap as Unwrap, type) + { + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return expr.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + // + // It's null when lifting non-nullable type + // + if (unwrap == null) { + // S -> T? is wrap only + if (type.IsNullableType) + return Wrap.Create (expr, type); + + // S -> T can be simplified + return expr; + } + + // Wrap target for T? + if (type.IsNullableType) { + expr = Wrap.Create (expr, type); + if (expr == null) + return null; + + null_value = LiftedNull.Create (type, loc); + } else if (TypeSpec.IsValueType (type)) { + null_value = LiftedNull.Create (type, loc); + } else { + null_value = new NullConstant (type, loc); + } + + eclass = ExprClass.Value; + return this; + } + + public override void Emit (EmitContext ec) + { + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + expr.Emit (ec); + + ec.Emit (OpCodes.Br, end_label); + ec.MarkLabel (is_null_label); + + null_value.Emit (ec); + ec.MarkLabel (end_label); + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + unwrap.AddressOf (ec, mode); + } + } + + public class LiftedUnaryOperator : Unary, IMemoryLocation + { + Unwrap unwrap; + Expression user_operator; + + public LiftedUnaryOperator (Unary.Operator op, Expression expr, Location loc) + : base (op, expr, loc) + { + } + + public void AddressOf (EmitContext ec, AddressOp mode) + { + unwrap.AddressOf (ec, mode); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (user_operator != null) + return user_operator.CreateExpressionTree (ec); + + if (Oper == Operator.UnaryPlus) + return Expr.CreateExpressionTree (ec); + + return base.CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + unwrap = Unwrap.Create (Expr, false); + if (unwrap == null) + return null; + + Expression res = base.ResolveOperator (ec, unwrap); + if (res != this) { + if (user_operator == null) + return res; + } else { + res = Expr = LiftExpression (ec, Expr); + } + + if (res == null) + return null; + + eclass = ExprClass.Value; + type = res.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + if (user_operator != null) { + user_operator.Emit (ec); + } else { + EmitOperator (ec, NullableInfo.GetUnderlyingType (type)); + } + + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + ec.Emit (OpCodes.Br_S, end_label); + + ec.MarkLabel (is_null_label); + LiftedNull.Create (type, loc).Emit (ec); + + ec.MarkLabel (end_label); + } + + Expression LiftExpression (ResolveContext ec, Expression expr) + { + var lifted_type = new NullableType (expr.Type, expr.Location); + if (lifted_type.ResolveAsType (ec) == null) + return null; + + expr.Type = lifted_type.Type; + return expr; + } + + protected override Expression ResolveEnumOperator (ResolveContext ec, Expression expr, TypeSpec[] predefined) + { + expr = base.ResolveEnumOperator (ec, expr, predefined); + if (expr == null) + return null; + + Expr = LiftExpression (ec, Expr); + return LiftExpression (ec, expr); + } + + protected override Expression ResolveUserOperator (ResolveContext ec, Expression expr) + { + expr = base.ResolveUserOperator (ec, expr); + if (expr == null) + return null; + + // + // When a user operator is of non-nullable type + // + if (Expr is Unwrap) { + user_operator = LiftExpression (ec, expr); + return user_operator; + } + + return expr; + } + } + + public class LiftedBinaryOperator : Binary + { + Unwrap left_unwrap, right_unwrap; + Expression left_orig, right_orig; + Expression user_operator; + MethodSpec wrap_ctor; + + public LiftedBinaryOperator (Binary.Operator op, Expression left, Expression right, Location loc) + : base (op, left, right, loc) + { + } + + bool IsBitwiseBoolean { + get { + return (Oper == Operator.BitwiseAnd || Oper == Operator.BitwiseOr) && + ((left_unwrap != null && left_unwrap.Type.BuiltinType == BuiltinTypeSpec.Type.Bool) || + (right_unwrap != null && right_unwrap.Type.BuiltinType == BuiltinTypeSpec.Type.Bool)); + } + } + + bool IsLeftNullLifted { + get { + return (state & State.LeftNullLifted) != 0; + } + } + + bool IsRightNullLifted { + get { + return (state & State.RightNullLifted) != 0; + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (user_operator != null) + return user_operator.CreateExpressionTree (ec); + + return base.CreateExpressionTree (ec); + } + + // + // CSC 2 has this behavior, it allows structs to be compared + // with the null literal *outside* of a generics context and + // inlines that as true or false. + // + Constant CreateNullConstant (ResolveContext ec, Expression expr) + { + // FIXME: Handle side effect constants + Constant c = new BoolConstant (ec.BuiltinTypes, Oper == Operator.Inequality, loc); + + if ((Oper & Operator.EqualityMask) != 0) { + ec.Report.Warning (472, 2, loc, "The result of comparing value type `{0}' with null is `{1}'", + TypeManager.CSharpName (expr.Type), c.GetValueAsLiteral ()); + } else { + ec.Report.Warning (464, 2, loc, "The result of comparing type `{0}' with null is always `{1}'", + TypeManager.CSharpName (expr.Type), c.GetValueAsLiteral ()); + } + + return ReducedExpression.Create (c, this); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if ((Oper & Operator.LogicalMask) != 0) { + Error_OperatorCannotBeApplied (ec, left, right); + return null; + } + + bool use_default_call = (Oper & (Operator.BitwiseMask | Operator.EqualityMask)) != 0; + left_orig = left; + if (left.Type.IsNullableType) { + left = left_unwrap = Unwrap.Create (left, use_default_call); + if (left == null) + return null; + } + + right_orig = right; + if (right.Type.IsNullableType) { + right = right_unwrap = Unwrap.Create (right, use_default_call); + if (right == null) + return null; + } + + // + // Some details are in 6.4.2, 7.2.7 + // Arguments can be lifted for equal operators when the return type is bool and both + // arguments are of same type + // + if (left_orig is NullLiteral) { + left = right; + state |= State.LeftNullLifted; + type = ec.BuiltinTypes.Bool; + } + + if (right_orig.IsNull) { + if ((Oper & Operator.ShiftMask) != 0) + right = new EmptyExpression (ec.BuiltinTypes.Int); + else + right = left; + + state |= State.RightNullLifted; + type = ec.BuiltinTypes.Bool; + } + + eclass = ExprClass.Value; + return DoResolveCore (ec, left_orig, right_orig); + } + + void EmitBitwiseBoolean (EmitContext ec) + { + Label load_left = ec.DefineLabel (); + Label load_right = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + // null & value, null | value + if (left_unwrap == null) { + left_unwrap = right_unwrap; + right_unwrap = null; + right = left; + } + + left_unwrap.Emit (ec); + ec.Emit (OpCodes.Brtrue_S, load_right); + + // value & null, value | null + if (right_unwrap != null) { + right_unwrap.Emit (ec); + ec.Emit (OpCodes.Brtrue_S, load_left); + } + + left_unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse_S, load_right); + + // load left + ec.MarkLabel (load_left); + + if (Oper == Operator.BitwiseAnd) { + left_unwrap.Load (ec); + } else { + if (right_unwrap == null) { + right.Emit (ec); + if (right is EmptyConstantCast || right is EmptyCast) + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } else { + right_unwrap.Load (ec); + right_unwrap = left_unwrap; + } + } + ec.Emit (OpCodes.Br_S, end_label); + + // load right + ec.MarkLabel (load_right); + if (right_unwrap == null) { + if (Oper == Operator.BitwiseAnd) { + right.Emit (ec); + if (right is EmptyConstantCast || right is EmptyCast) + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + } else { + left_unwrap.Load (ec); + } + } else { + right_unwrap.Load (ec); + } + + ec.MarkLabel (end_label); + } + + // + // Emits optimized equality or inequality operator when possible + // + void EmitEquality (EmitContext ec) + { + // + // Either left or right is null + // + if (left_unwrap != null && (IsRightNullLifted || right.IsNull)) { + left_unwrap.EmitCheck (ec); + if (Oper == Binary.Operator.Equality) { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + } + return; + } + + if (right_unwrap != null && (IsLeftNullLifted || left.IsNull)) { + right_unwrap.EmitCheck (ec); + if (Oper == Binary.Operator.Equality) { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + } + return; + } + + Label dissimilar_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + if (user_operator != null) { + user_operator.Emit (ec); + ec.Emit (Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label); + } else { + left.Emit (ec); + right.Emit (ec); + + ec.Emit (OpCodes.Bne_Un_S, dissimilar_label); + } + + if (left_unwrap != null) + left_unwrap.EmitCheck (ec); + + if (right_unwrap != null) + right_unwrap.EmitCheck (ec); + + if (left_unwrap != null && right_unwrap != null) { + if (Oper == Operator.Inequality) + ec.Emit (OpCodes.Xor); + else + ec.Emit (OpCodes.Ceq); + } else { + if (Oper == Operator.Inequality) { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Ceq); + } + } + + ec.Emit (OpCodes.Br_S, end_label); + + ec.MarkLabel (dissimilar_label); + if (Oper == Operator.Inequality) + ec.Emit (OpCodes.Ldc_I4_1); + else + ec.Emit (OpCodes.Ldc_I4_0); + + ec.MarkLabel (end_label); + } + + public override void EmitBranchable (EmitContext ec, Label target, bool onTrue) + { + Emit (ec); + ec.Emit (onTrue ? OpCodes.Brtrue : OpCodes.Brfalse, target); + } + + public override void Emit (EmitContext ec) + { + // + // Optimize same expression operation + // + if (right_unwrap != null && right.Equals (left)) + right_unwrap = left_unwrap; + + if (user_operator == null && IsBitwiseBoolean) { + EmitBitwiseBoolean (ec); + return; + } + + if ((Oper & Operator.EqualityMask) != 0) { + EmitEquality (ec); + return; + } + + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + if (left_unwrap != null) { + left_unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + } + + // + // Don't emit HasValue check when left and right expressions are same + // + if (right_unwrap != null && !left.Equals (right)) { + right_unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + } + + EmitOperator (ec, left.Type); + + if (wrap_ctor != null) + ec.Emit (OpCodes.Newobj, wrap_ctor); + + ec.Emit (OpCodes.Br_S, end_label); + ec.MarkLabel (is_null_label); + + if ((Oper & Operator.ComparisonMask) != 0) { + ec.Emit (OpCodes.Ldc_I4_0); + } else { + LiftedNull.Create (type, loc).Emit (ec); + } + + ec.MarkLabel (end_label); + } + + protected override void EmitOperator (EmitContext ec, TypeSpec l) + { + if (user_operator != null) { + user_operator.Emit (ec); + return; + } + + if (l.IsNullableType) + l = TypeManager.GetTypeArguments (l) [0]; + + base.EmitOperator (ec, l); + } + + Expression LiftResult (ResolveContext ec, Expression res_expr) + { + TypeSpec lifted_type; + + // + // Avoid double conversion + // + if (left_unwrap == null || IsLeftNullLifted || left_unwrap.Type != left.Type || (left_unwrap != null && IsRightNullLifted)) { + lifted_type = new NullableType (left.Type, loc).ResolveAsType (ec); + if (lifted_type == null) + return null; + + if (left is UserCast || left is TypeCast) + left.Type = lifted_type; + else + left = EmptyCast.Create (left, lifted_type); + } + + if (left != right && (right_unwrap == null || IsRightNullLifted || right_unwrap.Type != right.Type || (right_unwrap != null && IsLeftNullLifted))) { + lifted_type = new NullableType (right.Type, loc).ResolveAsType (ec); + if (lifted_type == null) + return null; + + var r = right; + if (r is ReducedExpression) + r = ((ReducedExpression) r).OriginalExpression; + + if (r is UserCast || r is TypeCast) + r.Type = lifted_type; + else + right = EmptyCast.Create (right, lifted_type); + } + + if ((Oper & Operator.ComparisonMask) == 0) { + lifted_type = new NullableType (res_expr.Type, loc).ResolveAsType (ec); + if (lifted_type == null) + return null; + + wrap_ctor = NullableInfo.GetConstructor (lifted_type); + type = res_expr.Type = lifted_type; + } + + if (IsLeftNullLifted) { + left = LiftedNull.Create (right.Type, left.Location); + + // + // Special case for bool?, the result depends on both null right side and left side value + // + if ((Oper == Operator.BitwiseAnd || Oper == Operator.BitwiseOr) && NullableInfo.GetUnderlyingType (type).BuiltinType == BuiltinTypeSpec.Type.Bool) { + return res_expr; + } + + if ((Oper & (Operator.ArithmeticMask | Operator.ShiftMask | Operator.BitwiseMask)) != 0) + return LiftedNull.CreateFromExpression (ec, res_expr); + + // + // Value types and null comparison + // + if (right_unwrap == null || (Oper & Operator.RelationalMask) != 0) + return CreateNullConstant (ec, right_orig); + } + + if (IsRightNullLifted) { + right = LiftedNull.Create (left.Type, right.Location); + + // + // Special case for bool?, the result depends on both null right side and left side value + // + if ((Oper == Operator.BitwiseAnd || Oper == Operator.BitwiseOr) && NullableInfo.GetUnderlyingType (type).BuiltinType == BuiltinTypeSpec.Type.Bool) { + return res_expr; + } + + if ((Oper & (Operator.ArithmeticMask | Operator.ShiftMask | Operator.BitwiseMask)) != 0) + return LiftedNull.CreateFromExpression (ec, res_expr); + + // + // Value types and null comparison + // + if (left_unwrap == null || (Oper & Operator.RelationalMask) != 0) + return CreateNullConstant (ec, left_orig); + } + + return res_expr; + } + + protected override Expression ResolveOperatorPredefined (ResolveContext ec, Binary.PredefinedOperator [] operators, bool primitives_only, TypeSpec enum_type) + { + Expression e = base.ResolveOperatorPredefined (ec, operators, primitives_only, enum_type); + + if (e == this || enum_type != null) + return LiftResult (ec, e); + + // + // 7.9.9 Equality operators and null + // + // The == and != operators permit one operand to be a value of a nullable type and + // the other to be the null literal, even if no predefined or user-defined operator + // (in unlifted or lifted form) exists for the operation. + // + if (e == null && (Oper & Operator.EqualityMask) != 0) { + if ((IsLeftNullLifted && right_unwrap != null) || (IsRightNullLifted && left_unwrap != null)) + return LiftResult (ec, this); + } + + return e; + } + + protected override Expression ResolveUserOperator (ResolveContext ec, Expression left, Expression right) + { + // + // Try original types first for exact match without unwrapping + // + Expression expr = base.ResolveUserOperator (ec, left_orig, right_orig); + if (expr != null) + return expr; + + State orig_state = state; + + // + // One side is a nullable type, try to match underlying types + // + if (left_unwrap != null || right_unwrap != null || (state & (State.RightNullLifted | State.LeftNullLifted)) != 0) { + expr = base.ResolveUserOperator (ec, left, right); + } + + if (expr == null) + return null; + + // + // Lift the result in the case it can be null and predefined or user operator + // result type is of a value type + // + if (!TypeSpec.IsValueType (expr.Type)) + return null; + + if (state != orig_state) + return expr; + + expr = LiftResult (ec, expr); + if (expr is Constant) + return expr; + + type = expr.Type; + user_operator = expr; + return this; + } + } + + public class NullCoalescingOperator : Expression + { + Expression left, right; + Unwrap unwrap; + + public Expression Left { + get { return this.left; } + } + + public Expression Right { + get { return this.right; } + } + + public NullCoalescingOperator (Expression left, Expression right, Location loc) + { + this.left = left; + this.right = right; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (left is NullLiteral) + ec.Report.Error (845, loc, "An expression tree cannot contain a coalescing operator with null left side"); + + UserCast uc = left as UserCast; + Expression conversion = null; + if (uc != null) { + left = uc.Source; + + Arguments c_args = new Arguments (2); + c_args.Add (new Argument (uc.CreateExpressionTree (ec))); + c_args.Add (new Argument (left.CreateExpressionTree (ec))); + conversion = CreateExpressionFactoryCall (ec, "Lambda", c_args); + } + + Arguments args = new Arguments (3); + args.Add (new Argument (left.CreateExpressionTree (ec))); + args.Add (new Argument (right.CreateExpressionTree (ec))); + if (conversion != null) + args.Add (new Argument (conversion)); + + return CreateExpressionFactoryCall (ec, "Coalesce", args); + } + + Expression ConvertExpression (ResolveContext ec) + { + // TODO: ImplicitConversionExists should take care of this + if (left.eclass == ExprClass.MethodGroup) + return null; + + TypeSpec ltype = left.Type; + + // + // If left is a nullable type and an implicit conversion exists from right to underlying type of left, + // the result is underlying type of left + // + if (ltype.IsNullableType) { + unwrap = Unwrap.Create (left, false); + if (unwrap == null) + return null; + + // + // Reduce (left ?? null) to left + // + if (right.IsNull) + return ReducedExpression.Create (left, this); + + if (Convert.ImplicitConversionExists (ec, right, unwrap.Type)) { + left = unwrap; + ltype = left.Type; + + // + // If right is a dynamic expression, the result type is dynamic + // + if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + type = right.Type; + + // Need to box underlying value type + left = Convert.ImplicitBoxingConversion (left, ltype, type); + return this; + } + + right = Convert.ImplicitConversion (ec, right, ltype, loc); + type = ltype; + return this; + } + } else if (TypeSpec.IsReferenceType (ltype)) { + if (Convert.ImplicitConversionExists (ec, right, ltype)) { + // + // If right is a dynamic expression, the result type is dynamic + // + if (right.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + type = right.Type; + return this; + } + + // + // Reduce ("foo" ?? expr) to expression + // + Constant lc = left as Constant; + if (lc != null && !lc.IsDefaultValue) + return ReducedExpression.Create (lc, this); + + // + // Reduce (left ?? null) to left OR (null-constant ?? right) to right + // + if (right.IsNull || lc != null) + return ReducedExpression.Create (lc != null ? right : left, this); + + right = Convert.ImplicitConversion (ec, right, ltype, loc); + type = ltype; + return this; + } + + // + // Special case null ?? null + // + if (ltype == right.Type) { + type = ltype; + return this; + } + } else { + return null; + } + + TypeSpec rtype = right.Type; + if (!Convert.ImplicitConversionExists (ec, unwrap != null ? unwrap : left, rtype) || right.eclass == ExprClass.MethodGroup) + return null; + + // + // Reduce (null ?? right) to right + // + if (left.IsNull) + return ReducedExpression.Create (right, this).Resolve (ec); + + left = Convert.ImplicitConversion (ec, unwrap != null ? unwrap : left, rtype, loc); + type = rtype; + return this; + } + + protected override Expression DoResolve (ResolveContext ec) + { + left = left.Resolve (ec); + right = right.Resolve (ec); + + if (left == null || right == null) + return null; + + eclass = ExprClass.Value; + + Expression e = ConvertExpression (ec); + if (e == null) { + Binary.Error_OperatorCannotBeApplied (ec, left, right, "??", loc); + return null; + } + + return e; + } + + public override void Emit (EmitContext ec) + { + Label end_label = ec.DefineLabel (); + + if (unwrap != null) { + Label is_null_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + left.Emit (ec); + ec.Emit (OpCodes.Br, end_label); + + ec.MarkLabel (is_null_label); + right.Emit (ec); + + ec.MarkLabel (end_label); + return; + } + + left.Emit (ec); + ec.Emit (OpCodes.Dup); + + // Only to make verifier happy + if (left.Type.IsGenericParameter) + ec.Emit (OpCodes.Box, left.Type); + + ec.Emit (OpCodes.Brtrue, end_label); + + ec.Emit (OpCodes.Pop); + right.Emit (ec); + + ec.MarkLabel (end_label); + } + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + NullCoalescingOperator target = (NullCoalescingOperator) t; + + target.left = left.Clone (clonectx); + target.right = right.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class LiftedUnaryMutator : ExpressionStatement + { + public readonly UnaryMutator.Mode Mode; + Expression expr; + UnaryMutator underlying; + Unwrap unwrap; + + public LiftedUnaryMutator (UnaryMutator.Mode mode, Expression expr, Location loc) + { + this.expr = expr; + this.Mode = mode; + this.loc = loc; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + return new SimpleAssign (this, this).CreateExpressionTree (ec); + } + + protected override Expression DoResolve (ResolveContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return null; + + unwrap = Unwrap.Create (expr, false); + if (unwrap == null) + return null; + + underlying = (UnaryMutator) new UnaryMutator (Mode, unwrap, loc).Resolve (ec); + if (underlying == null) + return null; + + + eclass = ExprClass.Value; + type = expr.Type; + return this; + } + + void DoEmit (EmitContext ec, bool is_expr) + { + Label is_null_label = ec.DefineLabel (); + Label end_label = ec.DefineLabel (); + + unwrap.EmitCheck (ec); + ec.Emit (OpCodes.Brfalse, is_null_label); + + if (is_expr) { + underlying.Emit (ec); + ec.Emit (OpCodes.Br_S, end_label); + } else { + underlying.EmitStatement (ec); + } + + ec.MarkLabel (is_null_label); + if (is_expr) + LiftedNull.Create (type, loc).Emit (ec); + + ec.MarkLabel (end_label); + } + + public override void Emit (EmitContext ec) + { + DoEmit (ec, true); + } + + public override void EmitStatement (EmitContext ec) + { + DoEmit (ec, false); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs new file mode 100644 index 0000000000..784cece95b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs @@ -0,0 +1,1024 @@ +// +// outline -- support for rendering in monop +// Some code stolen from updater.cs in monodoc. +// +// Authors: +// Ben Maurer (bmaurer@users.sourceforge.net) +// +// (C) 2004 Ben Maurer +// + +// +// 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.Reflection; +using System.Collections; +using System.CodeDom.Compiler; +using System.IO; +using System.Text; + +namespace Mono.CSharp { +public class Outline { + + bool declared_only; + bool show_private; + bool filter_obsolete; + + IndentedTextWriter o; + Type t; + + public Outline (Type t, TextWriter output, bool declared_only, bool show_private, bool filter_obsolete) + { + this.t = t; + this.o = new IndentedTextWriter (output, "\t"); + this.declared_only = declared_only; + this.show_private = show_private; + this.filter_obsolete = filter_obsolete; + } + + public void OutlineType () + { + bool first; + + OutlineAttributes (); + o.Write (GetTypeVisibility (t)); + + if (t.IsClass && !t.IsSubclassOf (typeof (System.MulticastDelegate))) { + if (t.IsSealed) + o.Write (t.IsAbstract ? " static" : " sealed"); + else if (t.IsAbstract) + o.Write (" abstract"); + } + + o.Write (" "); + o.Write (GetTypeKind (t)); + o.Write (" "); + + Type [] interfaces = (Type []) Comparer.Sort (TypeGetInterfaces (t, declared_only)); + Type parent = t.BaseType; + + if (t.IsSubclassOf (typeof (System.MulticastDelegate))) { + MethodInfo method; + + method = t.GetMethod ("Invoke"); + + o.Write (FormatType (method.ReturnType)); + o.Write (" "); + o.Write (GetTypeName (t)); + o.Write (" ("); + OutlineParams (method.GetParameters ()); + o.Write (")"); + +#if NET_2_0 + WriteGenericConstraints (t.GetGenericArguments ()); +#endif + + o.WriteLine (";"); + return; + } + + o.Write (GetTypeName (t)); + if (((parent != null && parent != typeof (object) && parent != typeof (ValueType)) || interfaces.Length != 0) && ! t.IsEnum) { + first = true; + o.Write (" : "); + + if (parent != null && parent != typeof (object) && parent != typeof (ValueType)) { + o.Write (FormatType (parent)); + first = false; + } + + foreach (Type intf in interfaces) { + if (!first) o.Write (", "); + first = false; + + o.Write (FormatType (intf)); + } + } + + if (t.IsEnum) { + Type underlyingType = System.Enum.GetUnderlyingType (t); + if (underlyingType != typeof (int)) + o.Write (" : {0}", FormatType (underlyingType)); + } +#if NET_2_0 + WriteGenericConstraints (t.GetGenericArguments ()); +#endif + o.WriteLine (" {"); + o.Indent++; + + if (t.IsEnum) { + bool is_first = true; + foreach (FieldInfo fi in t.GetFields (BindingFlags.Public | BindingFlags.Static)) { + + if (! is_first) + o.WriteLine (","); + is_first = false; + o.Write (fi.Name); + } + o.WriteLine (); + o.Indent--; o.WriteLine ("}"); + return; + } + + first = true; + + foreach (ConstructorInfo ci in t.GetConstructors (DefaultFlags)) { + + if (! ShowMember (ci)) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineConstructor (ci); + + o.WriteLine (); + } + + + first = true; + + foreach (MethodInfo m in Comparer.Sort (t.GetMethods (DefaultFlags))) { + + if (! ShowMember (m)) + continue; + + if ((m.Attributes & MethodAttributes.SpecialName) != 0) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineMethod (m); + + o.WriteLine (); + } + + first = true; + + foreach (MethodInfo m in t.GetMethods (DefaultFlags)) { + + if (! ShowMember (m)) + continue; + + if ((m.Attributes & MethodAttributes.SpecialName) == 0) + continue; + if (!(m.Name.StartsWith ("op_"))) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineOperator (m); + + o.WriteLine (); + } + + first = true; + + foreach (PropertyInfo pi in Comparer.Sort (t.GetProperties (DefaultFlags))) { + + if (! ((pi.CanRead && ShowMember (pi.GetGetMethod (true))) || + (pi.CanWrite && ShowMember (pi.GetSetMethod (true))))) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineProperty (pi); + + o.WriteLine (); + } + + first = true; + + foreach (FieldInfo fi in t.GetFields (DefaultFlags)) { + + if (! ShowMember (fi)) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineField (fi); + + o.WriteLine (); + } + + first = true; + + foreach (EventInfo ei in Comparer.Sort (t.GetEvents (DefaultFlags))) { + + if (! ShowMember (ei.GetAddMethod (true))) + continue; + + if (first) + o.WriteLine (); + first = false; + + OutlineEvent (ei); + + o.WriteLine (); + } + + first = true; + + foreach (Type ntype in Comparer.Sort (t.GetNestedTypes (DefaultFlags))) { + + if (! ShowMember (ntype)) + continue; + + if (first) + o.WriteLine (); + first = false; + + new Outline (ntype, o, declared_only, show_private, filter_obsolete).OutlineType (); + } + + o.Indent--; o.WriteLine ("}"); + } + + BindingFlags DefaultFlags { + get { + BindingFlags f = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; + + if (declared_only) + f |= BindingFlags.DeclaredOnly; + + return f; + } + } + + // FIXME: add other interesting attributes? + void OutlineAttributes () + { + if (t.IsSerializable) + o.WriteLine ("[Serializable]"); + + if (t.IsDefined (typeof (System.FlagsAttribute), true)) + o.WriteLine ("[Flags]"); + + if (t.IsDefined (typeof (System.ObsoleteAttribute), true)) + o.WriteLine ("[Obsolete]"); + } + + void OutlineEvent (EventInfo ei) + { + MethodBase accessor = ei.GetAddMethod (true); + + o.Write (GetMethodVisibility (accessor)); + o.Write ("event "); + o.Write (FormatType (ei.EventHandlerType)); + o.Write (" "); + o.Write (ei.Name); + o.Write (";"); + } + + void OutlineConstructor (ConstructorInfo ci) + { + o.Write (GetMethodVisibility (ci)); + o.Write (RemoveGenericArity (t.Name)); + o.Write (" ("); + OutlineParams (ci.GetParameters ()); + o.Write (");"); + } + + + void OutlineProperty (PropertyInfo pi) + { + ParameterInfo [] idxp = pi.GetIndexParameters (); + MethodBase g = pi.GetGetMethod (true); + MethodBase s = pi.GetSetMethod (true); + MethodBase accessor = g != null ? g : s; + + if (pi.CanRead && pi.CanWrite) { + + + // Get the more accessible accessor + if ((g.Attributes & MethodAttributes.MemberAccessMask) != + (s.Attributes & MethodAttributes.MemberAccessMask)) { + + if (g.IsPublic) accessor = g; + else if (s.IsPublic) accessor = s; + else if (g.IsFamilyOrAssembly) accessor = g; + else if (s.IsFamilyOrAssembly) accessor = s; + else if (g.IsAssembly || g.IsFamily) accessor = g; + else if (s.IsAssembly || s.IsFamily) accessor = s; + } + } + + o.Write (GetMethodVisibility (accessor)); + o.Write (GetMethodModifiers (accessor)); + o.Write (FormatType (pi.PropertyType)); + o.Write (" "); + + if (idxp.Length == 0) + o.Write (pi.Name); + else { + o.Write ("this ["); + OutlineParams (idxp); + o.Write ("]"); + } + + o.WriteLine (" {"); + o.Indent ++; + + if (g != null && ShowMember (g)) { + if ((g.Attributes & MethodAttributes.MemberAccessMask) != + (accessor.Attributes & MethodAttributes.MemberAccessMask)) + o.Write (GetMethodVisibility (g)); + o.WriteLine ("get;"); + } + + if (s != null && ShowMember (s)) { + if ((s.Attributes & MethodAttributes.MemberAccessMask) != + (accessor.Attributes & MethodAttributes.MemberAccessMask)) + o.Write (GetMethodVisibility (s)); + o.WriteLine ("set;"); + } + + o.Indent --; + o.Write ("}"); + } + + void OutlineMethod (MethodInfo mi) + { + if (MethodIsExplicitIfaceImpl (mi)) { + o.Write (FormatType (mi.ReturnType)); + o.Write (" "); + // MSFT has no way to get the method that we are overriding + // from the interface. this would allow us to pretty print + // the type name (and be more correct if there compiler + // were to do some strange naming thing). + } else { + o.Write (GetMethodVisibility (mi)); + o.Write (GetMethodModifiers (mi)); + o.Write (FormatType (mi.ReturnType)); + o.Write (" "); + } + + o.Write (mi.Name); +#if NET_2_0 + o.Write (FormatGenericParams (mi.GetGenericArguments ())); +#endif + o.Write (" ("); + OutlineParams (mi.GetParameters ()); + o.Write (")"); +#if NET_2_0 + WriteGenericConstraints (mi.GetGenericArguments ()); +#endif + o.Write (";"); + } + + void OutlineOperator (MethodInfo mi) + { + o.Write (GetMethodVisibility (mi)); + o.Write (GetMethodModifiers (mi)); + if (mi.Name == "op_Explicit" || mi.Name == "op_Implicit") { + o.Write (mi.Name.Substring (3).ToLower ()); + o.Write (" operator "); + o.Write (FormatType (mi.ReturnType)); + } else { + o.Write (FormatType (mi.ReturnType)); + o.Write (" operator "); + o.Write (OperatorFromName (mi.Name)); + } + o.Write (" ("); + OutlineParams (mi.GetParameters ()); + o.Write (");"); + } + + void OutlineParams (ParameterInfo [] pi) + { + int i = 0; + foreach (ParameterInfo p in pi) { + if (p.ParameterType.IsByRef) { + o.Write (p.IsOut ? "out " : "ref "); + o.Write (FormatType (p.ParameterType.GetElementType ())); + } else if (p.IsDefined (typeof (ParamArrayAttribute), false)) { + o.Write ("params "); + o.Write (FormatType (p.ParameterType)); + } else { + o.Write (FormatType (p.ParameterType)); + } + + o.Write (" "); + o.Write (p.Name); + if (i + 1 < pi.Length) + o.Write (", "); + i++; + } + } + + void OutlineField (FieldInfo fi) + { + if (fi.IsPublic) o.Write ("public "); + if (fi.IsFamily) o.Write ("protected "); + if (fi.IsPrivate) o.Write ("private "); + if (fi.IsAssembly) o.Write ("internal "); + if (fi.IsLiteral) o.Write ("const "); + else if (fi.IsStatic) o.Write ("static "); + if (fi.IsInitOnly) o.Write ("readonly "); + + o.Write (FormatType (fi.FieldType)); + o.Write (" "); + o.Write (fi.Name); + if (fi.IsLiteral) { + object v = fi.GetValue (this); + + // TODO: Escape values here + o.Write (" = "); + if (v is char) + o.Write ("'{0}'", v); + else if (v is string) + o.Write ("\"{0}\"", v); + else + o.Write (fi.GetValue (this)); + } + o.Write (";"); + } + + static string GetMethodVisibility (MethodBase m) + { + // itnerfaces have no modifiers here + if (m.DeclaringType.IsInterface) + return ""; + + if (m.IsPublic) return "public "; + if (m.IsFamily) return "protected "; + if (m.IsPrivate) return "private "; + if (m.IsAssembly) return "internal "; + + return null; + } + + static string GetMethodModifiers (MethodBase method) + { + if (method.IsStatic) + return "static "; + + if (method.IsFinal) { + // This will happen if you have + // class X : IA { + // public void A () {} + // static void Main () {} + // } + // interface IA { + // void A (); + // } + // + // A needs to be virtual (the CLR requires + // methods implementing an iface be virtual), + // but can not be inherited. It also can not + // be inherited. In C# this is represented + // with no special modifiers + + if (method.IsVirtual) + return null; + return "sealed "; + } + + // all interface methods are "virtual" but we don't say that in c# + if (method.IsVirtual && !method.DeclaringType.IsInterface) { + if (method.IsAbstract) + return "abstract "; + + return ((method.Attributes & MethodAttributes.NewSlot) != 0) ? + "virtual " : + "override "; + } + + return null; + } + + static string GetTypeKind (Type t) + { + if (t.IsEnum) + return "enum"; + if (t.IsClass) { + if (t.IsSubclassOf (typeof (System.MulticastDelegate))) + return "delegate"; + else + return "class"; + } + if (t.IsInterface) + return "interface"; + if (t.IsValueType) + return "struct"; + return "class"; + } + + static string GetTypeVisibility (Type t) + { + switch (t.Attributes & TypeAttributes.VisibilityMask){ + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + return "public"; + + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamANDAssem: + case TypeAttributes.NestedFamORAssem: + return "protected"; + + default: + return "internal"; + } + } + +#if NET_2_0 + string FormatGenericParams (Type [] args) + { + StringBuilder sb = new StringBuilder (); + if (args.Length == 0) + return ""; + + sb.Append ("<"); + for (int i = 0; i < args.Length; i++) { + if (i > 0) + sb.Append (","); + sb.Append (FormatType (args [i])); + } + sb.Append (">"); + return sb.ToString (); + } +#endif + + // TODO: fine tune this so that our output is less verbose. We need to figure + // out a way to do this while not making things confusing. + string FormatType (Type t) + { + if (t == null) + return ""; + + string type = GetFullName (t); + if (type == null) + return t.ToString (); + + if (!type.StartsWith ("System.")) { + if (t.Namespace == this.t.Namespace) + return t.Name; + return type; + } + + if (t.HasElementType) { + Type et = t.GetElementType (); + if (t.IsArray) + return FormatType (et) + " []"; + if (t.IsPointer) + return FormatType (et) + " *"; + if (t.IsByRef) + return "ref " + FormatType (et); + } + + switch (type) { + case "System.Byte": return "byte"; + case "System.SByte": return "sbyte"; + case "System.Int16": return "short"; + case "System.Int32": return "int"; + case "System.Int64": return "long"; + + case "System.UInt16": return "ushort"; + case "System.UInt32": return "uint"; + case "System.UInt64": return "ulong"; + + case "System.Single": return "float"; + case "System.Double": return "double"; + case "System.Decimal": return "decimal"; + case "System.Boolean": return "bool"; + case "System.Char": return "char"; + case "System.String": return "string"; + + case "System.Object": return "object"; + case "System.Void": return "void"; + } + + if (type.LastIndexOf(".") == 6) + return type.Substring(7); + + // + // If the namespace of the type is the namespace of what + // we are printing (or is a member of one if its children + // don't print it. This basically means that in C# we would + // automatically get the namespace imported by virtue of the + // namespace {} block. + // + if (this.t.Namespace.StartsWith (t.Namespace + ".") || t.Namespace == this.t.Namespace) + return type.Substring (t.Namespace.Length + 1); + + return type; + } + + public static string RemoveGenericArity (string name) + { + int start = 0; + StringBuilder sb = new StringBuilder (); + while (start < name.Length) { + int pos = name.IndexOf ('`', start); + if (pos < 0) { + sb.Append (name.Substring (start)); + break; + } + sb.Append (name.Substring (start, pos-start)); + + pos++; + + while ((pos < name.Length) && Char.IsNumber (name [pos])) + pos++; + + start = pos; + } + + return sb.ToString (); + } + + string GetTypeName (Type t) + { + StringBuilder sb = new StringBuilder (); + GetTypeName (sb, t); + return sb.ToString (); + } + + void GetTypeName (StringBuilder sb, Type t) + { + sb.Append (RemoveGenericArity (t.Name)); +#if NET_2_0 + sb.Append (FormatGenericParams (t.GetGenericArguments ())); +#endif + } + + string GetFullName (Type t) + { + StringBuilder sb = new StringBuilder (); + GetFullName_recursed (sb, t, false); + return sb.ToString (); + } + + void GetFullName_recursed (StringBuilder sb, Type t, bool recursed) + { +#if NET_2_0 + if (t.IsGenericParameter) { + sb.Append (t.Name); + return; + } +#endif + + if (t.DeclaringType != null) { + GetFullName_recursed (sb, t.DeclaringType, true); + sb.Append ("."); + } + + if (!recursed) { + string ns = t.Namespace; + if ((ns != null) && (ns != "")) { + sb.Append (ns); + sb.Append ("."); + } + } + + GetTypeName (sb, t); + } + +#if NET_2_0 + void WriteGenericConstraints (Type [] args) + { + + foreach (Type t in args) { + bool first = true; + Type[] ifaces = TypeGetInterfaces (t, true); + + GenericParameterAttributes attrs = t.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask; + GenericParameterAttributes [] interesting = { + GenericParameterAttributes.ReferenceTypeConstraint, + GenericParameterAttributes.NotNullableValueTypeConstraint, + GenericParameterAttributes.DefaultConstructorConstraint + }; + + if (t.BaseType != typeof (object) || ifaces.Length != 0 || attrs != 0) { + o.Write (" where "); + o.Write (FormatType (t)); + o.Write (" : "); + } + + if (t.BaseType != typeof (object)) { + o.Write (FormatType (t.BaseType)); + first = false; + } + + foreach (Type iface in ifaces) { + if (!first) + o.Write (", "); + first = false; + + o.Write (FormatType (iface)); + } + + foreach (GenericParameterAttributes a in interesting) { + if ((attrs & a) == 0) + continue; + + if (!first) + o.Write (", "); + first = false; + + switch (a) { + case GenericParameterAttributes.ReferenceTypeConstraint: + o.Write ("class"); + break; + case GenericParameterAttributes.NotNullableValueTypeConstraint: + o.Write ("struct"); + break; + case GenericParameterAttributes.DefaultConstructorConstraint: + o.Write ("new ()"); + break; + } + } + } + } +#endif + + string OperatorFromName (string name) + { + switch (name) { + case "op_UnaryPlus": return "+"; + case "op_UnaryNegation": return "-"; + case "op_LogicalNot": return "!"; + case "op_OnesComplement": return "~"; + case "op_Increment": return "++"; + case "op_Decrement": return "--"; + case "op_True": return "true"; + case "op_False": return "false"; + case "op_Addition": return "+"; + case "op_Subtraction": return "-"; + case "op_Multiply": return "*"; + case "op_Division": return "/"; + case "op_Modulus": return "%"; + case "op_BitwiseAnd": return "&"; + case "op_BitwiseOr": return "|"; + case "op_ExclusiveOr": return "^"; + case "op_LeftShift": return "<<"; + case "op_RightShift": return ">>"; + case "op_Equality": return "=="; + case "op_Inequality": return "!="; + case "op_GreaterThan": return ">"; + case "op_LessThan": return "<"; + case "op_GreaterThanOrEqual": return ">="; + case "op_LessThanOrEqual": return "<="; + default: return name; + } + } + + bool MethodIsExplicitIfaceImpl (MethodBase mb) + { + if (!(mb.IsFinal && mb.IsVirtual && mb.IsPrivate)) + return false; + + // UGH msft has no way to get the info about what method is + // getting overriden. Another reason to use cecil :-) + // + //MethodInfo mi = mb as MethodInfo; + //if (mi == null) + // return false; + // + //Console.WriteLine (mi.GetBaseDefinition ().DeclaringType); + //return mi.GetBaseDefinition ().DeclaringType.IsInterface; + + // So, we guess that virtual final private methods only come + // from ifaces :-) + return true; + } + + bool ShowMember (MemberInfo mi) + { + if (mi.MemberType == MemberTypes.Constructor && ((MethodBase) mi).IsStatic) + return false; + + if (show_private) + return true; + + if (filter_obsolete && mi.IsDefined (typeof (ObsoleteAttribute), false)) + return false; + + switch (mi.MemberType) { + case MemberTypes.Constructor: + case MemberTypes.Method: + MethodBase mb = mi as MethodBase; + + if (mb.IsFamily || mb.IsPublic || mb.IsFamilyOrAssembly) + return true; + + if (MethodIsExplicitIfaceImpl (mb)) + return true; + + return false; + + + case MemberTypes.Field: + FieldInfo fi = mi as FieldInfo; + + if (fi.IsFamily || fi.IsPublic || fi.IsFamilyOrAssembly) + return true; + + return false; + + + case MemberTypes.NestedType: + case MemberTypes.TypeInfo: + Type t = mi as Type; + + switch (t.Attributes & TypeAttributes.VisibilityMask){ + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + case TypeAttributes.NestedFamily: + case TypeAttributes.NestedFamORAssem: + return true; + } + + return false; + } + + // What am I !!! + return true; + } + + static Type [] TypeGetInterfaces (Type t, bool declonly) + { + if (t.IsGenericParameter) + return new Type [0]; + + Type [] ifaces = t.GetInterfaces (); + if (! declonly) + return ifaces; + + // Handle Object. Also, optimize for no interfaces + if (t.BaseType == null || ifaces.Length == 0) + return ifaces; + + ArrayList ar = new ArrayList (); + + foreach (Type i in ifaces) + if (! i.IsAssignableFrom (t.BaseType)) + ar.Add (i); + + return (Type []) ar.ToArray (typeof (Type)); + } +} + +public class Comparer : IComparer { + delegate int ComparerFunc (object a, object b); + + ComparerFunc cmp; + + Comparer (ComparerFunc f) + { + this.cmp = f; + } + + public int Compare (object a, object b) + { + return cmp (a, b); + } + + static int CompareType (object a, object b) + { + Type type1 = (Type) a; + Type type2 = (Type) b; + + if (type1.IsSubclassOf (typeof (System.MulticastDelegate)) != type2.IsSubclassOf (typeof (System.MulticastDelegate))) + return (type1.IsSubclassOf (typeof (System.MulticastDelegate)))? -1:1; + return string.Compare (type1.Name, type2.Name); + + } + +// static Comparer TypeComparer = new Comparer (new ComparerFunc (CompareType)); + +// static Type [] Sort (Type [] types) +// { +// Array.Sort (types, TypeComparer); +// return types; +// } + + static int CompareMemberInfo (object a, object b) + { + return string.Compare (((MemberInfo) a).Name, ((MemberInfo) b).Name); + } + + static Comparer MemberInfoComparer = new Comparer (new ComparerFunc (CompareMemberInfo)); + + public static MemberInfo [] Sort (MemberInfo [] inf) + { + Array.Sort (inf, MemberInfoComparer); + return inf; + } + + static int CompareMethodBase (object a, object b) + { + MethodBase aa = (MethodBase) a, bb = (MethodBase) b; + + if (aa.IsStatic == bb.IsStatic) { + int c = CompareMemberInfo (a, b); + if (c != 0) + return c; + ParameterInfo [] ap, bp; + + // + // Sort overloads by the names of their types + // put methods with fewer params first. + // + + ap = aa.GetParameters (); + bp = bb.GetParameters (); + int n = System.Math.Min (ap.Length, bp.Length); + + for (int i = 0; i < n; i ++) + if ((c = CompareType (ap [i].ParameterType, bp [i].ParameterType)) != 0) + return c; + + return ap.Length.CompareTo (bp.Length); + } + if (aa.IsStatic) + return -1; + + return 1; + } + + static Comparer MethodBaseComparer = new Comparer (new ComparerFunc (CompareMethodBase)); + + public static MethodBase [] Sort (MethodBase [] inf) + { + Array.Sort (inf, MethodBaseComparer); + return inf; + } + + static int ComparePropertyInfo (object a, object b) + { + PropertyInfo aa = (PropertyInfo) a, bb = (PropertyInfo) b; + + bool astatic = (aa.CanRead ? aa.GetGetMethod (true) : aa.GetSetMethod (true)).IsStatic; + bool bstatic = (bb.CanRead ? bb.GetGetMethod (true) : bb.GetSetMethod (true)).IsStatic; + + if (astatic == bstatic) + return CompareMemberInfo (a, b); + + if (astatic) + return -1; + + return 1; + } + + static Comparer PropertyInfoComparer = new Comparer (new ComparerFunc (ComparePropertyInfo)); + + public static PropertyInfo [] Sort (PropertyInfo [] inf) + { + Array.Sort (inf, PropertyInfoComparer); + return inf; + } + + static int CompareEventInfo (object a, object b) + { + EventInfo aa = (EventInfo) a, bb = (EventInfo) b; + + bool astatic = aa.GetAddMethod (true).IsStatic; + bool bstatic = bb.GetAddMethod (true).IsStatic; + + if (astatic == bstatic) + return CompareMemberInfo (a, b); + + if (astatic) + return -1; + + return 1; + } + + static Comparer EventInfoComparer = new Comparer (new ComparerFunc (CompareEventInfo)); + + public static EventInfo [] Sort (EventInfo [] inf) + { + Array.Sort (inf, EventInfoComparer); + return inf; + } +} +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs new file mode 100644 index 0000000000..c36699f93c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs @@ -0,0 +1,1306 @@ +// +// parameter.cs: Parameter definition. +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@seznam.cz) +// +// 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. +// +// +using System; +using System.Text; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using MetaType = System.Type; +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + /// + /// Abstract Base class for parameters of a method. + /// + public abstract class ParameterBase : Attributable + { + protected ParameterBuilder builder; + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { +#if false + if (a.Type == pa.MarshalAs) { + UnmanagedMarshal marshal = a.GetMarshal (this); + if (marshal != null) { + builder.SetMarshal (marshal); + } + return; + } +#endif + if (a.HasSecurityAttribute) { + a.Error_InvalidSecurityParent (); + return; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public ParameterBuilder Builder { + get { + return builder; + } + } + + public override bool IsClsComplianceRequired() + { + return false; + } + } + + /// + /// Class for applying custom attributes on the return type + /// + public class ReturnParameter : ParameterBase + { + MemberCore method; + + // TODO: merge method and mb + public ReturnParameter (MemberCore method, MethodBuilder mb, Location location) + { + this.method = method; + try { + builder = mb.DefineParameter (0, ParameterAttributes.None, ""); + } + catch (ArgumentOutOfRangeException) { + method.Compiler.Report.RuntimeMissingSupport (location, "custom attributes on the return type"); + } + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.CLSCompliant) { + method.Compiler.Report.Warning (3023, 1, a.Location, + "CLSCompliant attribute has no meaning when applied to return types. Try putting it on the method instead"); + } + + // This occurs after Warning -28 + if (builder == null) + return; + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.ReturnValue; + } + } + + /// + /// Is never called + /// + public override string[] ValidAttributeTargets { + get { + return null; + } + } + } + + public class ImplicitLambdaParameter : Parameter + { + public ImplicitLambdaParameter (string name, Location loc) + : base (null, name, Modifier.NONE, null, loc) + { + } + + public override TypeSpec Resolve (IMemberContext ec, int index) + { + if (parameter_type == null) + throw new InternalErrorException ("A type of implicit lambda parameter `{0}' is not set", + Name); + + base.idx = index; + return parameter_type; + } + + public void SetParameterType (TypeSpec type) + { + parameter_type = type; + } + } + + public class ParamsParameter : Parameter { + public ParamsParameter (FullNamedExpression type, string name, Attributes attrs, Location loc): + base (type, name, Parameter.Modifier.PARAMS, attrs, loc) + { + } + + public override TypeSpec Resolve (IMemberContext ec, int index) + { + if (base.Resolve (ec, index) == null) + return null; + + var ac = parameter_type as ArrayContainer; + if (ac == null || ac.Rank != 1) { + ec.Module.Compiler.Report.Error (225, Location, "The params parameter must be a single dimensional array"); + return null; + } + + return parameter_type; + } + + public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) + { + base.ApplyAttributes (mb, cb, index, pa); + pa.ParamArray.EmitAttribute (builder); + } + } + + public class ArglistParameter : Parameter { + // Doesn't have proper type because it's never chosen for better conversion + public ArglistParameter (Location loc) : + base (null, String.Empty, Parameter.Modifier.NONE, null, loc) + { + parameter_type = InternalType.Arglist; + } + + public override void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) + { + // Nothing to do + } + + public override bool CheckAccessibility (InterfaceMemberBase member) + { + return true; + } + + public override TypeSpec Resolve (IMemberContext ec, int index) + { + return parameter_type; + } + } + + public interface IParameterData + { + Expression DefaultValue { get; } + bool HasExtensionMethodModifier { get; } + bool HasDefaultValue { get; } + Parameter.Modifier ModFlags { get; } + string Name { get; } + } + + // + // Parameter information created by parser + // + public class Parameter : ParameterBase, IParameterData, ILocalVariable // TODO: INamedBlockVariable + { + [Flags] + public enum Modifier : byte { + NONE = 0, + REF = REFMASK | ISBYREF, + OUT = OUTMASK | ISBYREF, + PARAMS = 4, + // This is a flag which says that it's either REF or OUT. + ISBYREF = 8, + REFMASK = 32, + OUTMASK = 64, + SignatureMask = REFMASK | OUTMASK, + This = 128 + } + + static readonly string[] attribute_targets = new string[] { "param" }; + + FullNamedExpression texpr; + readonly Modifier modFlags; + string name; + Expression default_expr; + protected TypeSpec parameter_type; + readonly Location loc; + protected int idx; + public bool HasAddressTaken; + + TemporaryVariableReference expr_tree_variable; + + HoistedVariable hoisted_variant; + + public Modifier ParameterModifier { get { return modFlags; }} + public Expression DefaultExpression { get { return default_expr; }} + + public Parameter (FullNamedExpression type, string name, Modifier mod, Attributes attrs, Location loc) + { + this.name = name; + modFlags = mod; + this.loc = loc; + texpr = type; + + // Only assign, attributes will be attached during resolve + base.attributes = attrs; + } + + #region Properties + + public DefaultParameterValueExpression DefaultValue { + get { + return default_expr as DefaultParameterValueExpression; + } + set { + default_expr = value; + } + } + + Expression IParameterData.DefaultValue { + get { + var expr = default_expr as DefaultParameterValueExpression; + return expr == null ? default_expr : expr.Child; + } + } + + bool HasOptionalExpression { + get { + return default_expr is DefaultParameterValueExpression; + } + } + + public Location Location { + get { + return loc; + } + } + + public TypeSpec Type { + get { + return parameter_type; + } + set { + parameter_type = value; + } + } + + public FullNamedExpression TypeExpression { + get { + return texpr; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.In && ModFlags == Modifier.OUT) { + a.Report.Error (36, a.Location, "An out parameter cannot have the `In' attribute"); + return; + } + + if (a.Type == pa.ParamArray) { + a.Report.Error (674, a.Location, "Do not use `System.ParamArrayAttribute'. Use the `params' keyword instead"); + return; + } + + if (a.Type == pa.Out && (ModFlags & Modifier.REF) == Modifier.REF && + !OptAttributes.Contains (pa.In)) { + a.Report.Error (662, a.Location, + "Cannot specify only `Out' attribute on a ref parameter. Use both `In' and `Out' attributes or neither"); + return; + } + + if (a.Type == pa.CLSCompliant) { + a.Report.Warning (3022, 1, a.Location, "CLSCompliant attribute has no meaning when applied to parameters. Try putting it on the method instead"); + } + + if (a.Type == pa.DefaultParameterValue || a.Type == pa.OptionalParameter) { + if (HasOptionalExpression) { + a.Report.Error (1745, a.Location, + "Cannot specify `{0}' attribute on optional parameter `{1}'", + TypeManager.CSharpName (a.Type).Replace ("Attribute", ""), Name); + } + + if (a.Type == pa.DefaultParameterValue) + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public virtual bool CheckAccessibility (InterfaceMemberBase member) + { + if (parameter_type == null) + return true; + + return member.IsAccessibleAs (parameter_type); + } + + // + // Resolve is used in method definitions + // + public virtual TypeSpec Resolve (IMemberContext rc, int index) + { + if (parameter_type != null) + return parameter_type; + + if (attributes != null) + attributes.AttachTo (this, rc); + + parameter_type = texpr.ResolveAsType (rc); + if (parameter_type == null) + return null; + + this.idx = index; + + if ((modFlags & Parameter.Modifier.ISBYREF) != 0 && parameter_type.IsSpecialRuntimeType) { + rc.Module.Compiler.Report.Error (1601, Location, "Method or delegate parameter cannot be of type `{0}'", + GetSignatureForError ()); + return null; + } + + TypeManager.CheckTypeVariance (parameter_type, + (modFlags & Parameter.Modifier.ISBYREF) != 0 ? Variance.None : Variance.Contravariant, + rc); + + if (parameter_type.IsStatic) { + rc.Module.Compiler.Report.Error (721, Location, "`{0}': static types cannot be used as parameters", + texpr.GetSignatureForError ()); + return parameter_type; + } + + if ((modFlags & Modifier.This) != 0 && (parameter_type.IsPointer || parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic)) { + rc.Module.Compiler.Report.Error (1103, Location, "The extension method cannot be of type `{0}'", + TypeManager.CSharpName (parameter_type)); + } + + return parameter_type; + } + + public void ResolveDefaultValue (ResolveContext rc) + { + // + // Default value was specified using an expression + // + if (default_expr != null) { + ((DefaultParameterValueExpression)default_expr).Resolve (rc, this); + return; + } + + if (attributes == null) + return; + + var opt_attr = attributes.Search (rc.Module.PredefinedAttributes.OptionalParameter); + var def_attr = attributes.Search (rc.Module.PredefinedAttributes.DefaultParameterValue); + if (def_attr != null) { + if (def_attr.Resolve () == null) + return; + + var default_expr_attr = def_attr.GetParameterDefaultValue (); + if (default_expr_attr == null) + return; + + var dpa_rc = def_attr.CreateResolveContext (); + default_expr = default_expr_attr.Resolve (dpa_rc); + + if (default_expr is BoxedCast) + default_expr = ((BoxedCast) default_expr).Child; + + Constant c = default_expr as Constant; + if (c == null) { + if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) { + rc.Report.Error (1910, default_expr.Location, + "Argument of type `{0}' is not applicable for the DefaultParameterValue attribute", + default_expr.Type.GetSignatureForError ()); + } else { + rc.Report.Error (1909, default_expr.Location, + "The DefaultParameterValue attribute is not applicable on parameters of type `{0}'", + default_expr.Type.GetSignatureForError ()); ; + } + + default_expr = null; + return; + } + + if (TypeSpecComparer.IsEqual (default_expr.Type, parameter_type) || + (default_expr is NullConstant && TypeSpec.IsReferenceType (parameter_type) && !parameter_type.IsGenericParameter) || + parameter_type.BuiltinType == BuiltinTypeSpec.Type.Object) { + return; + } + + // + // LAMESPEC: Some really weird csc behaviour which we have to mimic + // User operators returning same type as parameter type are considered + // valid for this attribute only + // + // struct S { public static implicit operator S (int i) {} } + // + // void M ([DefaultParameterValue (3)]S s) + // + var expr = Convert.ImplicitUserConversion (dpa_rc, default_expr, parameter_type, loc); + if (expr != null && TypeSpecComparer.IsEqual (expr.Type, parameter_type)) { + return; + } + + rc.Report.Error (1908, default_expr.Location, "The type of the default value should match the type of the parameter"); + return; + } + + if (opt_attr != null) { + default_expr = EmptyExpression.MissingValue; + } + } + + public bool HasDefaultValue { + get { return default_expr != null; } + } + + public bool HasExtensionMethodModifier { + get { return (modFlags & Modifier.This) != 0; } + } + + // + // Hoisted parameter variant + // + public HoistedVariable HoistedVariant { + get { + return hoisted_variant; + } + set { + hoisted_variant = value; + } + } + + public Modifier ModFlags { + get { return modFlags & ~Modifier.This; } + } + + public string Name { + get { return name; } + set { name = value; } + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Parameter; + } + } + + 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; + if (parameter_type != null) + type_name = TypeManager.CSharpName (parameter_type); + else + type_name = texpr.GetSignatureForError (); + + string mod = GetModifierSignature (modFlags); + if (mod.Length > 0) + return String.Concat (mod, " ", type_name); + + return type_name; + } + + public static string GetModifierSignature (Modifier mod) + { + switch (mod) { + case Modifier.OUT: + return "out"; + case Modifier.PARAMS: + return "params"; + case Modifier.REF: + return "ref"; + case Modifier.This: + return "this"; + default: + return ""; + } + } + + public void IsClsCompliant (IMemberContext ctx) + { + if (parameter_type.IsCLSCompliant ()) + return; + + ctx.Module.Compiler.Report.Warning (3001, 1, Location, + "Argument type `{0}' is not CLS-compliant", parameter_type.GetSignatureForError ()); + } + + public virtual void ApplyAttributes (MethodBuilder mb, ConstructorBuilder cb, int index, PredefinedAttributes pa) + { + if (builder != null) + throw new InternalErrorException ("builder already exists"); + + var pattrs = ParametersCompiled.GetParameterAttribute (modFlags); + if (HasOptionalExpression) + pattrs |= ParameterAttributes.Optional; + + if (mb == null) + builder = cb.DefineParameter (index, pattrs, Name); + else + builder = mb.DefineParameter (index, pattrs, Name); + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (HasDefaultValue) { + // + // Emit constant values for true constants only, the other + // constant-like expressions will rely on default value expression + // + var def_value = DefaultValue; + Constant c = def_value != null ? def_value.Child as Constant : default_expr as Constant; + if (c != null) { + if (c.Type.BuiltinType == BuiltinTypeSpec.Type.Decimal) { + pa.DecimalConstant.EmitAttribute (builder, (decimal) c.GetValue (), c.Location); + } else { + builder.SetConstant (c.GetValue ()); + } + } else if (default_expr.Type.IsStruct) { + // + // Handles special case where default expression is used with value-type + // + // void Foo (S s = default (S)) {} + // + builder.SetConstant (null); + } + } + + if (parameter_type != null) { + if (parameter_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + pa.Dynamic.EmitAttribute (builder); + } else if (parameter_type.HasDynamicElement) { + pa.Dynamic.EmitAttribute (builder, parameter_type, Location); + } + } + } + + public Parameter Clone () + { + Parameter p = (Parameter) MemberwiseClone (); + if (attributes != null) + p.attributes = attributes.Clone (); + + return p; + } + + public ExpressionStatement CreateExpressionTreeVariable (BlockContext ec) + { + if ((modFlags & Modifier.ISBYREF) != 0) + ec.Report.Error (1951, Location, "An expression tree parameter cannot use `ref' or `out' modifier"); + + expr_tree_variable = TemporaryVariableReference.Create (ResolveParameterExpressionType (ec, Location).Type, ec.CurrentBlock.ParametersBlock, Location); + expr_tree_variable = (TemporaryVariableReference) expr_tree_variable.Resolve (ec); + + Arguments arguments = new Arguments (2); + arguments.Add (new Argument (new TypeOf (parameter_type, Location))); + arguments.Add (new Argument (new StringConstant (ec.BuiltinTypes, Name, Location))); + return new SimpleAssign (ExpressionTreeVariableReference (), + Expression.CreateExpressionFactoryCall (ec, "Parameter", null, arguments, Location)); + } + + public void Emit (EmitContext ec) + { + int arg_idx = idx; + if (!ec.IsStatic) + arg_idx++; + + ParameterReference.EmitLdArg (ec, arg_idx); + } + + public void EmitAssign (EmitContext ec) + { + int arg_idx = idx; + if (!ec.IsStatic) + arg_idx++; + + if (arg_idx <= 255) + ec.Emit (OpCodes.Starg_S, (byte) arg_idx); + else + ec.Emit (OpCodes.Starg, arg_idx); + } + + public void EmitAddressOf (EmitContext ec) + { + int arg_idx = idx; + + if (!ec.IsStatic) + arg_idx++; + + bool is_ref = (ModFlags & Modifier.ISBYREF) != 0; + if (is_ref) { + ParameterReference.EmitLdArg (ec, arg_idx); + } else { + if (arg_idx <= 255) + ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx); + else + ec.Emit (OpCodes.Ldarga, arg_idx); + } + } + + public TemporaryVariableReference ExpressionTreeVariableReference () + { + return expr_tree_variable; + } + + // + // System.Linq.Expressions.ParameterExpression type + // + public static TypeExpr ResolveParameterExpressionType (IMemberContext ec, Location location) + { + TypeSpec p_type = ec.Module.PredefinedTypes.ParameterExpression.Resolve (); + return new TypeExpression (p_type, location); + } + + public void Warning_UselessOptionalParameter (Report Report) + { + Report.Warning (1066, 1, Location, + "The default value specified for optional parameter `{0}' will never be used", + Name); + } + } + + // + // Imported or resolved parameter information + // + public class ParameterData : IParameterData + { + readonly string name; + readonly Parameter.Modifier modifiers; + readonly Expression default_value; + + public ParameterData (string name, Parameter.Modifier modifiers) + { + this.name = name; + this.modifiers = modifiers; + } + + public ParameterData (string name, Parameter.Modifier modifiers, Expression defaultValue) + : this (name, modifiers) + { + this.default_value = defaultValue; + } + + #region IParameterData Members + + public Expression DefaultValue { + get { return default_value; } + } + + public bool HasExtensionMethodModifier { + get { return (modifiers & Parameter.Modifier.This) != 0; } + } + + public bool HasDefaultValue { + get { return default_value != null; } + } + + public Parameter.Modifier ModFlags { + get { return modifiers & ~Parameter.Modifier.This; } + } + + public string Name { + get { return name; } + } + + #endregion + } + + public abstract class AParametersCollection + { + protected bool has_arglist; + protected bool has_params; + + // Null object pattern + protected IParameterData [] parameters; + protected TypeSpec [] types; + + public CallingConventions CallingConvention { + get { + return has_arglist ? + CallingConventions.VarArgs : + CallingConventions.Standard; + } + } + + public int Count { + get { return parameters.Length; } + } + + public TypeSpec ExtensionMethodType { + get { + if (Count == 0) + return null; + + return FixedParameters [0].HasExtensionMethodModifier ? + types [0] : null; + } + } + + public IParameterData [] FixedParameters { + get { + return parameters; + } + } + + public static ParameterAttributes GetParameterAttribute (Parameter.Modifier modFlags) + { + return (modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ? + ParameterAttributes.Out : ParameterAttributes.None; + } + + // Very expensive operation + public MetaType[] GetMetaInfo () + { + MetaType[] types; + if (has_arglist) { + if (Count == 1) + return MetaType.EmptyTypes; + + types = new MetaType[Count - 1]; + } else { + if (Count == 0) + return MetaType.EmptyTypes; + + types = new MetaType[Count]; + } + + for (int i = 0; i < types.Length; ++i) { + types[i] = Types[i].GetMetaInfo (); + + if ((FixedParameters [i].ModFlags & Parameter.Modifier.ISBYREF) == 0) + continue; + + // TODO MemberCache: Should go to MetaInfo getter + types [i] = types [i].MakeByRefType (); + } + + return types; + } + + // + // Returns the parameter information based on the name + // + public int GetParameterIndexByName (string name) + { + for (int idx = 0; idx < Count; ++idx) { + if (parameters [idx].Name == name) + return idx; + } + + return -1; + } + + public string GetSignatureForDocumentation () + { + if (IsEmpty) + return string.Empty; + + StringBuilder sb = new StringBuilder ("("); + for (int i = 0; i < Count; ++i) { + if (i != 0) + sb.Append (","); + + sb.Append (types [i].GetSignatureForDocumentation ()); + + if ((parameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) + sb.Append ("@"); + } + sb.Append (")"); + + return sb.ToString (); + } + + public string GetSignatureForError () + { + return GetSignatureForError ("(", ")", Count); + } + + public string GetSignatureForError (string start, string end, int count) + { + StringBuilder sb = new StringBuilder (start); + for (int i = 0; i < count; ++i) { + if (i != 0) + sb.Append (", "); + sb.Append (ParameterDesc (i)); + } + sb.Append (end); + return sb.ToString (); + } + + public bool HasArglist { + get { return has_arglist; } + } + + public bool HasExtensionMethodType { + get { + if (Count == 0) + return false; + + return FixedParameters [0].HasExtensionMethodModifier; + } + } + + public bool HasParams { + get { return has_params; } + } + + public bool IsEmpty { + get { return parameters.Length == 0; } + } + + public AParametersCollection Inflate (TypeParameterInflator inflator) + { + TypeSpec[] inflated_types = null; + bool default_value = false; + + for (int i = 0; i < Count; ++i) { + var inflated_param = inflator.Inflate (types[i]); + if (inflated_types == null) { + if (inflated_param == types[i]) + continue; + + default_value |= FixedParameters[i] is DefaultValueExpression; + inflated_types = new TypeSpec[types.Length]; + Array.Copy (types, inflated_types, types.Length); + } + + inflated_types[i] = inflated_param; + } + + if (inflated_types == null) + return this; + + var clone = (AParametersCollection) MemberwiseClone (); + clone.types = inflated_types; + if (default_value) { + for (int i = 0; i < Count; ++i) { + var dve = clone.FixedParameters[i] as DefaultValueExpression; + if (dve != null) { + throw new NotImplementedException ("net"); + // clone.FixedParameters [i].DefaultValue = new DefaultValueExpression (); + } + } + } + + return clone; + } + + public string ParameterDesc (int pos) + { + if (types == null || types [pos] == null) + return ((Parameter)FixedParameters [pos]).GetSignatureForError (); + + string type = TypeManager.CSharpName (types [pos]); + if (FixedParameters [pos].HasExtensionMethodModifier) + return "this " + type; + + Parameter.Modifier mod = FixedParameters [pos].ModFlags; + if (mod == 0) + return type; + + return Parameter.GetModifierSignature (mod) + " " + type; + } + + public TypeSpec[] Types { + get { return types; } + set { types = value; } + } + } + + // + // A collection of imported or resolved parameters + // + public class ParametersImported : AParametersCollection + { + public ParametersImported (IParameterData [] parameters, TypeSpec [] types, bool hasArglist, bool hasParams) + { + this.parameters = parameters; + this.types = types; + this.has_arglist = hasArglist; + this.has_params = hasParams; + } + + public ParametersImported (IParameterData[] param, TypeSpec[] types, bool hasParams) + { + this.parameters = param; + this.types = types; + this.has_params = hasParams; + } + } + + /// + /// Represents the methods parameters + /// + public class ParametersCompiled : AParametersCollection + { + public static readonly ParametersCompiled EmptyReadOnlyParameters = new ParametersCompiled (); + + // Used by C# 2.0 delegates + public static readonly ParametersCompiled Undefined = new ParametersCompiled (); + + private ParametersCompiled () + { + parameters = new Parameter [0]; + types = TypeSpec.EmptyTypes; + } + + private ParametersCompiled (IParameterData[] parameters, TypeSpec[] types) + { + this.parameters = parameters; + this.types = types; + } + + public ParametersCompiled (params Parameter[] parameters) + { + if (parameters == null || parameters.Length == 0) + throw new ArgumentException ("Use EmptyReadOnlyParameters"); + + this.parameters = parameters; + int count = parameters.Length; + + for (int i = 0; i < count; i++){ + has_params |= (parameters [i].ModFlags & Parameter.Modifier.PARAMS) != 0; + } + } + + public ParametersCompiled (Parameter [] parameters, bool has_arglist) : + this (parameters) + { + this.has_arglist = has_arglist; + } + + public static ParametersCompiled CreateFullyResolved (Parameter p, TypeSpec type) + { + return new ParametersCompiled (new Parameter [] { p }, new TypeSpec [] { type }); + } + + public static ParametersCompiled CreateFullyResolved (Parameter[] parameters, TypeSpec[] types) + { + return new ParametersCompiled (parameters, types); + } + + // + // TODO: This does not fit here, it should go to different version of AParametersCollection + // as the underlying type is not Parameter and some methods will fail to cast + // + public static AParametersCollection CreateFullyResolved (params TypeSpec[] types) + { + var pd = new ParameterData [types.Length]; + for (int i = 0; i < pd.Length; ++i) + pd[i] = new ParameterData (null, Parameter.Modifier.NONE, null); + + return new ParametersCompiled (pd, types); + } + + public static ParametersCompiled CreateImplicitParameter (FullNamedExpression texpr, Location loc) + { + return new ParametersCompiled ( + new[] { new Parameter (texpr, "value", Parameter.Modifier.NONE, null, loc) }, + null); + } + + public void CheckConstraints (IMemberContext mc) + { + foreach (Parameter p in parameters) { + // + // It's null for compiler generated types or special types like __arglist + // + if (p.TypeExpression != null) + ConstraintChecker.Check (mc, p.Type, p.TypeExpression.Location); + } + } + + // + // Returns non-zero value for equal CLS parameter signatures + // + public static int IsSameClsSignature (AParametersCollection a, AParametersCollection b) + { + int res = 0; + + for (int i = 0; i < a.Count; ++i) { + var a_type = a.Types[i]; + var b_type = b.Types[i]; + if (TypeSpecComparer.Override.IsEqual (a_type, b_type)) { + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out)) + res |= 1; + + continue; + } + + var ac_a = a_type as ArrayContainer; + if (ac_a == null) + return 0; + + var ac_b = b_type as ArrayContainer; + if (ac_b == null) + return 0; + + if (ac_a.Element is ArrayContainer || ac_b.Element is ArrayContainer) { + res |= 2; + continue; + } + + if (ac_a.Rank != ac_b.Rank && TypeSpecComparer.Override.IsEqual (ac_a.Element, ac_b.Element)) { + res |= 1; + continue; + } + + return 0; + } + + return res; + } + + public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter compilerParams, TypeSpec compilerTypes) + { + return MergeGenerated (ctx, userParams, checkConflicts, + new Parameter [] { compilerParams }, + new TypeSpec [] { compilerTypes }); + } + + // + // Use this method when you merge compiler generated parameters with user parameters + // + public static ParametersCompiled MergeGenerated (CompilerContext ctx, ParametersCompiled userParams, bool checkConflicts, Parameter[] compilerParams, TypeSpec[] compilerTypes) + { + Parameter[] all_params = new Parameter [userParams.Count + compilerParams.Length]; + userParams.FixedParameters.CopyTo(all_params, 0); + + TypeSpec [] all_types; + if (userParams.types != null) { + all_types = new TypeSpec [all_params.Length]; + userParams.Types.CopyTo (all_types, 0); + } else { + all_types = null; + } + + int last_filled = userParams.Count; + int index = 0; + foreach (Parameter p in compilerParams) { + for (int i = 0; i < last_filled; ++i) { + while (p.Name == all_params [i].Name) { + if (checkConflicts && i < userParams.Count) { + ctx.Report.Error (316, userParams[i].Location, + "The parameter name `{0}' conflicts with a compiler generated name", p.Name); + } + p.Name = '_' + p.Name; + } + } + all_params [last_filled] = p; + if (all_types != null) + all_types [last_filled] = compilerTypes [index++]; + ++last_filled; + } + + ParametersCompiled parameters = new ParametersCompiled (all_params, all_types); + parameters.has_params = userParams.has_params; + 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) + return true; + + types = new TypeSpec [Count]; + + bool ok = true; + Parameter p; + for (int i = 0; i < FixedParameters.Length; ++i) { + p = this [i]; + TypeSpec t = p.Resolve (ec, i); + if (t == null) { + ok = false; + continue; + } + + types [i] = t; + } + + return ok; + } + + public void ResolveDefaultValues (MemberCore m) + { + ResolveContext rc = null; + for (int i = 0; i < parameters.Length; ++i) { + Parameter p = (Parameter) parameters [i]; + + // + // Try not to enter default values resolution if there are is not any default value possible + // + if (p.HasDefaultValue || p.OptAttributes != null) { + if (rc == null) + rc = new ResolveContext (m); + + p.ResolveDefaultValue (rc); + } + } + } + + // Define each type attribute (in/out/ref) and + // the argument names. + public void ApplyAttributes (IMemberContext mc, MethodBase builder) + { + if (Count == 0) + return; + + MethodBuilder mb = builder as MethodBuilder; + ConstructorBuilder cb = builder as ConstructorBuilder; + var pa = mc.Module.PredefinedAttributes; + + for (int i = 0; i < Count; i++) { + this [i].ApplyAttributes (mb, cb, i + 1, pa); + } + } + + public void VerifyClsCompliance (IMemberContext ctx) + { + foreach (Parameter p in FixedParameters) + p.IsClsCompliant (ctx); + } + + public Parameter this [int pos] { + get { return (Parameter) parameters [pos]; } + } + + public Expression CreateExpressionTree (BlockContext ec, Location loc) + { + var initializers = new ArrayInitializer (Count, loc); + foreach (Parameter p in FixedParameters) { + // + // Each parameter expression is stored to local variable + // to save some memory when referenced later. + // + StatementExpression se = new StatementExpression (p.CreateExpressionTreeVariable (ec)); + if (se.Resolve (ec)) { + ec.CurrentBlock.AddScopeStatement (new TemporaryVariableReference.Declarator (p.ExpressionTreeVariableReference ())); + ec.CurrentBlock.AddScopeStatement (se); + } + + initializers.Add (p.ExpressionTreeVariableReference ()); + } + + return new ArrayCreation ( + Parameter.ResolveParameterExpressionType (ec, loc), + initializers, loc); + } + + public ParametersCompiled Clone () + { + ParametersCompiled p = (ParametersCompiled) MemberwiseClone (); + + p.parameters = new IParameterData [parameters.Length]; + for (int i = 0; i < Count; ++i) + p.parameters [i] = this [i].Clone (); + + return p; + } + } + + // + // Default parameter value expression. We need this wrapper to handle + // default parameter values of folded constants when for indexer parameters + // The expression is resolved only once but applied to two methods which + // both share reference to this expression and we ensure that resolving + // this expression always returns same instance + // + public class DefaultParameterValueExpression : CompositeExpression + { + public DefaultParameterValueExpression (Expression expr) + : base (expr) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + return base.DoResolve (rc); + } + + public void Resolve (ResolveContext rc, Parameter p) + { + var expr = Resolve (rc); + if (expr == null) + return; + + expr = Child; + + if (!(expr is Constant || expr is DefaultValueExpression || (expr is New && ((New) expr).IsDefaultStruct))) { + rc.Report.Error (1736, Location, + "The expression being assigned to optional parameter `{0}' must be a constant or default value", + p.Name); + + return; + } + + var parameter_type = p.Type; + if (type == parameter_type) + return; + + var res = Convert.ImplicitConversionStandard (rc, expr, parameter_type, Location); + if (res != null) { + if (parameter_type.IsNullableType && res is Nullable.Wrap) { + Nullable.Wrap wrap = (Nullable.Wrap) res; + res = wrap.Child; + if (!(res is Constant)) { + rc.Report.Error (1770, Location, + "The expression being assigned to nullable optional parameter `{0}' must be default value", + p.Name); + return; + } + } + + if (!expr.IsNull && TypeSpec.IsReferenceType (parameter_type) && parameter_type.BuiltinType != BuiltinTypeSpec.Type.String) { + rc.Report.Error (1763, Location, + "Optional parameter `{0}' of type `{1}' can only be initialized with `null'", + p.Name, parameter_type.GetSignatureForError ()); + + return; + } + + this.expr = res; + return; + } + + rc.Report.Error (1750, Location, + "Optional parameter expression of type `{0}' cannot be converted to parameter type `{1}'", + type.GetSignatureForError (), parameter_type.GetSignatureForError ()); + } + + public virtual object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs new file mode 100644 index 0000000000..696797aa01 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs @@ -0,0 +1,641 @@ +// +// pending.cs: Pending method implementation +// +// Authors: +// Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2008 Novell, Inc. +// + +using System; +using System.Collections.Generic; +using System.Linq; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + struct TypeAndMethods { + public TypeSpec type; + public IList methods; + + // + // Whether it is optional, this is used to allow the explicit/implicit + // implementation when a base class already implements an interface. + // + // For example: + // + // class X : IA { } class Y : X, IA { IA.Explicit (); } + // + public bool optional; + + // + // This flag on the method says `We found a match, but + // because it was private, we could not use the match + // + public MethodData [] found; + + // If a method is defined here, then we always need to + // create a proxy for it. This is used when implementing + // an interface's indexer with a different IndexerName. + public MethodSpec [] need_proxy; + } + + public class PendingImplementation + { + /// + /// The container for this PendingImplementation + /// + readonly TypeContainer container; + + /// + /// This is the array of TypeAndMethods that describes the pending implementations + /// (both interfaces and abstract methods in base class) + /// + TypeAndMethods [] pending_implementations; + + PendingImplementation (TypeContainer container, MissingInterfacesInfo[] missing_ifaces, MethodSpec[] abstract_methods, int total) + { + var type_builder = container.Definition; + + this.container = container; + pending_implementations = new TypeAndMethods [total]; + + int i = 0; + if (abstract_methods != null) { + int count = abstract_methods.Length; + pending_implementations [i].methods = new MethodSpec [count]; + pending_implementations [i].need_proxy = new MethodSpec [count]; + + pending_implementations [i].methods = abstract_methods; + pending_implementations [i].found = new MethodData [count]; + pending_implementations [i].type = type_builder; + ++i; + } + + foreach (MissingInterfacesInfo missing in missing_ifaces) { + var iface = missing.Type; + var mi = MemberCache.GetInterfaceMethods (iface); + + int count = mi.Count; + pending_implementations [i].type = iface; + pending_implementations [i].optional = missing.Optional; + pending_implementations [i].methods = mi; + pending_implementations [i].found = new MethodData [count]; + pending_implementations [i].need_proxy = new MethodSpec [count]; + i++; + } + } + + Report Report { + get { + return container.Module.Compiler.Report; + } + } + + struct MissingInterfacesInfo { + public TypeSpec Type; + public bool Optional; + + public MissingInterfacesInfo (TypeSpec t) + { + Type = t; + Optional = false; + } + } + + static readonly MissingInterfacesInfo [] EmptyMissingInterfacesInfo = new MissingInterfacesInfo [0]; + + static MissingInterfacesInfo [] GetMissingInterfaces (TypeContainer container) + { + // + // Notice that Interfaces will only return the interfaces that the Type + // is supposed to implement, not all the interfaces that the type implements. + // + var impl = container.Definition.Interfaces; + + if (impl == null || impl.Count == 0) + return EmptyMissingInterfacesInfo; + + MissingInterfacesInfo[] ret = new MissingInterfacesInfo[impl.Count]; + + for (int i = 0; i < impl.Count; i++) + ret [i] = new MissingInterfacesInfo (impl [i]); + + // we really should not get here because Object doesnt implement any + // interfaces. But it could implement something internal, so we have + // to handle that case. + if (container.BaseType == null) + return ret; + + var base_impls = container.BaseType.Interfaces; + if (base_impls != null) { + foreach (TypeSpec t in base_impls) { + for (int i = 0; i < ret.Length; i++) { + if (t == ret[i].Type) { + ret[i].Optional = true; + break; + } + } + } + } + + return ret; + } + + // + // Factory method: if there are pending implementation methods, we return a PendingImplementation + // object, otherwise we return null. + // + // Register method implementations are either abstract methods + // flagged as such on the base class or interface methods + // + static public PendingImplementation GetPendingImplementations (TypeContainer container) + { + TypeSpec b = container.BaseType; + + var missing_interfaces = GetMissingInterfaces (container); + + // + // If we are implementing an abstract class, and we are not + // ourselves abstract, and there are abstract methods (C# allows + // abstract classes that have no abstract methods), then allocate + // one slot. + // + // We also pre-compute the methods. + // + bool implementing_abstract = ((b != null) && b.IsAbstract && (container.ModFlags & Modifiers.ABSTRACT) == 0); + MethodSpec[] abstract_methods = null; + + if (implementing_abstract){ + var am = MemberCache.GetNotImplementedAbstractMethods (b); + + if (am == null) { + implementing_abstract = false; + } else { + abstract_methods = new MethodSpec[am.Count]; + am.CopyTo (abstract_methods, 0); + } + } + + int total = missing_interfaces.Length + (implementing_abstract ? 1 : 0); + if (total == 0) + return null; + + var pending = new PendingImplementation (container, missing_interfaces, abstract_methods, total); + + // + // check for inherited conflicting methods + // + foreach (var p in pending.pending_implementations) { + // + // It can happen for generic interfaces only + // + if (!p.type.IsGeneric) + continue; + + // + // CLR does not distinguishes between ref and out + // + for (int i = 0; i < p.methods.Count; ++i) { + MethodSpec compared_method = p.methods[i]; + if (compared_method.Parameters.IsEmpty) + continue; + + for (int ii = i + 1; ii < p.methods.Count; ++ii) { + MethodSpec tested_method = p.methods[ii]; + if (compared_method.Name != tested_method.Name) + continue; + + if (p.type != tested_method.DeclaringType) + continue; + + if (!TypeSpecComparer.Override.IsSame (compared_method.Parameters.Types, tested_method.Parameters.Types)) + continue; + + bool exact_match = true; + bool ref_only_difference = false; + var cp = compared_method.Parameters.FixedParameters; + var tp = tested_method.Parameters.FixedParameters; + + for (int pi = 0; pi < cp.Length; ++pi) { + // + // First check exact modifiers match + // + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((cp[pi].ModFlags & ref_out) == (tp[pi].ModFlags & ref_out)) + continue; + + if ((cp[pi].ModFlags & tp[pi].ModFlags & Parameter.Modifier.ISBYREF) != 0) { + ref_only_difference = true; + continue; + } + + exact_match = false; + break; + } + + if (!exact_match || !ref_only_difference) + continue; + + pending.Report.SymbolRelatedToPreviousError (compared_method); + pending.Report.SymbolRelatedToPreviousError (tested_method); + pending.Report.Error (767, container.Location, + "Cannot implement interface `{0}' with the specified type parameters because it causes method `{1}' to differ on parameter modifiers only", + p.type.GetDefinition().GetSignatureForError (), compared_method.GetSignatureForError ()); + + break; + } + } + } + + return pending; + } + + public enum Operation { + // + // If you change this, review the whole InterfaceMethod routine as there + // are a couple of assumptions on these three states + // + Lookup, ClearOne, ClearAll + } + + /// + /// Whether the specified method is an interface method implementation + /// + public MethodSpec IsInterfaceMethod (MemberName name, TypeSpec ifaceType, MethodData method, out MethodSpec ambiguousCandidate) + { + return InterfaceMethod (name, ifaceType, method, Operation.Lookup, out ambiguousCandidate); + } + + public void ImplementMethod (MemberName name, TypeSpec ifaceType, MethodData method, bool clear_one, out MethodSpec ambiguousCandidate) + { + InterfaceMethod (name, ifaceType, method, clear_one ? Operation.ClearOne : Operation.ClearAll, out ambiguousCandidate); + } + + /// + /// If a method in Type `t' (or null to look in all interfaces + /// and the base abstract class) with name `Name', return type `ret_type' and + /// arguments `args' implements an interface, this method will + /// return the MethodInfo that this method implements. + /// + /// If `name' is null, we operate solely on the method's signature. This is for + /// instance used when implementing indexers. + /// + /// The `Operation op' controls whether to lookup, clear the pending bit, or clear + /// all the methods with the given signature. + /// + /// The `MethodInfo need_proxy' is used when we're implementing an interface's + /// indexer in a class. If the new indexer's IndexerName does not match the one + /// that was used in the interface, then we always need to create a proxy for it. + /// + /// + public MethodSpec InterfaceMethod (MemberName name, TypeSpec iType, MethodData method, Operation op, out MethodSpec ambiguousCandidate) + { + ambiguousCandidate = null; + + if (pending_implementations == null) + return null; + + TypeSpec ret_type = method.method.ReturnType; + ParametersCompiled args = method.method.ParameterInfo; + bool is_indexer = method.method is Indexer.SetIndexerMethod || method.method is Indexer.GetIndexerMethod; + MethodSpec m; + + foreach (TypeAndMethods tm in pending_implementations){ + if (!(iType == null || tm.type == iType)) + continue; + + int method_count = tm.methods.Count; + for (int i = 0; i < method_count; i++){ + m = tm.methods [i]; + + if (m == null) + continue; + + if (is_indexer) { + if (!m.IsAccessor || m.Parameters.IsEmpty) + continue; + } else { + if (name.Name != m.Name) + continue; + + if (m.Arity != name.Arity) + continue; + } + + if (!TypeSpecComparer.Override.IsEqual (m.Parameters, args)) + continue; + + if (!TypeSpecComparer.Override.IsEqual (m.ReturnType, ret_type)) { + tm.found[i] = method; + continue; + } + + // + // `need_proxy' is not null when we're implementing an + // interface indexer and this is Clear(One/All) operation. + // + // If `name' is null, then we do a match solely based on the + // signature and not on the name (this is done in the Lookup + // for an interface indexer). + // + if (op != Operation.Lookup) { + if (m.IsAccessor != method.method.IsAccessor) + continue; + + // If `t != null', then this is an explicitly interface + // implementation and we can always clear the method. + // `need_proxy' is not null if we're implementing an + // interface indexer. In this case, we need to create + // a proxy if the implementation's IndexerName doesn't + // match the IndexerName in the interface. + if (m.DeclaringType.IsInterface && iType == null && name.Name != m.Name) { // TODO: This is very expensive comparison + tm.need_proxy[i] = method.method.Spec; + } else { + tm.methods[i] = null; + } + } else { + tm.found [i] = method; + } + + if (op == Operation.Lookup && name.Left != null && ambiguousCandidate == null) { + ambiguousCandidate = m; + continue; + } + + // + // Lookups and ClearOne return + // + if (op != Operation.ClearAll) + return m; + } + + // If a specific type was requested, we can stop now. + if (tm.type == iType) + break; + } + + m = ambiguousCandidate; + ambiguousCandidate = null; + return m; + } + + /// + /// C# allows this kind of scenarios: + /// interface I { void M (); } + /// class X { public void M (); } + /// class Y : X, I { } + /// + /// For that case, we create an explicit implementation function + /// I.M in Y. + /// + void DefineProxy (TypeSpec iface, MethodSpec base_method, MethodSpec iface_method) + { + // TODO: Handle nested iface names + string proxy_name; + var ns = iface.MemberDefinition.Namespace; + if (string.IsNullOrEmpty (ns)) + proxy_name = iface.MemberDefinition.Name + "." + iface_method.Name; + else + proxy_name = ns + "." + iface.MemberDefinition.Name + "." + iface_method.Name; + + var param = iface_method.Parameters; + + MethodBuilder proxy = container.TypeBuilder.DefineMethod ( + proxy_name, + MethodAttributes.Private | + MethodAttributes.HideBySig | + MethodAttributes.NewSlot | + MethodAttributes.CheckAccessOnOverride | + MethodAttributes.Virtual | MethodAttributes.Final, + CallingConventions.Standard | CallingConventions.HasThis, + base_method.ReturnType.GetMetaInfo (), param.GetMetaInfo ()); + + if (iface_method.IsGeneric) { + var gnames = iface_method.GenericDefinition.TypeParameters.Select (l => l.Name).ToArray (); + proxy.DefineGenericParameters (gnames); + } + + for (int i = 0; i < param.Count; i++) { + string name = param.FixedParameters [i].Name; + ParameterAttributes attr = ParametersCompiled.GetParameterAttribute (param.FixedParameters [i].ModFlags); + proxy.DefineParameter (i + 1, attr, name); + } + + int top = param.Count; + var ec = new EmitContext (null, proxy.GetILGenerator (), null); + // TODO: GetAllParametersArguments + for (int i = 0; i <= top; i++) + ParameterReference.EmitLdArg (ec, i); + + ec.Emit (OpCodes.Call, base_method); + ec.Emit (OpCodes.Ret); + + container.TypeBuilder.DefineMethodOverride (proxy, (MethodInfo) iface_method.GetMetaInfo ()); + } + + /// + /// This function tells whether one of our base classes implements + /// the given method (which turns out, it is valid to have an interface + /// implementation in a base + /// + bool BaseImplements (TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method) + { + base_method = null; + var base_type = container.BaseType; + + // + // Setup filter with no return type to give better error message + // about mismatch at return type when the check bellow rejects them + // + var parameters = mi.Parameters; + while (true) { + var candidates = MemberCache.FindMembers (base_type, mi.Name, false); + if (candidates == null) + return false; + + MethodSpec similar_candidate = null; + foreach (var candidate in candidates) { + if (candidate.Kind != MemberKind.Method) + continue; + + if (candidate.Arity != mi.Arity) + continue; + + var candidate_param = ((MethodSpec) candidate).Parameters; + if (!TypeSpecComparer.Override.IsSame (parameters.Types, candidate_param.Types)) + continue; + + bool modifiers_match = true; + for (int i = 0; i < parameters.Count; ++i) { + // + // First check exact ref/out match + // + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((parameters.FixedParameters[i].ModFlags & ref_out) == (candidate_param.FixedParameters[i].ModFlags & ref_out)) + continue; + + modifiers_match = false; + + // + // Different in ref/out only + // + if ((parameters.FixedParameters[i].ModFlags & candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0) { + if (similar_candidate == null) { + if (!candidate.IsPublic) + break; + + if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, ((MethodSpec) candidate).ReturnType)) + break; + + // It's used for ref/out ambiguity overload check + similar_candidate = (MethodSpec) candidate; + } + + continue; + } + + similar_candidate = null; + break; + } + + if (!modifiers_match) + continue; + + // + // From this point on the candidate is used for detailed error reporting + // because it's very close match to what we are looking for + // + base_method = (MethodSpec) candidate; + + if (!candidate.IsPublic) + return false; + + if (!TypeSpecComparer.Override.IsEqual (mi.ReturnType, base_method.ReturnType)) + return false; + } + + if (base_method != null) { + if (similar_candidate != null) { + Report.SymbolRelatedToPreviousError (similar_candidate); + Report.SymbolRelatedToPreviousError (mi); + Report.SymbolRelatedToPreviousError (container); + Report.Warning (1956, 1, ((MemberCore) base_method.MemberDefinition).Location, + "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'", + mi.GetSignatureForError (), base_method.GetSignatureForError (), similar_candidate.GetSignatureForError (), container.GetSignatureForError ()); + } + + break; + } + + base_type = candidates[0].DeclaringType.BaseType; + if (base_type == null) + return false; + } + + if (!base_method.IsVirtual) { +#if STATIC + var base_builder = base_method.GetMetaInfo () as MethodBuilder; + if (base_builder != null) { + // + // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can + // be done for all methods from compiled assembly + // + base_builder.__SetAttributes (base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot); + return true; + } +#endif + DefineProxy (iface_type, base_method, mi); + } + + return true; + } + + /// + /// Verifies that any pending abstract methods or interface methods + /// were implemented. + /// + public bool VerifyPendingMethods () + { + int top = pending_implementations.Length; + bool errors = false; + int i; + + for (i = 0; i < top; i++){ + TypeSpec type = pending_implementations [i].type; + + bool base_implements_type = type.IsInterface && + container.BaseType != null && + container.BaseType.ImplementsInterface (type, false); + + for (int j = 0; j < pending_implementations [i].methods.Count; ++j) { + var mi = pending_implementations[i].methods[j]; + if (mi == null) + continue; + + if (type.IsInterface){ + var need_proxy = + pending_implementations [i].need_proxy [j]; + + if (need_proxy != null) { + DefineProxy (type, need_proxy, mi); + continue; + } + + if (pending_implementations [i].optional) + continue; + + MethodSpec candidate = null; + if (base_implements_type || BaseImplements (type, mi, out candidate)) + continue; + + if (candidate == null) { + MethodData md = pending_implementations [i].found [j]; + if (md != null) + candidate = md.method.Spec; + } + + Report.SymbolRelatedToPreviousError (mi); + if (candidate != null) { + Report.SymbolRelatedToPreviousError (candidate); + 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)); + } 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", + container.GetSignatureForError (), mi.GetSignatureForError (), candidate.GetSignatureForError ()); + } 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)); + } + } else { + Report.Error (535, container.Location, "`{0}' does not implement interface member `{1}'", + container.GetSignatureForError (), mi.GetSignatureForError ()); + } + } else { + Report.SymbolRelatedToPreviousError (mi); + Report.Error (534, container.Location, "`{0}' does not implement inherited abstract member `{1}'", + container.GetSignatureForError (), mi.GetSignatureForError ()); + } + errors = true; + } + } + return errors; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs new file mode 100644 index 0000000000..d5adfccad9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs @@ -0,0 +1,1675 @@ +// +// property.cs: Property based handlers +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// 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 +// + +using System; +using System.Collections.Generic; +using System.Text; + +#if NET_2_1 +using XmlElement = System.Object; +#endif + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // It is used as a base class for all property based members + // This includes properties, indexers, and events + public abstract class PropertyBasedMember : InterfaceMemberBase + { + public PropertyBasedMember (DeclSpace parent, GenericMethod generic, + FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, + MemberName name, Attributes attrs) + : base (parent, generic, type, mod, allowed_mod, name, attrs) + { + } + + protected void CheckReservedNameConflict (string prefix, MethodSpec accessor) + { + string name; + AParametersCollection parameters; + if (accessor != null) { + name = accessor.Name; + parameters = accessor.Parameters; + } else { + name = prefix + ShortName; + if (IsExplicitImpl) + name = MemberName.Left + "." + name; + + if (this is Indexer) { + parameters = ((Indexer) this).ParameterInfo; + if (prefix[0] == 's') { + var data = new IParameterData[parameters.Count + 1]; + Array.Copy (parameters.FixedParameters, data, data.Length - 1); + data[data.Length - 1] = new ParameterData ("value", Parameter.Modifier.NONE); + var types = new TypeSpec[data.Length]; + Array.Copy (parameters.Types, types, data.Length - 1); + types[data.Length - 1] = member_type; + + parameters = new ParametersImported (data, types, false); + } + } else { + if (prefix[0] == 's') + parameters = ParametersCompiled.CreateFullyResolved (new[] { member_type }); + else + parameters = ParametersCompiled.EmptyReadOnlyParameters; + } + } + + var conflict = MemberCache.FindMember (Parent.Definition, + new MemberFilter (name, 0, MemberKind.Method, parameters, null), + BindingRestriction.DeclaredOnly | BindingRestriction.NoAccessors); + + if (conflict != null) { + Report.SymbolRelatedToPreviousError (conflict); + Report.Error (82, Location, "A member `{0}' is already reserved", conflict.GetSignatureForError ()); + } + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + if (!MemberType.IsCLSCompliant ()) { + Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant", + GetSignatureForError ()); + } + return true; + } + + } + + public class PropertySpec : MemberSpec, IInterfaceMemberSpec + { + PropertyInfo info; + TypeSpec memberType; + MethodSpec set, get; + + public PropertySpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, PropertyInfo info, Modifiers modifiers) + : base (kind, declaringType, definition, modifiers) + { + this.info = info; + this.memberType = memberType; + } + + #region Properties + + public MethodSpec Get { + get { + return get; + } + set { + get = value; + get.IsAccessor = true; + } + } + + public MethodSpec Set { + get { + return set; + } + set { + set = value; + set.IsAccessor = true; + } + } + + public bool HasDifferentAccessibility { + get { + return HasGet && HasSet && + (Get.Modifiers & Modifiers.AccessibilityMask) != (Set.Modifiers & Modifiers.AccessibilityMask); + } + } + + public bool HasGet { + get { + return Get != null; + } + } + + public bool HasSet { + get { + return Set != null; + } + } + + public PropertyInfo MetaInfo { + get { + if ((state & StateFlags.PendingMetaInflate) != 0) + throw new NotSupportedException (); + + return info; + } + } + + public TypeSpec MemberType { + get { + return memberType; + } + } + + #endregion + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var ps = (PropertySpec) base.InflateMember (inflator); + ps.memberType = inflator.Inflate (memberType); + return ps; + } + + public override List ResolveMissingDependencies () + { + return memberType.ResolveMissingDependencies (); + } + } + + // + // Properties and Indexers both generate PropertyBuilders, we use this to share + // their common bits. + // + abstract public class PropertyBase : PropertyBasedMember { + + public class GetMethod : PropertyMethod + { + static readonly string[] attribute_targets = new string [] { "method", "return" }; + + internal const string Prefix = "get_"; + + public GetMethod (PropertyBase method, Modifiers modifiers, Attributes attrs, Location loc) + : base (method, Prefix, modifiers, attrs, loc) + { + } + + public override MethodBuilder Define (DeclSpace parent) + { + base.Define (parent); + + Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags); + + method_data = new MethodData (method, ModFlags, flags, this); + + if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + return null; + + Spec.SetMetaInfo (method_data.MethodBuilder); + + return method_data.MethodBuilder; + } + + public override TypeSpec ReturnType { + get { + return method.MemberType; + } + } + + public override ParametersCompiled ParameterInfo { + get { + return ParametersCompiled.EmptyReadOnlyParameters; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + + public class SetMethod : PropertyMethod { + + static readonly string[] attribute_targets = new string[] { "method", "param", "return" }; + + internal const string Prefix = "set_"; + + protected ParametersCompiled parameters; + + public SetMethod (PropertyBase method, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc) + : base (method, Prefix, modifiers, attrs, loc) + { + this.parameters = parameters; + } + + protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Parameter) { + parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + public override MethodBuilder Define (DeclSpace parent) + { + parameters.Resolve (this); + + base.Define (parent); + + Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, null, ParameterInfo, ModFlags); + + method_data = new MethodData (method, ModFlags, flags, this); + + if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + return null; + + Spec.SetMetaInfo (method_data.MethodBuilder); + + return method_data.MethodBuilder; + } + + public override TypeSpec ReturnType { + get { + return Parent.Compiler.BuiltinTypes.Void; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + } + + static readonly string[] attribute_targets = new string[] { "property" }; + + public abstract class PropertyMethod : AbstractPropertyEventMethod + { + const Modifiers AllowedModifiers = + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE; + + protected readonly PropertyBase method; + protected MethodAttributes flags; + + public PropertyMethod (PropertyBase method, string prefix, Modifiers modifiers, Attributes attrs, Location loc) + : base (method, prefix, attrs, loc) + { + this.method = method; + this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, modifiers, 0, loc, Report); + this.ModFlags |= (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.MethodImpl) { + method.is_external_implementation = a.IsInternalCall (); + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method; + } + } + + public override bool IsClsComplianceRequired () + { + return method.IsClsComplianceRequired (); + } + + public virtual MethodBuilder Define (DeclSpace parent) + { + TypeContainer container = parent.PartialContainer; + + // + // Check for custom access modifier + // + if ((ModFlags & Modifiers.AccessibilityMask) == 0) { + ModFlags |= method.ModFlags; + flags = method.flags; + } else { + if (container.Kind == MemberKind.Interface) + Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface", + GetSignatureForError ()); + else if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) { + Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ()); + } + + CheckModifiers (ModFlags); + ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask)); + ModFlags |= Modifiers.PROPERTY_CUSTOM; + flags = ModifiersExtensions.MethodAttr (ModFlags); + flags |= (method.flags & (~MethodAttributes.MemberAccessMask)); + } + + CheckAbstractAndExtern (block != null); + CheckProtectedModifier (); + + if (block != null && block.IsIterator) + Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags); + + return null; + } + + public bool HasCustomAccessModifier { + get { + return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0; + } + } + + public PropertyBase Property { + get { + return method; + } + } + + public override ObsoleteAttribute GetAttributeObsolete () + { + return method.GetAttributeObsolete (); + } + + public override string GetSignatureForError() + { + return method.GetSignatureForError () + "." + prefix.Substring (0, 3); + } + + void CheckModifiers (Modifiers modflags) + { + if (!ModifiersExtensions.IsRestrictedModifier (modflags & Modifiers.AccessibilityMask, method.ModFlags & Modifiers.AccessibilityMask)) { + Report.Error (273, Location, + "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'", + GetSignatureForError (), method.GetSignatureForError ()); + } + } + } + + PropertyMethod get, set, first; + PropertyBuilder PropertyBuilder; + + public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, + Modifiers allowed_mod, MemberName name, Attributes attrs) + : base (parent, null, type, mod_flags, allowed_mod, name, attrs) + { + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Property; + } + } + + public PropertyMethod AccessorFirst { + get { + return first; + } + } + + public PropertyMethod AccessorSecond { + get { + return first == get ? set : get; + } + } + + public override Variance ExpectedMemberTypeVariance { + get { + return (get != null && set != null) ? + Variance.None : set == null ? + Variance.Covariant : + Variance.Contravariant; + } + } + + public PropertyMethod Get { + get { + return get; + } + set { + get = value; + if (first == null) + first = value; + + Parent.AddMember (get); + } + } + + public PropertyMethod Set { + get { + return set; + } + set { + set = value; + if (first == null) + first = value; + + Parent.AddMember (set); + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.HasSecurityAttribute) { + a.Error_InvalidSecurityParent (); + return; + } + + if (a.Type == pa.Dynamic) { + a.Error_MisusedDynamicAttribute (); + return; + } + + PropertyBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + void CheckMissingAccessor (MemberKind kind, ParametersCompiled parameters, bool get) + { + if (IsExplicitImpl) { + MemberFilter filter; + if (kind == MemberKind.Indexer) + filter = new MemberFilter (MemberCache.IndexerNameAlias, 0, kind, parameters, null); + else + filter = new MemberFilter (MemberName.Name, 0, kind, null, null); + + var implementing = MemberCache.FindMember (InterfaceType, filter, BindingRestriction.DeclaredOnly) as PropertySpec; + + if (implementing == null) + return; + + var accessor = get ? implementing.Get : implementing.Set; + if (accessor != null) { + Report.SymbolRelatedToPreviousError (accessor); + Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'", + GetSignatureForError (), accessor.GetSignatureForError ()); + } + } + } + + protected override bool CheckOverrideAgainstBase (MemberSpec base_member) + { + var ok = base.CheckOverrideAgainstBase (base_member); + + // + // Check base property accessors conflict + // + var base_prop = (PropertySpec) base_member; + if (Get != null) { + if (!base_prop.HasGet) { + if (ok) { + Report.SymbolRelatedToPreviousError (base_prop); + Report.Error (545, Get.Location, + "`{0}': cannot override because `{1}' does not have an overridable get accessor", + Get.GetSignatureForError (), base_prop.GetSignatureForError ()); + ok = false; + } + } else if (Get.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) { + if (!CheckAccessModifiers (Get, base_prop.Get)) { + Error_CannotChangeAccessModifiers (Get, base_prop.Get); + ok = false; + } + } + } + + if (Set != null) { + if (!base_prop.HasSet) { + if (ok) { + Report.SymbolRelatedToPreviousError (base_prop); + Report.Error (546, Set.Location, + "`{0}': cannot override because `{1}' does not have an overridable set accessor", + Set.GetSignatureForError (), base_prop.GetSignatureForError ()); + ok = false; + } + } else if (Set.HasCustomAccessModifier || base_prop.HasDifferentAccessibility) { + if (!CheckAccessModifiers (Set, base_prop.Set)) { + Error_CannotChangeAccessModifiers (Set, base_prop.Set); + ok = false; + } + } + } + + if ((Set == null || !Set.HasCustomAccessModifier) && (Get == null || !Get.HasCustomAccessModifier)) { + if (!CheckAccessModifiers (this, base_prop)) { + Error_CannotChangeAccessModifiers (this, base_prop); + ok = false; + } + } + + return ok; + } + + protected override void DoMemberTypeDependentChecks () + { + base.DoMemberTypeDependentChecks (); + + IsTypePermitted (); + + if (MemberType.IsStatic) + Error_StaticReturnType (); + } + + protected override void DoMemberTypeIndependentChecks () + { + base.DoMemberTypeIndependentChecks (); + + // + // Accessors modifiers check + // + if (AccessorSecond != null) { + if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) { + Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer", + GetSignatureForError ()); + } + } else if ((ModFlags & Modifiers.OVERRIDE) == 0 && + (Get == null && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) || + (Set == null && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) { + Report.Error (276, Location, + "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor", + GetSignatureForError ()); + } + } + + protected bool DefineAccessors () + { + first.Define (Parent); + if (AccessorSecond != null) + AccessorSecond.Define (Parent); + + return true; + } + + protected void DefineBuilders (MemberKind kind, ParametersCompiled parameters) + { + PropertyBuilder = Parent.TypeBuilder.DefineProperty ( + GetFullName (MemberName), PropertyAttributes.None, +#if !BOOTSTRAP_BASIC // Requires trunk version mscorlib + IsStatic ? 0 : CallingConventions.HasThis, +#endif + MemberType.GetMetaInfo (), null, null, + parameters.GetMetaInfo (), null, null); + + PropertySpec spec; + if (kind == MemberKind.Indexer) + spec = new IndexerSpec (Parent.Definition, this, MemberType, parameters, PropertyBuilder, ModFlags); + else + spec = new PropertySpec (kind, Parent.Definition, this, MemberType, PropertyBuilder, ModFlags); + + if (Get != null) { + spec.Get = Get.Spec; + + var method = Get.Spec.GetMetaInfo () as MethodBuilder; + if (method != null) { + PropertyBuilder.SetGetMethod (method); + Parent.MemberCache.AddMember (this, method.Name, Get.Spec); + } + } else { + CheckMissingAccessor (kind, parameters, true); + } + + if (Set != null) { + spec.Set = Set.Spec; + + var method = Set.Spec.GetMetaInfo () as MethodBuilder; + if (method != null) { + PropertyBuilder.SetSetMethod (method); + Parent.MemberCache.AddMember (this, method.Name, Set.Spec); + } + } else { + CheckMissingAccessor (kind, parameters, false); + } + + Parent.MemberCache.AddMember (this, PropertyBuilder.Name, spec); + } + + public override void Emit () + { + CheckReservedNameConflict (GetMethod.Prefix, get == null ? null : get.Spec); + CheckReservedNameConflict (SetMethod.Prefix, set == null ? null : set.Spec); + + if (OptAttributes != null) + OptAttributes.Emit (); + + if (member_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder); + } else if (member_type.HasDynamicElement) { + Module.PredefinedAttributes.Dynamic.EmitAttribute (PropertyBuilder, member_type, Location); + } + + ConstraintChecker.Check (this, member_type, type_expr.Location); + + first.Emit (Parent); + if (AccessorSecond != null) + AccessorSecond.Emit (Parent); + + base.Emit (); + } + + public override bool IsUsed { + get { + if (IsExplicitImpl) + return true; + + return Get.IsUsed | Set.IsUsed; + } + } + + protected override void SetMemberName (MemberName new_name) + { + base.SetMemberName (new_name); + + if (Get != null) + Get.UpdateName (this); + + if (Set != null) + Set.UpdateName (this); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { return "P:"; } + } + } + + public class Property : PropertyBase + { + public sealed class BackingField : Field + { + readonly Property property; + + public BackingField (Property p) + : base (p.Parent, p.type_expr, + Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), + new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null) + { + this.property = p; + } + + public string OriginalName { + get { + return property.Name; + } + } + + public override string GetSignatureForError () + { + return property.GetSignatureForError (); + } + } + + public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod, + MemberName name, Attributes attrs) + : base (parent, type, mod, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct : + AllowedModifiersClass, + name, attrs) + { + } + + void CreateAutomaticProperty () + { + // Create backing field + Field field = new BackingField (this); + if (!field.Define ()) + return; + + Parent.PartialContainer.AddField (field); + + FieldExpr fe = new FieldExpr (field, Location); + if ((field.ModFlags & Modifiers.STATIC) == 0) + fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location); + + // Create get block + Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location); + Return r = new Return (fe, Location); + Get.Block.AddStatement (r); + + // Create set block + Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location); + Assign a = new SimpleAssign (fe, new SimpleName ("value", Location)); + Set.Block.AddStatement (new StatementExpression (a)); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + + if (!IsInterface && (ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 && + AccessorSecond != null && Get.Block == null && Set.Block == null) { + if (Compiler.Settings.Version <= LanguageVersion.ISO_2) + Report.FeatureIsNotAvailable (Compiler, Location, "automatically implemented properties"); + + Get.ModFlags |= Modifiers.COMPILER_GENERATED; + Set.ModFlags |= Modifiers.COMPILER_GENERATED; + CreateAutomaticProperty (); + } + + if (!DefineAccessors ()) + return false; + + if (!CheckBase ()) + return false; + + DefineBuilders (MemberKind.Property, ParametersCompiled.EmptyReadOnlyParameters); + return true; + } + + public override void Emit () + { + if ((AccessorFirst.ModFlags & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) { + Report.Error (842, Location, + "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute", + GetSignatureForError ()); + } + + base.Emit (); + } + } + + /// + /// For case when event is declared like property (with add and remove accessors). + /// + public class EventProperty: Event { + public abstract class AEventPropertyAccessor : AEventAccessor + { + protected AEventPropertyAccessor (EventProperty method, string prefix, Attributes attrs, Location loc) + : base (method, prefix, attrs, loc) + { + } + + public override MethodBuilder Define (DeclSpace ds) + { + CheckAbstractAndExtern (block != null); + return base.Define (ds); + } + + public override string GetSignatureForError () + { + return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1); + } + } + + public sealed class AddDelegateMethod: AEventPropertyAccessor + { + public AddDelegateMethod (EventProperty method, Attributes attrs, Location loc) + : base (method, AddPrefix, attrs, loc) + { + } + } + + public sealed class RemoveDelegateMethod: AEventPropertyAccessor + { + public RemoveDelegateMethod (EventProperty method, Attributes attrs, Location loc) + : base (method, RemovePrefix, attrs, loc) + { + } + } + + static readonly string[] attribute_targets = new string [] { "event" }; + + public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, type, mod_flags, name, attrs) + { + } + + public override bool Define() + { + if (!base.Define ()) + return false; + + SetIsUsed (); + return true; + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + } + + /// + /// Event is declared like field. + /// + public class EventField : Event + { + abstract class EventFieldAccessor : AEventAccessor + { + protected EventFieldAccessor (EventField method, string prefix) + : base (method, prefix, null, Location.Null) + { + } + + protected abstract MethodSpec GetOperation (Location loc); + + public override void Emit (DeclSpace parent) + { + if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) { + block = new ToplevelBlock (Compiler, ParameterInfo, Location); + FabricateBodyStatement (); + } + + base.Emit (parent); + } + + void FabricateBodyStatement () + { + // + // Delegate obj1 = backing_field + // do { + // Delegate obj2 = obj1; + // obj1 = Interlocked.CompareExchange (ref backing_field, Delegate.Combine|Remove(obj2, value), obj1); + // } while (obj1 != obj2) + // + + var field_info = ((EventField) method).backing_field; + FieldExpr f_expr = new FieldExpr (field_info, Location); + if (!IsStatic) + f_expr.InstanceExpression = new CompilerGeneratedThis (Parent.CurrentType, Location); + + var obj1 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); + var obj2 = LocalVariable.CreateCompilerGenerated (field_info.MemberType, block, Location); + + block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (obj1, Location), f_expr))); + + var cond = new BooleanExpression (new Binary (Binary.Operator.Inequality, + new LocalVariableReference (obj1, Location), new LocalVariableReference (obj2, Location), Location)); + + var body = new ExplicitBlock (block, Location, Location); + block.AddStatement (new Do (body, cond, Location)); + + body.AddStatement (new StatementExpression ( + new SimpleAssign (new LocalVariableReference (obj2, Location), new LocalVariableReference (obj1, Location)))); + + var args_oper = new Arguments (2); + args_oper.Add (new Argument (new LocalVariableReference (obj2, Location))); + args_oper.Add (new Argument (block.GetParameterReference (0, Location))); + + var op_method = GetOperation (Location); + + var args = new Arguments (3); + args.Add (new Argument (f_expr, Argument.AType.Ref)); + args.Add (new Argument (new Cast ( + new TypeExpression (field_info.MemberType, Location), + new Invocation (MethodGroupExpr.CreatePredefined (op_method, op_method.DeclaringType, Location), args_oper), + Location))); + args.Add (new Argument (new LocalVariableReference (obj1, Location))); + + var cas = Module.PredefinedMembers.InterlockedCompareExchange_T.Resolve (Location); + if (cas == null) + return; + + body.AddStatement (new StatementExpression (new SimpleAssign ( + new LocalVariableReference (obj1, Location), + new Invocation (MethodGroupExpr.CreatePredefined (cas, cas.DeclaringType, Location), args)))); + } + } + + sealed class AddDelegateMethod: EventFieldAccessor + { + public AddDelegateMethod (EventField method): + base (method, AddPrefix) + { + } + + protected override MethodSpec GetOperation (Location loc) + { + return Module.PredefinedMembers.DelegateCombine.Resolve (loc); + } + } + + sealed class RemoveDelegateMethod: EventFieldAccessor + { + public RemoveDelegateMethod (EventField method): + base (method, RemovePrefix) + { + } + + protected override MethodSpec GetOperation (Location loc) + { + return Module.PredefinedMembers.DelegateRemove.Resolve (loc); + } + } + + + static readonly string[] attribute_targets = new string [] { "event", "field", "method" }; + static readonly string[] attribute_targets_interface = new string[] { "event", "method" }; + + Expression initializer; + Field backing_field; + List declarators; + + public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, type, mod_flags, name, attrs) + { + Add = new AddDelegateMethod (this); + Remove = new RemoveDelegateMethod (this); + } + + #region Properties + + bool HasBackingField { + get { + return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + initializer = value; + } + } + + public override string[] ValidAttributeTargets { + get { + return HasBackingField ? attribute_targets : attribute_targets_interface; + } + } + + public List Declarators { + get { + return this.declarators; + } + } + + #endregion + + public void AddDeclarator (FieldDeclarator declarator) + { + if (declarators == null) + declarators = new List (2); + + declarators.Add (declarator); + + // TODO: This will probably break + Parent.AddMember (this, declarator.Name.Value); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Field) { + backing_field.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + if (a.Target == AttributeTargets.Method) { + int errors = Report.Errors; + Add.ApplyAttributeBuilder (a, ctor, cdata, pa); + if (errors == Report.Errors) + Remove.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override bool Define() + { + var mod_flags_src = ModFlags; + + if (!base.Define ()) + return false; + + if (declarators != null) { + if ((mod_flags_src & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) + mod_flags_src &= ~(Modifiers.AccessibilityMask | Modifiers.DEFAULT_ACCESS_MODIFER); + + var t = new TypeExpression (MemberType, TypeExpression.Location); + int index = Parent.PartialContainer.Events.IndexOf (this); + foreach (var d in declarators) { + var ef = new EventField (Parent, t, mod_flags_src, new MemberName (d.Name.Value, d.Name.Location), OptAttributes); + + if (d.Initializer != null) + ef.initializer = d.Initializer; + + Parent.PartialContainer.Events.Insert (++index, ef); + } + } + + if (!HasBackingField) { + SetIsUsed (); + return true; + } + + if (Add.IsInterfaceImplementation) + SetIsUsed (); + + backing_field = new Field (Parent, + new TypeExpression (MemberType, Location), + Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)), + MemberName, null); + + Parent.PartialContainer.AddField (backing_field); + backing_field.Initializer = Initializer; + backing_field.ModFlags &= ~Modifiers.COMPILER_GENERATED; + + // Call define because we passed fields definition + backing_field.Define (); + + // Set backing field for event fields + spec.BackingField = backing_field.Spec; + + return true; + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + } + + public abstract class Event : PropertyBasedMember + { + public abstract class AEventAccessor : AbstractPropertyEventMethod + { + protected readonly Event method; + readonly ParametersCompiled parameters; + + static readonly string[] attribute_targets = new string [] { "method", "param", "return" }; + + public const string AddPrefix = "add_"; + public const string RemovePrefix = "remove_"; + + protected AEventAccessor (Event method, string prefix, Attributes attrs, Location loc) + : base (method, prefix, attrs, loc) + { + this.method = method; + this.ModFlags = method.ModFlags; + this.parameters = ParametersCompiled.CreateImplicitParameter (method.TypeExpression, loc); + } + + public bool IsInterfaceImplementation { + get { return method_data.implementing != null; } + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.MethodImpl) { + method.is_external_implementation = a.IsInternalCall (); + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected override void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Parameter) { + parameters[0].ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Method; + } + } + + public override bool IsClsComplianceRequired () + { + return method.IsClsComplianceRequired (); + } + + public virtual MethodBuilder Define (DeclSpace parent) + { + // Fill in already resolved event type to speed things up and + // avoid confusing duplicate errors + ((Parameter) parameters.FixedParameters[0]).Type = method.member_type; + parameters.Types = new TypeSpec[] { method.member_type }; + + method_data = new MethodData (method, method.ModFlags, + method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this); + + if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + return null; + + MethodBuilder mb = method_data.MethodBuilder; + + Spec = new MethodSpec (MemberKind.Method, parent.PartialContainer.Definition, this, ReturnType, mb, ParameterInfo, method.ModFlags); + Spec.IsAccessor = true; + + return mb; + } + + public override TypeSpec ReturnType { + get { + return Parent.Compiler.BuiltinTypes.Void; + } + } + + public override ObsoleteAttribute GetAttributeObsolete () + { + return method.GetAttributeObsolete (); + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + public override ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + } + + AEventAccessor add, remove; + EventBuilder EventBuilder; + protected EventSpec spec; + + protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs) + : base (parent, null, type, mod_flags, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface : + parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct : + AllowedModifiersClass, + name, attrs) + { + } + + #region Properties + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Event; + } + } + + public AEventAccessor Add { + get { + return this.add; + } + set { + add = value; + Parent.AddMember (value); + } + } + + public override Variance ExpectedMemberTypeVariance { + get { + return Variance.Contravariant; + } + } + + public AEventAccessor Remove { + get { + return this.remove; + } + set { + remove = value; + Parent.AddMember (value); + } + } + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if ((a.HasSecurityAttribute)) { + a.Error_InvalidSecurityParent (); + return; + } + + EventBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + protected override bool CheckOverrideAgainstBase (MemberSpec base_member) + { + var ok = base.CheckOverrideAgainstBase (base_member); + + if (!CheckAccessModifiers (this, base_member)) { + Error_CannotChangeAccessModifiers (this, base_member); + ok = false; + } + + return ok; + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!TypeManager.IsDelegateType (MemberType)) { + Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ()); + } + + if (!CheckBase ()) + return false; + + // + // Now define the accessors + // + var AddBuilder = Add.Define (Parent); + if (AddBuilder == null) + return false; + + var RemoveBuilder = remove.Define (Parent); + if (RemoveBuilder == null) + return false; + + EventBuilder = Parent.TypeBuilder.DefineEvent (GetFullName (MemberName), EventAttributes.None, MemberType.GetMetaInfo ()); + EventBuilder.SetAddOnMethod (AddBuilder); + EventBuilder.SetRemoveOnMethod (RemoveBuilder); + + spec = new EventSpec (Parent.Definition, this, MemberType, ModFlags, Add.Spec, remove.Spec); + + Parent.MemberCache.AddMember (this, Name, spec); + Parent.MemberCache.AddMember (this, AddBuilder.Name, Add.Spec); + Parent.MemberCache.AddMember (this, RemoveBuilder.Name, remove.Spec); + + return true; + } + + public override void Emit () + { + CheckReservedNameConflict (null, add.Spec); + CheckReservedNameConflict (null, remove.Spec); + + if (OptAttributes != null) { + OptAttributes.Emit (); + } + + ConstraintChecker.Check (this, member_type, type_expr.Location); + + Add.Emit (Parent); + Remove.Emit (Parent); + + base.Emit (); + } + + // + // Represents header string for documentation comment. + // + public override string DocCommentHeader { + get { return "E:"; } + } + } + + public class EventSpec : MemberSpec, IInterfaceMemberSpec + { + MethodSpec add, remove; + FieldSpec backing_field; + + public EventSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec eventType, Modifiers modifiers, MethodSpec add, MethodSpec remove) + : base (MemberKind.Event, declaringType, definition, modifiers) + { + this.AccessorAdd = add; + this.AccessorRemove = remove; + this.MemberType = eventType; + } + + #region Properties + + public MethodSpec AccessorAdd { + get { + return add; + } + set { + add = value; + } + } + + public MethodSpec AccessorRemove { + get { + return remove; + } + set { + remove = value; + } + } + + public FieldSpec BackingField { + get { + return backing_field; + } + set { + backing_field = value; + } + } + + public TypeSpec MemberType { get; private set; } + + #endregion + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var es = (EventSpec) base.InflateMember (inflator); + es.MemberType = inflator.Inflate (MemberType); + + if (backing_field != null) + es.backing_field = (FieldSpec) backing_field.InflateMember (inflator); + + return es; + } + + public override List ResolveMissingDependencies () + { + return MemberType.ResolveMissingDependencies (); + } + } + + public class Indexer : PropertyBase, IParametersMember + { + public class GetIndexerMethod : GetMethod, IParametersMember + { + ParametersCompiled parameters; + + public GetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc) + : base (property, modifiers, attrs, loc) + { + this.parameters = parameters; + } + + public override MethodBuilder Define (DeclSpace parent) + { + parameters.Resolve (this); + return base.Define (parent); + } + + public override ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + #region IParametersMember Members + + AParametersCollection IParametersMember.Parameters { + get { + return parameters; + } + } + + TypeSpec IInterfaceMemberSpec.MemberType { + get { + return ReturnType; + } + } + + #endregion + } + + public class SetIndexerMethod : SetMethod, IParametersMember + { + public SetIndexerMethod (PropertyBase property, Modifiers modifiers, ParametersCompiled parameters, Attributes attrs, Location loc) + : base (property, modifiers, parameters, attrs, loc) + { + } + + #region IParametersMember Members + + AParametersCollection IParametersMember.Parameters { + get { + return parameters; + } + } + + TypeSpec IInterfaceMemberSpec.MemberType { + get { + return ReturnType; + } + } + + #endregion + } + + const Modifiers AllowedModifiers = + Modifiers.NEW | + Modifiers.PUBLIC | + Modifiers.PROTECTED | + Modifiers.INTERNAL | + Modifiers.PRIVATE | + Modifiers.VIRTUAL | + Modifiers.SEALED | + Modifiers.OVERRIDE | + Modifiers.UNSAFE | + Modifiers.EXTERN | + Modifiers.ABSTRACT; + + const Modifiers AllowedInterfaceModifiers = + Modifiers.NEW; + + readonly ParametersCompiled parameters; + + public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod, + ParametersCompiled parameters, Attributes attrs) + : base (parent, type, mod, + parent.PartialContainer.Kind == MemberKind.Interface ? AllowedInterfaceModifiers : AllowedModifiers, + name, attrs) + { + this.parameters = parameters; + } + + #region Properties + + AParametersCollection IParametersMember.Parameters { + get { + return parameters; + } + } + + public ParametersCompiled ParameterInfo { + get { + return parameters; + } + } + + #endregion + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Type == pa.IndexerName) { + if (IsExplicitImpl) { + Report.Error (415, a.Location, + "The `{0}' attribute is valid only on an indexer that is not an explicit interface member declaration", + TypeManager.CSharpName (a.Type)); + } + + // Attribute was copied to container + return; + } + + base.ApplyAttributeBuilder (a, ctor, cdata, pa); + } + + protected override bool CheckForDuplications () + { + return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters); + } + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public override bool Define () + { + if (!base.Define ()) + return false; + + if (!DefineParameters (parameters)) + return false; + + if (OptAttributes != null) { + Attribute indexer_attr = OptAttributes.Search (Module.PredefinedAttributes.IndexerName); + if (indexer_attr != null) { + var compiling = indexer_attr.Type.MemberDefinition as TypeContainer; + if (compiling != null) + compiling.Define (); + + string name = indexer_attr.GetIndexerAttributeValue (); + if ((ModFlags & Modifiers.OVERRIDE) != 0) { + Report.Error (609, indexer_attr.Location, + "Cannot set the `IndexerName' attribute on an indexer marked override"); + } + + if (!string.IsNullOrEmpty (name)) + ShortName = name; + } + } + + if (InterfaceType != null) { + string base_IndexerName = InterfaceType.MemberDefinition.GetAttributeDefaultMember (); + if (base_IndexerName != Name) + ShortName = base_IndexerName; + } + + if (!Parent.PartialContainer.AddMember (this)) + return false; + + flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName; + + if (!DefineAccessors ()) + return false; + + if (!CheckBase ()) + return false; + + DefineBuilders (MemberKind.Indexer, parameters); + return true; + } + + public override bool EnableOverloadChecks (MemberCore overload) + { + if (overload is Indexer) { + caching_flags |= Flags.MethodOverloadsExist; + return true; + } + + return base.EnableOverloadChecks (overload); + } + + public override void Emit () + { + parameters.CheckConstraints (this); + + base.Emit (); + } + + public override string GetSignatureForError () + { + StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ()); + if (MemberName.Left != null) { + sb.Append ("."); + sb.Append (MemberName.Left.GetSignatureForError ()); + } + + sb.Append (".this"); + sb.Append (parameters.GetSignatureForError ("[", "]", parameters.Count)); + return sb.ToString (); + } + + public override string GetSignatureForDocumentation () + { + return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation (); + } + + protected override bool VerifyClsCompliance () + { + if (!base.VerifyClsCompliance ()) + return false; + + parameters.VerifyClsCompliance (this); + return true; + } + } + + public class IndexerSpec : PropertySpec, IParametersMember + { + AParametersCollection parameters; + + public IndexerSpec (TypeSpec declaringType, IMemberDefinition definition, TypeSpec memberType, AParametersCollection parameters, PropertyInfo info, Modifiers modifiers) + : base (MemberKind.Indexer, declaringType, definition, memberType, info, modifiers) + { + this.parameters = parameters; + } + + #region Properties + public AParametersCollection Parameters { + get { + return parameters; + } + } + #endregion + + public override string GetSignatureForDocumentation () + { + return base.GetSignatureForDocumentation () + parameters.GetSignatureForDocumentation (); + } + + public override string GetSignatureForError () + { + return DeclaringType.GetSignatureForError () + ".this" + parameters.GetSignatureForError ("[", "]", parameters.Count); + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var spec = (IndexerSpec) base.InflateMember (inflator); + spec.parameters = parameters.Inflate (inflator); + return spec; + } + + public override List ResolveMissingDependencies () + { + var missing = base.ResolveMissingDependencies (); + foreach (var pt in parameters.Types) { + var m = pt.GetMissingDependencies (); + if (m == null) + continue; + + if (missing == null) + missing = new List (); + + missing.AddRange (m); + } + + return missing; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs new file mode 100644 index 0000000000..6f2f183a83 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs @@ -0,0 +1,557 @@ +// +// reflection.cs: System.Reflection and System.Reflection.Emit specific implementations +// +// Author: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2009-2010 Novell, Inc. +// +// + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.IO; +using System.Runtime.CompilerServices; +using System.Reflection.Emit; +using System.Security; + +namespace Mono.CSharp +{ +#if STATIC + public class ReflectionImporter + { + public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin) + { + throw new NotSupportedException (); + } + + public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace) + { + throw new NotSupportedException (); + } + + public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace) + { + throw new NotSupportedException (); + } + + public TypeSpec ImportType (Type type) + { + throw new NotSupportedException (); + } + } +#else + public sealed class ReflectionImporter : MetadataImporter + { + public ReflectionImporter (ModuleContainer module, BuiltinTypes builtin) + : base (module) + { + Initialize (builtin); + } + + public override void AddCompiledType (TypeBuilder builder, TypeSpec spec) + { + } + + protected override MemberKind DetermineKindFromBaseType (Type baseType) + { + if (baseType == typeof (ValueType)) + return MemberKind.Struct; + + if (baseType == typeof (System.Enum)) + return MemberKind.Enum; + + if (baseType == typeof (MulticastDelegate)) + return MemberKind.Delegate; + + return MemberKind.Class; + } + + protected override bool HasVolatileModifier (Type[] modifiers) + { + foreach (var t in modifiers) { + if (t == typeof (IsVolatile)) + return true; + } + + return false; + } + + public void ImportAssembly (Assembly assembly, RootNamespace targetNamespace) + { + // It can be used more than once when importing same assembly + // into 2 or more global aliases + var definition = GetAssemblyDefinition (assembly); + + // + // This part tries to simulate loading of top-level + // types only, any missing dependencies are ignores here. + // Full error report is reported later when the type is + // actually used + // + Type[] all_types; + try { + all_types = assembly.GetTypes (); + } catch (ReflectionTypeLoadException e) { + all_types = e.Types; + } + + ImportTypes (all_types, targetNamespace, definition.HasExtensionMethod); + } + + public ImportedModuleDefinition ImportModule (Module module, RootNamespace targetNamespace) + { + var module_definition = new ImportedModuleDefinition (module); + module_definition.ReadAttributes (); + + Type[] all_types; + try { + all_types = module.GetTypes (); + } catch (ReflectionTypeLoadException e) { + all_types = e.Types; + } + + ImportTypes (all_types, targetNamespace, false); + + return module_definition; + } + + void Initialize (BuiltinTypes builtin) + { + // + // Setup mapping for build-in types to avoid duplication of their definition + // + compiled_types.Add (typeof (object), builtin.Object); + compiled_types.Add (typeof (System.ValueType), builtin.ValueType); + compiled_types.Add (typeof (System.Attribute), builtin.Attribute); + + compiled_types.Add (typeof (int), builtin.Int); + compiled_types.Add (typeof (long), builtin.Long); + compiled_types.Add (typeof (uint), builtin.UInt); + compiled_types.Add (typeof (ulong), builtin.ULong); + compiled_types.Add (typeof (byte), builtin.Byte); + compiled_types.Add (typeof (sbyte), builtin.SByte); + compiled_types.Add (typeof (short), builtin.Short); + compiled_types.Add (typeof (ushort), builtin.UShort); + + compiled_types.Add (typeof (System.Collections.IEnumerator), builtin.IEnumerator); + compiled_types.Add (typeof (System.Collections.IEnumerable), builtin.IEnumerable); + compiled_types.Add (typeof (System.IDisposable), builtin.IDisposable); + + compiled_types.Add (typeof (char), builtin.Char); + compiled_types.Add (typeof (string), builtin.String); + compiled_types.Add (typeof (float), builtin.Float); + compiled_types.Add (typeof (double), builtin.Double); + compiled_types.Add (typeof (decimal), builtin.Decimal); + compiled_types.Add (typeof (bool), builtin.Bool); + compiled_types.Add (typeof (System.IntPtr), builtin.IntPtr); + compiled_types.Add (typeof (System.UIntPtr), builtin.UIntPtr); + + compiled_types.Add (typeof (System.MulticastDelegate), builtin.MulticastDelegate); + compiled_types.Add (typeof (System.Delegate), builtin.Delegate); + compiled_types.Add (typeof (System.Enum), builtin.Enum); + compiled_types.Add (typeof (System.Array), builtin.Array); + compiled_types.Add (typeof (void), builtin.Void); + compiled_types.Add (typeof (System.Type), builtin.Type); + compiled_types.Add (typeof (System.Exception), builtin.Exception); + compiled_types.Add (typeof (System.RuntimeFieldHandle), builtin.RuntimeFieldHandle); + compiled_types.Add (typeof (System.RuntimeTypeHandle), builtin.RuntimeTypeHandle); + } + } + + [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Explicit)] + struct SingleConverter + { + [System.Runtime.InteropServices.FieldOffset (0)] + int i; + [System.Runtime.InteropServices.FieldOffset (0)] + float f; + + public static int SingleToInt32Bits (float v) + { + SingleConverter c = new SingleConverter (); + c.f = v; + return c.i; + } + } + +#endif + + public class AssemblyDefinitionDynamic : AssemblyDefinition + { + // + // In-memory only assembly container + // + public AssemblyDefinitionDynamic (ModuleContainer module, string name) + : base (module, name) + { + } + + // + // Assembly container with file output + // + public AssemblyDefinitionDynamic (ModuleContainer module, string name, string fileName) + : base (module, name, fileName) + { + } + + public Module IncludeModule (string moduleFile) + { + return builder_extra.AddModule (moduleFile); + } + +#if !STATIC + public override ModuleBuilder CreateModuleBuilder () + { + if (file_name == null) + return Builder.DefineDynamicModule (Name, false); + + return base.CreateModuleBuilder (); + } +#endif + // + // Initializes the code generator + // + public bool Create (AppDomain domain, AssemblyBuilderAccess access) + { +#if STATIC + throw new NotSupportedException (); +#else + ResolveAssemblySecurityAttributes (); + var an = CreateAssemblyName (); + + Builder = file_name == null ? + domain.DefineDynamicAssembly (an, access) : + domain.DefineDynamicAssembly (an, access, Dirname (file_name)); + + module.Create (this, CreateModuleBuilder ()); + builder_extra = new AssemblyBuilderMonoSpecific (Builder, Compiler); + return true; +#endif + } + + static string Dirname (string name) + { + int pos = name.LastIndexOf ('/'); + + if (pos != -1) + return name.Substring (0, pos); + + pos = name.LastIndexOf ('\\'); + if (pos != -1) + return name.Substring (0, pos); + + return "."; + } + +#if !STATIC + protected override void SaveModule (PortableExecutableKinds pekind, ImageFileMachine machine) + { + try { + var module_only = typeof (AssemblyBuilder).GetProperty ("IsModuleOnly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + var set_module_only = module_only.GetSetMethod (true); + + set_module_only.Invoke (Builder, new object[] { true }); + } catch { + base.SaveModule (pekind, machine); + } + + Builder.Save (file_name, pekind, machine); + } +#endif + } + + // + // Extension to System.Reflection.Emit.AssemblyBuilder to have fully compatible + // compiler + // + class AssemblyBuilderMonoSpecific : AssemblyBuilderExtension + { + static MethodInfo adder_method; + static MethodInfo add_permission; + static MethodInfo add_type_forwarder; + static MethodInfo win32_icon_define; + static FieldInfo assembly_version; + static FieldInfo assembly_algorithm; + static FieldInfo assembly_culture; + static FieldInfo assembly_flags; + + AssemblyBuilder builder; + + public AssemblyBuilderMonoSpecific (AssemblyBuilder ab, CompilerContext ctx) + : base (ctx) + { + this.builder = ab; + } + + public override Module AddModule (string module) + { + try { + if (adder_method == null) + adder_method = typeof (AssemblyBuilder).GetMethod ("AddModule", BindingFlags.Instance | BindingFlags.NonPublic); + + return (Module) adder_method.Invoke (builder, new object[] { module }); + } catch { + return base.AddModule (module); + } + } + + public override void AddPermissionRequests (PermissionSet[] permissions) + { + try { + if (add_permission == null) + add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic); + + add_permission.Invoke (builder, permissions); + } catch { + base.AddPermissionRequests (permissions); + } + } + + public override void AddTypeForwarder (TypeSpec type, Location loc) + { + try { + if (add_type_forwarder == null) { + add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder", BindingFlags.NonPublic | BindingFlags.Instance); + } + + add_type_forwarder.Invoke (builder, new object[] { type.GetMetaInfo () }); + } catch { + base.AddTypeForwarder (type, loc); + } + } + + public override void DefineWin32IconResource (string fileName) + { + try { + if (win32_icon_define == null) + win32_icon_define = typeof (AssemblyBuilder).GetMethod ("DefineIconResource", BindingFlags.Instance | BindingFlags.NonPublic); + + win32_icon_define.Invoke (builder, new object[] { fileName }); + } catch { + base.DefineWin32IconResource (fileName); + } + } + + public override void SetAlgorithmId (uint value, Location loc) + { + try { + if (assembly_algorithm == null) + assembly_algorithm = typeof (AssemblyBuilder).GetField ("algid", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_algorithm.SetValue (builder, value); + } catch { + base.SetAlgorithmId (value, loc); + } + } + + public override void SetCulture (string culture, Location loc) + { + try { + if (assembly_culture == null) + assembly_culture = typeof (AssemblyBuilder).GetField ("culture", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_culture.SetValue (builder, culture); + } catch { + base.SetCulture (culture, loc); + } + } + + public override void SetFlags (uint flags, Location loc) + { + try { + if (assembly_flags == null) + assembly_flags = typeof (AssemblyBuilder).GetField ("flags", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_flags.SetValue (builder, flags); + } catch { + base.SetFlags (flags, loc); + } + } + + public override void SetVersion (Version version, Location loc) + { + try { + if (assembly_version == null) + assembly_version = typeof (AssemblyBuilder).GetField ("version", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField); + + assembly_version.SetValue (builder, version.ToString (4)); + } catch { + base.SetVersion (version, loc); + } + } + } + + // + // Reflection based references loader + // + class DynamicLoader : AssemblyReferencesLoader + { + readonly ReflectionImporter importer; + + public DynamicLoader (ReflectionImporter importer, CompilerContext compiler) + : base (compiler) + { + paths.Add (GetSystemDir ()); + + this.importer = importer; + } + + public ReflectionImporter Importer { + get { + return importer; + } + } + + protected override string[] GetDefaultReferences () + { + // + // For now the "default config" is harcoded into the compiler + // we can move this outside later + // + var default_references = new List (8); + + default_references.Add ("System"); + default_references.Add ("System.Xml"); +#if NET_2_1 + default_references.Add ("System.Net"); + default_references.Add ("System.Windows"); + default_references.Add ("System.Windows.Browser"); +#endif + + if (compiler.Settings.Version > LanguageVersion.ISO_2) + default_references.Add ("System.Core"); + if (compiler.Settings.Version > LanguageVersion.V_3) + default_references.Add ("Microsoft.CSharp"); + + return default_references.ToArray (); + } + + // + // Returns the directory where the system assemblies are installed + // + static string GetSystemDir () + { + return Path.GetDirectoryName (typeof (object).Assembly.Location); + } + + public override bool HasObjectType (Assembly assembly) + { + return assembly.GetType (compiler.BuiltinTypes.Object.FullName) != null; + } + + public override Assembly LoadAssemblyFile (string fileName) + { + return LoadAssemblyFile (fileName, false); + } + + Assembly LoadAssemblyFile (string assembly, bool soft) + { + Assembly a = null; + + try { + try { + char[] path_chars = { '/', '\\' }; + + if (assembly.IndexOfAny (path_chars) != -1) { + a = Assembly.LoadFrom (assembly); + } else { + string ass = assembly; + if (ass.EndsWith (".dll") || ass.EndsWith (".exe")) + ass = assembly.Substring (0, assembly.Length - 4); + a = Assembly.Load (ass); + } + } catch (FileNotFoundException) { + bool err = !soft; + foreach (string dir in paths) { + string full_path = Path.Combine (dir, assembly); + if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe")) + full_path += ".dll"; + + try { + a = Assembly.LoadFrom (full_path); + err = false; + break; + } catch (FileNotFoundException) { + } + } + + if (err) { + Error_FileNotFound (assembly); + return a; + } + } + } catch (BadImageFormatException) { + Error_FileCorrupted (assembly); + } + + return a; + } + + public override Assembly LoadAssemblyDefault (string fileName) + { + return LoadAssemblyFile (fileName, true); + } + + Module LoadModuleFile (AssemblyDefinitionDynamic assembly, string module) + { + string total_log = ""; + + try { + try { + return assembly.IncludeModule (module); + } catch (FileNotFoundException) { + bool err = true; + foreach (string dir in paths) { + string full_path = Path.Combine (dir, module); + if (!module.EndsWith (".netmodule")) + full_path += ".netmodule"; + + try { + return assembly.IncludeModule (full_path); + } catch (FileNotFoundException ff) { + total_log += ff.FusionLog; + } + } + if (err) { + Error_FileNotFound (module); + return null; + } + } + } catch (BadImageFormatException) { + Error_FileCorrupted (module); + } + + return null; + } + + public void LoadModules (AssemblyDefinitionDynamic assembly, RootNamespace targetNamespace) + { + foreach (var moduleName in compiler.Settings.Modules) { + var m = LoadModuleFile (assembly, moduleName); + if (m == null) + continue; + + var md = importer.ImportModule (m, targetNamespace); + assembly.AddModule (md); + } + } + + public override void LoadReferences (ModuleContainer module) + { + Assembly corlib; + List> loaded; + base.LoadReferencesCore (module, out corlib, out loaded); + + if (corlib == null) + return; + + importer.ImportAssembly (corlib, module.GlobalRootNamespace); + foreach (var entry in loaded) { + importer.ImportAssembly (entry.Item2, entry.Item1); + } + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt new file mode 100644 index 0000000000..4f71772f6c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt @@ -0,0 +1,168 @@ +Things to do for the REPL support in MCS: + +Documentation for the REPL mode for MCS can be found here: + + http://mono-project.com/CsharpRepl + +* Embedding API + + * Booting the compiler without Main () + * Expose LoadAssembly/LoadPackage + * Register fields? + * Register a lookup function for fields? + * Register classes to expose to REPL + +* Embedded Library + + * Run a REPL on a socket (from Joe Shaw) + * Host a REPL on XSP (from Nat). + +* TODO + + Clear struct fields inside the clearing code. + +* Other ideas: + + MD addin for "csharp" + +* Supporting class-level declarations + + Currently the evaluator has this feature disabled, to enable + it edit the eval.cs file and make this be the default: + +- parser.Lexer.putback_char = Tokenizer.EvalUsingDeclarationsParserCharacter; +- //parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter; ++ //parser.Lexer.putback_char = Tokenizer.EvalUsingDeclarationsParserCharacter; ++ parser.Lexer.putback_char = Tokenizer.EvalCompilationUnitParserCharacter; + + + It currently has a few problems: + + * Support for overwritting existing defined + classes is not supported. + + * The usability is not as useful, since the defaults + for C# are still to make members private, we should + change this default to be public in those cases. + + * The error lookup system lacks information from types, for + example this causes an unsupported call into a TypeBuilder: + + csharp>class D { void DD () {} } + csharp>var d = new D (); + csharp>d.DD (); + + Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class0::Host] + System.NotSupportedException: The invoked member is not supported in a dynamic module. + at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in :0 + at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00000] in + at Mono.CSharp.MethodGroupExpr.NoExactMatch (Mono.CSharp.ResolveContext ec, + Mono.CSharp.Arguments& Arguments, IDictionary`2 c + + + The above is caused by TypeManager.LookupDeclSpace (dt) + failing to return a value (it returns null) so our code + assumes we have an Assembly instead of an assemblybuilder. + + + +* Declaring a class twice produces an internal parse error: + + class X {} + class X {} + + The second declaration will no longer be parsed, so it could even + contain junk, and wont be flagged. We probably need to allow for + type redefinition in REPL modes, the exception from the second is: + + csharp -v -v + > class X {} + > class X {} + + System.ArgumentException: An element with the same key already exists in the dictionary. + at System.Collections.Generic.Dictionary`2[System.String,Mono.CSharp.DeclSpace].Add (System.String key, Mono.CSharp.DeclSpace value) [0x00000] in :0 + at Mono.CSharp.Namespace.AddDeclSpace (System.String name, Mono.CSharp.DeclSpace ds) [0x00000] in :0 + at Mono.CSharp.ModuleCompiled.AddMemberType (Mono.CSharp.DeclSpace ds) [0x00000] in :0 + at Mono.CSharp.TypeContainer.AddTypeContainer (Mono.CSharp.TypeContainer tc) [0x00000] in :0 + at Mono.CSharp.CSharpParser.push_current_class (Mono.CSharp.TypeContainer tc, System.Object partial_token) [0x00000] in :0 + at Mono.CSharp.CSharpParser.yyparse (yyInput yyLex) [0x00000] in :0 + at Mono.CSharp.CSharpParser.yyparse (yyInput yyLex, System.Object yyd) [0x00000] in :0 + at Mono.CSharp.CSharpParser.parse () [0x00000] in :0 + +* Mix statements with other top-level declarations. + +csharp> class Y {static void Main () {Console.WriteLine ("Foo"); }} +csharp> typeof (Y); +Y +csharp> Y.Main (); +Exception caught by the compiler while compiling: + Block that caused the problem begin at: Internal(1,1): + Block being compiled: [(1,2):,(1,11):] +System.NotSupportedException: The invoked member is not supported in a dynamic module. +Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class2::Host] +System.NotSupportedException: The invoked member is not supported in a dynamic module. + at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in /second/home/cvs/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs:214 + at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00036] in /second/home/cvs/mcs/mcs/report.cs:664 + at Mono.CSharp.Expression.Error_MemberLookupFailed (System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, System.String class_name, MemberTypes mt, BindingFlags bf) [0x00121] in /second/home/cvs/mcs/mcs/ecore.cs:857 + at Mono.CSharp.MemberAccess.DoResolve (Mono.CSharp.EmitContext ec, Mono.CSharp.Expression right_side) [0x00230] in /second/home/cvs/mcs/mcs/expression.cs:7426 + at Mono.CSharp.MemberAccess.DoResolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/expression.cs:7494 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Invocation.DoResolve (Mono.CSharp.EmitContext ec) [0x0000d] in /second/home/cvs/mcs/mcs/expression.cs:4725 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.OptionalAssign.DoResolve (Mono.CSharp.EmitContext ec) [0x00013] in /second/home/cvs/mcs/mcs/repl.cs:681 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:1307 + at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.EmitContext ec) [0x0000b] in /second/home/cvs/mcs/mcs/statement.cs:743 + at Mono.CSharp.Block.Resolve (Mono.CSharp.EmitContext ec) [0x000f0] in /second/home/cvs/mcs/mcs/statement.cs:2254 + at Mono.CSharp.ExplicitBlock.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/statement.cs:2550 + at Mono.CSharp.EmitContext.ResolveTopBlock (Mono.CSharp.EmitContext anonymous_method_host, Mono.CSharp.ToplevelBlock block, Mono.CSharp.Parameters ip, IMethodData md, System.Boolean& unreachable) [0x00087] in /second/home/cvs/mcs/mcs/codegen.cs:796 +csharp> + +* Another one: + +csharp> class X { X (){ Console.WriteLine ("Called"); } } +csharp> new X (); +Exception caught by the compiler while compiling: + Block that caused the problem begin at: Internal(1,1): + Block being compiled: [(1,2):,(1,10):] +System.NotSupportedException: The invoked member is not supported in a dynamic module. +Internal compiler error at Internal(1,1):: exception caught while emitting MethodBuilder [Class0::Host] +System.NotSupportedException: The invoked member is not supported in a dynamic module. + at System.Reflection.Emit.AssemblyBuilder.get_Location () [0x00000] in /second/home/cvs/mcs/class/corlib/System.Reflection.Emit/AssemblyBuilder.cs:214 + at Mono.CSharp.Report.SymbolRelatedToPreviousError (System.Reflection.MemberInfo mi) [0x00036] in /second/home/cvs/mcs/mcs/report.cs:664 + at Mono.CSharp.Expression.Error_MemberLookupFailed (System.Type container_type, System.Type qualifier_type, System.Type queried_type, System.String name, System.String class_name, MemberTypes mt, BindingFlags bf) [0x00121] in /second/home/cvs/mcs/mcs/ecore.cs:857 + at Mono.CSharp.Expression.MemberLookupFinal (Mono.CSharp.EmitContext ec, System.Type qualifier_type, System.Type queried_type, System.String name, MemberTypes mt, BindingFlags bf, Location loc) [0x0002f] in /second/home/cvs/mcs/mcs/ecore.cs:804 + at Mono.CSharp.New.DoResolve (Mono.CSharp.EmitContext ec) [0x002ad] in /second/home/cvs/mcs/mcs/expression.cs:5486 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.OptionalAssign.DoResolve (Mono.CSharp.EmitContext ec) [0x00013] in /second/home/cvs/mcs/mcs/repl.cs:687 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec, ResolveFlags flags) [0x00075] in /second/home/cvs/mcs/mcs/ecore.cs:479 + at Mono.CSharp.Expression.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:506 + at Mono.CSharp.ExpressionStatement.ResolveStatement (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/ecore.cs:1307 + at Mono.CSharp.StatementExpression.Resolve (Mono.CSharp.EmitContext ec) [0x0000b] in /second/home/cvs/mcs/mcs/statement.cs:743 + at Mono.CSharp.Block.Resolve (Mono.CSharp.EmitContext ec) [0x000f0] in /second/home/cvs/mcs/mcs/statement.cs:2254 + at Mono.CSharp.ExplicitBlock.Resolve (Mono.CSharp.EmitContext ec) [0x00000] in /second/home/cvs/mcs/mcs/statement.cs:2550 + at Mono.CSharp.EmitContext.ResolveTopBlock (Mono.CSharp.EmitContext anonymous_method_host, Mono.CSharp.ToplevelBlock block, Mono.CSharp.Parameters ip, IMethodData md, System.Boolean& unreachable) [0x00087] in /second/home/cvs/mcs/mcs/codegen.cs:796 +csharp> + +* Important: we need to replace TypeBuidlers with Types after things + have been emitted, or stuff like this happens: + +csharp> public class y {} +csharp> typeof (y); +Class1 + + +* Clearing data + + TODO: when clearing data for variables that have been overwritten + we need to check for structs and clear all the fields that contain + reference types. + +* DEBATABLE: Implement auto-insert-semicolon + + This is easy to implement, just retry the parse with a + semicolon, the question is whether this is a good idea to do + in the first place or not. diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs new file mode 100644 index 0000000000..e34e6951f0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs @@ -0,0 +1,1221 @@ +// +// report.cs: report errors and warnings. +// +// Author: Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001 Ximian, Inc. (http://www.ximian.com) +// + +using System; +using System.IO; +using System.Text; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Mono.CSharp { + + // + // Errors and warnings manager + // + public class Report + { + /// + /// Whether warnings should be considered errors + /// + public bool WarningsAreErrors; + List warnings_as_error; + List warnings_only; + + public const int RuntimeErrorId = 10000; + + // + // Keeps track of the warnings that we are ignoring + // + HashSet warning_ignore_table; + + Dictionary warning_regions_table; + + int warning_level; + + ReportPrinter printer; + + int reporting_disabled; + + /// + /// List of symbols related to reported error/warning. You have to fill it before error/warning is reported. + /// + List extra_information = new List (); + + // + // IF YOU ADD A NEW WARNING YOU HAVE TO ADD ITS ID HERE + // + public static readonly int[] AllWarnings = new int[] { + 28, 67, 78, + 105, 108, 109, 114, 162, 164, 168, 169, 183, 184, 197, + 219, 251, 252, 253, 278, 282, + 402, 414, 419, 420, 429, 436, 437, 440, 458, 464, 465, 467, 469, 472, 473, + 612, 618, 626, 628, 642, 649, 652, 657, 658, 659, 660, 661, 665, 672, 675, 693, + 728, + 809, 824, + 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, 1711, 1717, 1718, 1720, 1735, + 1901, 1956, 1981, + 2002, 2023, 2029, + 3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009, + 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, + 3021, 3022, 3023, 3024, 3026, 3027 + }; + + static HashSet AllWarningsHashSet; + + public Report (ReportPrinter printer) + { + if (printer == null) + throw new ArgumentNullException ("printer"); + + this.printer = printer; + warning_level = 4; + } + + public void DisableReporting () + { + ++reporting_disabled; + } + + public void EnableReporting () + { + --reporting_disabled; + } + + public void FeatureIsNotAvailable (CompilerContext compiler, Location loc, string feature) + { + string version; + switch (compiler.Settings.Version) { + case LanguageVersion.ISO_1: + version = "1.0"; + break; + case LanguageVersion.ISO_2: + version = "2.0"; + break; + case LanguageVersion.V_3: + version = "3.0"; + break; + default: + throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version); + } + + Error (1644, loc, + "Feature `{0}' cannot be used because it is not part of the C# {1} language specification", + feature, version); + } + + public void FeatureIsNotSupported (Location loc, string feature) + { + Error (1644, loc, + "Feature `{0}' is not supported in Mono mcs1 compiler. Consider using the `gmcs' compiler instead", + feature); + } + + bool IsWarningEnabled (int code, int level, Location loc) + { + if (WarningLevel < level) + return false; + + if (IsWarningDisabledGlobally (code)) + return false; + + if (warning_regions_table == null || loc.IsNull) + return true; + + WarningRegions regions; + if (!warning_regions_table.TryGetValue (loc.File, out regions)) + return true; + + return regions.IsWarningEnabled (code, loc.Row); + } + + public bool IsWarningDisabledGlobally (int code) + { + return warning_ignore_table != null && warning_ignore_table.Contains (code); + } + + bool IsWarningAsError (int code) + { + bool is_error = WarningsAreErrors; + + // Check specific list + if (warnings_as_error != null) + is_error |= warnings_as_error.Contains (code); + + // Ignore excluded warnings + if (warnings_only != null && warnings_only.Contains (code)) + is_error = false; + + return is_error; + } + + public void RuntimeMissingSupport (Location loc, string feature) + { + Error (-88, loc, "Your .NET Runtime does not support `{0}'. Please use the latest Mono runtime instead.", feature); + } + + /// + /// In most error cases is very useful to have information about symbol that caused the error. + /// Call this method before you call Report.Error when it makes sense. + /// + public void SymbolRelatedToPreviousError (Location loc, string symbol) + { + SymbolRelatedToPreviousError (loc.ToString ()); + } + + public void SymbolRelatedToPreviousError (MemberSpec ms) + { + if (reporting_disabled > 0 || !printer.HasRelatedSymbolSupport) + return; + + var mc = ms.MemberDefinition as MemberCore; + while (ms is ElementTypeSpec) { + ms = ((ElementTypeSpec) ms).Element; + mc = ms.MemberDefinition as MemberCore; + } + + if (mc != null) { + SymbolRelatedToPreviousError (mc); + } else { + if (ms.DeclaringType != null) + ms = ms.DeclaringType; + + var imported_type = ms.MemberDefinition as ImportedTypeDefinition; + if (imported_type != null) { + var iad = imported_type.DeclaringAssembly as ImportedAssemblyDefinition; + SymbolRelatedToPreviousError (iad.Location); + } + } + } + + public void SymbolRelatedToPreviousError (MemberCore mc) + { + SymbolRelatedToPreviousError (mc.Location, mc.GetSignatureForError ()); + } + + public void SymbolRelatedToPreviousError (string loc) + { + string msg = String.Format ("{0} (Location of the symbol related to previous ", loc); + if (extra_information.Contains (msg)) + return; + + extra_information.Add (msg); + } + + public void AddWarningAsError (string warningId) + { + int id; + try { + id = int.Parse (warningId); + } catch { + CheckWarningCode (warningId, Location.Null); + return; + } + + if (!CheckWarningCode (id, Location.Null)) + return; + + if (warnings_as_error == null) + warnings_as_error = new List (); + + warnings_as_error.Add (id); + } + + public void RemoveWarningAsError (string warningId) + { + int id; + try { + id = int.Parse (warningId); + } catch { + CheckWarningCode (warningId, Location.Null); + return; + } + + if (!CheckWarningCode (id, Location.Null)) + return; + + if (warnings_only == null) + warnings_only = new List (); + + warnings_only.Add (id); + } + + public bool CheckWarningCode (string code, Location loc) + { + Warning (1691, 1, loc, "`{0}' is not a valid warning number", code); + return false; + } + + public bool CheckWarningCode (int code, Location loc) + { + if (AllWarningsHashSet == null) + AllWarningsHashSet = new HashSet (AllWarnings); + + if (AllWarningsHashSet.Contains (code)) + return true; + + return CheckWarningCode (code.ToString (), loc); + } + + public void ExtraInformation (Location loc, string msg) + { + extra_information.Add (String.Format ("{0} {1}", loc, msg)); + } + + public WarningRegions RegisterWarningRegion (Location location) + { + WarningRegions regions; + if (warning_regions_table == null) { + regions = null; + warning_regions_table = new Dictionary (); + } else { + warning_regions_table.TryGetValue (location.File, out regions); + } + + if (regions == null) { + regions = new WarningRegions (); + warning_regions_table.Add (location.File, regions); + } + + return regions; + } + + public void Warning (int code, int level, Location loc, string message) + { + if (reporting_disabled > 0) + return; + + if (!IsWarningEnabled (code, level, loc)) + return; + + AbstractMessage msg; + if (IsWarningAsError (code)) { + message = "Warning as Error: " + message; + msg = new ErrorMessage (code, loc, message, extra_information); + } else { + msg = new WarningMessage (code, loc, message, extra_information); + } + + extra_information.Clear (); + printer.Print (msg); + } + + public void Warning (int code, int level, Location loc, string format, string arg) + { + Warning (code, level, loc, String.Format (format, arg)); + } + + public void Warning (int code, int level, Location loc, string format, string arg1, string arg2) + { + Warning (code, level, loc, String.Format (format, arg1, arg2)); + } + + public void Warning (int code, int level, Location loc, string format, params object[] args) + { + Warning (code, level, loc, String.Format (format, args)); + } + + public void Warning (int code, int level, string message) + { + Warning (code, level, Location.Null, message); + } + + public void Warning (int code, int level, string format, string arg) + { + Warning (code, level, Location.Null, format, arg); + } + + public void Warning (int code, int level, string format, string arg1, string arg2) + { + Warning (code, level, Location.Null, format, arg1, arg2); + } + + public void Warning (int code, int level, string format, params string[] args) + { + Warning (code, level, Location.Null, String.Format (format, args)); + } + + // + // Warnings encountered so far + // + public int Warnings { + get { return printer.WarningsCount; } + } + + public void Error (int code, Location loc, string error) + { + if (reporting_disabled > 0) + return; + + ErrorMessage msg = new ErrorMessage (code, loc, error, extra_information); + extra_information.Clear (); + + printer.Print (msg); + } + + public void Error (int code, Location loc, string format, string arg) + { + Error (code, loc, String.Format (format, arg)); + } + + public void Error (int code, Location loc, string format, string arg1, string arg2) + { + Error (code, loc, String.Format (format, arg1, arg2)); + } + + public void Error (int code, Location loc, string format, params string[] args) + { + Error (code, loc, String.Format (format, args)); + } + + public void Error (int code, string error) + { + Error (code, Location.Null, error); + } + + public void Error (int code, string format, string arg) + { + Error (code, Location.Null, format, arg); + } + + public void Error (int code, string format, string arg1, string arg2) + { + Error (code, Location.Null, format, arg1, arg2); + } + + public void Error (int code, string format, params string[] args) + { + Error (code, Location.Null, String.Format (format, args)); + } + + // + // Errors encountered so far + // + public int Errors { + get { return printer.ErrorsCount; } + } + + public bool IsDisabled { + get { + return reporting_disabled > 0; + } + } + + public ReportPrinter Printer { + get { return printer; } + } + + public void SetIgnoreWarning (int code) + { + if (warning_ignore_table == null) + warning_ignore_table = new HashSet (); + + warning_ignore_table.Add (code); + } + + public ReportPrinter SetPrinter (ReportPrinter printer) + { + ReportPrinter old = this.printer; + this.printer = printer; + return old; + } + + public int WarningLevel { + get { + return warning_level; + } + set { + warning_level = value; + } + } + + [Conditional ("MCS_DEBUG")] + static public void Debug (string message, params object[] args) + { + Debug (4, message, args); + } + + [Conditional ("MCS_DEBUG")] + static public void Debug (int category, string message, params object[] args) + { +// if ((category & DebugFlags) == 0) +// return; + + StringBuilder sb = new StringBuilder (message); + + if ((args != null) && (args.Length > 0)) { + sb.Append (": "); + + bool first = true; + foreach (object arg in args) { + if (first) + first = false; + else + sb.Append (", "); + if (arg == null) + sb.Append ("null"); +// else if (arg is ICollection) +// sb.Append (PrintCollection ((ICollection) arg)); + else + sb.Append (arg); + } + } + + Console.WriteLine (sb.ToString ()); + } +/* + static public string PrintCollection (ICollection collection) + { + StringBuilder sb = new StringBuilder (); + + sb.Append (collection.GetType ()); + sb.Append ("("); + + bool first = true; + foreach (object o in collection) { + if (first) + first = false; + else + sb.Append (", "); + sb.Append (o); + } + + sb.Append (")"); + return sb.ToString (); + } +*/ + } + + public abstract class AbstractMessage + { + readonly string[] extra_info; + protected readonly int code; + protected readonly Location location; + readonly string message; + + protected AbstractMessage (int code, Location loc, string msg, List extraInfo) + { + this.code = code; + if (code < 0) + this.code = 8000 - code; + + this.location = loc; + this.message = msg; + if (extraInfo.Count != 0) { + this.extra_info = extraInfo.ToArray (); + } + } + + protected AbstractMessage (AbstractMessage aMsg) + { + this.code = aMsg.code; + this.location = aMsg.location; + this.message = aMsg.message; + this.extra_info = aMsg.extra_info; + } + + public int Code { + get { return code; } + } + + public override bool Equals (object obj) + { + AbstractMessage msg = obj as AbstractMessage; + if (msg == null) + return false; + + return code == msg.code && location.Equals (msg.location) && message == msg.message; + } + + public override int GetHashCode () + { + return code.GetHashCode (); + } + + public abstract bool IsWarning { get; } + + public Location Location { + get { return location; } + } + + public abstract string MessageType { get; } + + public string[] RelatedSymbols { + get { return extra_info; } + } + + public string Text { + get { return message; } + } + } + + sealed class WarningMessage : AbstractMessage + { + public WarningMessage (int code, Location loc, string message, List extra_info) + : base (code, loc, message, extra_info) + { + } + + public override bool IsWarning { + get { return true; } + } + + public override string MessageType { + get { + return "warning"; + } + } + } + + sealed class ErrorMessage : AbstractMessage + { + public ErrorMessage (int code, Location loc, string message, List extraInfo) + : base (code, loc, message, extraInfo) + { + } + + public ErrorMessage (AbstractMessage aMsg) + : base (aMsg) + { + } + + public override bool IsWarning { + get { return false; } + } + + public override string MessageType { + get { + return "error"; + } + } + } + + // + // Generic base for any message writer + // + public abstract class ReportPrinter + { + #region Properties + + public int FatalCounter { get; set; } + + public int ErrorsCount { get; protected set; } + + public bool ShowFullPaths { get; set; } + + // + // Whether to dump a stack trace on errors. + // + public bool Stacktrace { get; set; } + + public int WarningsCount { get; private set; } + + // + // When (symbols related to previous ...) can be used + // + public virtual bool HasRelatedSymbolSupport { + get { return true; } + } + + #endregion + + + protected virtual string FormatText (string txt) + { + return txt; + } + + public virtual void Print (AbstractMessage msg) + { + if (msg.IsWarning) { + ++WarningsCount; + } else { + ++ErrorsCount; + + if (ErrorsCount == FatalCounter) + throw new Exception (msg.Text); + } + } + + protected void Print (AbstractMessage msg, TextWriter output) + { + StringBuilder txt = new StringBuilder (); + if (!msg.Location.IsNull) { + if (ShowFullPaths) + txt.Append (msg.Location.ToStringFullName ()); + else + txt.Append (msg.Location.ToString ()); + + txt.Append (" "); + } + + txt.AppendFormat ("{0} CS{1:0000}: {2}", msg.MessageType, msg.Code, msg.Text); + + if (!msg.IsWarning) + output.WriteLine (FormatText (txt.ToString ())); + else + output.WriteLine (txt.ToString ()); + + if (msg.RelatedSymbols != null) { + foreach (string s in msg.RelatedSymbols) + output.WriteLine (s + msg.MessageType + ")"); + } + } + + public void Reset () + { + // HACK: Temporary hack for broken repl flow + ErrorsCount = WarningsCount = 0; + } + } + + sealed class NullReportPrinter : ReportPrinter + { + } + + // + // Default message recorder, it uses two types of message groups. + // Common messages: messages reported in all sessions. + // Merged messages: union of all messages in all sessions. + // + // Used by the Lambda expressions to compile the code with various + // parameter values, or by attribute resolver + // + class SessionReportPrinter : ReportPrinter + { + List session_messages; + // + // A collection of exactly same messages reported in all sessions + // + List common_messages; + + // + // A collection of unique messages reported in all sessions + // + List merged_messages; + + public override void Print (AbstractMessage msg) + { + // + // This line is useful when debugging recorded messages + // + // Console.WriteLine ("RECORDING: {0}", msg.ToString ()); + + if (session_messages == null) + session_messages = new List (); + + session_messages.Add (msg); + + base.Print (msg); + } + + public void EndSession () + { + if (session_messages == null) + return; + + // + // Handles the first session + // + if (common_messages == null) { + common_messages = new List (session_messages); + merged_messages = session_messages; + session_messages = null; + return; + } + + // + // Store common messages if any + // + for (int i = 0; i < common_messages.Count; ++i) { + AbstractMessage cmsg = common_messages[i]; + bool common_msg_found = false; + foreach (AbstractMessage msg in session_messages) { + if (cmsg.Equals (msg)) { + common_msg_found = true; + break; + } + } + + if (!common_msg_found) + common_messages.RemoveAt (i); + } + + // + // Merge session and previous messages + // + for (int i = 0; i < session_messages.Count; ++i) { + AbstractMessage msg = session_messages[i]; + bool msg_found = false; + for (int ii = 0; ii < merged_messages.Count; ++ii) { + if (msg.Equals (merged_messages[ii])) { + msg_found = true; + break; + } + } + + if (!msg_found) + merged_messages.Add (msg); + } + } + + public bool IsEmpty { + get { + return merged_messages == null && common_messages == null; + } + } + + // + // Prints collected messages, common messages have a priority + // + public bool Merge (ReportPrinter dest) + { + var messages_to_print = merged_messages; + if (common_messages != null && common_messages.Count > 0) { + messages_to_print = common_messages; + } + + if (messages_to_print == null) + return false; + + bool error_msg = false; + foreach (AbstractMessage msg in messages_to_print) { + dest.Print (msg); + error_msg |= !msg.IsWarning; + } + + return error_msg; + } + } + + public class StreamReportPrinter : ReportPrinter + { + readonly TextWriter writer; + + public StreamReportPrinter (TextWriter writer) + { + this.writer = writer; + } + + public override void Print (AbstractMessage msg) + { + Print (msg, writer); + base.Print (msg); + } + } + + public class ConsoleReportPrinter : StreamReportPrinter + { + static readonly string prefix, postfix; + + static ConsoleReportPrinter () + { + string term = Environment.GetEnvironmentVariable ("TERM"); + bool xterm_colors = false; + + switch (term){ + case "xterm": + case "rxvt": + case "rxvt-unicode": + if (Environment.GetEnvironmentVariable ("COLORTERM") != null){ + xterm_colors = true; + } + break; + + case "xterm-color": + case "xterm-256color": + xterm_colors = true; + break; + } + if (!xterm_colors) + return; + + if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2))) + return; + + string config = Environment.GetEnvironmentVariable ("MCS_COLORS"); + if (config == null){ + config = "errors=red"; + //config = "brightwhite,red"; + } + + if (config == "disable") + return; + + if (!config.StartsWith ("errors=")) + return; + + config = config.Substring (7); + + int p = config.IndexOf (","); + if (p == -1) + prefix = GetForeground (config); + else + prefix = GetBackground (config.Substring (p+1)) + GetForeground (config.Substring (0, p)); + postfix = "\x001b[0m"; + } + + public ConsoleReportPrinter () + : base (Console.Error) + { + } + + public ConsoleReportPrinter (TextWriter writer) + : base (writer) + { + } + + static int NameToCode (string s) + { + switch (s) { + case "black": + return 0; + case "red": + return 1; + case "green": + return 2; + case "yellow": + return 3; + case "blue": + return 4; + case "magenta": + return 5; + case "cyan": + return 6; + case "grey": + case "white": + return 7; + } + return 7; + } + + // + // maps a color name to its xterm color code + // + static string GetForeground (string s) + { + string highcode; + + if (s.StartsWith ("bright")) { + highcode = "1;"; + s = s.Substring (6); + } else + highcode = ""; + + return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m"; + } + + static string GetBackground (string s) + { + return "\x001b[" + (40 + NameToCode (s)).ToString () + "m"; + } + + protected override string FormatText (string txt) + { + if (prefix != null) + return prefix + txt + postfix; + + return txt; + } + + static string FriendlyStackTrace (StackTrace t) + { + StringBuilder sb = new StringBuilder (); + + bool foundUserCode = false; + + for (int i = 0; i < t.FrameCount; i++) { + StackFrame f = t.GetFrame (i); + var mb = f.GetMethod (); + + if (!foundUserCode && mb.ReflectedType == typeof (Report)) + continue; + + foundUserCode = true; + + sb.Append ("\tin "); + + if (f.GetFileLineNumber () > 0) + sb.AppendFormat ("(at {0}:{1}) ", f.GetFileName (), f.GetFileLineNumber ()); + + sb.AppendFormat ("{0}.{1} (", mb.ReflectedType.Name, mb.Name); + + bool first = true; + foreach (var pi in mb.GetParameters ()) { + if (!first) + sb.Append (", "); + first = false; + + sb.Append (pi.ParameterType.FullName); + } + sb.Append (")\n"); + } + + return sb.ToString (); + } + + public override void Print (AbstractMessage msg) + { + base.Print (msg); + + if (Stacktrace) + Console.WriteLine (FriendlyStackTrace (new StackTrace (true))); + } + + public static string FriendlyStackTrace (Exception e) + { + return FriendlyStackTrace (new StackTrace (e, true)); + } + + public static void StackTrace () + { + Console.WriteLine (FriendlyStackTrace (new StackTrace (true))); + } + } + + class TimeReporter + { + public enum TimerType + { + ParseTotal, + AssemblyBuilderSetup, + CreateTypeTotal, + ReferencesLoading, + ReferencesImporting, + PredefinedTypesInit, + ModuleDefinitionTotal, + UsingResolve, + EmitTotal, + CloseTypes, + Resouces, + OutputSave, + DebugSave, + } + + readonly Stopwatch[] timers; + Stopwatch total; + + public TimeReporter (bool enabled) + { + if (!enabled) + return; + + timers = new Stopwatch[System.Enum.GetValues(typeof (TimerType)).Length]; + } + + public void Start (TimerType type) + { + if (timers != null) { + var sw = new Stopwatch (); + timers[(int) type] = sw; + sw.Start (); + } + } + + public void StartTotal () + { + total = new Stopwatch (); + total.Start (); + } + + public void Stop (TimerType type) + { + if (timers != null) { + timers[(int) type].Stop (); + } + } + + public void StopTotal () + { + total.Stop (); + } + + public void ShowStats () + { + if (timers == null) + return; + + Dictionary timer_names = new Dictionary () { + { TimerType.ParseTotal, "Parsing source files" }, + { TimerType.AssemblyBuilderSetup, "Assembly builder setup" }, + { TimerType.CreateTypeTotal, "Compiled types created" }, + { TimerType.ReferencesLoading, "Referenced assemblies loading" }, + { TimerType.ReferencesImporting, "Referenced assemblies importing" }, + { TimerType.PredefinedTypesInit, "Predefined types initialization" }, + { TimerType.ModuleDefinitionTotal, "Module definition" }, + { TimerType.UsingResolve, "Top-level usings resolve" }, + { TimerType.EmitTotal, "Resolving and emitting members blocks" }, + { TimerType.CloseTypes, "Module types closed" }, + { TimerType.Resouces, "Embedding resources" }, + { TimerType.OutputSave, "Writing output file" }, + { TimerType.DebugSave, "Writing debug symbols file" }, + }; + + int counter = 0; + double percentage = (double) total.ElapsedMilliseconds / 100; + long subtotal = total.ElapsedMilliseconds; + foreach (var timer in timers) { + string msg = timer_names[(TimerType) counter++]; + var ms = timer == null ? 0 : timer.ElapsedMilliseconds; + Console.WriteLine ("{0,4:0.0}% {1,5}ms {2}", ms / percentage, ms, msg); + subtotal -= ms; + } + + Console.WriteLine ("{0,4:0.0}% {1,5}ms Other tasks", subtotal / percentage, subtotal); + Console.WriteLine (); + Console.WriteLine ("Total elapsed time: {0}", total.Elapsed); + } + } + + public class InternalErrorException : Exception { + public InternalErrorException (MemberCore mc, Exception e) + : base (mc.Location + " " + mc.GetSignatureForError (), e) + { + } + + public InternalErrorException () + : base ("Internal error") + { + } + + public InternalErrorException (string message) + : base (message) + { + } + + public InternalErrorException (string message, params object[] args) + : base (String.Format (message, args)) + { + } + + public InternalErrorException (Exception exception, string message, params object[] args) + : base (String.Format (message, args), exception) + { + } + + public InternalErrorException (Exception e, Location loc) + : base (loc.ToString (), e) + { + } + } + + /// + /// Handles #pragma warning + /// + public class WarningRegions { + + abstract class PragmaCmd + { + public int Line; + + protected PragmaCmd (int line) + { + Line = line; + } + + public abstract bool IsEnabled (int code, bool previous); + } + + class Disable : PragmaCmd + { + int code; + public Disable (int line, int code) + : base (line) + { + this.code = code; + } + + public override bool IsEnabled (int code, bool previous) + { + return this.code == code ? false : previous; + } + } + + class DisableAll : PragmaCmd + { + public DisableAll (int line) + : base (line) {} + + public override bool IsEnabled(int code, bool previous) + { + return false; + } + } + + class Enable : PragmaCmd + { + int code; + public Enable (int line, int code) + : base (line) + { + this.code = code; + } + + public override bool IsEnabled(int code, bool previous) + { + return this.code == code ? true : previous; + } + } + + class EnableAll : PragmaCmd + { + public EnableAll (int line) + : base (line) {} + + public override bool IsEnabled(int code, bool previous) + { + return true; + } + } + + + List regions = new List (); + + public void WarningDisable (int line) + { + regions.Add (new DisableAll (line)); + } + + public void WarningDisable (Location location, int code, Report Report) + { + if (Report.CheckWarningCode (code, location)) + regions.Add (new Disable (location.Row, code)); + } + + public void WarningEnable (int line) + { + regions.Add (new EnableAll (line)); + } + + public void WarningEnable (Location location, int code, Report Report) + { + if (!Report.CheckWarningCode (code, location)) + return; + + if (Report.IsWarningDisabledGlobally (code)) + Report.Warning (1635, 1, location, "Cannot restore warning `CS{0:0000}' because it was disabled globally", code); + + regions.Add (new Enable (location.Row, code)); + } + + public bool IsWarningEnabled (int code, int src_line) + { + bool result = true; + foreach (PragmaCmd pragma in regions) { + if (src_line < pragma.Line) + break; + + result = pragma.IsEnabled (code, result); + } + return result; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs new file mode 100644 index 0000000000..a3b379ce69 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs @@ -0,0 +1,1462 @@ +// +// rootcontext.cs: keeps track of our tree representation, and assemblies loaded. +// +// Author: Miguel de Icaza (miguel@ximian.com) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2008 Novell, Inc + +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Globalization; +using System; + +namespace Mono.CSharp { + + public enum LanguageVersion + { + ISO_1 = 1, + ISO_2 = 2, + V_3 = 3, + V_4 = 4, + Future = 100, + + Default = LanguageVersion.V_4, + } + + public enum RuntimeVersion + { + v1, + v2, + v4 + } + + public enum Target + { + Library, Exe, Module, WinExe + } + + public enum Platform + { + AnyCPU, X86, X64, IA64 + } + + public class CompilerSettings + { + public Target Target; + public Platform Platform; + public string TargetExt; + public bool VerifyClsCompliance; + public bool Optimize; + public LanguageVersion Version; + public bool EnhancedWarnings; + public bool LoadDefaultReferences; + public string SdkVersion; + + public string StrongNameKeyFile; + public string StrongNameKeyContainer; + public bool StrongNameDelaySign; + + // + // Assemblies references to be loaded + // + public List AssemblyReferences; + + // + // External aliases for assemblies + // + public List> AssemblyReferencesAliases; + + // + // Modules to be embedded + // + public List Modules; + + // + // Lookup paths for referenced assemblies + // + public List ReferencesLookupPaths; + + // + // Encoding. + // + public Encoding Encoding; + + // + // If set, enable XML documentation generation + // + public string DocumentationFile; + + public string MainClass; + + // + // Output file + // + public string OutputFile; + + // + // The default compiler checked state + // + public bool Checked; + + // + // If true, the compiler is operating in statement mode, + // this currently turns local variable declaration into + // static variables of a class + // + public bool StatementMode; // TODO: SUPER UGLY + + // + // Whether to allow Unsafe code + // + public bool Unsafe; + + public string Win32ResourceFile; + public string Win32IconFile; + + // + // A list of resource files for embedding + // + public List Resources; + + public bool GenerateDebugInfo; + + // Compiler debug flags only + public bool ParseOnly, TokenizeOnly, Timestamps; + public int DebugFlags; + + // + // Whether we are being linked against the standard libraries. + // This is only used to tell whether `System.Object' should + // have a base class or not. + // + public bool StdLib; + + public RuntimeVersion StdLibRuntimeVersion; + + readonly List conditional_symbols; + + readonly List source_files; + + public CompilerSettings () + { + StdLib = true; + Target = Target.Exe; + TargetExt = ".exe"; + Platform = Platform.AnyCPU; + Version = LanguageVersion.Default; + VerifyClsCompliance = true; + Optimize = true; + Encoding = Encoding.UTF8; + LoadDefaultReferences = true; + StdLibRuntimeVersion = RuntimeVersion.v4; + + AssemblyReferences = new List (); + AssemblyReferencesAliases = new List> (); + Modules = new List (); + ReferencesLookupPaths = new List (); + + conditional_symbols = new List (); + // + // Add default mcs define + // + conditional_symbols.Add ("__MonoCS__"); + + source_files = new List (); + } + + #region Properties + + public CompilationSourceFile FirstSourceFile { + get { + return source_files.Count > 0 ? source_files [0] : null; + } + } + + public bool HasKeyFileOrContainer { + get { + return StrongNameKeyFile != null || StrongNameKeyContainer != null; + } + } + + public bool NeedsEntryPoint { + get { + return Target == Target.Exe || Target == Target.WinExe; + } + } + + public List SourceFiles { + get { + return source_files; + } + } + + #endregion + + public void AddConditionalSymbol (string symbol) + { + if (!conditional_symbols.Contains (symbol)) + conditional_symbols.Add (symbol); + } + + public bool IsConditionalSymbolDefined (string symbol) + { + return conditional_symbols.Contains (symbol); + } + } + + public class CommandLineParser + { + enum ParseResult + { + Success, + Error, + Stop, + UnknownOption + } + + static readonly char[] argument_value_separator = new char[] { ';', ',' }; + static readonly char[] numeric_value_separator = new char[] { ';', ',', ' ' }; + + readonly Report report; + readonly TextWriter output; + bool stop_argument; + + Dictionary source_file_index; + + public event Func UnknownOptionHandler; + + public CommandLineParser (Report report) + : this (report, Console.Out) + { + } + + public CommandLineParser (Report report, TextWriter messagesOutput) + { + this.report = report; + this.output = messagesOutput; + } + + public bool HasBeenStopped { + get { + return stop_argument; + } + } + + void About () + { + output.WriteLine ( + "The Mono C# compiler is Copyright 2001-2011, Novell, Inc.\n\n" + + "The compiler source code is released under the terms of the \n" + + "MIT X11 or GNU GPL licenses\n\n" + + + "For more information on Mono, visit the project Web site\n" + + " http://www.mono-project.com\n\n" + + + "The compiler was written by Miguel de Icaza, Ravi Pratap, Martin Baulig, Marek Safar, Raja R Harinath, Atushi Enomoto"); + } + + public CompilerSettings ParseArguments (string[] args) + { + CompilerSettings settings = new CompilerSettings (); + List response_file_list = null; + bool parsing_options = true; + stop_argument = false; + source_file_index = new Dictionary (); + + for (int i = 0; i < args.Length; i++) { + string arg = args[i]; + if (arg.Length == 0) + continue; + + if (arg[0] == '@') { + string[] extra_args; + string response_file = arg.Substring (1); + + if (response_file_list == null) + response_file_list = new List (); + + if (response_file_list.Contains (response_file)) { + report.Error (1515, "Response file `{0}' specified multiple times", response_file); + return null; + } + + response_file_list.Add (response_file); + + extra_args = LoadArgs (response_file); + if (extra_args == null) { + report.Error (2011, "Unable to open response file: " + response_file); + return null; + } + + args = AddArgs (args, extra_args); + continue; + } + + if (parsing_options) { + if (arg == "--") { + parsing_options = false; + continue; + } + + bool dash_opt = arg[0] == '-'; + bool slash_opt = arg[0] == '/'; + if (dash_opt) { + switch (ParseOptionUnix (arg, ref args, ref i, settings)) { + case ParseResult.Error: + case ParseResult.Success: + continue; + case ParseResult.Stop: + stop_argument = true; + return settings; + case ParseResult.UnknownOption: + if (UnknownOptionHandler != null) { + var ret = UnknownOptionHandler (args, i); + if (ret != -1) { + i = ret; + continue; + } + } + break; + } + } + + if (dash_opt || slash_opt) { + // Try a -CSCOPTION + string csc_opt = dash_opt ? "/" + arg.Substring (1) : arg; + switch (ParseOption (csc_opt, ref args, settings)) { + case ParseResult.Error: + case ParseResult.Success: + continue; + case ParseResult.UnknownOption: + // Need to skip `/home/test.cs' however /test.cs is considered as error + if ((slash_opt && arg.Length > 3 && arg.IndexOf ('/', 2) > 0)) + break; + + if (UnknownOptionHandler != null) { + var ret = UnknownOptionHandler (args, i); + if (ret != -1) { + i = ret; + continue; + } + } + + Error_WrongOption (arg); + return null; + + case ParseResult.Stop: + stop_argument = true; + return settings; + } + } + } + + ProcessSourceFiles (arg, false, settings.SourceFiles); + } + + return settings; + } + + void ProcessSourceFiles (string spec, bool recurse, List sourceFiles) + { + string path, pattern; + + SplitPathAndPattern (spec, out path, out pattern); + if (pattern.IndexOf ('*') == -1) { + AddSourceFile (spec, sourceFiles); + return; + } + + string[] files = null; + try { + files = Directory.GetFiles (path, pattern); + } catch (System.IO.DirectoryNotFoundException) { + report.Error (2001, "Source file `" + spec + "' could not be found"); + return; + } catch (System.IO.IOException) { + report.Error (2001, "Source file `" + spec + "' could not be found"); + return; + } + foreach (string f in files) { + AddSourceFile (f, sourceFiles); + } + + if (!recurse) + return; + + string[] dirs = null; + + try { + dirs = Directory.GetDirectories (path); + } catch { + } + + foreach (string d in dirs) { + + // Don't include path in this string, as each + // directory entry already does + ProcessSourceFiles (d + "/" + pattern, true, sourceFiles); + } + } + + static string[] AddArgs (string[] args, string[] extra_args) + { + string[] new_args; + new_args = new string[extra_args.Length + args.Length]; + + // if args contains '--' we have to take that into account + // split args into first half and second half based on '--' + // and add the extra_args before -- + int split_position = Array.IndexOf (args, "--"); + if (split_position != -1) { + Array.Copy (args, new_args, split_position); + extra_args.CopyTo (new_args, split_position); + Array.Copy (args, split_position, new_args, split_position + extra_args.Length, args.Length - split_position); + } else { + args.CopyTo (new_args, 0); + extra_args.CopyTo (new_args, args.Length); + } + + return new_args; + } + + void AddAssemblyReference (string alias, string assembly, CompilerSettings settings) + { + if (assembly.Length == 0) { + report.Error (1680, "Invalid reference alias `{0}='. Missing filename", alias); + return; + } + + if (!IsExternAliasValid (alias)) { + report.Error (1679, "Invalid extern alias for -reference. Alias `{0}' is not a valid identifier", alias); + return; + } + + settings.AssemblyReferencesAliases.Add (Tuple.Create (alias, assembly)); + } + + void AddResource (AssemblyResource res, CompilerSettings settings) + { + if (settings.Resources == null) { + settings.Resources = new List (); + settings.Resources.Add (res); + return; + } + + if (settings.Resources.Contains (res)) { + report.Error (1508, "The resource identifier `{0}' has already been used in this assembly", res.Name); + return; + } + + settings.Resources.Add (res); + } + + void AddSourceFile (string fileName, List sourceFiles) + { + string path = Path.GetFullPath (fileName); + + int index; + if (source_file_index.TryGetValue (path, out index)) { + string other_name = sourceFiles[index - 1].Name; + if (fileName.Equals (other_name)) + report.Warning (2002, 1, "Source file `{0}' specified multiple times", other_name); + else + report.Warning (2002, 1, "Source filenames `{0}' and `{1}' both refer to the same file: {2}", fileName, other_name, path); + + return; + } + + var unit = new CompilationSourceFile (fileName, path, sourceFiles.Count + 1); + sourceFiles.Add (unit); + source_file_index.Add (path, unit.Index); + } + + void Error_RequiresArgument (string option) + { + report.Error (2006, "Missing argument for `{0}' option", option); + } + + void Error_RequiresFileName (string option) + { + report.Error (2005, "Missing file specification for `{0}' option", option); + } + + void Error_WrongOption (string option) + { + report.Error (2007, "Unrecognized command-line option: `{0}'", option); + } + + static bool IsExternAliasValid (string identifier) + { + if (identifier.Length == 0) + return false; + if (identifier[0] != '_' && !char.IsLetter (identifier[0])) + return false; + + for (int i = 1; i < identifier.Length; i++) { + char c = identifier[i]; + if (char.IsLetter (c) || char.IsDigit (c)) + continue; + + UnicodeCategory category = char.GetUnicodeCategory (c); + if (category != UnicodeCategory.Format || category != UnicodeCategory.NonSpacingMark || + category != UnicodeCategory.SpacingCombiningMark || + category != UnicodeCategory.ConnectorPunctuation) + return false; + } + + return true; + } + + static string[] LoadArgs (string file) + { + StreamReader f; + var args = new List (); + string line; + try { + f = new StreamReader (file); + } catch { + return null; + } + + StringBuilder sb = new StringBuilder (); + + while ((line = f.ReadLine ()) != null) { + int t = line.Length; + + for (int i = 0; i < t; i++) { + char c = line[i]; + + if (c == '"' || c == '\'') { + char end = c; + + for (i++; i < t; i++) { + c = line[i]; + + if (c == end) + break; + sb.Append (c); + } + } else if (c == ' ') { + if (sb.Length > 0) { + args.Add (sb.ToString ()); + sb.Length = 0; + } + } else + sb.Append (c); + } + if (sb.Length > 0) { + args.Add (sb.ToString ()); + sb.Length = 0; + } + } + + return args.ToArray (); + } + + void OtherFlags () + { + output.WriteLine ( + "Other flags in the compiler\n" + + " --fatal[=COUNT] Makes errors after COUNT fatal\n" + + " --lint Enhanced warnings\n" + + " --parse Only parses the source file\n" + + " --runtime:VERSION Sets mscorlib.dll metadata version: v1, v2, v4\n" + + " --stacktrace Shows stack trace at error location\n" + + " --timestamp Displays time stamps of various compiler events\n" + + " -v Verbose parsing (for debugging the parser)\n" + + " --mcs-debug X Sets MCS debugging level to X\n"); + } + + // + // This parses the -arg and /arg options to the compiler, even if the strings + // in the following text use "/arg" on the strings. + // + ParseResult ParseOption (string option, ref string[] args, CompilerSettings settings) + { + int idx = option.IndexOf (':'); + string arg, value; + + if (idx == -1) { + arg = option; + value = ""; + } else { + arg = option.Substring (0, idx); + + value = option.Substring (idx + 1); + } + + switch (arg.ToLowerInvariant ()) { + case "/nologo": + return ParseResult.Success; + + case "/t": + case "/target": + switch (value) { + case "exe": + settings.Target = Target.Exe; + break; + + case "winexe": + settings.Target = Target.WinExe; + break; + + case "library": + settings.Target = Target.Library; + settings.TargetExt = ".dll"; + break; + + case "module": + settings.Target = Target.Module; + settings.TargetExt = ".netmodule"; + break; + + default: + report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'"); + return ParseResult.Error; + } + return ParseResult.Success; + + case "/out": + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + settings.OutputFile = value; + return ParseResult.Success; + + case "/o": + case "/o+": + case "/optimize": + case "/optimize+": + settings.Optimize = true; + return ParseResult.Success; + + case "/o-": + case "/optimize-": + settings.Optimize = false; + return ParseResult.Success; + + // TODO: Not supported by csc 3.5+ + case "/incremental": + case "/incremental+": + case "/incremental-": + // nothing. + return ParseResult.Success; + + case "/d": + case "/define": { + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + foreach (string d in value.Split (argument_value_separator)) { + string conditional = d.Trim (); + if (!Tokenizer.IsValidIdentifier (conditional)) { + report.Warning (2029, 1, "Invalid conditional define symbol `{0}'", conditional); + continue; + } + + settings.AddConditionalSymbol (conditional); + } + return ParseResult.Success; + } + + case "/bugreport": + // + // We should collect data, runtime, etc and store in the file specified + // + output.WriteLine ("To file bug reports, please visit: http://www.mono-project.com/Bugs"); + return ParseResult.Success; + + case "/pkg": { + string packages; + + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + packages = String.Join (" ", value.Split (new Char[] { ';', ',', '\n', '\r' })); + string pkgout = Driver.GetPackageFlags (packages, report); + + if (pkgout == null) + return ParseResult.Error; + + string[] xargs = pkgout.Trim (new Char[] { ' ', '\n', '\r', '\t' }).Split (new Char[] { ' ', '\t' }); + args = AddArgs (args, xargs); + return ParseResult.Success; + } + + case "/linkres": + case "/linkresource": + case "/res": + case "/resource": + AssemblyResource res = null; + string[] s = value.Split (argument_value_separator, StringSplitOptions.RemoveEmptyEntries); + switch (s.Length) { + case 1: + if (s[0].Length == 0) + goto default; + res = new AssemblyResource (s[0], Path.GetFileName (s[0])); + break; + case 2: + res = new AssemblyResource (s[0], s[1]); + break; + case 3: + if (s[2] != "public" && s[2] != "private") { + report.Error (1906, "Invalid resource visibility option `{0}'. Use either `public' or `private' instead", s[2]); + return ParseResult.Error; + } + res = new AssemblyResource (s[0], s[1], s[2] == "private"); + break; + default: + report.Error (-2005, "Wrong number of arguments for option `{0}'", option); + return ParseResult.Error; + } + + if (res != null) { + res.IsEmbeded = arg[1] == 'r' || arg[1] == 'R'; + AddResource (res, settings); + } + + return ParseResult.Success; + + case "/recurse": + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + ProcessSourceFiles (value, true, settings.SourceFiles); + return ParseResult.Success; + + case "/r": + case "/reference": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + string[] refs = value.Split (argument_value_separator); + foreach (string r in refs) { + if (r.Length == 0) + continue; + + string val = r; + int index = val.IndexOf ('='); + if (index > -1) { + string alias = r.Substring (0, index); + string assembly = r.Substring (index + 1); + AddAssemblyReference (alias, assembly, settings); + if (refs.Length != 1) { + report.Error (2034, "Cannot specify multiple aliases using single /reference option"); + return ParseResult.Error; + } + } else { + settings.AssemblyReferences.Add (val); + } + } + return ParseResult.Success; + } + case "/addmodule": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + string[] refs = value.Split (argument_value_separator); + foreach (string r in refs) { + settings.Modules.Add (r); + } + return ParseResult.Success; + } + case "/win32res": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + if (settings.Win32IconFile != null) + report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time"); + + settings.Win32ResourceFile = value; + return ParseResult.Success; + } + case "/win32icon": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + if (settings.Win32ResourceFile != null) + report.Error (1565, "Cannot specify the `win32res' and the `win32ico' compiler option at the same time"); + + settings.Win32IconFile = value; + return ParseResult.Success; + } + case "/doc": { + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + settings.DocumentationFile = value; + return ParseResult.Success; + } + case "/lib": { + string[] libdirs; + + if (value.Length == 0) { + return ParseResult.Error; + } + + libdirs = value.Split (argument_value_separator); + foreach (string dir in libdirs) + settings.ReferencesLookupPaths.Add (dir); + return ParseResult.Success; + } + + case "/debug-": + settings.GenerateDebugInfo = false; + return ParseResult.Success; + + case "/debug": + if (value == "full" || value == "") + settings.GenerateDebugInfo = true; + + return ParseResult.Success; + + case "/debug+": + settings.GenerateDebugInfo = true; + return ParseResult.Success; + + case "/checked": + case "/checked+": + settings.Checked = true; + return ParseResult.Success; + + case "/checked-": + settings.Checked = false; + return ParseResult.Success; + + case "/clscheck": + case "/clscheck+": + settings.VerifyClsCompliance = true; + return ParseResult.Success; + + case "/clscheck-": + settings.VerifyClsCompliance = false; + return ParseResult.Success; + + case "/unsafe": + case "/unsafe+": + settings.Unsafe = true; + return ParseResult.Success; + + case "/unsafe-": + settings.Unsafe = false; + return ParseResult.Success; + + case "/warnaserror": + case "/warnaserror+": + if (value.Length == 0) { + report.WarningsAreErrors = true; + } else { + foreach (string wid in value.Split (numeric_value_separator)) + report.AddWarningAsError (wid); + } + return ParseResult.Success; + + case "/warnaserror-": + if (value.Length == 0) { + report.WarningsAreErrors = false; + } else { + foreach (string wid in value.Split (numeric_value_separator)) + report.RemoveWarningAsError (wid); + } + return ParseResult.Success; + + case "/warn": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + SetWarningLevel (value); + return ParseResult.Success; + + case "/nowarn": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + var warns = value.Split (numeric_value_separator); + foreach (string wc in warns) { + try { + if (wc.Trim ().Length == 0) + continue; + + int warn = Int32.Parse (wc); + if (warn < 1) { + throw new ArgumentOutOfRangeException ("warn"); + } + report.SetIgnoreWarning (warn); + } catch { + report.Error (1904, "`{0}' is not a valid warning number", wc); + return ParseResult.Error; + } + } + return ParseResult.Success; + + case "/noconfig": + settings.LoadDefaultReferences = false; + return ParseResult.Success; + + case "/platform": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + switch (value.ToLower (CultureInfo.InvariantCulture)) { + case "anycpu": + settings.Platform = Platform.AnyCPU; + break; + case "x86": + settings.Platform = Platform.X86; + break; + case "x64": + settings.Platform = Platform.X64; + break; + case "itanium": + settings.Platform = Platform.IA64; + break; + default: + report.Error (1672, "Invalid platform type for -platform. Valid options are `anycpu', `x86', `x64' or `itanium'"); + return ParseResult.Error; + } + + return ParseResult.Success; + + case "/sdk": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + settings.SdkVersion = value; + return ParseResult.Success; + + // We just ignore this. + case "/errorreport": + case "/filealign": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + return ParseResult.Success; + + case "/helpinternal": + OtherFlags (); + return ParseResult.Stop; + + case "/help": + case "/?": + Usage (); + return ParseResult.Stop; + + case "/main": + case "/m": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + settings.MainClass = value; + return ParseResult.Success; + + case "/nostdlib": + case "/nostdlib+": + settings.StdLib = false; + return ParseResult.Success; + + case "/nostdlib-": + settings.StdLib = true; + return ParseResult.Success; + + case "/fullpaths": + report.Printer.ShowFullPaths = true; + return ParseResult.Success; + + case "/keyfile": + if (value.Length == 0) { + Error_RequiresFileName (option); + return ParseResult.Error; + } + + settings.StrongNameKeyFile = value; + return ParseResult.Success; + + case "/keycontainer": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + settings.StrongNameKeyContainer = value; + return ParseResult.Success; + + case "/delaysign+": + case "/delaysign": + settings.StrongNameDelaySign = true; + return ParseResult.Success; + + case "/delaysign-": + settings.StrongNameDelaySign = false; + return ParseResult.Success; + + case "/langversion": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + switch (value.ToLowerInvariant ()) { + case "iso-1": + settings.Version = LanguageVersion.ISO_1; + return ParseResult.Success; + case "default": + settings.Version = LanguageVersion.Default; + return ParseResult.Success; + case "iso-2": + settings.Version = LanguageVersion.ISO_2; + return ParseResult.Success; + case "3": + settings.Version = LanguageVersion.V_3; + 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); + return ParseResult.Error; + + case "/codepage": + if (value.Length == 0) { + Error_RequiresArgument (option); + return ParseResult.Error; + } + + switch (value) { + case "utf8": + settings.Encoding = Encoding.UTF8; + break; + case "reset": + settings.Encoding = Encoding.Default; + break; + default: + try { + settings.Encoding = Encoding.GetEncoding (int.Parse (value)); + } catch { + report.Error (2016, "Code page `{0}' is invalid or not installed", value); + } + return ParseResult.Error; + } + return ParseResult.Success; + + default: + return ParseResult.UnknownOption; + } + } + + // + // Currently handles the Unix-like command line options, but will be + // deprecated in favor of the CSCParseOption, which will also handle the + // options that start with a dash in the future. + // + ParseResult ParseOptionUnix (string arg, ref string[] args, ref int i, CompilerSettings settings) + { + switch (arg){ + case "-v": + CSharpParser.yacc_verbose_flag++; + return ParseResult.Success; + + case "--version": + Version (); + return ParseResult.Stop; + + case "--parse": + settings.ParseOnly = true; + return ParseResult.Success; + + case "--main": case "-m": + report.Warning (-29, 1, "Compatibility: Use -main:CLASS instead of --main CLASS or -m CLASS"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + settings.MainClass = args[++i]; + return ParseResult.Success; + + case "--unsafe": + report.Warning (-29, 1, "Compatibility: Use -unsafe instead of --unsafe"); + settings.Unsafe = true; + return ParseResult.Success; + + case "/?": case "/h": case "/help": + case "--help": + Usage (); + return ParseResult.Stop; + + case "--define": + report.Warning (-29, 1, "Compatibility: Use -d:SYMBOL instead of --define SYMBOL"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + settings.AddConditionalSymbol (args [++i]); + return ParseResult.Success; + + case "--tokenize": + settings.TokenizeOnly = true; + return ParseResult.Success; + + case "-o": + case "--output": + report.Warning (-29, 1, "Compatibility: Use -out:FILE instead of --output FILE or -o FILE"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + settings.OutputFile = args[++i]; + return ParseResult.Success; + + case "--checked": + report.Warning (-29, 1, "Compatibility: Use -checked instead of --checked"); + settings.Checked = true; + return ParseResult.Success; + + case "--stacktrace": + report.Printer.Stacktrace = true; + return ParseResult.Success; + + case "--linkresource": + case "--linkres": + report.Warning (-29, 1, "Compatibility: Use -linkres:VALUE instead of --linkres VALUE"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + AddResource (new AssemblyResource (args[++i], args[i]), settings); + return ParseResult.Success; + + case "--resource": + case "--res": + report.Warning (-29, 1, "Compatibility: Use -res:VALUE instead of --res VALUE"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + AddResource (new AssemblyResource (args[++i], args[i], true), settings); + return ParseResult.Success; + + case "--target": + report.Warning (-29, 1, "Compatibility: Use -target:KIND instead of --target KIND"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + string type = args [++i]; + switch (type){ + case "library": + settings.Target = Target.Library; + settings.TargetExt = ".dll"; + break; + + case "exe": + settings.Target = Target.Exe; + break; + + case "winexe": + settings.Target = Target.WinExe; + break; + + case "module": + settings.Target = Target.Module; + settings.TargetExt = ".dll"; + break; + default: + report.Error (2019, "Invalid target type for -target. Valid options are `exe', `winexe', `library' or `module'"); + break; + } + return ParseResult.Success; + + case "-r": + report.Warning (-29, 1, "Compatibility: Use -r:LIBRARY instead of -r library"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + string val = args [++i]; + int idx = val.IndexOf ('='); + if (idx > -1) { + string alias = val.Substring (0, idx); + string assembly = val.Substring (idx + 1); + AddAssemblyReference (alias, assembly, settings); + return ParseResult.Success; + } + + settings.AssemblyReferences.Add (val); + return ParseResult.Success; + + case "-L": + report.Warning (-29, 1, "Compatibility: Use -lib:ARG instead of --L arg"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + settings.ReferencesLookupPaths.Add (args [++i]); + return ParseResult.Success; + + case "--lint": + settings.EnhancedWarnings = true; + return ParseResult.Success; + + case "--nostdlib": + report.Warning (-29, 1, "Compatibility: Use -nostdlib instead of --nostdlib"); + settings.StdLib = false; + return ParseResult.Success; + + case "--nowarn": + report.Warning (-29, 1, "Compatibility: Use -nowarn instead of --nowarn"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + int warn = 0; + + try { + warn = int.Parse (args [++i]); + } catch { + Usage (); + Environment.Exit (1); + } + report.SetIgnoreWarning (warn); + return ParseResult.Success; + + case "--wlevel": + report.Warning (-29, 1, "Compatibility: Use -warn:LEVEL instead of --wlevel LEVEL"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + SetWarningLevel (args [++i]); + return ParseResult.Success; + + case "--mcs-debug": + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + try { + settings.DebugFlags = int.Parse (args [++i]); + } catch { + Error_RequiresArgument (arg); + return ParseResult.Error; + } + + return ParseResult.Success; + + case "--about": + About (); + return ParseResult.Stop; + + case "--recurse": + report.Warning (-29, 1, "Compatibility: Use -recurse:PATTERN option instead --recurse PATTERN"); + if ((i + 1) >= args.Length){ + Error_RequiresArgument (arg); + return ParseResult.Error; + } + ProcessSourceFiles (args [++i], true, settings.SourceFiles); + return ParseResult.Success; + + case "--timestamp": + settings.Timestamps = true; + return ParseResult.Success; + + case "--debug": case "-g": + report.Warning (-29, 1, "Compatibility: Use -debug option instead of -g or --debug"); + settings.GenerateDebugInfo = true; + return ParseResult.Success; + + case "--noconfig": + report.Warning (-29, 1, "Compatibility: Use -noconfig option instead of --noconfig"); + settings.LoadDefaultReferences = false; + return ParseResult.Success; + + default: + if (arg.StartsWith ("--fatal")){ + int fatal = 1; + if (arg.StartsWith ("--fatal=")) + int.TryParse (arg.Substring (8), out fatal); + + report.Printer.FatalCounter = fatal; + return ParseResult.Success; + } + if (arg.StartsWith ("--runtime:", StringComparison.Ordinal)) { + string version = arg.Substring (10); + + switch (version) { + case "v1": + case "V1": + settings.StdLibRuntimeVersion = RuntimeVersion.v1; + break; + case "v2": + case "V2": + settings.StdLibRuntimeVersion = RuntimeVersion.v2; + break; + case "v4": + case "V4": + settings.StdLibRuntimeVersion = RuntimeVersion.v4; + break; + } + return ParseResult.Success; + } + + return ParseResult.UnknownOption; + } + } + + void SetWarningLevel (string s) + { + int level = -1; + + try { + level = int.Parse (s); + } catch { + } + if (level < 0 || level > 4) { + report.Error (1900, "Warning level must be in the range 0-4"); + return; + } + report.WarningLevel = level; + } + + // + // Given a path specification, splits the path from the file/pattern + // + static void SplitPathAndPattern (string spec, out string path, out string pattern) + { + int p = spec.LastIndexOf ('/'); + if (p != -1) { + // + // Windows does not like /file.cs, switch that to: + // "\", "file.cs" + // + if (p == 0) { + path = "\\"; + pattern = spec.Substring (1); + } else { + path = spec.Substring (0, p); + pattern = spec.Substring (p + 1); + } + return; + } + + p = spec.LastIndexOf ('\\'); + if (p != -1) { + path = spec.Substring (0, p); + pattern = spec.Substring (p + 1); + return; + } + + path = "."; + pattern = spec; + } + + void Usage () + { + output.WriteLine ( + "Mono C# compiler, Copyright 2001 - 2011 Novell, Inc.\n" + + "mcs [options] source-files\n" + + " --about About the Mono C# compiler\n" + + " -addmodule:M1[,Mn] Adds the module to the generated assembly\n" + + " -checked[+|-] Sets default aritmetic overflow context\n" + + " -clscheck[+|-] Disables CLS Compliance verifications\n" + + " -codepage:ID Sets code page to the one in ID (number, utf8, reset)\n" + + " -define:S1[;S2] Defines one or more conditional symbols (short: -d)\n" + + " -debug[+|-], -g Generate debugging information\n" + + " -delaysign[+|-] Only insert the public key into the assembly (no signing)\n" + + " -doc:FILE Process documentation comments to XML file\n" + + " -fullpaths Any issued error or warning uses absolute file path\n" + + " -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" + + " -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" + + " -nostdlib[+|-] Does not reference mscorlib.dll library\n" + + " -nowarn:W1[,Wn] Suppress one or more compiler warnings\n" + + " -optimize[+|-] Enables advanced compiler optimizations (short: -o)\n" + + " -out:FILE Specifies output assembly name\n" + + " -pkg:P1[,Pn] References packages P1..Pn\n" + + " -platform:ARCH Specifies the target platform of the output assembly\n" + + " ARCH can be one of: anycpu, x86, x64 or itanium\n" + + " -recurse:SPEC Recursively compiles files according to SPEC pattern\n" + + " -reference:A1[,An] Imports metadata from the specified assembly (short: -r)\n" + + " -reference:ALIAS=A Imports metadata using specified extern alias (short: -r)\n" + + " -sdk:VERSION Specifies SDK version of referenced assemblies\n" + + " VERSION can be one of: 2, 4 (default) or custom value\n" + + " -target:KIND Specifies the format of the output assembly (short: -t)\n" + + " KIND can be one of: exe, winexe, library, module\n" + + " -unsafe[+|-] Allows to compile code which uses unsafe keyword\n" + + " -warnaserror[+|-] Treats all warnings as errors\n" + + " -warnaserror[+|-]:W1[,Wn] Treats one or more compiler warnings as errors\n" + + " -warn:0-4 Sets warning level, the default is 4 (short -w:)\n" + + " -helpinternal Shows internal and advanced compiler options\n" + + "\n" + + "Resources:\n" + + " -linkresource:FILE[,ID] Links FILE as a resource (short: -linkres)\n" + + " -resource:FILE[,ID] Embed FILE as a resource (short: -res)\n" + + " -win32res:FILE Specifies Win32 resource file (.res)\n" + + " -win32icon:FILE Use this icon for the output\n" + + " @file Read response file for more options\n\n" + + "Options can be of the form -option or /option"); + } + + void Version () + { + string version = System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType.Assembly.GetName ().Version.ToString (); + output.WriteLine ("Mono C# compiler version {0}", version); + } + } + + public class RootContext + { + // + // Contains the parsed tree + // + static ModuleContainer root; + + static public ModuleContainer ToplevelTypes { + get { return root; } + set { root = value; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs new file mode 100644 index 0000000000..df7962043c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs @@ -0,0 +1,621 @@ +// +// roottypes.cs: keeps a tree representation of the generated code +// +// Authors: Miguel de Icaza (miguel@gnu.org) +// Marek Safar (marek.safar@gmail.com) +// +// 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. +// + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Mono.CompilerServices.SymbolWriter; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp +{ + // + // Module (top-level type) container + // + public sealed class ModuleContainer : TypeContainer + { +#if STATIC + // + // Compiler generated container for static data + // + sealed class StaticDataContainer : CompilerGeneratedClass + { + readonly Dictionary size_types; + new int fields; + + public StaticDataContainer (ModuleContainer module) + : base (module, new MemberName ("" + module.builder.ModuleVersionId.ToString ("B"), Location.Null), Modifiers.STATIC) + { + size_types = new Dictionary (); + } + + public override void CloseType () + { + base.CloseType (); + + foreach (var entry in size_types) { + entry.Value.CloseType (); + } + } + + public FieldSpec DefineInitializedData (byte[] data, Location loc) + { + Struct size_type; + if (!size_types.TryGetValue (data.Length, out size_type)) { + // + // Build common type for this data length. We cannot use + // DefineInitializedData because it creates public type, + // and its name is not unique among modules + // + size_type = new Struct (null, this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null); + size_type.CreateType (); + size_type.DefineType (); + + size_types.Add (data.Length, size_type); + + // It has to work even if StructLayoutAttribute does not exist + size_type.TypeBuilder.__SetLayout (1, data.Length); + } + + var name = "$field-" + fields.ToString ("X"); + ++fields; + const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL; + var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA); + fbuilder.__SetDataAndRVA (data); + + return new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod); + } + } + + StaticDataContainer static_data; + + // + // Makes const data field inside internal type container + // + public FieldSpec MakeStaticData (byte[] data, Location loc) + { + if (static_data == null) { + static_data = new StaticDataContainer (this); + static_data.CreateType (); + static_data.DefineType (); + + AddCompilerGeneratedClass (static_data); + } + + return static_data.DefineInitializedData (data, loc); + } +#endif + + public CharSet? DefaultCharSet; + public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass; + + readonly Dictionary> anonymous_types; + readonly Dictionary array_types; + readonly Dictionary pointer_types; + readonly Dictionary reference_types; + readonly Dictionary attrs_cache; + + // Used for unique namespaces/types during parsing + Dictionary defined_type_containers; + + AssemblyDefinition assembly; + readonly CompilerContext context; + readonly RootNamespace global_ns; + readonly Dictionary alias_ns; + + ModuleBuilder builder; + + bool has_extenstion_method; + + PredefinedAttributes predefined_attributes; + PredefinedTypes predefined_types; + PredefinedMembers predefined_members; + + static readonly string[] attribute_targets = new string[] { "assembly", "module" }; + + public ModuleContainer (CompilerContext context) + : base (null, null, MemberName.Null, null, 0) + { + this.context = context; + + caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected); + + types = new List (); + anonymous_types = new Dictionary> (); + global_ns = new GlobalRootNamespace (); + alias_ns = new Dictionary (); + array_types = new Dictionary (); + pointer_types = new Dictionary (); + reference_types = new Dictionary (); + attrs_cache = new Dictionary (); + + defined_type_containers = new Dictionary (); + } + + #region Properties + + internal Dictionary ArrayTypesCache { + get { + return array_types; + } + } + + // + // Cache for parameter-less attributes + // + internal Dictionary AttributeConstructorCache { + get { + return attrs_cache; + } + } + + public override AttributeTargets AttributeTargets { + get { + return AttributeTargets.Assembly; + } + } + + public ModuleBuilder Builder { + get { + return builder; + } + } + + public override CompilerContext Compiler { + get { + return context; + } + } + + public override AssemblyDefinition DeclaringAssembly { + get { + return assembly; + } + } + + internal DocumentationBuilder DocumentationBuilder { + get; set; + } + + public Evaluator Evaluator { + get; set; + } + + public bool HasDefaultCharSet { + get { + return DefaultCharSet.HasValue; + } + } + + public bool HasExtensionMethod { + get { + return has_extenstion_method; + } + set { + has_extenstion_method = value; + } + } + + public bool HasTypesFullyDefined { + get; set; + } + + // + // Returns module global:: namespace + // + public RootNamespace GlobalRootNamespace { + get { + return global_ns; + } + } + + public override ModuleContainer Module { + get { + return this; + } + } + + internal Dictionary PointerTypesCache { + get { + return pointer_types; + } + } + + internal PredefinedAttributes PredefinedAttributes { + get { + return predefined_attributes; + } + } + + internal PredefinedMembers PredefinedMembers { + get { + return predefined_members; + } + } + + internal PredefinedTypes PredefinedTypes { + get { + return predefined_types; + } + } + + internal Dictionary ReferenceTypesCache { + get { + return reference_types; + } + } + + public override string[] ValidAttributeTargets { + get { + return attribute_targets; + } + } + + #endregion + + public override void Accept (StructuralVisitor visitor) + { + visitor.Visit (this); + } + + public void AddAnonymousType (AnonymousTypeClass type) + { + List existing; + if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing)) + if (existing == null) { + existing = new List (); + anonymous_types.Add (type.Parameters.Count, existing); + } + + existing.Add (type); + } + + public void AddAttribute (Attribute attr, IMemberContext context) + { + attr.AttachTo (this, context); + + if (attributes == null) { + attributes = new Attributes (attr); + return; + } + + attributes.AddAttribute (attr); + } + + public override TypeContainer AddPartial (TypeContainer nextPart) + { + return AddPartial (nextPart, nextPart.Name); + } + + public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa) + { + if (a.Target == AttributeTargets.Assembly) { + assembly.ApplyAttributeBuilder (a, ctor, cdata, pa); + return; + } + + if (a.Type == pa.DefaultCharset) { + switch (a.GetCharSetValue ()) { + case CharSet.Ansi: + case CharSet.None: + break; + case CharSet.Auto: + DefaultCharSet = CharSet.Auto; + DefaultCharSetType = TypeAttributes.AutoClass; + break; + case CharSet.Unicode: + DefaultCharSet = CharSet.Unicode; + DefaultCharSetType = TypeAttributes.UnicodeClass; + break; + default: + Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid", + a.GetSignatureForError ()); + break; + } + } else if (a.Type == pa.CLSCompliant) { + Attribute cls = DeclaringAssembly.CLSCompliantAttribute; + if (cls == null) { + Report.Warning (3012, 1, a.Location, + "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking"); + } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) { + Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ()); + Report.Warning (3017, 1, a.Location, + "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly"); + return; + } + } + + builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata); + } + + public override void CloseType () + { + foreach (TypeContainer tc in types) { + tc.CloseType (); + } + + if (compiler_generated != null) + foreach (CompilerGeneratedClass c in compiler_generated) + c.CloseType (); + } + + public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize) + { + return builder.DefineType (name, attr, null, typeSize); + } + + // + // Creates alias global namespace + // + public RootNamespace CreateRootNamespace (string alias) + { + if (alias == global_ns.Alias) { + NamespaceContainer.Error_GlobalNamespaceRedefined (Location.Null, Report); + return global_ns; + } + + RootNamespace rn; + if (!alias_ns.TryGetValue (alias, out rn)) { + rn = new RootNamespace (alias); + alias_ns.Add (alias, rn); + } + + return rn; + } + + public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder) + { + this.assembly = assembly; + builder = moduleBuilder; + } + + public new void CreateType () + { + // Release cache used by parser only + if (Evaluator == null) + defined_type_containers = null; + else + defined_type_containers.Clear (); + + foreach (TypeContainer tc in types) + tc.CreateType (); + } + + public new void Define () + { + foreach (TypeContainer tc in types) + tc.DefineType (); + + foreach (TypeContainer tc in types) + tc.ResolveTypeParameters (); + + foreach (TypeContainer tc in types) { + try { + tc.Define (); + } catch (Exception e) { + throw new InternalErrorException (tc, e); + } + } + + HasTypesFullyDefined = true; + } + + public override void Emit () + { + if (OptAttributes != null) + OptAttributes.Emit (); + + if (Compiler.Settings.Unsafe) { + var pa = PredefinedAttributes.UnverifiableCode; + if (pa.IsDefined) + pa.EmitAttribute (builder); + } + + foreach (var tc in types) + tc.DefineConstants (); + + foreach (TypeContainer tc in types) + tc.EmitType (); + + if (Compiler.Report.Errors > 0) + return; + + foreach (TypeContainer tc in types) + tc.VerifyMembers (); + + if (compiler_generated != null) + foreach (var c in compiler_generated) + c.EmitType (); + } + + internal override void GenerateDocComment (DocumentationBuilder builder) + { + foreach (var tc in types) + tc.GenerateDocComment (builder); + } + + public AnonymousTypeClass GetAnonymousType (IList parameters) + { + List candidates; + if (!anonymous_types.TryGetValue (parameters.Count, out candidates)) + return null; + + int i; + foreach (AnonymousTypeClass at in candidates) { + for (i = 0; i < parameters.Count; ++i) { + if (!parameters [i].Equals (at.Parameters [i])) + break; + } + + if (i == parameters.Count) + return at; + } + + return null; + } + + public RootNamespace GetRootNamespace (string name) + { + RootNamespace rn; + alias_ns.TryGetValue (name, out rn); + return rn; + } + + public override string GetSignatureForError () + { + return ""; + } + + public void InitializePredefinedTypes () + { + predefined_attributes = new PredefinedAttributes (this); + predefined_types = new PredefinedTypes (this); + predefined_members = new PredefinedMembers (this); + } + + public override bool IsClsComplianceRequired () + { + return DeclaringAssembly.IsCLSCompliant; + } + + protected override bool AddMemberType (TypeContainer tc) + { + if (AddTypesContainer (tc)) { + if ((tc.ModFlags & Modifiers.PARTIAL) != 0) + defined_names.Add (tc.Name, tc); + + tc.NamespaceEntry.NS.AddType (this, tc.Definition); + return true; + } + + return false; + } + + public bool AddTypesContainer (ITypesContainer container) + { + var mn = container.MemberName; + ITypesContainer found; + if (!defined_type_containers.TryGetValue (mn, out found)) { + defined_type_containers.Add (mn, container); + return true; + } + + if (container is NamespaceContainer && found is NamespaceContainer) + return true; + + var container_tc = container as TypeContainer; + var found_tc = found as TypeContainer; + if (container_tc != null && found_tc != null && container_tc.Kind == found_tc.Kind) { + if ((found_tc.ModFlags & container_tc.ModFlags & Modifiers.PARTIAL) != 0) { + return false; + } + + if (((found_tc.ModFlags | container_tc.ModFlags) & Modifiers.PARTIAL) != 0) { + Report.SymbolRelatedToPreviousError (found_tc); + Error_MissingPartialModifier (container_tc); + return false; + } + } + + string ns = mn.Left != null ? mn.Left.GetSignatureForError () : Module.GlobalRootNamespace.GetSignatureForError (); + mn = new MemberName (mn.Name, mn.TypeArguments, mn.Location); + + Report.SymbolRelatedToPreviousError (found.Location, ""); + Report.Error (101, container.Location, + "The namespace `{0}' already contains a definition for `{1}'", + ns, mn.GetSignatureForError ()); + return false; + } + + protected override void RemoveMemberType (TypeContainer ds) + { + defined_type_containers.Remove (ds.MemberName); + ds.NamespaceEntry.NS.RemoveDeclSpace (ds.Basename); + base.RemoveMemberType (ds); + } + + public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type) + { + Attribute a = OptAttributes.Search ("assembly", a_type); + if (a != null) { + a.Resolve (); + } + return a; + } + + public void SetDeclaringAssembly (AssemblyDefinition assembly) + { + // TODO: This setter is quite ugly but I have not found a way around it yet + this.assembly = assembly; + } + } + + sealed class RootDeclSpace : TypeContainer { + public RootDeclSpace (ModuleContainer module, NamespaceContainer ns) + : base (ns, null, MemberName.Null, null, 0) + { + PartialContainer = module; + } + + public override AttributeTargets AttributeTargets { + get { throw new InternalErrorException ("should not be called"); } + } + + public override CompilerContext Compiler { + get { + return PartialContainer.Compiler; + } + } + + public override string DocCommentHeader { + get { throw new InternalErrorException ("should not be called"); } + } + + public override void DefineType () + { + throw new InternalErrorException ("should not be called"); + } + + public override ModuleContainer Module { + get { + return PartialContainer.Module; + } + } + + public override void Accept (StructuralVisitor visitor) + { + throw new InternalErrorException ("should not be called"); + } + + public override bool IsClsComplianceRequired () + { + return PartialContainer.IsClsComplianceRequired (); + } + + public override IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + { + return null; + } + + public override FullNamedExpression LookupNamespaceAlias (string name) + { + return NamespaceEntry.LookupNamespaceAlias (name); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources new file mode 100644 index 0000000000..208d2eee29 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources @@ -0,0 +1,53 @@ +AssemblyInfo.cs +anonymous.cs +argument.cs +assign.cs +attribute.cs +driver.cs +cs-tokenizer.cs +cfold.cs +class.cs +codegen.cs +complete.cs +const.cs +constant.cs +convert.cs +context.cs +decl.cs +delegate.cs +doc-bootstrap.cs +dynamic.cs +enum.cs +ecore.cs +eval.cs +expression.cs +field.cs +flowanalysis.cs +generic.cs +import.cs +iterators.cs +lambda.cs +linq.cs +literal.cs +location.cs +membercache.cs +method.cs +modifiers.cs +namespace.cs +nullable.cs +parameter.cs +pending.cs +property.cs +report.cs +rootcontext.cs +roottypes.cs +statement.cs +support.cs +typemanager.cs +typespec.cs +symbolwriter.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolFile.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolTable.cs +../class/Mono.CompilerServices.SymbolWriter/MonoSymbolWriter.cs +../class/corlib/Mono.Security.Cryptography/CryptoConvert.cs +../build/common/Consts.cs diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml new file mode 100644 index 0000000000..92fc799bbd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml @@ -0,0 +1,384 @@ +../build/common/MonoTODOAttribute.cs +../build/common/Locale.cs +../class/System.XML/Mono.Xml.Schema/XmlSchemaValidatingReader.cs +../class/System.XML/Mono.Xml.Schema/XsdIdentityPath.cs +../class/System.XML/Mono.Xml.Schema/XsdIdentityState.cs +../class/System.XML/Mono.Xml.Schema/XsdKeyTable.cs +../class/System.XML/Mono.Xml.Schema/XsdParticleValidationState.cs +../class/System.XML/Mono.Xml.Schema/XsdValidatingReader.cs +../class/System.XML/Mono.Xml.Schema/XsdWildcard.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocument.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNavigator.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNode.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocument2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentBuilder2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathDocumentWriter2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNavigator2.cs +../class/System.XML/Mono.Xml.XPath/DTMXPathNode2.cs +../class/System.XML/Mono.Xml.XPath/IdPattern.cs +../class/System.XML/Mono.Xml.XPath/KeyPattern.cs +../class/System.XML/Mono.Xml.XPath/LocationPathPattern.cs +../class/System.XML/Mono.Xml.XPath/Pattern.cs +../class/System.XML/Mono.Xml.XPath/UnionPattern.cs +../class/System.XML/Mono.Xml.XPath/XPathEditableDocument.cs +../class/System.XML/Mono.Xml.XPath/XPathNavigatorReader.cs +../class/System.XML/Mono.Xml/IHasXmlParserContext.cs +../class/System.XML/Mono.Xml/IHasXmlSchemaInfo.cs +../class/System.XML/Mono.Xml/SubtreeXmlReader.cs +../class/System.XML/Mono.Xml/XmlFilterReader.cs +../class/System.XML/Mono.Xml/XmlNodeWriter.cs +../class/System.XML/System.Xml/ConformanceLevel.cs +../class/System.XML/System.Xml/DTDAutomata.cs +../class/System.XML/System.Xml/DTDObjectModel.cs +../class/System.XML/System.Xml/DTDReader.cs +../class/System.XML/System.Xml/DTDValidatingReader2.cs +../class/System.XML/System.Xml/EntityResolvingXmlReader.cs +../class/System.XML/System.Xml/EntityHandling.cs +../class/System.XML/System.Xml/Formatting.cs +../class/System.XML/System.Xml/IHasXmlNode.cs +../class/System.XML/System.Xml/IXmlLineInfo.cs +../class/System.XML/System.Xml/IHasXmlChildNode.cs +../class/System.XML/System.Xml/IXmlNamespaceResolver.cs +../class/System.XML/System.Xml/MonoFIXAttribute.cs +../class/System.XML/System.Xml/NameTable.cs +../class/System.XML/System.Xml/NewLineHandling.cs +../class/System.XML/System.Xml/ReadState.cs +../class/System.XML/System.Xml/ValidationType.cs +../class/System.XML/System.Xml/WhitespaceHandling.cs +../class/System.XML/System.Xml/WriteState.cs +../class/System.XML/System.Xml/XmlEntity.cs +../class/System.XML/System.Xml/XmlAttribute.cs +../class/System.XML/System.Xml/XmlAttributeCollection.cs +../class/System.XML/System.Xml/XmlCDataSection.cs +../class/System.XML/System.Xml/XmlConstructs.cs +../class/System.XML/System.Xml/XmlChar.cs +../class/System.XML/System.Xml/XmlCharacterData.cs +../class/System.XML/System.Xml/XmlComment.cs +../class/System.XML/System.Xml/XmlNotation.cs +../class/System.XML/System.Xml/XmlDeclaration.cs +../class/System.XML/System.Xml/XmlDocument.cs +../class/System.XML/System.Xml/XmlDocumentFragment.cs +../class/System.XML/System.Xml/XmlDocumentNavigator.cs +../class/System.XML/System.Xml/XmlDocumentType.cs +../class/System.XML/System.Xml/XmlElement.cs +../class/System.XML/System.Xml/XmlEntityReference.cs +../class/System.XML/System.Xml/XmlException.cs +../class/System.XML/System.Xml/XmlImplementation.cs +../class/System.XML/System.Xml/XmlConvert.cs +../class/System.XML/System.Xml/XmlDateTimeSerializationMode.cs +../class/System.XML/System.Xml/XmlLinkedNode.cs +../class/System.XML/System.Xml/XmlNameEntry.cs +../class/System.XML/System.Xml/XmlNameEntryCache.cs +../class/System.XML/System.Xml/XmlNameTable.cs +../class/System.XML/System.Xml/XmlNamedNodeMap.cs +../class/System.XML/System.Xml/XmlNamespaceScope.cs +../class/System.XML/System.Xml/XmlNamespaceManager.cs +../class/System.XML/System.Xml/XmlNode.cs +../class/System.XML/System.Xml/XmlNodeChangedAction.cs +../class/System.XML/System.Xml/XmlNodeChangedEventArgs.cs +../class/System.XML/System.Xml/XmlNodeChangedEventHandler.cs +../class/System.XML/System.Xml/XmlNodeList.cs +../class/System.XML/System.Xml/XmlNodeListChildren.cs +../class/System.XML/System.Xml/XmlNodeArrayList.cs +../class/System.XML/System.Xml/XmlIteratorNodeList.cs +../class/System.XML/System.Xml/XmlNodeOrder.cs +../class/System.XML/System.Xml/XmlNodeReader2.cs +../class/System.XML/System.Xml/XmlNodeReaderImpl.cs +../class/System.XML/System.Xml/XmlNodeType.cs +../class/System.XML/System.Xml/XmlOutputMethod.cs +../class/System.XML/System.Xml/XmlParserContext.cs +../class/System.XML/System.Xml/XmlProcessingInstruction.cs +../class/System.XML/System.Xml/XmlQualifiedName.cs +../class/System.XML/System.Xml/XmlReader.cs +../class/System.XML/System.Xml/XmlReaderBinarySupport.cs +../class/System.XML/System.Xml/XmlReaderSettings.cs +../class/System.XML/System.Xml/XmlResolver.cs +../class/System.XML/System.Xml/XmlSecureResolver.cs +../class/System.XML/System.Xml/XmlSignificantWhitespace.cs +../class/System.XML/System.Xml/XmlSpace.cs +../class/System.XML/System.Xml/XmlText.cs +../class/System.XML/System.Xml/XmlTextReader.cs +../class/System.XML/System.Xml/XmlTextReader2.cs +../class/System.XML/System.Xml/XmlTokenizedType.cs +../class/System.XML/System.Xml/XmlUrlResolver.cs +../class/System.XML/System.Xml/XmlValidatingReader.cs +../class/System.XML/System.Xml/XmlWhitespace.cs +../class/System.XML/System.Xml/XmlWriter.cs +../class/System.XML/System.Xml/XmlWriterSettings.cs +../class/System.XML/System.Xml/XmlTextWriter2.cs +../class/System.XML/System.Xml/XmlInputStream.cs +../class/System.XML/System.Xml/XmlParserInput.cs +../class/System.XML/System.Xml.XPath/IXPathNavigable.cs +../class/System.XML/System.Xml.XPath/XPathNavigator.cs +../class/System.XML/System.Xml.XPath/XPathExpression.cs +../class/System.XML/System.Xml.XPath/XPathItem.cs +../class/System.XML/System.Xml.XPath/XPathNamespaceScope.cs +../class/System.XML/System.Xml.XPath/XPathNodeIterator.cs +../class/System.XML/System.Xml.XPath/XPathResultType.cs +../class/System.XML/System.Xml.XPath/XPathNodeType.cs +../class/System.XML/System.Xml.XPath/XmlDataType.cs +../class/System.XML/System.Xml.XPath/XmlSortOrder.cs +../class/System.XML/System.Xml.XPath/XmlCaseOrder.cs +../class/System.XML/System.Xml.XPath/XPathDocument.cs +../class/System.XML/System.Xml.XPath/XPathException.cs +../class/System.XML/System.Xml.XPath/XPathComparer.cs +../class/System.XML/System.Xml.XPath/DefaultContext.cs +../class/System.XML/System.Xml.XPath/Expression.cs +../class/System.XML/System.Xml.XPath/Iterator.cs +../class/System.XML/System.Xml.XPath/Tokenizer.cs +../class/System.XML/System.Xml.XPath/Parser.cs +../class/System.XML/System.Xml.Schema/BuiltInDatatype.cs +../class/System.XML/System.Xml.Schema/IXmlSchemaInfo.cs +../class/System.XML/System.Xml.Schema/SchemaDataValueType.cs +../class/System.XML/System.Xml.Schema/ValidationEventArgs.cs +../class/System.XML/System.Xml.Schema/XmlAtomicValue.cs +../class/System.XML/System.Xml.Schema/XmlSchema.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAll.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAnnotated.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAnnotation.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAny.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAnyAttribute.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAppInfo.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAttribute.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAttributeGroup.cs +../class/System.XML/System.Xml.Schema/XmlSchemaAttributeGroupRef.cs +../class/System.XML/System.Xml.Schema/XmlSchemaChoice.cs +../class/System.XML/System.Xml.Schema/XmlSchemaCollection.cs +../class/System.XML/System.Xml.Schema/XmlSchemaCollectionEnumerator.cs +../class/System.XML/System.Xml.Schema/XmlSchemaCompilationSettings.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexContentExtension.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexContentRestriction.cs +../class/System.XML/System.Xml.Schema/XmlSchemaComplexType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContentModel.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContentProcessing.cs +../class/System.XML/System.Xml.Schema/XmlSchemaContentType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDatatype.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDatatypeVariety.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDerivationMethod.cs +../class/System.XML/System.Xml.Schema/XmlSchemaDocumentation.cs +../class/System.XML/System.Xml.Schema/XmlSchemaElement.cs +../class/System.XML/System.Xml.Schema/XmlSchemaEnumerationFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaException.cs +../class/System.XML/System.Xml.Schema/XmlSchemaExternal.cs +../class/System.XML/System.Xml.Schema/XmlSchemaFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaForm.cs +../class/System.XML/System.Xml.Schema/XmlSchemaFractionDigitsFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaGroup.cs +../class/System.XML/System.Xml.Schema/XmlSchemaGroupBase.cs +../class/System.XML/System.Xml.Schema/XmlSchemaGroupRef.cs +../class/System.XML/System.Xml.Schema/XmlSchemaIdentityConstraint.cs +../class/System.XML/System.Xml.Schema/XmlSchemaImport.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInclude.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInference.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInferenceException.cs +../class/System.XML/System.Xml.Schema/XmlSchemaInfo.cs +../class/System.XML/System.Xml.Schema/XmlSchemaKey.cs +../class/System.XML/System.Xml.Schema/XmlSchemaKeyref.cs +../class/System.XML/System.Xml.Schema/XmlSchemaLengthFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMaxExclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMaxInclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMaxLengthFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMinExclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMinInclusiveFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaMinLengthFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaNotation.cs +../class/System.XML/System.Xml.Schema/XmlSchemaNumericFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObject.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObjectCollection.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObjectEnumerator.cs +../class/System.XML/System.Xml.Schema/XmlSchemaObjectTable.cs +../class/System.XML/System.Xml.Schema/XmlSchemaParticle.cs +../class/System.XML/System.Xml.Schema/XmlSchemaPatternFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaRedefine.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSequence.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSerializer.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContentExtension.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleContentRestriction.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeContent.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeList.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeRestriction.cs +../class/System.XML/System.Xml.Schema/XmlSchemaSimpleTypeUnion.cs +../class/System.XML/System.Xml.Schema/XmlSchemaTotalDigitsFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaType.cs +../class/System.XML/System.Xml.Schema/XmlSchemaUnique.cs +../class/System.XML/System.Xml.Schema/XmlSchemaUse.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidator.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidity.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidationException.cs +../class/System.XML/System.Xml.Schema/XmlSchemaWhiteSpaceFacet.cs +../class/System.XML/System.Xml.Schema/XmlSchemaXPath.cs +../class/System.XML/System.Xml.Schema/XmlSeverityType.cs +../class/System.XML/System.Xml.Schema/ValidationHandler.cs +../class/System.XML/System.Xml.Schema/XmlSchemaUtil.cs +../class/System.XML/System.Xml.Schema/XmlSchemaReader.cs +../class/System.XML/System.Xml.Schema/XmlSchemaValidationFlags.cs +../class/System.XML/System.Xml.Schema/XmlTypeCode.cs +../class/System.XML/System.Xml.Schema/XmlValueGetter.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslApplyImports.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslApplyTemplates.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslAttribute.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslAvt.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCallTemplate.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslChoose.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslComment.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCompiledElement.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCopy.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslCopyOf.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslElement.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslFallback.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslForEach.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslIf.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslLiteralElement.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslMessage.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslNotSupportedOperation.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslNumber.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslOperation.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslProcessingInstruction.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslTemplateContent.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslText.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslValueOf.cs +../class/System.XML/Mono.Xml.Xsl.Operations/XslVariable.cs +../class/System.XML/Mono.Xml.Xsl/Attribute.cs +../class/System.XML/Mono.Xml.Xsl/Compiler.cs +../class/System.XML/Mono.Xml.Xsl/Debug.cs +../class/System.XML/Mono.Xml.Xsl/Emitter.cs +../class/System.XML/Mono.Xml.Xsl/GenericOutputter.cs +../class/System.XML/Mono.Xml.Xsl/HtmlEmitter.cs +../class/System.XML/Mono.Xml.Xsl/MSXslScriptManager.cs +../class/System.XML/Mono.Xml.Xsl/Outputter.cs +../class/System.XML/Mono.Xml.Xsl/ScriptCompilerInfo.cs +../class/System.XML/Mono.Xml.Xsl/TextEmitter.cs +../class/System.XML/Mono.Xml.Xsl/TextOutputter.cs +../class/System.XML/Mono.Xml.Xsl/PatternParser.cs +../class/System.XML/Mono.Xml.Xsl/PatternTokenizer.cs +../class/System.XML/Mono.Xml.Xsl/XmlWriterEmitter.cs +../class/System.XML/Mono.Xml.Xsl/XslAttributeSet.cs +../class/System.XML/Mono.Xml.Xsl/XslDecimalFormat.cs +../class/System.XML/Mono.Xml.Xsl/XslKey.cs +../class/System.XML/Mono.Xml.Xsl/XslOutput.cs +../class/System.XML/Mono.Xml.Xsl/XslSortEvaluator.cs +../class/System.XML/Mono.Xml.Xsl/XslStylesheet.cs +../class/System.XML/Mono.Xml.Xsl/XslTemplate.cs +../class/System.XML/Mono.Xml.Xsl/XslTransformProcessor.cs +../class/System.XML/Mono.Xml.Xsl/XsltCompiledContext.cs +../class/System.XML/Mono.Xml.Xsl/XsltDebuggerWrapper.cs +../class/System.XML/Mono.Xml.Xsl/XslFunctions.cs +../class/System.XML/System.Xml.Xsl/IXsltContextFunction.cs +../class/System.XML/System.Xml.Xsl/IXsltContextVariable.cs +../class/System.XML/System.Xml.Xsl/XslCompiledTransform.cs +../class/System.XML/System.Xml.Xsl/XslTransform.cs +../class/System.XML/System.Xml.Xsl/XsltArgumentList.cs +../class/System.XML/System.Xml.Xsl/XsltCompileException.cs +../class/System.XML/System.Xml.Xsl/XsltContext.cs +../class/System.XML/System.Xml.Xsl/XsltException.cs +../class/System.XML/System.Xml.Xsl/XsltMessageEncounteredEventArgs.cs +../class/System.XML/System.Xml.Xsl/XsltMessageEncounteredEventHandler.cs +../class/System.XML/System.Xml.Xsl/XsltSettings.cs +../class/System.XML/System.Xml/XQueryConvert.cs +../class/System.XML/System.Xml.Serialization/IXmlTextParser.cs +../class/System.XML/System.Xml.Serialization/CodeExporter.cs +../class/System.XML/System.Xml.Serialization/CodeGenerationOptions.cs +../class/System.XML/System.Xml.Serialization/CodeIdentifier.cs +../class/System.XML/System.Xml.Serialization/CodeIdentifiers.cs +../class/System.XML/System.Xml.Serialization/IXmlSerializable.cs +../class/System.XML/System.Xml.Serialization/ImportContext.cs +../class/System.XML/System.Xml.Serialization/MapCodeGenerator.cs +../class/System.XML/System.Xml.Serialization/ReflectionHelper.cs +../class/System.XML/System.Xml.Serialization/SchemaImporter.cs +../class/System.XML/System.Xml.Serialization/SchemaTypes.cs +../class/System.XML/System.Xml.Serialization/SerializationCodeGenerator.cs +../class/System.XML/System.Xml.Serialization/SerializationCodeGeneratorConfiguration.cs +../class/System.XML/System.Xml.Serialization/SerializationSource.cs +../class/System.XML/System.Xml.Serialization/SoapAttributeAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapAttributeOverrides.cs +../class/System.XML/System.Xml.Serialization/SoapAttributes.cs +../class/System.XML/System.Xml.Serialization/SoapCodeExporter.cs +../class/System.XML/System.Xml.Serialization/SoapElementAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapEnumAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapIgnoreAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapIncludeAttribute.cs +../class/System.XML/System.Xml.Serialization/SoapSchemaImporter.cs +../class/System.XML/System.Xml.Serialization/SoapSchemaExporter.cs +../class/System.XML/System.Xml.Serialization/SoapSchemaMember.cs +../class/System.XML/System.Xml.Serialization/SoapReflectionImporter.cs +../class/System.XML/System.Xml.Serialization/SoapTypeAttribute.cs +../class/System.XML/System.Xml.Serialization/TypeData.cs +../class/System.XML/System.Xml.Serialization/TypeMember.cs +../class/System.XML/System.Xml.Serialization/TypeTranslator.cs +../class/System.XML/System.Xml.Serialization/UnreferencedObjectEventArgs.cs +../class/System.XML/System.Xml.Serialization/UnreferencedObjectEventHandler.cs +../class/System.XML/System.Xml.Serialization/XmlAnyAttributeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlAnyElementAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlAnyElementAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlArrayAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlArrayItemAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlArrayItemAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeEventArgs.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeEventHandler.cs +../class/System.XML/System.Xml.Serialization/XmlAttributeOverrides.cs +../class/System.XML/System.Xml.Serialization/XmlAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlCodeExporter.cs +../class/System.XML/System.Xml.Serialization/XmlChoiceIdentifierAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlCustomFormatter.cs +../class/System.XML/System.Xml.Serialization/XmlDeserializationEvents.cs +../class/System.XML/System.Xml.Serialization/XmlElementAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlElementAttributes.cs +../class/System.XML/System.Xml.Serialization/XmlElementEventArgs.cs +../class/System.XML/System.Xml.Serialization/XmlEnumAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlIgnoreAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlIncludeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlMemberMapping.cs +../class/System.XML/System.Xml.Serialization/XmlMembersMapping.cs +../class/System.XML/System.Xml.Serialization/XmlMapping.cs +../class/System.XML/System.Xml.Serialization/XmlMappingAccess.cs +../class/System.XML/System.Xml.Serialization/XmlNamespaceDeclarationsAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlNodeEventArgs.cs +../class/System.XML/System.Xml.Serialization/XmlReflectionImporter.cs +../class/System.XML/System.Xml.Serialization/XmlReflectionMember.cs +../class/System.XML/System.Xml.Serialization/XmlRootAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaEnumerator.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaExporter.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaImporter.cs +../class/System.XML/System.Xml.Serialization/XmlSchemaProviderAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlSchemas.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationCollectionFixupCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationFixupCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationGeneratedCode.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationReadCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationReader.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationWriteCallback.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationWriter.cs +../class/System.XML/System.Xml.Serialization/XmlSerializationWriterInterpreter.cs +../class/System.XML/System.Xml.Serialization/XmlSerializer.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerAssemblyAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerFactory.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerImplementation.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerNamespaces.cs +../class/System.XML/System.Xml.Serialization/XmlSerializerVersionAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTextAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTypeAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapElementInfo.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMember.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberAttribute.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberElement.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapMemberNamespaces.cs +../class/System.XML/System.Xml.Serialization/XmlTypeMapping.cs +../class/System.XML/System.Xml.Serialization/XmlElementEventHandler.cs +../class/System.XML/System.Xml.Serialization/XmlNodeEventHandler.cs +../class/System.XML/System.Xml.Serialization.Advanced/SchemaImporterExtension.cs +../class/System.XML/System.Xml.Serialization.Advanced/SchemaImporterExtensionCollection.cs +../class/System.XML/System.Xml.Serialization.Configuration/DateTimeSerializationSection.cs +../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionElement.cs +../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionElementCollection.cs +../class/System.XML/System.Xml.Serialization.Configuration/SchemaImporterExtensionsSection.cs +../class/System.XML/System.Xml.Serialization.Configuration/SerializationSectionGroup.cs +../class/System.XML/System.Xml.Serialization.Configuration/XmlSerializerSection.cs diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs new file mode 100644 index 0000000000..db028e02bd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs @@ -0,0 +1,5969 @@ +// +// statement.cs: Statement representation for the IL tree. +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@seznam.cz) +// +// Copyright 2001, 2002, 2003 Ximian, Inc. +// Copyright 2003, 2004 Novell, Inc. +// + +using System; +using System.Collections.Generic; + +#if STATIC +using IKVM.Reflection.Emit; +#else +using System.Reflection.Emit; +#endif + +namespace Mono.CSharp { + + public abstract class Statement { + public Location loc; + + /// + /// Resolves the statement, true means that all sub-statements + /// did resolve ok. + // + public virtual bool Resolve (BlockContext bc) + { + return true; + } + + /// + /// We already know that the statement is unreachable, but we still + /// need to resolve it to catch errors. + /// + public virtual bool ResolveUnreachable (BlockContext ec, bool warn) + { + // + // This conflicts with csc's way of doing this, but IMHO it's + // the right thing to do. + // + // If something is unreachable, we still check whether it's + // correct. This means that you cannot use unassigned variables + // in unreachable code, for instance. + // + + if (warn) + ec.Report.Warning (162, 2, loc, "Unreachable code detected"); + + ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc); + bool ok = Resolve (ec); + ec.KillFlowBranching (); + + return ok; + } + + /// + /// Return value indicates whether all code paths emitted return. + /// + protected abstract void DoEmit (EmitContext ec); + + public virtual void Emit (EmitContext ec) + { + ec.Mark (loc); + DoEmit (ec); + } + + // + // This routine must be overrided in derived classes and make copies + // of all the data that might be modified if resolved + // + protected abstract void CloneTo (CloneContext clonectx, Statement target); + + public Statement Clone (CloneContext clonectx) + { + Statement s = (Statement) this.MemberwiseClone (); + CloneTo (clonectx, s); + return s; + } + + public virtual Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (834, loc, "A lambda expression with statement body cannot be converted to an expresion tree"); + return null; + } + + public virtual object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public sealed class EmptyStatement : Statement + { + public EmptyStatement (Location loc) + { + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + return true; + } + + public override bool ResolveUnreachable (BlockContext ec, bool warn) + { + return true; + } + + public override void Emit (EmitContext ec) + { + } + + protected override void DoEmit (EmitContext ec) + { + throw new NotSupportedException (); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // nothing needed. + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class If : Statement { + Expression expr; + public Statement TrueStatement; + public Statement FalseStatement; + + bool is_true_ret; + + public If (Expression bool_expr, Statement true_statement, Location l) + : this (bool_expr, true_statement, null, l) + { + } + + public If (Expression bool_expr, + Statement true_statement, + Statement false_statement, + Location l) + { + this.expr = bool_expr; + TrueStatement = true_statement; + FalseStatement = false_statement; + loc = l; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + expr = expr.Resolve (ec); + if (expr == null) { + ok = false; + } else { + // + // Dead code elimination + // + if (expr is Constant) { + bool take = !((Constant) expr).IsDefaultValue; + + if (take) { + if (!TrueStatement.Resolve (ec)) + return false; + + if ((FalseStatement != null) && + !FalseStatement.ResolveUnreachable (ec, true)) + return false; + FalseStatement = null; + } else { + if (!TrueStatement.ResolveUnreachable (ec, true)) + return false; + TrueStatement = null; + + if ((FalseStatement != null) && + !FalseStatement.Resolve (ec)) + return false; + } + + return true; + } + } + + ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc); + + ok &= TrueStatement.Resolve (ec); + + is_true_ret = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + ec.CurrentBranching.CreateSibling (); + + if (FalseStatement != null) + ok &= FalseStatement.Resolve (ec); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + Label false_target = ec.DefineLabel (); + Label end; + + // + // If we're a boolean constant, Resolve() already + // eliminated dead code for us. + // + Constant c = expr as Constant; + if (c != null){ + c.EmitSideEffect (ec); + + if (!c.IsDefaultValue) + TrueStatement.Emit (ec); + else if (FalseStatement != null) + FalseStatement.Emit (ec); + + return; + } + + expr.EmitBranchable (ec, false_target, false); + + TrueStatement.Emit (ec); + + if (FalseStatement != null){ + bool branch_emitted = false; + + end = ec.DefineLabel (); + if (!is_true_ret){ + ec.Emit (OpCodes.Br, end); + branch_emitted = true; + } + + ec.MarkLabel (false_target); + FalseStatement.Emit (ec); + + if (branch_emitted) + ec.MarkLabel (end); + } else { + ec.MarkLabel (false_target); + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + If target = (If) t; + + target.expr = expr.Clone (clonectx); + target.TrueStatement = TrueStatement.Clone (clonectx); + if (FalseStatement != null) + target.FalseStatement = FalseStatement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Do : Statement { + public Expression expr; + public Statement EmbeddedStatement; + + public Do (Statement statement, BooleanExpression bool_expr, Location l) + { + expr = bool_expr; + EmbeddedStatement = statement; + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + + bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!EmbeddedStatement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable && !was_unreachable) + ec.Report.Warning (162, 2, expr.Location, "Unreachable code detected"); + + expr = expr.Resolve (ec); + if (expr == null) + ok = false; + else if (expr is Constant){ + bool infinite = !((Constant) expr).IsDefaultValue; + if (infinite) + ec.CurrentBranching.CurrentUsageVector.Goto (); + } + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + Label loop = ec.DefineLabel (); + Label old_begin = ec.LoopBegin; + Label old_end = ec.LoopEnd; + + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + ec.MarkLabel (loop); + EmbeddedStatement.Emit (ec); + ec.MarkLabel (ec.LoopBegin); + + // + // Dead code elimination + // + if (expr is Constant){ + bool res = !((Constant) expr).IsDefaultValue; + + expr.EmitSideEffect (ec); + if (res) + ec.Emit (OpCodes.Br, loop); + } else + expr.EmitBranchable (ec, loop, true); + + ec.MarkLabel (ec.LoopEnd); + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Do target = (Do) t; + + target.EmbeddedStatement = EmbeddedStatement.Clone (clonectx); + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class While : Statement { + public Expression expr; + public Statement Statement; + bool infinite, empty; + + public While (BooleanExpression bool_expr, Statement statement, Location l) + { + this.expr = bool_expr; + Statement = statement; + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + expr = expr.Resolve (ec); + if (expr == null) + ok = false; + + // + // Inform whether we are infinite or not + // + if (expr is Constant){ + bool value = !((Constant) expr).IsDefaultValue; + + if (value == false){ + if (!Statement.ResolveUnreachable (ec, true)) + return false; + empty = true; + return true; + } else + infinite = true; + } + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + if (!infinite) + ec.CurrentBranching.CreateSibling (); + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!Statement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + // There's no direct control flow from the end of the embedded statement to the end of the loop + ec.CurrentBranching.CurrentUsageVector.Goto (); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + if (empty) { + expr.EmitSideEffect (ec); + return; + } + + Label old_begin = ec.LoopBegin; + Label old_end = ec.LoopEnd; + + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + // + // Inform whether we are infinite or not + // + if (expr is Constant){ + // expr is 'true', since the 'empty' case above handles the 'false' case + ec.MarkLabel (ec.LoopBegin); + expr.EmitSideEffect (ec); + Statement.Emit (ec); + ec.Emit (OpCodes.Br, ec.LoopBegin); + + // + // Inform that we are infinite (ie, `we return'), only + // if we do not `break' inside the code. + // + ec.MarkLabel (ec.LoopEnd); + } else { + Label while_loop = ec.DefineLabel (); + + ec.Emit (OpCodes.Br, ec.LoopBegin); + ec.MarkLabel (while_loop); + + Statement.Emit (ec); + + ec.MarkLabel (ec.LoopBegin); + ec.Mark (loc); + + expr.EmitBranchable (ec, while_loop, true); + + ec.MarkLabel (ec.LoopEnd); + } + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + public override void Emit (EmitContext ec) + { + DoEmit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + While target = (While) t; + + target.expr = expr.Clone (clonectx); + target.Statement = Statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + 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; } + 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; + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + if (InitStatement != null){ + if (!InitStatement.Resolve (ec)) + ok = false; + } + + if (Test != null){ + Test = Test.Resolve (ec); + if (Test == null) + ok = false; + else if (Test is Constant){ + bool value = !((Constant) Test).IsDefaultValue; + + if (value == false){ + if (!Statement.ResolveUnreachable (ec, true)) + return false; + if ((Increment != null) && + !Increment.ResolveUnreachable (ec, false)) + return false; + empty = true; + return true; + } else + infinite = true; + } + } else + infinite = true; + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + if (!infinite) + ec.CurrentBranching.CreateSibling (); + + bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!Statement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + if (Increment != null){ + if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable) { + if (!Increment.ResolveUnreachable (ec, !was_unreachable)) + ok = false; + } else { + if (!Increment.Resolve (ec)) + ok = false; + } + } + + // There's no direct control flow from the end of the embedded statement to the end of the loop + ec.CurrentBranching.CurrentUsageVector.Goto (); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + if (InitStatement != null) + InitStatement.Emit (ec); + + if (empty) { + Test.EmitSideEffect (ec); + return; + } + + Label old_begin = ec.LoopBegin; + Label old_end = ec.LoopEnd; + Label loop = ec.DefineLabel (); + Label test = ec.DefineLabel (); + + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + ec.Emit (OpCodes.Br, test); + ec.MarkLabel (loop); + Statement.Emit (ec); + + ec.MarkLabel (ec.LoopBegin); + Increment.Emit (ec); + + ec.MarkLabel (test); + // + // If test is null, there is no test, and we are just + // an infinite loop + // + if (Test != 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); + ec.Emit (OpCodes.Br, loop); + } else { + Test.EmitBranchable (ec, loop, true); + } + + } else + ec.Emit (OpCodes.Br, loop); + ec.MarkLabel (ec.LoopEnd); + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + 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); + target.Statement = Statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class StatementExpression : Statement + { + ExpressionStatement expr; + + public StatementExpression (ExpressionStatement expr) + { + this.expr = expr; + loc = expr.Location; + } + + public ExpressionStatement Expr { + get { return this.expr; } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + StatementExpression target = (StatementExpression) t; + target.expr = (ExpressionStatement) expr.Clone (clonectx); + } + + protected override void DoEmit (EmitContext ec) + { + expr.EmitStatement (ec); + } + + public override bool Resolve (BlockContext ec) + { + expr = expr.ResolveStatement (ec); + return expr != null; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Simple version of statement list not requiring a block + // + public class StatementList : Statement + { + List statements; + + public StatementList (Statement first, Statement second) + { + statements = new List () { first, second }; + } + + #region Properties + public IList Statements { + get { + return statements; + } + } + #endregion + + public void Add (Statement statement) + { + statements.Add (statement); + } + + public override bool Resolve (BlockContext ec) + { + foreach (var s in statements) + s.Resolve (ec); + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + foreach (var s in statements) + s.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + StatementList t = (StatementList) target; + + t.statements = new List (statements.Count); + foreach (Statement s in statements) + t.statements.Add (s.Clone (clonectx)); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // A 'return' or a 'yield break' + public abstract class ExitStatement : Statement + { + protected bool unwind_protect; + protected abstract bool DoResolve (BlockContext ec); + + public virtual void Error_FinallyClause (Report Report) + { + Report.Error (157, loc, "Control cannot leave the body of a finally clause"); + } + + public sealed override bool Resolve (BlockContext ec) + { + if (!DoResolve (ec)) + return false; + + unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, this); + if (unwind_protect) + ec.NeedReturnLabel (); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + } + + /// + /// Implements the return statement + /// + public class Return : ExitStatement + { + public Expression Expr { get; protected set; } + + public Return (Expression expr, Location l) + { + Expr = expr; + loc = l; + } + + #region Properties + public Expression Expression { + get { + return Expr; + } + } + #endregion + + protected override bool DoResolve (BlockContext ec) + { + if (Expr == null) { + 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 { + ec.Report.Error (126, loc, + "An object of a type convertible to `{0}' is required for the return statement", + ec.ReturnType.GetSignatureForError ()); + } + + return false; + } + + Expr = Expr.Resolve (ec); + TypeSpec block_return_type = ec.ReturnType; + + AnonymousExpression am = ec.CurrentAnonymousMethod; + if (am == null) { + if (block_return_type.Kind == MemberKind.Void) { + ec.Report.Error (127, loc, + "`{0}': A return keyword must not be followed by any expression when method returns void", + ec.GetSignatureForError ()); + } + } else { + if (am.IsIterator) { + Error_ReturnFromIterator (ec); + return false; + } + + 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", + ec.GetSignatureForError ()); + return false; + } + + // + // The return type is actually Task type argument + // + block_return_type = async_type.TypeArguments[0]; + } + } else { + var l = am as AnonymousMethodBody; + if (l != null && l.ReturnTypeInference != null && Expr != null) { + l.ReturnTypeInference.AddCommonTypeBound (Expr.Type); + return true; + } + } + } + + if (Expr == null) + return false; + + if (Expr.Type != block_return_type) { + Expr = Convert.ImplicitConversionRequired (ec, Expr, block_return_type, loc); + + if (Expr == null) { + if (am != null && block_return_type == ec.ReturnType) { + ec.Report.Error (1662, loc, + "Cannot convert `{0}' to delegate type `{1}' because some of the return types in the block are not implicitly convertible to the delegate return type", + am.ContainerType, am.GetSignatureForError ()); + } + return false; + } + } + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + if (Expr != null) { + Expr.Emit (ec); + + var async_body = ec.CurrentAnonymousMethod as AsyncInitializer; + if (async_body != null) { + var async_return = ((AsyncTaskStorey) async_body.Storey).HoistedReturn; + + // It's null for await without async + if (async_return != null) + async_return.EmitAssign (ec); + + return; + } + + if (unwind_protect) + ec.Emit (OpCodes.Stloc, ec.TemporaryReturn ()); + } + + if (unwind_protect) + ec.Emit (OpCodes.Leave, ec.ReturnLabel); + else + ec.Emit (OpCodes.Ret); + } + + void Error_ReturnFromIterator (ResolveContext rc) + { + rc.Report.Error (1622, loc, + "Cannot return a value from iterators. Use the yield return statement to return a value, or yield break to end the iteration"); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Return target = (Return) t; + // It's null for simple return; + if (Expr != null) + target.Expr = Expr.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Goto : Statement { + string target; + LabeledStatement label; + bool unwind_protect; + + public override bool Resolve (BlockContext ec) + { + unwind_protect = ec.CurrentBranching.AddGotoOrigin (ec.CurrentBranching.CurrentUsageVector, this); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + public Goto (string label, Location l) + { + loc = l; + target = label; + } + + public string Target { + get { return target; } + } + + public void SetResolvedTarget (LabeledStatement label) + { + this.label = label; + label.AddReference (); + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // Nothing to clone + } + + protected override void DoEmit (EmitContext ec) + { + if (label == null) + throw new InternalErrorException ("goto emitted before target resolved"); + Label l = label.LabelTarget (ec); + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class LabeledStatement : Statement { + string name; + bool defined; + bool referenced; + Label label; + Block block; + + FlowBranching.UsageVector vectors; + + public LabeledStatement (string name, Block block, Location l) + { + this.name = name; + this.block = block; + this.loc = l; + } + + public Label LabelTarget (EmitContext ec) + { + if (defined) + return label; + + label = ec.DefineLabel (); + defined = true; + return label; + } + + public Block Block { + get { + return block; + } + } + + public string Name { + get { return name; } + } + + public bool IsDefined { + get { return defined; } + } + + public bool HasBeenReferenced { + get { return referenced; } + } + + public FlowBranching.UsageVector JumpOrigins { + get { return vectors; } + } + + public void AddUsageVector (FlowBranching.UsageVector vector) + { + vector = vector.Clone (); + vector.Next = vectors; + vectors = vector; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // nothing to clone + } + + public override bool Resolve (BlockContext ec) + { + // this flow-branching will be terminated when the surrounding block ends + ec.StartFlowBranching (this); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + if (!HasBeenReferenced) + ec.Report.Warning (164, 2, loc, "This label has not been referenced"); + + LabelTarget (ec); + ec.MarkLabel (label); + } + + public void AddReference () + { + referenced = true; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + + /// + /// `goto default' statement + /// + public class GotoDefault : Statement { + + public GotoDefault (Location l) + { + loc = l; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + // nothing to clone + } + + public override bool Resolve (BlockContext ec) + { + ec.CurrentBranching.CurrentUsageVector.Goto (); + + if (ec.Switch == null) { + ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement"); + return false; + } + + if (!ec.Switch.GotDefault) { + FlowBranchingBlock.Error_UnknownLabel (loc, "default", ec.Report); + return false; + } + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (OpCodes.Br, ec.Switch.DefaultLabel); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// `goto case' statement + /// + public class GotoCase : Statement { + Expression expr; + SwitchLabel sl; + + public GotoCase (Expression e, Location l) + { + expr = e; + loc = l; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + if (ec.Switch == null){ + ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement"); + return false; + } + + ec.CurrentBranching.CurrentUsageVector.Goto (); + + expr = expr.Resolve (ec); + if (expr == null) + return false; + + Constant c = expr as Constant; + if (c == null) { + ec.Report.Error (150, expr.Location, "A constant value is expected"); + return false; + } + + Constant res; + if (ec.Switch.IsNullable && c is NullLiteral) { + res = c; + } else { + TypeSpec type = ec.Switch.SwitchType; + res = c.TryReduce (ec, type, c.Location); + if (res == null) { + c.Error_ValueCannotBeConverted (ec, loc, type, true); + return false; + } + + if (!Convert.ImplicitStandardConversionExists (c, type)) + ec.Report.Warning (469, 2, loc, + "The `goto case' value is not implicitly convertible to type `{0}'", + TypeManager.CSharpName (type)); + + } + + sl = ec.Switch.ResolveGotoCase (ec, res); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (OpCodes.Br, sl.GetILLabel (ec)); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + GotoCase target = (GotoCase) t; + + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Throw : Statement { + Expression expr; + + public Throw (Expression expr, Location l) + { + this.expr = expr; + loc = l; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + if (expr == null) { + ec.CurrentBranching.CurrentUsageVector.Goto (); + return ec.CurrentBranching.CheckRethrow (loc); + } + + expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue); + ec.CurrentBranching.CurrentUsageVector.Goto (); + + if (expr == null) + return false; + + var et = ec.BuiltinTypes.Exception; + if (Convert.ImplicitConversionExists (ec, expr, et)) + expr = Convert.ImplicitConversion (ec, expr, et, loc); + else + ec.Report.Error (155, expr.Location, "The type caught or thrown must be derived from System.Exception"); + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + if (expr == null) + ec.Emit (OpCodes.Rethrow); + else { + expr.Emit (ec); + + ec.Emit (OpCodes.Throw); + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Throw target = (Throw) t; + + if (expr != null) + target.expr = expr.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Break : Statement { + + public Break (Location l) + { + loc = l; + } + + bool unwind_protect; + + public override bool Resolve (BlockContext ec) + { + unwind_protect = ec.CurrentBranching.AddBreakOrigin (ec.CurrentBranching.CurrentUsageVector, loc); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + // nothing needed + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Continue : Statement { + + public Continue (Location l) + { + loc = l; + } + + bool unwind_protect; + + public override bool Resolve (BlockContext ec) + { + unwind_protect = ec.CurrentBranching.AddContinueOrigin (ec.CurrentBranching.CurrentUsageVector, loc); + ec.CurrentBranching.CurrentUsageVector.Goto (); + return true; + } + + protected override void DoEmit (EmitContext ec) + { + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + // nothing needed. + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public interface ILocalVariable + { + void Emit (EmitContext ec); + void EmitAssign (EmitContext ec); + void EmitAddressOf (EmitContext ec); + } + + public interface INamedBlockVariable + { + Block Block { get; } + Expression CreateReferenceExpression (ResolveContext rc, Location loc); + bool IsDeclared { get; } + Location Location { get; } + } + + public class BlockVariableDeclaration : Statement + { + public class Declarator + { + LocalVariable li; + Expression initializer; + + public Declarator (LocalVariable li, Expression initializer) + { + if (li.Type != null) + throw new ArgumentException ("Expected null variable type"); + + this.li = li; + this.initializer = initializer; + } + + public Declarator (Declarator clone, Expression initializer) + { + this.li = clone.li; + this.initializer = initializer; + } + + #region Properties + + public LocalVariable Variable { + get { + return li; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + initializer = value; + } + } + + #endregion + } + + Expression initializer; + protected FullNamedExpression type_expr; + protected LocalVariable li; + protected List declarators; + + public BlockVariableDeclaration (FullNamedExpression type, LocalVariable li) + { + this.type_expr = type; + this.li = li; + this.loc = type_expr.Location; + } + + protected BlockVariableDeclaration (LocalVariable li) + { + this.li = li; + } + + #region Properties + + public List Declarators { + get { + return declarators; + } + } + + public Expression Initializer { + get { + return initializer; + } + set { + initializer = value; + } + } + + public FullNamedExpression TypeExpression { + get { + return type_expr; + } + } + + public LocalVariable Variable { + get { + return li; + } + } + + #endregion + + public void AddDeclarator (Declarator decl) + { + if (declarators == null) + declarators = new List (); + + declarators.Add (decl); + } + + void CreateEvaluatorVariable (BlockContext bc, LocalVariable li) + { + var container = bc.CurrentMemberDefinition.Parent; + + Field f = new Field (container, new TypeExpression (li.Type, li.Location), Modifiers.PUBLIC | Modifiers.STATIC, + new MemberName (li.Name, li.Location), null); + + container.AddField (f); + f.Define (); + + li.HoistedVariant = new HoistedEvaluatorVariable (f); + li.SetIsUsed (); + } + + public override bool Resolve (BlockContext bc) + { + if (li.Type == null) { + TypeSpec type = null; + var vexpr = type_expr as VarExpr; + + // + // C# 3.0 introduced contextual keywords (var) which behaves like a type if type with + // same name exists or as a keyword when no type was found + // + if (vexpr != null && !vexpr.IsPossibleTypeOrNamespace (bc)) { + if (bc.Module.Compiler.Settings.Version < LanguageVersion.V_3) + bc.Report.FeatureIsNotAvailable (bc.Module.Compiler, loc, "implicitly typed local variable"); + + if (li.IsFixed) { + bc.Report.Error (821, loc, "A fixed statement cannot use an implicitly typed local variable"); + return false; + } + + if (li.IsConstant) { + bc.Report.Error (822, loc, "An implicitly typed local variable cannot be a constant"); + return false; + } + + if (Initializer == null) { + bc.Report.Error (818, loc, "An implicitly typed local variable declarator must include an initializer"); + return false; + } + + if (declarators != null) { + bc.Report.Error (819, loc, "An implicitly typed local variable declaration cannot include multiple declarators"); + declarators = null; + } + + Initializer = Initializer.Resolve (bc); + if (Initializer != null) { + ((VarExpr) type_expr).InferType (bc, Initializer); + type = type_expr.Type; + } + } + + if (type == null) { + type = type_expr.ResolveAsType (bc); + if (type == null) + return false; + + if (li.IsConstant && !type.IsConstantCompatible) { + Const.Error_InvalidConstantType (type, loc, bc.Report); + } + } + + if (type.IsStatic) + FieldBase.Error_VariableOfStaticClass (loc, li.Name, type, bc.Report); + + li.Type = type; + } + + bool eval_global = bc.Module.Compiler.Settings.StatementMode && bc.CurrentBlock is ToplevelBlock; + if (eval_global) { + CreateEvaluatorVariable (bc, li); + } else { + li.PrepareForFlowAnalysis (bc); + } + + if (initializer != null) { + initializer = ResolveInitializer (bc, li, initializer); + // li.Variable.DefinitelyAssigned + } + + if (declarators != null) { + foreach (var d in declarators) { + d.Variable.Type = li.Type; + if (eval_global) { + CreateEvaluatorVariable (bc, d.Variable); + } else { + d.Variable.PrepareForFlowAnalysis (bc); + } + + if (d.Initializer != null) { + d.Initializer = ResolveInitializer (bc, d.Variable, d.Initializer); + // d.Variable.DefinitelyAssigned + } + } + } + + return true; + } + + protected virtual Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + var a = new SimpleAssign (li.CreateReferenceExpression (bc, li.Location), initializer, li.Location); + return a.ResolveStatement (bc); + } + + protected override void DoEmit (EmitContext ec) + { + if (li.IsConstant) + return; + + li.CreateBuilder (ec); + + if (Initializer != null) + ((ExpressionStatement) Initializer).EmitStatement (ec); + + if (declarators != null) { + foreach (var d in declarators) { + d.Variable.CreateBuilder (ec); + if (d.Initializer != null) + ((ExpressionStatement) d.Initializer).EmitStatement (ec); + } + } + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + BlockVariableDeclaration t = (BlockVariableDeclaration) target; + + if (type_expr != null) + t.type_expr = (FullNamedExpression) type_expr.Clone (clonectx); + + if (initializer != null) + t.initializer = initializer.Clone (clonectx); + + if (declarators != null) { + t.declarators = null; + foreach (var d in declarators) + t.AddDeclarator (new Declarator (d, d.Initializer == null ? null : d.Initializer.Clone (clonectx))); + } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class BlockConstantDeclaration : BlockVariableDeclaration + { + public BlockConstantDeclaration (FullNamedExpression type, LocalVariable li) + : base (type, li) + { + } + + protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + initializer = initializer.Resolve (bc); + if (initializer == null) + return null; + + var c = initializer as Constant; + if (c == null) { + initializer.Error_ExpressionMustBeConstant (bc, initializer.Location, li.Name); + return null; + } + + c = c.ConvertImplicitly (li.Type); + if (c == null) { + if (TypeSpec.IsReferenceType (li.Type)) + initializer.Error_ConstantCanBeInitializedWithNullOnly (bc, li.Type, initializer.Location, li.Name); + else + initializer.Error_ValueCannotBeConverted (bc, initializer.Location, li.Type, false); + + return null; + } + + li.ConstantValue = c; + return initializer; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // The information about a user-perceived local variable + // + public class LocalVariable : INamedBlockVariable, ILocalVariable + { + [Flags] + public enum Flags + { + Used = 1, + IsThis = 1 << 1, + AddressTaken = 1 << 2, + CompilerGenerated = 1 << 3, + Constant = 1 << 4, + ForeachVariable = 1 << 5, + FixedVariable = 1 << 6, + UsingVariable = 1 << 7, +// DefinitelyAssigned = 1 << 8, + IsLocked = 1 << 9, + + ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable + } + + TypeSpec type; + readonly string name; + readonly Location loc; + readonly Block block; + Flags flags; + Constant const_value; + + public VariableInfo VariableInfo; + HoistedVariable hoisted_variant; + + LocalBuilder builder; + + public LocalVariable (Block block, string name, Location loc) + { + this.block = block; + this.name = name; + this.loc = loc; + } + + public LocalVariable (Block block, string name, Flags flags, Location loc) + : this (block, name, loc) + { + this.flags = flags; + } + + // + // Used by variable declarators + // + public LocalVariable (LocalVariable li, string name, Location loc) + : this (li.block, name, li.flags, loc) + { + } + + #region Properties + + public bool AddressTaken { + get { return (flags & Flags.AddressTaken) != 0; } + set { flags |= Flags.AddressTaken; } + } + + public Block Block { + get { + return block; + } + } + + public Constant ConstantValue { + get { + return const_value; + } + set { + const_value = value; + } + } + + // + // Hoisted local variable variant + // + public HoistedVariable HoistedVariant { + get { + return hoisted_variant; + } + set { + hoisted_variant = value; + } + } + + public bool IsDeclared { + get { + return type != null; + } + } + + public bool IsConstant { + get { + return (flags & Flags.Constant) != 0; + } + } + + public bool IsLocked { + get { + return (flags & Flags.IsLocked) != 0; + } + set { + flags = value ? flags | Flags.IsLocked : flags & ~Flags.IsLocked; + } + } + + public bool IsThis { + get { + return (flags & Flags.IsThis) != 0; + } + } + + public bool IsFixed { + get { + return (flags & Flags.FixedVariable) != 0; + } + } + + public bool IsReadonly { + get { + return (flags & Flags.ReadonlyMask) != 0; + } + } + + public Location Location { + get { + return loc; + } + } + + public string Name { + get { + return name; + } + } + + public TypeSpec Type { + get { + return type; + } + set { + type = value; + } + } + + #endregion + + public void CreateBuilder (EmitContext ec) + { + if ((flags & Flags.Used) == 0) { + if (VariableInfo == null) { + // Missing flow analysis or wrong variable flags + throw new InternalErrorException ("VariableInfo is null and the variable `{0}' is not used", name); + } + + if (VariableInfo.IsEverAssigned) + ec.Report.Warning (219, 3, Location, "The variable `{0}' is assigned but its value is never used", Name); + else + ec.Report.Warning (168, 3, Location, "The variable `{0}' is declared but never used", Name); + } + + if (HoistedVariant != null) + return; + + if (builder != null) { + if ((flags & Flags.CompilerGenerated) != 0) + return; + + // To avoid Used warning duplicates + throw new InternalErrorException ("Already created variable `{0}'", name); + } + + // + // All fixed variabled are pinned, a slot has to be alocated + // + builder = ec.DeclareLocal (Type, IsFixed); + if (SymbolWriter.HasSymbolWriter) + ec.DefineLocalVariable (name, builder); + } + + public static LocalVariable CreateCompilerGenerated (TypeSpec type, Block block, Location loc) + { + LocalVariable li = new LocalVariable (block, "<$$>", Flags.CompilerGenerated | Flags.Used, loc); + li.Type = type; + return li; + } + + public Expression CreateReferenceExpression (ResolveContext rc, Location loc) + { + if (IsConstant && const_value != null) + return Constant.CreateConstantFromValue (Type, const_value.GetValue (), loc); + + return new LocalVariableReference (this, loc); + } + + public void Emit (EmitContext ec) + { + // TODO: Need something better for temporary variables + if ((flags & Flags.CompilerGenerated) != 0) + CreateBuilder (ec); + + ec.Emit (OpCodes.Ldloc, builder); + } + + public void EmitAssign (EmitContext ec) + { + // TODO: Need something better for temporary variables + if ((flags & Flags.CompilerGenerated) != 0) + CreateBuilder (ec); + + ec.Emit (OpCodes.Stloc, builder); + } + + public void EmitAddressOf (EmitContext ec) + { + ec.Emit (OpCodes.Ldloca, builder); + } + + public string GetReadOnlyContext () + { + switch (flags & Flags.ReadonlyMask) { + case Flags.FixedVariable: + return "fixed variable"; + case Flags.ForeachVariable: + return "foreach iteration variable"; + case Flags.UsingVariable: + return "using variable"; + } + + throw new InternalErrorException ("Variable is not readonly"); + } + + public bool IsThisAssigned (BlockContext ec, Block block) + { + if (VariableInfo == null) + throw new Exception (); + + if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo)) + return true; + + return VariableInfo.TypeInfo.IsFullyInitialized (ec, VariableInfo, block.StartLocation); + } + + public bool IsAssigned (BlockContext ec) + { + if (VariableInfo == null) + throw new Exception (); + + return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo); + } + + public void PrepareForFlowAnalysis (BlockContext bc) + { + // + // No need for definitely assigned check for these guys + // + if ((flags & (Flags.Constant | Flags.ReadonlyMask | Flags.CompilerGenerated)) != 0) + return; + + VariableInfo = new VariableInfo (this, bc.FlowOffset); + bc.FlowOffset += VariableInfo.Length; + } + + // + // Mark the variables as referenced in the user code + // + public void SetIsUsed () + { + flags |= Flags.Used; + } + + public override string ToString () + { + return string.Format ("LocalInfo ({0},{1},{2},{3})", name, type, VariableInfo, Location); + } + } + + /// + /// Block represents a C# block. + /// + /// + /// + /// This class is used in a number of places: either to represent + /// explicit blocks that the programmer places or implicit blocks. + /// + /// Implicit blocks are used as labels or to introduce variable + /// declarations. + /// + /// Top-level blocks derive from Block, and they are called ToplevelBlock + /// they contain extra information that is not necessary on normal blocks. + /// + public class Block : Statement { + [Flags] + public enum Flags + { + Unchecked = 1, + HasRet = 8, + Unsafe = 16, + IsIterator = 32, + HasCapturedVariable = 64, + HasCapturedThis = 1 << 7, + IsExpressionTree = 1 << 8, + CompilerGenerated = 1 << 9, + IsAsync = 1 << 10 + } + + public Block Parent; + public Location StartLocation; + public Location EndLocation; + + public ExplicitBlock Explicit; + public ParametersBlock ParametersBlock; + + protected Flags flags; + + // + // The statements in this block + // + protected List statements; + + protected List scope_initializers; + + int? resolving_init_idx; + + protected Block original; + +#if DEBUG + static int id; + public int ID = id++; + + static int clone_id_counter; + int clone_id; +#endif + +// int assignable_slots; + bool unreachable_shown; + bool unreachable; + + public Block (Block parent, Location start, Location end) + : this (parent, 0, start, end) + { + } + + public Block (Block parent, Flags flags, Location start, Location end) + { + if (parent != null) { + // the appropriate constructors will fixup these fields + ParametersBlock = parent.ParametersBlock; + Explicit = parent.Explicit; + } + + this.Parent = parent; + this.flags = flags; + this.StartLocation = start; + this.EndLocation = end; + this.loc = start; + statements = new List (4); + + this.original = this; + } + + #region Properties + + public bool HasRet { + get { return (flags & Flags.HasRet) != 0; } + } + + public Block Original { + get { + return original; + } + } + + public bool IsCompilerGenerated { + get { return (flags & Flags.CompilerGenerated) != 0; } + set { flags = value ? flags | Flags.CompilerGenerated : flags & ~Flags.CompilerGenerated; } + } + + public bool Unchecked { + get { return (flags & Flags.Unchecked) != 0; } + set { flags = value ? flags | Flags.Unchecked : flags & ~Flags.Unchecked; } + } + + public bool Unsafe { + get { return (flags & Flags.Unsafe) != 0; } + set { flags |= Flags.Unsafe; } + } + + public List Statements { + get { return this.statements; } + } + #endregion + + public Block CreateSwitchBlock (Location start) + { + // FIXME: Only explicit block should be created + var new_block = new Block (this, start, start); + new_block.IsCompilerGenerated = true; + return new_block; + } + + public void SetEndLocation (Location loc) + { + EndLocation = loc; + } + + public void AddLabel (LabeledStatement target) + { + ParametersBlock.TopBlock.AddLabel (target.Name, target); + } + + public void AddLocalName (LocalVariable li) + { + AddLocalName (li.Name, li); + } + + public virtual void AddLocalName (string name, INamedBlockVariable li) + { + ParametersBlock.TopBlock.AddLocalName (name, li); + } + + public virtual void Error_AlreadyDeclared (string name, INamedBlockVariable variable, string reason) + { + if (reason == null) { + Error_AlreadyDeclared (name, variable); + return; + } + + ParametersBlock.TopBlock.Report.Error (136, variable.Location, + "A local variable named `{0}' cannot be declared in this scope because it would give a different meaning " + + "to `{0}', which is already used in a `{1}' scope to denote something else", + name, reason); + } + + public virtual void Error_AlreadyDeclared (string name, INamedBlockVariable variable) + { + var pi = variable as ParametersBlock.ParameterInfo; + if (pi != null) { + 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); + } + } + + public virtual void Error_AlreadyDeclaredTypeParameter (string name, Location loc) + { + ParametersBlock.TopBlock.Report.Error (412, loc, + "The type parameter name `{0}' is the same as local variable or parameter name", + name); + } + + // + // It should be used by expressions which require to + // register a statement during resolve process. + // + public void AddScopeStatement (Statement s) + { + if (scope_initializers == null) + scope_initializers = new List (); + + // + // Simple recursive helper, when resolve scope initializer another + // new scope initializer can be added, this ensures it's initialized + // before existing one. For now this can happen with expression trees + // in base ctor initializer only + // + if (resolving_init_idx.HasValue) { + scope_initializers.Insert (resolving_init_idx.Value, s); + ++resolving_init_idx; + } else { + scope_initializers.Add (s); + } + } + + public void AddStatement (Statement s) + { + statements.Add (s); + } + + public int AssignableSlots { + get { + // FIXME: HACK, we don't know the block available variables count now, so set this high enough + return 4096; +// return assignable_slots; + } + } + + public LabeledStatement LookupLabel (string name) + { + return ParametersBlock.TopBlock.GetLabel (name, this); + } + + public override bool Resolve (BlockContext ec) + { + Block prev_block = ec.CurrentBlock; + bool ok = true; + + ec.CurrentBlock = this; + ec.StartFlowBranching (this); + + // + // Compiler generated scope statements + // + if (scope_initializers != null) { + for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) { + scope_initializers[resolving_init_idx.Value].Resolve (ec); + } + + resolving_init_idx = null; + } + + // + // This flag is used to notate nested statements as unreachable from the beginning of this block. + // For the purposes of this resolution, it doesn't matter that the whole block is unreachable + // from the beginning of the function. The outer Resolve() that detected the unreachability is + // responsible for handling the situation. + // + int statement_count = statements.Count; + for (int ix = 0; ix < statement_count; ix++){ + Statement s = statements [ix]; + + // + // Warn if we detect unreachable code. + // + if (unreachable) { + if (s is EmptyStatement) + continue; + + if (!unreachable_shown && !(s is LabeledStatement)) { + ec.Report.Warning (162, 2, s.loc, "Unreachable code detected"); + unreachable_shown = true; + } + + Block c_block = s as Block; + if (c_block != null) + c_block.unreachable = c_block.unreachable_shown = true; + } + + // + // Note that we're not using ResolveUnreachable() for unreachable + // statements here. ResolveUnreachable() creates a temporary + // flow branching and kills it afterwards. This leads to problems + // if you have two unreachable statements where the first one + // assigns a variable and the second one tries to access it. + // + + if (!s.Resolve (ec)) { + ok = false; + if (ec.IsInProbingMode) + break; + + statements [ix] = new EmptyStatement (s.loc); + continue; + } + + if (unreachable && !(s is LabeledStatement) && !(s is Block)) + statements [ix] = new EmptyStatement (s.loc); + + unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + if (unreachable && s is LabeledStatement) + throw new InternalErrorException ("should not happen"); + } + + while (ec.CurrentBranching is FlowBranchingLabeled) + ec.EndFlowBranching (); + + bool flow_unreachable = ec.EndFlowBranching (); + + ec.CurrentBlock = prev_block; + + if (flow_unreachable) + flags |= Flags.HasRet; + + // If we're a non-static `struct' constructor which doesn't have an + // initializer, then we must initialize all of the struct's fields. + if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable) + ok = false; + + return ok; + } + + public override bool ResolveUnreachable (BlockContext ec, bool warn) + { + unreachable_shown = true; + unreachable = true; + + if (warn) + ec.Report.Warning (162, 2, loc, "Unreachable code detected"); + + ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc); + bool ok = Resolve (ec); + ec.KillFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + for (int ix = 0; ix < statements.Count; ix++){ + statements [ix].Emit (ec); + } + } + + public override void Emit (EmitContext ec) + { + if (scope_initializers != null) + EmitScopeInitializers (ec); + + ec.Mark (StartLocation); + DoEmit (ec); + + if (SymbolWriter.HasSymbolWriter) + EmitSymbolInfo (ec); + } + + protected void EmitScopeInitializers (EmitContext ec) + { + SymbolWriter.OpenCompilerGeneratedBlock (ec); + + using (ec.With (EmitContext.Options.OmitDebugInfo, true)) { + foreach (Statement s in scope_initializers) + s.Emit (ec); + } + + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + protected virtual void EmitSymbolInfo (EmitContext ec) + { + } + +#if DEBUG + public override string ToString () + { + return String.Format ("{0} ({1}:{2})", GetType (), ID, StartLocation); + } +#endif + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Block target = (Block) t; +#if DEBUG + target.clone_id = clone_id_counter++; +#endif + + clonectx.AddBlockMap (this, target); + if (original != this) + clonectx.AddBlockMap (original, target); + + target.ParametersBlock = (ParametersBlock) (ParametersBlock == this ? target : clonectx.RemapBlockCopy (ParametersBlock)); + target.Explicit = (ExplicitBlock) (Explicit == this ? target : clonectx.LookupBlock (Explicit)); + + if (Parent != null) + target.Parent = clonectx.RemapBlockCopy (Parent); + + target.statements = new List (statements.Count); + foreach (Statement s in statements) + target.statements.Add (s.Clone (clonectx)); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class ExplicitBlock : Block + { + protected AnonymousMethodStorey am_storey; + + public ExplicitBlock (Block parent, Location start, Location end) + : this (parent, (Flags) 0, start, end) + { + } + + public ExplicitBlock (Block parent, Flags flags, Location start, Location end) + : base (parent, flags, start, end) + { + this.Explicit = this; + } + + #region Properties + + public AnonymousMethodStorey AnonymousMethodStorey { + get { + return am_storey; + } + } + + public bool HasCapturedThis { + set { flags = value ? flags | Flags.HasCapturedThis : flags & ~Flags.HasCapturedThis; } + get { + return (flags & Flags.HasCapturedThis) != 0; + } + } + + public bool HasCapturedVariable { + set { flags = value ? flags | Flags.HasCapturedVariable : flags & ~Flags.HasCapturedVariable; } + get { + return (flags & Flags.HasCapturedVariable) != 0; + } + } + + #endregion + + // + // Creates anonymous method storey in current block + // + public AnonymousMethodStorey CreateAnonymousMethodStorey (ResolveContext ec) + { + // + // An iterator has only 1 storey block + // + if (ec.CurrentIterator != null) + return ec.CurrentIterator.Storey; + + // + // When referencing a variable in iterator storey from children anonymous method + // + if (ParametersBlock.am_storey is IteratorStorey) { + return ParametersBlock.am_storey; + } + + if (am_storey == null) { + MemberBase mc = ec.MemberContext as MemberBase; + + // + // Creates anonymous method storey for this block + // + am_storey = new AnonymousMethodStorey (this, ec.CurrentMemberDefinition.Parent.PartialContainer, mc, ec.CurrentTypeParameters, "AnonStorey"); + } + + return am_storey; + } + + public override void Emit (EmitContext ec) + { + if (am_storey != null) { + DefineAnonymousStorey (ec); + am_storey.EmitStoreyInstantiation (ec, this); + } + + bool emit_debug_info = SymbolWriter.HasSymbolWriter && Parent != null && !(am_storey is IteratorStorey); + if (emit_debug_info) + ec.BeginScope (); + + base.Emit (ec); + + if (emit_debug_info) + ec.EndScope (); + } + + void DefineAnonymousStorey (EmitContext ec) + { + // + // Creates anonymous method storey + // + if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null) { + // + // Creates parent storey reference when hoisted this is accessible + // + if (am_storey.OriginalSourceBlock.Explicit.HasCapturedThis) { + ExplicitBlock parent = am_storey.OriginalSourceBlock.Explicit.Parent.Explicit; + + // + // Hoisted this exists in top-level parent storey only + // + while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey) + parent = parent.Parent.Explicit; + + am_storey.AddParentStoreyReference (ec, parent.am_storey); + } + + am_storey.SetNestedStoryParent (ec.CurrentAnonymousMethod.Storey); + + // TODO MemberCache: Review + am_storey.Mutator = ec.CurrentAnonymousMethod.Storey.Mutator; + } + + am_storey.CreateType (); + am_storey.DefineType (); + am_storey.ResolveTypeParameters (); + + var ref_blocks = am_storey.ReferencesFromChildrenBlock; + if (ref_blocks != null) { + foreach (ExplicitBlock ref_block in ref_blocks) { + for (ExplicitBlock b = ref_block.Explicit; b.am_storey != am_storey; b = b.Parent.Explicit) { + if (b.am_storey != null) { + b.am_storey.AddParentStoreyReference (ec, am_storey); + + // Stop propagation inside same top block + if (b.ParametersBlock.Original == ParametersBlock.Original) + break; + + b = b.ParametersBlock; + } + + b.HasCapturedVariable = true; + } + } + } + + am_storey.Define (); + am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey); + } + + public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock) + { + tryBlock.statements = statements; + statements = new List (1); + statements.Add (tf); + } + } + + // + // ParametersBlock was introduced to support anonymous methods + // and lambda expressions + // + public class ParametersBlock : ExplicitBlock + { + public class ParameterInfo : INamedBlockVariable + { + readonly ParametersBlock block; + readonly int index; + public VariableInfo VariableInfo; + bool is_locked; + + public ParameterInfo (ParametersBlock block, int index) + { + this.block = block; + this.index = index; + } + + #region Properties + + public Block Block { + get { + return block; + } + } + + public bool IsDeclared { + get { + return true; + } + } + + public bool IsLocked { + get { + return is_locked; + } + set { + is_locked = value; + } + } + + public Location Location { + get { + return Parameter.Location; + } + } + + public Parameter Parameter { + get { + return block.Parameters [index]; + } + } + + public TypeSpec ParameterType { + get { + return Parameter.Type; + } + } + + #endregion + + public Expression CreateReferenceExpression (ResolveContext rc, Location loc) + { + return new ParameterReference (this, loc); + } + } + + // + // Block is converted into an expression + // + sealed class BlockScopeExpression : Expression + { + Expression child; + readonly ParametersBlock block; + + public BlockScopeExpression (Expression child, ParametersBlock block) + { + this.child = child; + this.block = block; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + throw new NotSupportedException (); + } + + protected override Expression DoResolve (ResolveContext ec) + { + if (child == null) + return null; + + child = child.Resolve (ec); + if (child == null) + return null; + + eclass = child.eclass; + type = child.Type; + return this; + } + + public override void Emit (EmitContext ec) + { + block.EmitScopeInitializers (ec); + child.Emit (ec); + } + } + + protected ParametersCompiled parameters; + protected ParameterInfo[] parameter_info; + bool resolved; + protected bool unreachable; + protected ToplevelBlock top_block; + + public ParametersBlock (Block parent, ParametersCompiled parameters, Location start) + : base (parent, 0, start, start) + { + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + this.parameters = parameters; + ParametersBlock = this; + + this.top_block = parent.ParametersBlock.top_block; + ProcessParameters (); + } + + protected ParametersBlock (ParametersCompiled parameters, Location start) + : base (null, 0, start, start) + { + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + this.parameters = parameters; + ParametersBlock = this; + } + + // + // It's supposed to be used by method body implementation of anonymous methods + // + protected ParametersBlock (ParametersBlock source, ParametersCompiled parameters) + : base (null, 0, source.StartLocation, source.EndLocation) + { + this.parameters = parameters; + this.statements = source.statements; + this.scope_initializers = source.scope_initializers; + + this.resolved = true; + this.unreachable = source.unreachable; + this.am_storey = source.am_storey; + + ParametersBlock = this; + + // + // Overwrite original for comparison purposes when linking cross references + // between anonymous methods + // + original = source; + } + + #region Properties + + public bool IsAsync + { + get { + return (flags & Flags.IsAsync) != 0; + } + set { + flags = value ? flags | Flags.IsAsync : flags & ~Flags.IsAsync; + } + } + + // + // Block has been converted to expression tree + // + public bool IsExpressionTree { + get { + return (flags & Flags.IsExpressionTree) != 0; + } + } + + // + // The parameters for the block. + // + public ParametersCompiled Parameters { + get { + return parameters; + } + } + + public ToplevelBlock TopBlock { + get { + return top_block; + } + } + + public bool Resolved { + get { + return resolved; + } + } + + #endregion + + // + // Check whether all `out' parameters have been assigned. + // + public void CheckOutParameters (FlowBranching.UsageVector vector, Location loc) + { + if (vector.IsUnreachable) + return; + + int n = parameter_info == null ? 0 : parameter_info.Length; + + for (int i = 0; i < n; i++) { + VariableInfo var = parameter_info[i].VariableInfo; + + if (var == null) + continue; + + 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); + } + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + if (statements.Count == 1) { + Expression expr = ((Statement) statements[0]).CreateExpressionTree (ec); + if (scope_initializers != null) + expr = new BlockScopeExpression (expr, this); + + return expr; + } + + return base.CreateExpressionTree (ec); + } + + public ParameterInfo GetParameterInfo (Parameter p) + { + for (int i = 0; i < parameters.Count; ++i) { + if (parameters[i] == p) + return parameter_info[i]; + } + + throw new ArgumentException ("Invalid parameter"); + } + + public Expression GetParameterReference (int index, Location loc) + { + return new ParameterReference (parameter_info[index], loc); + } + + public Statement PerformClone () + { + CloneContext clonectx = new CloneContext (); + return Clone (clonectx); + } + + protected void ProcessParameters () + { + if (parameters.Count == 0) + return; + + parameter_info = new ParameterInfo[parameters.Count]; + for (int i = 0; i < parameter_info.Length; ++i) { + var p = parameters.FixedParameters[i]; + if (p == null) + continue; + + // TODO: Should use Parameter only and more block there + parameter_info[i] = new ParameterInfo (this, i); + if (p.Name != null) + AddLocalName (p.Name, parameter_info[i]); + } + } + + public bool Resolve (FlowBranching parent, BlockContext rc, IMethodData md) + { + if (resolved) + return true; + + resolved = true; + + if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion)) + flags |= Flags.IsExpressionTree; + + try { + ResolveMeta (rc); + + using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) { + FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent); + + if (!Resolve (rc)) + return false; + + unreachable = top_level.End (); + } + } catch (Exception e) { + if (e is CompletionResult || rc.Report.IsDisabled) + throw; + + if (rc.CurrentBlock != null) { + rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message); + } else { + rc.Report.Error (587, "Internal compiler error: {0}", e.Message); + } + + if (rc.Module.Compiler.Settings.DebugFlags > 0) + throw; + } + + if (rc.ReturnType.Kind != MemberKind.Void && !unreachable) { + if (rc.CurrentAnonymousMethod == null) { + // FIXME: Missing FlowAnalysis for generated iterator MoveNext method + if (md is StateMachineMethod) { + unreachable = true; + } else { + rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ()); + 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; + } + } + + return true; + } + + void ResolveMeta (BlockContext ec) + { + int orig_count = parameters.Count; + + for (int i = 0; i < orig_count; ++i) { + Parameter.Modifier mod = parameters.FixedParameters[i].ModFlags; + + if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT) + continue; + + VariableInfo vi = new VariableInfo (parameters, i, ec.FlowOffset); + parameter_info[i].VariableInfo = vi; + ec.FlowOffset += vi.Length; + } + } + + public void WrapIntoIterator (IMethodData method, TypeContainer host, TypeSpec iterator_type, bool is_enumerable) + { + ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); + pb.EndLocation = EndLocation; + pb.statements = statements; + + var iterator = new Iterator (pb, method, host, iterator_type, is_enumerable); + am_storey = new IteratorStorey (iterator); + + statements = new List (1); + AddStatement (new Return (iterator, iterator.Location)); + } + + public void WrapIntoAsyncTask (TypeContainer host, TypeSpec returnType) + { + ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); + pb.EndLocation = EndLocation; + pb.statements = statements; + + var block_type = host.Module.Compiler.BuiltinTypes.Void; + var initializer = new AsyncInitializer (pb, host, block_type); + initializer.Type = block_type; + + am_storey = new AsyncTaskStorey (initializer, returnType); + + statements = new List (1); + AddStatement (new StatementExpression (initializer)); + } + } + + // + // + // + public class ToplevelBlock : ParametersBlock + { + LocalVariable this_variable; + CompilerContext compiler; + Dictionary names; + Dictionary labels; + + public HoistedVariable HoistedThisVariable; + + public Report Report { + get { return compiler.Report; } + } + + public ToplevelBlock (CompilerContext ctx, Location loc) + : this (ctx, ParametersCompiled.EmptyReadOnlyParameters, loc) + { + } + + public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start) + : base (parameters, start) + { + this.compiler = ctx; + top_block = this; + + ProcessParameters (); + } + + // + // Recreates a top level block from parameters block. Used for + // compiler generated methods where the original block comes from + // explicit child block. This works for already resolved blocks + // only to ensure we resolve them in the correct flow order + // + public ToplevelBlock (ParametersBlock source, ParametersCompiled parameters) + : base (source, parameters) + { + this.compiler = source.TopBlock.compiler; + top_block = this; + } + + public bool IsIterator + { + get { + return (flags & Flags.IsIterator) != 0; + } + set { + flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator; + } + } + + public override void AddLocalName (string name, INamedBlockVariable li) + { + if (names == null) + names = new Dictionary (); + + object value; + if (!names.TryGetValue (name, out value)) { + names.Add (name, li); + return; + } + + INamedBlockVariable existing = value as INamedBlockVariable; + List existing_list; + if (existing != null) { + existing_list = new List (); + existing_list.Add (existing); + names[name] = existing_list; + } else { + existing_list = (List) value; + } + + // + // A collision checking between local names + // + for (int i = 0; i < existing_list.Count; ++i) { + existing = existing_list[i]; + Block b = existing.Block; + + // Collision at same level + if (li.Block == b) { + li.Block.Error_AlreadyDeclared (name, li); + break; + } + + // Collision with parent + b = li.Block; + while ((b = b.Parent) != null) { + if (existing.Block == b) { + li.Block.Error_AlreadyDeclared (name, li, "parent or current"); + i = existing_list.Count; + break; + } + } + + // Collision with with children + b = existing.Block; + while ((b = b.Parent) != null) { + if (li.Block == b) { + li.Block.Error_AlreadyDeclared (name, li, "child"); + i = existing_list.Count; + break; + } + } + } + + existing_list.Add (li); + } + + public void AddLabel (string name, LabeledStatement label) + { + if (labels == null) + labels = new Dictionary (); + + object value; + if (!labels.TryGetValue (name, out value)) { + labels.Add (name, label); + return; + } + + LabeledStatement existing = value as LabeledStatement; + List existing_list; + if (existing != null) { + existing_list = new List (); + existing_list.Add (existing); + labels[name] = existing_list; + } else { + existing_list = (List) value; + } + + // + // A collision checking between labels + // + for (int i = 0; i < existing_list.Count; ++i) { + existing = existing_list[i]; + Block b = existing.Block; + + // Collision at same level + if (label.Block == b) { + Report.SymbolRelatedToPreviousError (existing.loc, name); + Report.Error (140, label.loc, "The label `{0}' is a duplicate", name); + break; + } + + // Collision with parent + b = label.Block; + while ((b = b.Parent) != null) { + if (existing.Block == b) { + Report.Error (158, label.loc, + "The label `{0}' shadows another label by the same name in a contained scope", name); + i = existing_list.Count; + break; + } + } + + // Collision with with children + b = existing.Block; + while ((b = b.Parent) != null) { + if (label.Block == b) { + Report.Error (158, label.loc, + "The label `{0}' shadows another label by the same name in a contained scope", name); + i = existing_list.Count; + break; + } + } + } + + existing_list.Add (label); + } + + // + // Creates an arguments set from all parameters, useful for method proxy calls + // + public Arguments GetAllParametersArguments () + { + int count = parameters.Count; + Arguments args = new Arguments (count); + for (int i = 0; i < count; ++i) { + var arg_expr = GetParameterReference (i, parameter_info[i].Location); + args.Add (new Argument (arg_expr)); + } + + return args; + } + + // + // Lookup inside a block, the returned value can represent 3 states + // + // true+variable: A local name was found and it's valid + // false+variable: A local name was found in a child block only + // false+null: No local name was found + // + public bool GetLocalName (string name, Block block, ref INamedBlockVariable variable) + { + if (names == null) + return false; + + object value; + if (!names.TryGetValue (name, out value)) + return false; + + variable = value as INamedBlockVariable; + Block b = block; + if (variable != null) { + do { + if (variable.Block == b.Original) + return true; + + b = b.Parent; + } while (b != null); + + b = variable.Block; + do { + if (block == b) + return false; + + b = b.Parent; + } while (b != null); + } else { + List list = (List) value; + for (int i = 0; i < list.Count; ++i) { + variable = list[i]; + do { + if (variable.Block == b.Original) + return true; + + b = b.Parent; + } while (b != null); + + b = variable.Block; + do { + if (block == b) + return false; + + b = b.Parent; + } while (b != null); + + b = block; + } + } + + variable = null; + return false; + } + + public LabeledStatement GetLabel (string name, Block block) + { + if (labels == null) + return null; + + object value; + if (!labels.TryGetValue (name, out value)) { + return null; + } + + var label = value as LabeledStatement; + Block b = block; + if (label != null) { + if (label.Block == b.Original) + return label; + + // TODO: Temporary workaround for the switch block implicit label block + if (label.Block.IsCompilerGenerated && label.Block.Parent == b.Original) + return label; + } else { + List list = (List) value; + for (int i = 0; i < list.Count; ++i) { + label = list[i]; + if (label.Block == b.Original) + return label; + + // TODO: Temporary workaround for the switch block implicit label block + if (label.Block.IsCompilerGenerated && label.Block.Parent == b.Original) + return label; + } + } + + return null; + } + + // + // Returns the "this" instance variable of this block. + // See AddThisVariable() for more information. + // + public LocalVariable ThisVariable { + get { return this_variable; } + } + + // + // This is used by non-static `struct' constructors which do not have an + // initializer - in this case, the constructor must initialize all of the + // struct's fields. To do this, we add a "this" variable and use the flow + // analysis code to ensure that it's been fully initialized before control + // leaves the constructor. + // + public LocalVariable AddThisVariable (BlockContext bc, TypeContainer ds, Location l) + { + 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); + } + + return this_variable; + } + + public bool IsThisAssigned (BlockContext ec) + { + return this_variable == null || this_variable.IsThisAssigned (ec, this); + } + + public override void Emit (EmitContext ec) + { + if (Report.Errors > 0) + return; + +#if PRODUCTION + try { +#endif + if (ec.HasReturnLabel) + ec.ReturnLabel = ec.DefineLabel (); + + base.Emit (ec); + + ec.Mark (EndLocation); + + if (ec.HasReturnLabel) + ec.MarkLabel (ec.ReturnLabel); + + if (ec.return_value != null) { + ec.Emit (OpCodes.Ldloc, ec.return_value); + ec.Emit (OpCodes.Ret); + } else { + // + // If `HasReturnLabel' is set, then we already emitted a + // jump to the end of the method, so we must emit a `ret' + // there. + // + // Unfortunately, System.Reflection.Emit automatically emits + // a leave to the end of a finally block. This is a problem + // if no code is following the try/finally block since we may + // jump to a point after the end of the method. + // As a workaround, we're always creating a return label in + // this case. + // + + if (ec.HasReturnLabel || !unreachable) { + if (ec.ReturnType.Kind != MemberKind.Void) + ec.Emit (OpCodes.Ldloc, ec.TemporaryReturn ()); + ec.Emit (OpCodes.Ret); + } + } + +#if PRODUCTION + } catch (Exception e){ + Console.WriteLine ("Exception caught by the compiler while emitting:"); + Console.WriteLine (" Block that caused the problem begin at: " + block.loc); + + Console.WriteLine (e.GetType ().FullName + ": " + e.Message); + throw; + } +#endif + } + + protected override void EmitSymbolInfo (EmitContext ec) + { + AnonymousExpression ae = ec.CurrentAnonymousMethod; + if ((ae != null) && (ae.Storey != null)) + SymbolWriter.DefineScopeVariable (ae.Storey.ID); + + base.EmitSymbolInfo (ec); + } + } + + public class SwitchLabel { + Expression label; + Constant converted; + readonly Location loc; + + Label? il_label; + + // + // if expr == null, then it is the default case. + // + public SwitchLabel (Expression expr, Location l) + { + label = expr; + loc = l; + } + + public bool IsDefault { + get { + return label == null; + } + } + + public Expression Label { + get { + return label; + } + } + + public Location Location { + get { + return loc; + } + } + + public Constant Converted { + get { + return converted; + } + set { + converted = value; + } + } + + public Label GetILLabel (EmitContext ec) + { + if (il_label == null){ + il_label = ec.DefineLabel (); + } + + return il_label.Value; + } + + // + // Resolves the expression, reduces it to a literal if possible + // and then converts it to the requested type. + // + public bool ResolveAndReduce (ResolveContext ec, TypeSpec required_type, bool allow_nullable) + { + Expression e = label.Resolve (ec); + + if (e == null) + return false; + + Constant c = e as Constant; + if (c == null){ + ec.Report.Error (150, loc, "A constant value is expected"); + return false; + } + + if (allow_nullable && c is NullLiteral) { + converted = c; + return true; + } + + converted = c.ImplicitConversionRequired (ec, required_type, loc); + return converted != null; + } + + public void Error_AlreadyOccurs (ResolveContext ec, TypeSpec switch_type, SwitchLabel collision_with) + { + string label; + if (converted == null) + label = "default"; + else + label = converted.GetValueAsLiteral (); + + ec.Report.SymbolRelatedToPreviousError (collision_with.loc, null); + ec.Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label); + } + + public SwitchLabel Clone (CloneContext clonectx) + { + if (label == null) + return this; + + return new SwitchLabel (label.Clone (clonectx), loc); + } + } + + public class SwitchSection { + public readonly List Labels; + public readonly Block Block; + + public SwitchSection (List labels, Block block) + { + Labels = labels; + Block = block; + } + + public SwitchSection Clone (CloneContext clonectx) + { + var cloned_labels = new List (); + + foreach (SwitchLabel sl in Labels) + cloned_labels.Add (sl.Clone (clonectx)); + + return new SwitchSection (cloned_labels, clonectx.LookupBlock (Block)); + } + } + + public class Switch : Statement + { + // structure used to hold blocks of keys while calculating table switch + sealed class LabelsRange : IComparable + { + public readonly long min; + public long max; + public readonly List label_values; + + public LabelsRange (long value) + { + min = max = value; + label_values = new List (); + label_values.Add (value); + } + + public LabelsRange (long min, long max, ICollection values) + { + this.min = min; + this.max = max; + this.label_values = new List (values); + } + + public long Range { + get { + return max - min + 1; + } + } + + public bool AddValue (long value) + { + var gap = value - min + 1; + // Ensure the range has > 50% occupancy + if (gap > 2 * (label_values.Count + 1) || gap <= 0) + return false; + + max = value; + label_values.Add (value); + return true; + } + + public int CompareTo (LabelsRange other) + { + int nLength = label_values.Count; + int nLengthOther = other.label_values.Count; + if (nLengthOther == nLength) + return (int) (other.min - min); + + return nLength - nLengthOther; + } + } + + public List Sections; + public Expression Expr; + + // + // Mapping of all labels to their SwitchLabels + // + Dictionary labels; + Dictionary string_labels; + + /// + /// The governing switch type + /// + public TypeSpec SwitchType; + + // + // Computed + // + Label default_target; + Label null_target; + Expression new_expr; + bool is_constant; + + SwitchSection constant_section; + SwitchSection default_section; + SwitchLabel null_section; + + ExpressionStatement string_dictionary; + FieldExpr switch_cache_field; + static int unique_counter; + ExplicitBlock block; + + // + // Nullable Types support + // + Nullable.Unwrap unwrap; + + public Switch (Expression e, ExplicitBlock block, List sects, Location l) + { + Expr = e; + this.block = block; + Sections = sects; + loc = l; + } + + public ExplicitBlock Block { + get { + return block; + } + } + + public Label DefaultLabel { + get { + return default_target; + } + } + + public bool GotDefault { + get { + return default_section != null; + } + } + + public bool IsNullable { + get { + return unwrap != null; + } + } + + // + // Determines the governing type for a switch. The returned + // expression might be the expression from the switch, or an + // expression that includes any potential conversions to + // + Expression SwitchGoverningType (ResolveContext ec, Expression expr) + { + switch (expr.Type.BuiltinType) { + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.String: + case BuiltinTypeSpec.Type.Bool: + return expr; + } + + if (expr.Type.IsEnum) + return expr; + + // + // Try to find a *user* defined implicit conversion. + // + // If there is no implicit conversion, or if there are multiple + // conversions, we have to report an error + // + Expression converted = null; + foreach (TypeSpec tt in ec.BuiltinTypes.SwitchUserTypes) { + Expression e; + + e = Convert.ImplicitUserConversion (ec, expr, tt, loc); + if (e == null) + continue; + + // + // Ignore over-worked ImplicitUserConversions that do + // an implicit conversion in addition to the user conversion. + // + if (!(e is UserCast)) + continue; + + if (converted != null){ + ec.Report.ExtraInformation (loc, "(Ambiguous implicit user defined conversion in previous "); + return null; + } + + converted = e; + } + return converted; + } + + public static TypeSpec[] CreateSwitchUserTypes (BuiltinTypes types) + { + // LAMESPEC: For some reason it does not contain bool which looks like csc bug + return new[] { + types.SByte, + types.Byte, + types.Short, + types.UShort, + types.Int, + types.UInt, + types.Long, + types.ULong, + types.Char, + types.String + }; + } + + // + // Performs the basic sanity checks on the switch statement + // (looks for duplicate keys and non-constant expressions). + // + // It also returns a hashtable with the keys that we will later + // use to compute the switch tables + // + bool CheckSwitch (ResolveContext ec) + { + bool error = false; + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String) + string_labels = new Dictionary (Sections.Count + 1); + else + labels = new Dictionary (Sections.Count + 1); + + foreach (SwitchSection ss in Sections){ + foreach (SwitchLabel sl in ss.Labels){ + if (sl.IsDefault){ + if (default_section != null){ + sl.Error_AlreadyOccurs (ec, SwitchType, default_section.Labels [0]); + error = true; + } + default_section = ss; + continue; + } + + if (!sl.ResolveAndReduce (ec, SwitchType, IsNullable)) { + error = true; + continue; + } + + try { + if (string_labels != null) { + string s = sl.Converted.GetValue () as string; + if (s == null) + null_section = sl; + else + string_labels.Add (s, sl); + } else { + if (sl.Converted is NullLiteral) { + null_section = sl; + } else { + labels.Add (sl.Converted.GetValueAsLong (), sl); + } + } + } catch (ArgumentException) { + if (string_labels != null) + sl.Error_AlreadyOccurs (ec, SwitchType, string_labels[(string) sl.Converted.GetValue ()]); + else + sl.Error_AlreadyOccurs (ec, SwitchType, labels[sl.Converted.GetValueAsLong ()]); + + error = true; + } + } + } + return !error; + } + + // + // This method emits code for a lookup-based switch statement (non-string) + // Basically it groups the cases into blocks that are at least half full, + // and then spits out individual lookup opcodes for each block. + // It emits the longest blocks first, and short blocks are just + // handled with direct compares. + // + void EmitTableSwitch (EmitContext ec, Expression val) + { + Label lbl_default = default_target; + + if (labels.Count > 0) { + List ranges; + if (string_labels != null) { + // We have done all hard work for string already + // setup single range only + ranges = new List (1); + ranges.Add (new LabelsRange (0, labels.Count - 1, labels.Keys)); + } else { + var element_keys = new long[labels.Count]; + labels.Keys.CopyTo (element_keys, 0); + Array.Sort (element_keys); + + // + // Build possible ranges of switch labes to reduce number + // of comparisons + // + ranges = new List (element_keys.Length); + var range = new LabelsRange (element_keys[0]); + ranges.Add (range); + for (int i = 1; i < element_keys.Length; ++i) { + var l = element_keys[i]; + if (range.AddValue (l)) + continue; + + range = new LabelsRange (l); + ranges.Add (range); + } + + // sort the blocks so we can tackle the largest ones first + ranges.Sort (); + } + + TypeSpec compare_type = TypeManager.IsEnumType (SwitchType) ? EnumSpec.GetUnderlyingType (SwitchType) : SwitchType; + + for (int range_index = ranges.Count - 1; range_index >= 0; --range_index) { + LabelsRange kb = ranges[range_index]; + lbl_default = (range_index == 0) ? default_target : ec.DefineLabel (); + + // Optimize small ranges using simple equality check + if (kb.Range <= 2) { + foreach (var key in kb.label_values) { + SwitchLabel sl = labels[key]; + if (sl.Converted.IsDefaultValue) { + val.EmitBranchable (ec, sl.GetILLabel (ec), false); + } else { + val.Emit (ec); + sl.Converted.Emit (ec); + ec.Emit (OpCodes.Beq, sl.GetILLabel (ec)); + } + } + } else { + // TODO: if all the keys in the block are the same and there are + // no gaps/defaults then just use a range-check. + if (compare_type.BuiltinType == BuiltinTypeSpec.Type.Long || compare_type.BuiltinType == BuiltinTypeSpec.Type.ULong) { + // TODO: optimize constant/I4 cases + + // check block range (could be > 2^31) + val.Emit (ec); + ec.EmitLong (kb.min); + ec.Emit (OpCodes.Blt, lbl_default); + + val.Emit (ec); + ec.EmitLong (kb.max); + ec.Emit (OpCodes.Bgt, lbl_default); + + // normalize range + val.Emit (ec); + if (kb.min != 0) { + ec.EmitLong (kb.min); + ec.Emit (OpCodes.Sub); + } + + ec.Emit (OpCodes.Conv_I4); // assumes < 2^31 labels! + } else { + // normalize range + val.Emit (ec); + int first = (int) kb.min; + if (first > 0) { + ec.EmitInt (first); + ec.Emit (OpCodes.Sub); + } else if (first < 0) { + ec.EmitInt (-first); + ec.Emit (OpCodes.Add); + } + } + + // first, build the list of labels for the switch + int iKey = 0; + long cJumps = kb.Range; + Label[] switch_labels = new Label[cJumps]; + for (int iJump = 0; iJump < cJumps; iJump++) { + var key = kb.label_values[iKey]; + if (key == kb.min + iJump) { + switch_labels[iJump] = labels[key].GetILLabel (ec); + iKey++; + } else { + switch_labels[iJump] = lbl_default; + } + } + + // emit the switch opcode + ec.Emit (OpCodes.Switch, switch_labels); + } + + // mark the default for this block + if (range_index != 0) + ec.MarkLabel (lbl_default); + } + + // the last default just goes to the end + if (ranges.Count > 0) + ec.Emit (OpCodes.Br, lbl_default); + } + + // now emit the code for the sections + bool found_default = false; + + foreach (SwitchSection ss in Sections) { + foreach (SwitchLabel sl in ss.Labels) { + if (sl.IsDefault) { + ec.MarkLabel (lbl_default); + found_default = true; + if (null_section == null) + ec.MarkLabel (null_target); + } else if (sl.Converted.IsNull) { + ec.MarkLabel (null_target); + } + + ec.MarkLabel (sl.GetILLabel (ec)); + } + + ss.Block.Emit (ec); + } + + if (!found_default) { + ec.MarkLabel (lbl_default); + if (null_section == null) { + ec.MarkLabel (null_target); + } + } + } + + SwitchLabel FindLabel (Constant value) + { + SwitchLabel sl = null; + + if (string_labels != null) { + string s = value.GetValue () as string; + if (s == null) { + if (null_section != null) + sl = null_section; + else if (default_section != null) + sl = default_section.Labels[0]; + } else { + string_labels.TryGetValue (s, out sl); + } + } else { + if (value is NullLiteral) { + sl = null_section; + } else { + labels.TryGetValue (value.GetValueAsLong (), out sl); + } + } + + return sl; + } + + SwitchSection FindSection (SwitchLabel label) + { + foreach (SwitchSection ss in Sections){ + foreach (SwitchLabel sl in ss.Labels){ + if (label == sl) + return ss; + } + } + + return null; + } + + public static void Reset () + { + unique_counter = 0; + } + + public override bool Resolve (BlockContext ec) + { + Expr = Expr.Resolve (ec); + if (Expr == null) + return false; + + new_expr = SwitchGoverningType (ec, Expr); + + if (new_expr == null && Expr.Type.IsNullableType) { + unwrap = Nullable.Unwrap.Create (Expr, false); + if (unwrap == null) + return false; + + new_expr = SwitchGoverningType (ec, unwrap); + } + + if (new_expr == null){ + ec.Report.Error (151, loc, + "A switch expression of type `{0}' cannot be converted to an integral type, bool, char, string, enum or nullable type", + TypeManager.CSharpName (Expr.Type)); + return false; + } + + // Validate switch. + SwitchType = new_expr.Type; + + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.Bool && ec.Module.Compiler.Settings.Version == LanguageVersion.ISO_1) { + ec.Report.FeatureIsNotAvailable (ec.Module.Compiler, loc, "switch expression of boolean type"); + return false; + } + + if (!CheckSwitch (ec)) + return false; + + Switch old_switch = ec.Switch; + ec.Switch = this; + ec.Switch.SwitchType = SwitchType; + + ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc); + + var constant = new_expr as Constant; + if (constant != null) { + is_constant = true; + SwitchLabel label = FindLabel (constant); + if (label != null) + constant_section = FindSection (label); + + if (constant_section == null) + constant_section = default_section; + } + + bool first = true; + bool ok = true; + foreach (SwitchSection ss in Sections){ + if (!first) + ec.CurrentBranching.CreateSibling ( + null, FlowBranching.SiblingType.SwitchSection); + else + first = false; + + if (is_constant && (ss != constant_section)) { + // If we're a constant switch, we're only emitting + // one single section - mark all the others as + // unreachable. + ec.CurrentBranching.CurrentUsageVector.Goto (); + if (!ss.Block.ResolveUnreachable (ec, true)) { + ok = false; + } + } else { + if (!ss.Block.Resolve (ec)) + ok = false; + } + } + + if (default_section == null) + ec.CurrentBranching.CreateSibling ( + null, FlowBranching.SiblingType.SwitchSection); + + ec.EndFlowBranching (); + ec.Switch = old_switch; + + if (!ok) + return false; + + if (SwitchType.BuiltinType == BuiltinTypeSpec.Type.String && !is_constant) { + // TODO: Optimize single case, and single+default case + ResolveStringSwitchMap (ec); + } + + return true; + } + + public SwitchLabel ResolveGotoCase (ResolveContext rc, Constant value) + { + var sl = FindLabel (value); + + if (sl == null) { + FlowBranchingBlock.Error_UnknownLabel (loc, "case " + value.GetValueAsLiteral (), rc.Report); + } + + return sl; + } + + void ResolveStringSwitchMap (ResolveContext ec) + { + FullNamedExpression string_dictionary_type; + if (ec.Module.PredefinedTypes.Dictionary.Define ()) { + string_dictionary_type = new TypeExpression ( + ec.Module.PredefinedTypes.Dictionary.TypeSpec.MakeGenericType (ec, + new [] { ec.BuiltinTypes.String, ec.BuiltinTypes.Int }), + loc); + } else if (ec.Module.PredefinedTypes.Hashtable.Define ()) { + string_dictionary_type = new TypeExpression (ec.Module.PredefinedTypes.Hashtable.TypeSpec, loc); + } else { + ec.Module.PredefinedTypes.Dictionary.Resolve (); + return; + } + + var ctype = ec.CurrentMemberDefinition.Parent.PartialContainer; + Field field = new Field (ctype, string_dictionary_type, + Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, + new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null); + if (!field.Define ()) + return; + ctype.AddField (field); + + var init = new List (); + int counter = 0; + labels = new Dictionary (string_labels.Count); + string value = null; + foreach (SwitchSection section in Sections) { + bool contains_label = false; + foreach (SwitchLabel sl in section.Labels) { + if (sl.IsDefault || sl.Converted.IsNull) + continue; + + if (!contains_label) { + labels.Add (counter, sl); + contains_label = true; + } + + value = (string) sl.Converted.GetValue (); + var init_args = new List (2); + init_args.Add (new StringLiteral (ec.BuiltinTypes, value, sl.Location)); + + sl.Converted = new IntConstant (ec.BuiltinTypes, counter, loc); + init_args.Add (sl.Converted); + + init.Add (new CollectionElementInitializer (init_args, loc)); + } + + // + // Don't add empty sections + // + if (contains_label) + ++counter; + } + + Arguments args = new Arguments (1); + args.Add (new Argument (new IntConstant (ec.BuiltinTypes, init.Count, loc))); + Expression initializer = new NewInitialize (string_dictionary_type, args, + new CollectionOrObjectInitializers (init, loc), loc); + + switch_cache_field = new FieldExpr (field, loc); + string_dictionary = new SimpleAssign (switch_cache_field, initializer.Resolve (ec)); + } + + void DoEmitStringSwitch (LocalTemporary value, EmitContext ec) + { + Label l_initialized = ec.DefineLabel (); + + // + // Skip initialization when value is null + // + value.EmitBranchable (ec, null_target, false); + + // + // Check if string dictionary is initialized and initialize + // + switch_cache_field.EmitBranchable (ec, l_initialized, true); + string_dictionary.EmitStatement (ec); + ec.MarkLabel (l_initialized); + + LocalTemporary string_switch_variable = new LocalTemporary (ec.BuiltinTypes.Int); + + ResolveContext rc = new ResolveContext (ec.MemberContext); + + if (switch_cache_field.Type.IsGeneric) { + Arguments get_value_args = new Arguments (2); + get_value_args.Add (new Argument (value)); + get_value_args.Add (new Argument (string_switch_variable, Argument.AType.Out)); + Expression get_item = new Invocation (new MemberAccess (switch_cache_field, "TryGetValue", loc), get_value_args).Resolve (rc); + if (get_item == null) + return; + + // + // A value was not found, go to default case + // + get_item.EmitBranchable (ec, default_target, false); + } else { + Arguments get_value_args = new Arguments (1); + get_value_args.Add (new Argument (value)); + + Expression get_item = new ElementAccess (switch_cache_field, get_value_args, loc).Resolve (rc); + if (get_item == null) + return; + + LocalTemporary get_item_object = new LocalTemporary (ec.BuiltinTypes.Object); + get_item_object.EmitAssign (ec, get_item, true, false); + ec.Emit (OpCodes.Brfalse, default_target); + + ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable, + new Cast (new TypeExpression (ec.BuiltinTypes.Int, loc), get_item_object, loc)).Resolve (rc); + + get_item_int.EmitStatement (ec); + get_item_object.Release (ec); + } + + EmitTableSwitch (ec, string_switch_variable); + string_switch_variable.Release (ec); + } + + protected override void DoEmit (EmitContext ec) + { + // + // Needed to emit anonymous storey initialization + // Otherwise it does not contain any statements for now + // + block.Emit (ec); + + 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; + + // + // Setup the codegen context + // + Label old_end = ec.LoopEnd; + Switch old_switch = ec.Switch; + + ec.LoopEnd = ec.DefineLabel (); + ec.Switch = this; + + // Emit Code. + if (is_constant) { + if (constant_section != null) + constant_section.Block.Emit (ec); + } else if (string_dictionary != null) { + DoEmitStringSwitch (value, ec); + } else { + EmitTableSwitch (ec, value); + } + + if (value != null) + value.Release (ec); + + // Restore context state. + ec.MarkLabel (ec.LoopEnd); + + // + // Restore the previous context + // + ec.LoopEnd = old_end; + ec.Switch = old_switch; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Switch target = (Switch) t; + + target.Expr = Expr.Clone (clonectx); + target.Sections = new List (); + foreach (SwitchSection ss in Sections){ + target.Sections.Add (ss.Clone (clonectx)); + } + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // A place where execution can restart in an iterator + public abstract class ResumableStatement : Statement + { + bool prepared; + protected Label resume_point; + + public Label PrepareForEmit (EmitContext ec) + { + if (!prepared) { + prepared = true; + resume_point = ec.DefineLabel (); + } + return resume_point; + } + + public virtual Label PrepareForDispose (EmitContext ec, Label end) + { + return end; + } + + public virtual void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end, bool have_dispatcher) + { + } + } + + // Base class for statements that are implemented in terms of try...finally + public abstract class ExceptionStatement : ResumableStatement + { + bool code_follows; + Iterator iter; + List resume_points; + int first_resume_pc; + protected Statement stmt; + Label dispose_try_block; + bool prepared_for_dispose, emitted_dispose; + + protected ExceptionStatement (Statement stmt, Location loc) + { + this.stmt = stmt; + this.loc = loc; + } + + #region Properties + + public Statement Statement { + get { + return stmt; + } + } + + #endregion + + protected abstract void EmitPreTryBody (EmitContext ec); + protected abstract void EmitTryBody (EmitContext ec); + protected abstract void EmitFinallyBody (EmitContext ec); + + protected sealed override void DoEmit (EmitContext ec) + { + EmitPreTryBody (ec); + + if (resume_points != null) { + ec.EmitInt ((int) IteratorStorey.State.Running); + ec.Emit (OpCodes.Stloc, iter.CurrentPC); + } + + ec.BeginExceptionBlock (); + + if (resume_points != null) { + ec.MarkLabel (resume_point); + + // For normal control flow, we want to fall-through the Switch + // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above + ec.Emit (OpCodes.Ldloc, iter.CurrentPC); + ec.EmitInt (first_resume_pc); + ec.Emit (OpCodes.Sub); + + Label [] labels = new Label [resume_points.Count]; + for (int i = 0; i < resume_points.Count; ++i) + labels [i] = resume_points [i].PrepareForEmit (ec); + ec.Emit (OpCodes.Switch, labels); + } + + EmitTryBody (ec); + + ec.BeginFinallyBlock (); + + Label start_finally = ec.DefineLabel (); + if (resume_points != null) { + ec.Emit (OpCodes.Ldloc, iter.SkipFinally); + ec.Emit (OpCodes.Brfalse_S, start_finally); + ec.Emit (OpCodes.Endfinally); + } + + ec.MarkLabel (start_finally); + EmitFinallyBody (ec); + + ec.EndExceptionBlock (); + } + + public void SomeCodeFollows () + { + code_follows = true; + } + + public override bool Resolve (BlockContext ec) + { + // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause + // So, ensure there's some IL code after this statement. + if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) + ec.NeedReturnLabel (); + + iter = ec.CurrentIterator; + return true; + } + + public void AddResumePoint (ResumableStatement stmt, int pc) + { + if (resume_points == null) { + resume_points = new List (); + first_resume_pc = pc; + } + + if (pc != first_resume_pc + resume_points.Count) + throw new InternalErrorException ("missed an intervening AddResumePoint?"); + + resume_points.Add (stmt); + } + + public override Label PrepareForDispose (EmitContext ec, Label end) + { + if (!prepared_for_dispose) { + prepared_for_dispose = true; + dispose_try_block = ec.DefineLabel (); + } + return dispose_try_block; + } + + public override void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end, bool have_dispatcher) + { + if (emitted_dispose) + return; + + emitted_dispose = true; + + Label end_of_try = ec.DefineLabel (); + + // Ensure that the only way we can get into this code is through a dispatcher + if (have_dispatcher) + ec.Emit (OpCodes.Br, end); + + ec.BeginExceptionBlock (); + + ec.MarkLabel (dispose_try_block); + + Label [] labels = null; + for (int i = 0; i < resume_points.Count; ++i) { + ResumableStatement s = resume_points [i]; + Label ret = s.PrepareForDispose (ec, end_of_try); + if (ret.Equals (end_of_try) && labels == null) + continue; + if (labels == null) { + labels = new Label [resume_points.Count]; + for (int j = 0; j < i; ++j) + labels [j] = end_of_try; + } + labels [i] = ret; + } + + if (labels != null) { + int j; + for (j = 1; j < labels.Length; ++j) + if (!labels [0].Equals (labels [j])) + break; + bool emit_dispatcher = j < labels.Length; + + if (emit_dispatcher) { + //SymbolWriter.StartIteratorDispatcher (ec.ig); + ec.Emit (OpCodes.Ldloc, pc); + ec.EmitInt (first_resume_pc); + ec.Emit (OpCodes.Sub); + ec.Emit (OpCodes.Switch, labels); + //SymbolWriter.EndIteratorDispatcher (ec.ig); + } + + foreach (ResumableStatement s in resume_points) + s.EmitForDispose (ec, pc, end_of_try, emit_dispatcher); + } + + ec.MarkLabel (end_of_try); + + ec.BeginFinallyBlock (); + + EmitFinallyBody (ec); + + ec.EndExceptionBlock (); + } + } + + public class Lock : ExceptionStatement + { + Expression expr; + TemporaryVariableReference expr_copy; + TemporaryVariableReference lock_taken; + + public Lock (Expression expr, Statement stmt, Location loc) + : base (stmt, loc) + { + this.expr = expr; + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return false; + + if (!TypeSpec.IsReferenceType (expr.Type)) { + ec.Report.Error (185, loc, + "`{0}' is not a reference type as required by the lock statement", + expr.Type.GetSignatureForError ()); + } + + if (expr.Type.IsGenericParameter) { + expr = Convert.ImplicitTypeParameterConversion (expr, (TypeParameterSpec)expr.Type, ec.BuiltinTypes.Object); + } + + VariableReference lv = expr as VariableReference; + bool locked; + if (lv != null) { + locked = lv.IsLockedByStatement; + lv.IsLockedByStatement = true; + } else { + lv = null; + locked = false; + } + + using (ec.Set (ResolveContext.Options.LockScope)) { + ec.StartFlowBranching (this); + Statement.Resolve (ec); + ec.EndFlowBranching (); + } + + if (lv != null) { + lv.IsLockedByStatement = locked; + } + + base.Resolve (ec); + + // + // Have to keep original lock value around to unlock same location + // in the case the original has changed or is null + // + expr_copy = TemporaryVariableReference.Create (ec.BuiltinTypes.Object, ec.CurrentBlock.Parent, loc); + expr_copy.Resolve (ec); + + // + // Ensure Monitor methods are available + // + if (ResolvePredefinedMethods (ec) > 1) { + lock_taken = TemporaryVariableReference.Create (ec.BuiltinTypes.Bool, ec.CurrentBlock.Parent, loc); + lock_taken.Resolve (ec); + } + + return true; + } + + protected override void EmitPreTryBody (EmitContext ec) + { + expr_copy.EmitAssign (ec, expr); + + if (lock_taken != null) { + // + // Initialize ref variable + // + lock_taken.EmitAssign (ec, new BoolLiteral (ec.BuiltinTypes, false, loc)); + } else { + // + // Monitor.Enter (expr_copy) + // + expr_copy.Emit (ec); + ec.Emit (OpCodes.Call, ec.Module.PredefinedMembers.MonitorEnter.Get ()); + } + } + + protected override void EmitTryBody (EmitContext ec) + { + // + // Monitor.Enter (expr_copy, ref lock_taken) + // + if (lock_taken != null) { + expr_copy.Emit (ec); + lock_taken.LocalInfo.CreateBuilder (ec); + lock_taken.AddressOf (ec, AddressOp.Load); + ec.Emit (OpCodes.Call, ec.Module.PredefinedMembers.MonitorEnter_v4.Get ()); + } + + Statement.Emit (ec); + } + + protected override void EmitFinallyBody (EmitContext ec) + { + // + // if (lock_taken) Monitor.Exit (expr_copy) + // + Label skip = ec.DefineLabel (); + + if (lock_taken != null) { + lock_taken.Emit (ec); + ec.Emit (OpCodes.Brfalse_S, skip); + } + + expr_copy.Emit (ec); + var m = ec.Module.PredefinedMembers.MonitorExit.Resolve (loc); + if (m != null) + ec.Emit (OpCodes.Call, m); + + ec.MarkLabel (skip); + } + + int ResolvePredefinedMethods (ResolveContext rc) + { + // Try 4.0 Monitor.Enter (object, ref bool) overload first + var m = rc.Module.PredefinedMembers.MonitorEnter_v4.Get (); + if (m != null) + return 4; + + m = rc.Module.PredefinedMembers.MonitorEnter.Get (); + if (m != null) + return 1; + + rc.Module.PredefinedMembers.MonitorEnter_v4.Resolve (loc); + return 0; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Lock target = (Lock) t; + + target.expr = expr.Clone (clonectx); + target.stmt = Statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + + } + + public class Unchecked : Statement { + public Block Block; + + public Unchecked (Block b, Location loc) + { + Block = b; + b.Unchecked = true; + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, false)) + return Block.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + Block.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Unchecked target = (Unchecked) t; + + target.Block = clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Checked : Statement { + public Block Block; + + public Checked (Block b, Location loc) + { + Block = b; + b.Unchecked = false; + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + using (ec.With (ResolveContext.Options.AllCheckStateFlags, true)) + return Block.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + Block.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Checked target = (Checked) t; + + target.Block = clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Unsafe : Statement { + public Block Block; + + public Unsafe (Block b, Location loc) + { + Block = b; + Block.Unsafe = true; + this.loc = loc; + } + + public override bool Resolve (BlockContext ec) + { + if (ec.CurrentIterator != null) + ec.Report.Error (1629, loc, "Unsafe code may not appear in iterators"); + + using (ec.Set (ResolveContext.Options.UnsafeScope)) + return Block.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + Block.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Unsafe target = (Unsafe) t; + + target.Block = clonectx.LookupBlock (Block); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + // + // Fixed statement + // + public class Fixed : Statement + { + abstract class Emitter : ShimExpression + { + protected LocalVariable vi; + + protected Emitter (Expression expr, LocalVariable li) + : base (expr) + { + vi = li; + } + + public abstract void EmitExit (EmitContext ec); + } + + class ExpressionEmitter : Emitter { + public ExpressionEmitter (Expression converted, LocalVariable li) : + base (converted, li) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + throw new NotImplementedException (); + } + + public override void Emit (EmitContext ec) { + // + // Store pointer in pinned location + // + expr.Emit (ec); + vi.EmitAssign (ec); + } + + public override void EmitExit (EmitContext ec) + { + ec.Emit (OpCodes.Ldc_I4_0); + ec.Emit (OpCodes.Conv_U); + vi.EmitAssign (ec); + } + } + + class StringEmitter : Emitter + { + LocalVariable pinned_string; + + public StringEmitter (Expression expr, LocalVariable li, Location loc) + : base (expr, li) + { + } + + protected override Expression DoResolve (ResolveContext rc) + { + pinned_string = new LocalVariable (vi.Block, "$pinned", + LocalVariable.Flags.FixedVariable | LocalVariable.Flags.CompilerGenerated | LocalVariable.Flags.Used, + vi.Location); + pinned_string.Type = rc.BuiltinTypes.String; + + eclass = ExprClass.Variable; + type = rc.BuiltinTypes.Int; + return this; + } + + public override void Emit (EmitContext ec) + { + pinned_string.CreateBuilder (ec); + + expr.Emit (ec); + pinned_string.EmitAssign (ec); + + // TODO: Should use Binary::Add + pinned_string.Emit (ec); + ec.Emit (OpCodes.Conv_I); + + var m = ec.Module.PredefinedMembers.RuntimeHelpersOffsetToStringData.Resolve (loc); + if (m == null) + return; + + PropertyExpr pe = new PropertyExpr (m, pinned_string.Location); + //pe.InstanceExpression = pinned_string; + pe.Resolve (new ResolveContext (ec.MemberContext)).Emit (ec); + + ec.Emit (OpCodes.Add); + vi.EmitAssign (ec); + } + + public override void EmitExit (EmitContext ec) + { + ec.Emit (OpCodes.Ldnull); + pinned_string.EmitAssign (ec); + } + } + + + public class VariableDeclaration : BlockVariableDeclaration + { + public VariableDeclaration (FullNamedExpression type, LocalVariable li) + : base (type, li) + { + } + + protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + if (!Variable.Type.IsPointer && li == Variable) { + bc.Report.Error (209, TypeExpression.Location, + "The type of locals declared in a fixed statement must be a pointer type"); + return null; + } + + // + // The rules for the possible declarators are pretty wise, + // but the production on the grammar is more concise. + // + // So we have to enforce these rules here. + // + // We do not resolve before doing the case 1 test, + // because the grammar is explicit in that the token & + // is present, so we need to test for this particular case. + // + + if (initializer is Cast) { + bc.Report.Error (254, initializer.Location, "The right hand side of a fixed statement assignment may not be a cast expression"); + return null; + } + + initializer = initializer.Resolve (bc); + + if (initializer == null) + return null; + + // + // Case 1: Array + // + if (initializer.Type.IsArray) { + TypeSpec array_type = TypeManager.GetElementType (initializer.Type); + + // + // Provided that array_type is unmanaged, + // + if (!TypeManager.VerifyUnmanaged (bc.Module, array_type, loc)) + return null; + + // + // and T* is implicitly convertible to the + // pointer type given in the fixed statement. + // + ArrayPtr array_ptr = new ArrayPtr (initializer, array_type, loc); + + Expression converted = Convert.ImplicitConversionRequired (bc, array_ptr.Resolve (bc), li.Type, loc); + if (converted == null) + return null; + + // + // fixed (T* e_ptr = (e == null || e.Length == 0) ? null : converted [0]) + // + converted = new Conditional (new BooleanExpression (new Binary (Binary.Operator.LogicalOr, + new Binary (Binary.Operator.Equality, initializer, new NullLiteral (loc), loc), + new Binary (Binary.Operator.Equality, new MemberAccess (initializer, "Length"), new IntConstant (bc.BuiltinTypes, 0, loc), loc), loc)), + new NullLiteral (loc), + converted, loc); + + converted = converted.Resolve (bc); + + return new ExpressionEmitter (converted, li); + } + + // + // Case 2: string + // + if (initializer.Type.BuiltinType == BuiltinTypeSpec.Type.String) { + return new StringEmitter (initializer, li, loc).Resolve (bc); + } + + // Case 3: fixed buffer + if (initializer is FixedBufferPtr) { + return new ExpressionEmitter (initializer, li); + } + + // + // Case 4: & object. + // + bool already_fixed = true; + Unary u = initializer as Unary; + if (u != null && u.Oper == Unary.Operator.AddressOf) { + IVariableReference vr = u.Expr as IVariableReference; + if (vr == null || !vr.IsFixed) { + already_fixed = false; + } + } + + if (already_fixed) { + bc.Report.Error (213, loc, "You cannot use the fixed statement to take the address of an already fixed expression"); + } + + initializer = Convert.ImplicitConversionRequired (bc, initializer, li.Type, loc); + return new ExpressionEmitter (initializer, li); + } + } + + + VariableDeclaration decl; + Statement statement; + bool has_ret; + + public Fixed (VariableDeclaration decl, Statement stmt, Location l) + { + this.decl = decl; + statement = stmt; + loc = l; + } + + #region Properties + + public Statement Statement { + get { + return statement; + } + } + + public BlockVariableDeclaration Variables { + get { + return decl; + } + } + + #endregion + + public override bool Resolve (BlockContext ec) + { + using (ec.Set (ResolveContext.Options.FixedInitializerScope)) { + if (!decl.Resolve (ec)) + return false; + } + + ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc); + bool ok = statement.Resolve (ec); + bool flow_unreachable = ec.EndFlowBranching (); + has_ret = flow_unreachable; + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + decl.Variable.CreateBuilder (ec); + decl.Initializer.Emit (ec); + if (decl.Declarators != null) { + foreach (var d in decl.Declarators) { + d.Variable.CreateBuilder (ec); + d.Initializer.Emit (ec); + } + } + + statement.Emit (ec); + + if (has_ret) + return; + + // + // Clear the pinned variable + // + ((Emitter) decl.Initializer).EmitExit (ec); + if (decl.Declarators != null) { + foreach (var d in decl.Declarators) { + ((Emitter)d.Initializer).EmitExit (ec); + } + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Fixed target = (Fixed) t; + + target.decl = (VariableDeclaration) decl.Clone (clonectx); + target.statement = statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Catch : Statement + { + Block block; + LocalVariable li; + FullNamedExpression type_expr; + CompilerAssign assign; + TypeSpec type; + + public Catch (Block block, Location loc) + { + this.block = block; + this.loc = loc; + } + + #region Properties + + public Block Block { + get { + return block; + } + } + + public TypeSpec CatchType { + get { + return type; + } + } + + public bool IsGeneral { + get { + return type_expr == null; + } + } + + public FullNamedExpression TypeExpression { + get { + return type_expr; + } + set { + type_expr = value; + } + } + + public LocalVariable Variable { + get { + return li; + } + set { + li = value; + } + } + + #endregion + + protected override void DoEmit (EmitContext ec) + { + if (IsGeneral) + ec.BeginCatchBlock (ec.BuiltinTypes.Object); + else + ec.BeginCatchBlock (CatchType); + + if (li != null) { + li.CreateBuilder (ec); + + // + // Special case hoisted catch variable, we have to use a temporary variable + // to pass via anonymous storey initialization with the value still on top + // of the stack + // + if (li.HoistedVariant != null) { + LocalTemporary lt = new LocalTemporary (li.Type); + SymbolWriter.OpenCompilerGeneratedBlock (ec); + lt.Store (ec); + SymbolWriter.CloseCompilerGeneratedBlock (ec); + + // switch to assigning from the temporary variable and not from top of the stack + assign.UpdateSource (lt); + } + } else { + SymbolWriter.OpenCompilerGeneratedBlock (ec); + ec.Emit (OpCodes.Pop); + SymbolWriter.CloseCompilerGeneratedBlock (ec); + } + + Block.Emit (ec); + } + + public override bool Resolve (BlockContext ec) + { + using (ec.With (ResolveContext.Options.CatchScope, true)) { + if (type_expr != null) { + type = type_expr.ResolveAsType (ec); + if (type == null) + return false; + + if (type.BuiltinType != BuiltinTypeSpec.Type.Exception && !TypeSpec.IsBaseClass (type, ec.BuiltinTypes.Exception, false)) { + ec.Report.Error (155, loc, "The type caught or thrown must be derived from System.Exception"); + } else if (li != null) { + li.Type = type; + li.PrepareForFlowAnalysis (ec); + + // source variable is at the top of the stack + Expression source = new EmptyExpression (li.Type); + if (li.Type.IsGenericParameter) + source = new UnboxCast (source, li.Type); + + assign = new CompilerAssign (new LocalVariableReference (li, loc), source, loc); + Block.AddScopeStatement (new StatementExpression (assign)); + } + } + + return Block.Resolve (ec); + } + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Catch target = (Catch) t; + + if (type_expr != null) + target.type_expr = (FullNamedExpression) type_expr.Clone (clonectx); + + target.block = clonectx.LookupBlock (block); + } + } + + public class TryFinally : ExceptionStatement { + Block fini; + + public Statement Stmt { + get { return this.stmt; } + } + + public Block Fini { + get { return this.fini; } + } + + public TryFinally (Statement stmt, Block fini, Location loc) + : base (stmt, loc) + { + this.fini = fini; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + ec.StartFlowBranching (this); + + if (!stmt.Resolve (ec)) + ok = false; + + if (ok) + ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally); + using (ec.With (ResolveContext.Options.FinallyScope, true)) { + if (!fini.Resolve (ec)) + ok = false; + } + + ec.EndFlowBranching (); + + ok &= base.Resolve (ec); + + return ok; + } + + protected override void EmitPreTryBody (EmitContext ec) + { + } + + protected override void EmitTryBody (EmitContext ec) + { + stmt.Emit (ec); + } + + protected override void EmitFinallyBody (EmitContext ec) + { + fini.Emit (ec); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + TryFinally target = (TryFinally) t; + + target.stmt = (Statement) stmt.Clone (clonectx); + if (fini != null) + target.fini = clonectx.LookupBlock (fini); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class TryCatch : Statement { + public Block Block; + public List Specific; + public Catch General; + bool inside_try_finally, code_follows; + + public TryCatch (Block block, List catch_clauses, Location l, bool inside_try_finally) + { + this.Block = block; + this.Specific = catch_clauses; + this.inside_try_finally = inside_try_finally; + + Catch c = catch_clauses [0]; + if (c.IsGeneral) { + this.General = c; + catch_clauses.RemoveAt (0); + } + + loc = l; + } + + public override bool Resolve (BlockContext ec) + { + bool ok = true; + + ec.StartFlowBranching (this); + + if (!Block.Resolve (ec)) + ok = false; + + TypeSpec[] prev_catches = new TypeSpec [Specific.Count]; + int last_index = 0; + foreach (Catch c in Specific){ + ec.CurrentBranching.CreateSibling (c.Block, FlowBranching.SiblingType.Catch); + + if (!c.Resolve (ec)) { + ok = false; + continue; + } + + TypeSpec resolved_type = c.CatchType; + for (int ii = 0; ii < last_index; ++ii) { + if (resolved_type == prev_catches[ii] || TypeSpec.IsBaseClass (resolved_type, prev_catches[ii], true)) { + ec.Report.Error (160, c.loc, + "A previous catch clause already catches all exceptions of this or a super type `{0}'", + TypeManager.CSharpName (prev_catches [ii])); + ok = false; + } + } + + prev_catches [last_index++] = resolved_type; + } + + if (General != null) { + foreach (Catch c in Specific) { + if (c.CatchType.BuiltinType != BuiltinTypeSpec.Type.Exception) + continue; + + if (!ec.Module.DeclaringAssembly.WrapNonExceptionThrows) + continue; + + if (!ec.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined) + continue; + + ec.Report.Warning (1058, 1, c.loc, + "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'"); + } + + ec.CurrentBranching.CreateSibling (General.Block, FlowBranching.SiblingType.Catch); + + if (!General.Resolve (ec)) + ok = false; + } + + ec.EndFlowBranching (); + + // System.Reflection.Emit automatically emits a 'leave' at the end of a try/catch clause + // So, ensure there's some IL code after this statement + if (!inside_try_finally && !code_follows && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) + ec.NeedReturnLabel (); + + return ok; + } + + public void SomeCodeFollows () + { + code_follows = true; + } + + protected override void DoEmit (EmitContext ec) + { + if (!inside_try_finally) + ec.BeginExceptionBlock (); + + Block.Emit (ec); + + foreach (Catch c in Specific) + c.Emit (ec); + + if (General != null) + General.Emit (ec); + + if (!inside_try_finally) + ec.EndExceptionBlock (); + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + TryCatch target = (TryCatch) t; + + target.Block = clonectx.LookupBlock (Block); + if (General != null) + target.General = (Catch) General.Clone (clonectx); + if (Specific != null){ + target.Specific = new List (); + foreach (Catch c in Specific) + target.Specific.Add ((Catch) c.Clone (clonectx)); + } + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + public class Using : ExceptionStatement + { + public class VariableDeclaration : BlockVariableDeclaration + { + Statement dispose_call; + + public VariableDeclaration (FullNamedExpression type, LocalVariable li) + : base (type, li) + { + } + + public VariableDeclaration (LocalVariable li, Location loc) + : base (li) + { + this.loc = loc; + } + + public VariableDeclaration (Expression expr) + : base (null) + { + loc = expr.Location; + Initializer = expr; + } + + #region Properties + + public bool IsNested { get; private set; } + + #endregion + + public void EmitDispose (EmitContext ec) + { + dispose_call.Emit (ec); + } + + public override bool Resolve (BlockContext bc) + { + if (IsNested) + return true; + + return base.Resolve (bc); + } + + public Expression ResolveExpression (BlockContext bc) + { + var e = Initializer.Resolve (bc); + if (e == null) + return null; + + li = LocalVariable.CreateCompilerGenerated (e.Type, bc.CurrentBlock, loc); + Initializer = ResolveInitializer (bc, Variable, e); + return e; + } + + protected override Expression ResolveInitializer (BlockContext bc, LocalVariable li, Expression initializer) + { + if (li.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + initializer = initializer.Resolve (bc); + if (initializer == null) + return null; + + // Once there is dynamic used defer conversion to runtime even if we know it will never succeed + Arguments args = new Arguments (1); + args.Add (new Argument (initializer)); + initializer = new DynamicConversion (bc.BuiltinTypes.IDisposable, 0, args, initializer.Location).Resolve (bc); + if (initializer == null) + return null; + + var var = LocalVariable.CreateCompilerGenerated (initializer.Type, bc.CurrentBlock, loc); + dispose_call = CreateDisposeCall (bc, var); + dispose_call.Resolve (bc); + + return base.ResolveInitializer (bc, li, new SimpleAssign (var.CreateReferenceExpression (bc, loc), initializer, loc)); + } + + if (li == Variable) { + CheckIDiposableConversion (bc, li, initializer); + dispose_call = CreateDisposeCall (bc, li); + dispose_call.Resolve (bc); + } + + return base.ResolveInitializer (bc, li, initializer); + } + + protected virtual void CheckIDiposableConversion (BlockContext bc, LocalVariable li, Expression initializer) + { + var type = li.Type; + + if (type.BuiltinType != BuiltinTypeSpec.Type.IDisposable && !type.ImplementsInterface (bc.BuiltinTypes.IDisposable, false)) { + if (type.IsNullableType) { + // it's handled in CreateDisposeCall + return; + } + + bc.Report.SymbolRelatedToPreviousError (type); + var loc = type_expr == null ? initializer.Location : type_expr.Location; + bc.Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'", + type.GetSignatureForError ()); + + return; + } + } + + protected virtual Statement CreateDisposeCall (BlockContext bc, LocalVariable lv) + { + var lvr = lv.CreateReferenceExpression (bc, lv.Location); + var type = lv.Type; + var loc = lv.Location; + + var idt = bc.BuiltinTypes.IDisposable; + var m = bc.Module.PredefinedMembers.IDisposableDispose.Resolve (loc); + + var dispose_mg = MethodGroupExpr.CreatePredefined (m, idt, loc); + dispose_mg.InstanceExpression = type.IsNullableType ? + new Cast (new TypeExpression (idt, loc), lvr, loc).Resolve (bc) : + lvr; + + Statement dispose = new StatementExpression (new Invocation (dispose_mg, null)); + + // Add conditional call when disposing possible null variable + if (!type.IsStruct || type.IsNullableType) + dispose = new If (new Binary (Binary.Operator.Inequality, lvr, new NullLiteral (loc), loc), dispose, loc); + + return dispose; + } + + public Statement RewriteForDeclarators (BlockContext bc, Statement stmt) + { + for (int i = declarators.Count - 1; i >= 0; --i) { + var d = declarators [i]; + var vd = new VariableDeclaration (d.Variable, type_expr.Location); + vd.Initializer = d.Initializer; + vd.IsNested = true; + vd.dispose_call = CreateDisposeCall (bc, d.Variable); + vd.dispose_call.Resolve (bc); + + stmt = new Using (vd, stmt, d.Variable.Location); + } + + declarators = null; + return stmt; + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + VariableDeclaration decl; + + public Using (VariableDeclaration decl, Statement stmt, Location loc) + : base (stmt, loc) + { + this.decl = decl; + } + + public Using (Expression expr, Statement stmt, Location loc) + : base (stmt, loc) + { + this.decl = new VariableDeclaration (expr); + } + + #region Properties + + public Expression Expression { + get { + return decl.Variable == null ? decl.Initializer : null; + } + } + + public BlockVariableDeclaration Variables { + get { + return decl; + } + } + + #endregion + + protected override void EmitPreTryBody (EmitContext ec) + { + decl.Emit (ec); + } + + protected override void EmitTryBody (EmitContext ec) + { + stmt.Emit (ec); + } + + protected override void EmitFinallyBody (EmitContext ec) + { + decl.EmitDispose (ec); + } + + public override bool Resolve (BlockContext ec) + { + VariableReference vr; + bool vr_locked = false; + + using (ec.Set (ResolveContext.Options.UsingInitializerScope)) { + if (decl.Variable == null) { + vr = decl.ResolveExpression (ec) as VariableReference; + if (vr != null) { + vr_locked = vr.IsLockedByStatement; + vr.IsLockedByStatement = true; + } + } else { + if (!decl.Resolve (ec)) + return false; + + if (decl.Declarators != null) { + stmt = decl.RewriteForDeclarators (ec, stmt); + } + + vr = null; + } + } + + ec.StartFlowBranching (this); + + stmt.Resolve (ec); + + ec.EndFlowBranching (); + + if (vr != null) + vr.IsLockedByStatement = vr_locked; + + base.Resolve (ec); + + return true; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Using target = (Using) t; + + target.decl = (VariableDeclaration) decl.Clone (clonectx); + target.stmt = stmt.Clone (clonectx); + } + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + /// + /// Implementation of the foreach C# statement + /// + public class Foreach : Statement { + + sealed class ArrayForeach : Statement + { + readonly Foreach for_each; + readonly Statement statement; + + Expression conv; + TemporaryVariableReference[] lengths; + Expression [] length_exprs; + StatementExpression[] counter; + TemporaryVariableReference[] variables; + + TemporaryVariableReference copy; + Expression access; + LocalVariableReference variable; + + public ArrayForeach (Foreach @foreach, int rank) + { + 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]; + length_exprs = new Expression [rank]; + + // + // Only use temporary length variables when dealing with + // multi-dimensional arrays + // + if (rank > 1) + lengths = new TemporaryVariableReference [rank]; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + public override bool Resolve (BlockContext ec) + { + Block variables_block = variable.local_info.Block; + copy = TemporaryVariableReference.Create (for_each.expr.Type, variables_block, loc); + copy.Resolve (ec); + + int rank = length_exprs.Length; + Arguments list = new Arguments (rank); + for (int i = 0; i < rank; i++) { + var v = TemporaryVariableReference.Create (ec.BuiltinTypes.Int, variables_block, loc); + variables[i] = v; + counter[i] = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, v, loc)); + counter[i].Resolve (ec); + + if (rank == 1) { + length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec); + } else { + lengths[i] = TemporaryVariableReference.Create (ec.BuiltinTypes.Int, variables_block, loc); + lengths[i].Resolve (ec); + + Arguments args = new Arguments (1); + args.Add (new Argument (new IntConstant (ec.BuiltinTypes, i, loc))); + length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec); + } + + list.Add (new Argument (v)); + } + + access = new ElementAccess (copy, list, loc).Resolve (ec); + if (access == null) + return false; + + TypeSpec var_type; + if (for_each.type is VarExpr) { + // Infer implicitly typed local variable from foreach array type + var_type = access.Type; + } else { + var_type = for_each.type.ResolveAsType (ec); + } + + if (var_type == null) + return false; + + conv = Convert.ExplicitConversion (ec, access, var_type, loc); + if (conv == null) + return false; + + bool ok = true; + + ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); + ec.CurrentBranching.CreateSibling (); + + variable.local_info.Type = conv.Type; + variable.Resolve (ec); + + ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); + if (!statement.Resolve (ec)) + ok = false; + ec.EndFlowBranching (); + + // There's no direct control flow from the end of the embedded statement to the end of the loop + ec.CurrentBranching.CurrentUsageVector.Goto (); + + ec.EndFlowBranching (); + + return ok; + } + + protected override void DoEmit (EmitContext ec) + { + copy.EmitAssign (ec, for_each.expr); + + int rank = length_exprs.Length; + Label[] test = new Label [rank]; + Label[] loop = new Label [rank]; + + for (int i = 0; i < rank; i++) { + test [i] = ec.DefineLabel (); + loop [i] = ec.DefineLabel (); + + if (lengths != null) + lengths [i].EmitAssign (ec, length_exprs [i]); + } + + IntConstant zero = new IntConstant (ec.BuiltinTypes, 0, loc); + for (int i = 0; i < rank; i++) { + variables [i].EmitAssign (ec, zero); + + ec.Emit (OpCodes.Br, test [i]); + ec.MarkLabel (loop [i]); + } + + variable.local_info.CreateBuilder (ec); + variable.EmitAssign (ec, conv, false, false); + + statement.Emit (ec); + + ec.MarkLabel (ec.LoopBegin); + + for (int i = rank - 1; i >= 0; i--){ + counter [i].Emit (ec); + + ec.MarkLabel (test [i]); + variables [i].Emit (ec); + + if (lengths != null) + lengths [i].Emit (ec); + else + length_exprs [i].Emit (ec); + + ec.Emit (OpCodes.Blt, loop [i]); + } + + ec.MarkLabel (ec.LoopEnd); + } + } + + sealed class CollectionForeach : Statement, OverloadResolver.IErrorHandler + { + class Body : Statement + { + TypeSpec type; + LocalVariableReference variable; + Expression current, conv; + Statement statement; + + public Body (TypeSpec type, LocalVariable variable, + Expression current, Statement statement, + Location loc) + { + this.type = type; + this.variable = new LocalVariableReference (variable, loc); + this.current = current; + this.statement = statement; + this.loc = loc; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + public override bool Resolve (BlockContext ec) + { + current = current.Resolve (ec); + if (current == null) + return false; + + conv = Convert.ExplicitConversion (ec, current, type, loc); + if (conv == null) + return false; + + variable.local_info.Type = conv.Type; + variable.Resolve (ec); + + if (!statement.Resolve (ec)) + return false; + + return true; + } + + protected override void DoEmit (EmitContext ec) + { + variable.local_info.CreateBuilder (ec); + variable.EmitAssign (ec, conv, false, false); + + statement.Emit (ec); + } + } + + class RuntimeDispose : Using.VariableDeclaration + { + public RuntimeDispose (LocalVariable lv, Location loc) + : base (lv, loc) + { + } + + protected override void CheckIDiposableConversion (BlockContext bc, LocalVariable li, Expression initializer) + { + // Defered to runtime check + } + + protected override Statement CreateDisposeCall (BlockContext bc, LocalVariable lv) + { + var idt = bc.BuiltinTypes.IDisposable; + + // + // Fabricates code like + // + // if ((temp = vr as IDisposable) != null) temp.Dispose (); + // + + var dispose_variable = LocalVariable.CreateCompilerGenerated (idt, bc.CurrentBlock, loc); + + var idisaposable_test = new Binary (Binary.Operator.Inequality, new CompilerAssign ( + dispose_variable.CreateReferenceExpression (bc, loc), + new As (lv.CreateReferenceExpression (bc, loc), new TypeExpression (dispose_variable.Type, loc), loc), + loc), new NullLiteral (loc), loc); + + var m = bc.Module.PredefinedMembers.IDisposableDispose.Resolve (loc); + + var dispose_mg = MethodGroupExpr.CreatePredefined (m, idt, loc); + dispose_mg.InstanceExpression = dispose_variable.CreateReferenceExpression (bc, loc); + + Statement dispose = new StatementExpression (new Invocation (dispose_mg, null)); + return new If (idisaposable_test, dispose, loc); + } + } + + LocalVariable variable; + Expression expr; + Statement statement; + Expression var_type; + ExpressionStatement init; + TemporaryVariableReference enumerator_variable; + bool ambiguous_getenumerator_name; + + public CollectionForeach (Expression var_type, LocalVariable var, Expression expr, Statement stmt, Location l) + { + this.var_type = var_type; + this.variable = var; + this.expr = expr; + statement = stmt; + loc = l; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + void Error_WrongEnumerator (ResolveContext rc, MethodSpec enumerator) + { + rc.Report.SymbolRelatedToPreviousError (enumerator); + rc.Report.Error (202, loc, + "foreach statement requires that the return type `{0}' of `{1}' must have a suitable public MoveNext method and public Current property", + enumerator.ReturnType.GetSignatureForError (), enumerator.GetSignatureForError ()); + } + + MethodGroupExpr ResolveGetEnumerator (ResolveContext rc) + { + // + // Option 1: Try to match by name GetEnumerator first + // + var mexpr = Expression.MemberLookup (rc, false, expr.Type, + "GetEnumerator", 0, Expression.MemberLookupRestrictions.ExactArity, loc); // TODO: What if CS0229 ? + + var mg = mexpr as MethodGroupExpr; + if (mg != null) { + mg.InstanceExpression = expr; + Arguments args = new Arguments (0); + mg = mg.OverloadResolve (rc, ref args, this, OverloadResolver.Restrictions.None); + + // For ambiguous GetEnumerator name warning CS0278 was reported, but Option 2 could still apply + if (ambiguous_getenumerator_name) + mg = null; + + if (mg != null && args.Count == 0 && !mg.BestCandidate.IsStatic && mg.BestCandidate.IsPublic) { + return mg; + } + } + + // + // Option 2: Try to match using IEnumerable interfaces with preference of generic version + // + var t = expr.Type; + PredefinedMember iface_candidate = null; + var ptypes = rc.Module.PredefinedTypes; + var gen_ienumerable = ptypes.IEnumerableGeneric; + if (!gen_ienumerable.Define ()) + gen_ienumerable = null; + + do { + var ifaces = t.Interfaces; + if (ifaces != null) { + foreach (var iface in ifaces) { + if (gen_ienumerable != null && iface.MemberDefinition == gen_ienumerable.TypeSpec.MemberDefinition) { + if (iface_candidate != null && iface_candidate != rc.Module.PredefinedMembers.IEnumerableGetEnumerator) { + rc.Report.SymbolRelatedToPreviousError (expr.Type); + rc.Report.Error (1640, loc, + "foreach statement cannot operate on variables of type `{0}' because it contains multiple implementation of `{1}'. Try casting to a specific implementation", + expr.Type.GetSignatureForError (), gen_ienumerable.TypeSpec.GetSignatureForError ()); + + return null; + } + + // TODO: Cache this somehow + iface_candidate = new PredefinedMember (rc.Module, iface, + MemberFilter.Method ("GetEnumerator", 0, ParametersCompiled.EmptyReadOnlyParameters, null)); + + continue; + } + + if (iface.BuiltinType == BuiltinTypeSpec.Type.IEnumerable && iface_candidate == null) { + iface_candidate = rc.Module.PredefinedMembers.IEnumerableGetEnumerator; + } + } + } + + if (t.IsGenericParameter) + t = t.BaseType; + else + t = null; + + } while (t != null); + + if (iface_candidate == null) { + rc.Report.Error (1579, loc, + "foreach statement cannot operate on variables of type `{0}' because it does not contain a definition for `{1}' or is inaccessible", + expr.Type.GetSignatureForError (), "GetEnumerator"); + + return null; + } + + var method = iface_candidate.Resolve (loc); + if (method == null) + return null; + + mg = MethodGroupExpr.CreatePredefined (method, expr.Type, loc); + mg.InstanceExpression = expr; + return mg; + } + + MethodGroupExpr ResolveMoveNext (ResolveContext rc, MethodSpec enumerator) + { + var ms = MemberCache.FindMember (enumerator.ReturnType, + MemberFilter.Method ("MoveNext", 0, ParametersCompiled.EmptyReadOnlyParameters, rc.BuiltinTypes.Bool), + BindingRestriction.InstanceOnly) as MethodSpec; + + if (ms == null || !ms.IsPublic) { + Error_WrongEnumerator (rc, enumerator); + return null; + } + + return MethodGroupExpr.CreatePredefined (ms, enumerator.ReturnType, loc); + } + + PropertySpec ResolveCurrent (ResolveContext rc, MethodSpec enumerator) + { + var ps = MemberCache.FindMember (enumerator.ReturnType, + MemberFilter.Property ("Current", null), + BindingRestriction.InstanceOnly) as PropertySpec; + + if (ps == null || !ps.IsPublic) { + Error_WrongEnumerator (rc, enumerator); + return null; + } + + return ps; + } + + public override bool Resolve (BlockContext ec) + { + bool is_dynamic = expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + + if (is_dynamic) { + expr = Convert.ImplicitConversionRequired (ec, expr, ec.BuiltinTypes.IEnumerable, loc); + } else if (expr.Type.IsNullableType) { + expr = new Nullable.UnwrapCall (expr).Resolve (ec); + } + + var get_enumerator_mg = ResolveGetEnumerator (ec); + if (get_enumerator_mg == null) { + return false; + } + + var get_enumerator = get_enumerator_mg.BestCandidate; + enumerator_variable = TemporaryVariableReference.Create (get_enumerator.ReturnType, variable.Block, loc); + enumerator_variable.Resolve (ec); + + // Prepare bool MoveNext () + var move_next_mg = ResolveMoveNext (ec, get_enumerator); + if (move_next_mg == null) { + return false; + } + + move_next_mg.InstanceExpression = enumerator_variable; + + // Prepare ~T~ Current { get; } + var current_prop = ResolveCurrent (ec, get_enumerator); + if (current_prop == null) { + return false; + } + + var current_pe = new PropertyExpr (current_prop, loc) { InstanceExpression = enumerator_variable }.Resolve (ec); + if (current_pe == null) + return false; + + VarExpr ve = var_type as VarExpr; + + if (ve != null) { + if (is_dynamic) { + // Source type is dynamic, set element type to dynamic too + variable.Type = ec.BuiltinTypes.Dynamic; + } else { + // Infer implicitly typed local variable from foreach enumerable type + variable.Type = current_pe.Type; + } + } else { + if (is_dynamic) { + // Explicit cast of dynamic collection elements has to be done at runtime + current_pe = EmptyCast.Create (current_pe, ec.BuiltinTypes.Dynamic); + } + + variable.Type = var_type.ResolveAsType (ec); + } + + if (variable.Type == null) + return false; + + var init = new Invocation (get_enumerator_mg, null); + + statement = new While (new BooleanExpression (new Invocation (move_next_mg, null)), + new Body (variable.Type, variable, current_pe, statement, loc), loc); + + var enum_type = enumerator_variable.Type; + + // + // Add Dispose method call when enumerator can be IDisposable + // + if (!enum_type.ImplementsInterface (ec.BuiltinTypes.IDisposable, false)) { + if (!enum_type.IsSealed && !TypeSpec.IsValueType (enum_type)) { + // + // Runtime Dispose check + // + var vd = new RuntimeDispose (enumerator_variable.LocalInfo, loc); + vd.Initializer = init; + statement = new Using (vd, statement, loc); + } else { + // + // No Dispose call needed + // + this.init = new SimpleAssign (enumerator_variable, init); + this.init.Resolve (ec); + } + } else { + // + // Static Dispose check + // + var vd = new Using.VariableDeclaration (enumerator_variable.LocalInfo, loc); + vd.Initializer = init; + statement = new Using (vd, statement, loc); + } + + return statement.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + enumerator_variable.LocalInfo.CreateBuilder (ec); + + if (init != null) + init.EmitStatement (ec); + + statement.Emit (ec); + } + + #region IErrorHandler Members + + bool OverloadResolver.IErrorHandler.AmbiguousCandidates (ResolveContext ec, MemberSpec best, MemberSpec ambiguous) + { + ec.Report.SymbolRelatedToPreviousError (best); + ec.Report.Warning (278, 2, loc, + "`{0}' contains ambiguous implementation of `{1}' pattern. Method `{2}' is ambiguous with method `{3}'", + expr.Type.GetSignatureForError (), "enumerable", + best.GetSignatureForError (), ambiguous.GetSignatureForError ()); + + ambiguous_getenumerator_name = true; + return true; + } + + bool OverloadResolver.IErrorHandler.ArgumentMismatch (ResolveContext rc, MemberSpec best, Argument arg, int index) + { + return false; + } + + bool OverloadResolver.IErrorHandler.NoArgumentMatch (ResolveContext rc, MemberSpec best) + { + return false; + } + + bool OverloadResolver.IErrorHandler.TypeInferenceFailed (ResolveContext rc, MemberSpec best) + { + return false; + } + + #endregion + } + + Expression type; + LocalVariable variable; + Expression expr; + Statement statement; + + public Expression TypeExpr { + get { return this.type; } + } + + public LocalVariable Variable { + get { return this.variable; } + } + + public Foreach (Expression type, LocalVariable var, Expression expr, Statement stmt, Location l) + { + this.type = type; + this.variable = var; + this.expr = expr; + statement = stmt; + loc = l; + } + + public Statement Statement { + get { return statement; } + } + + public Expression Expr { + get { return this.expr; } + } + + public override bool Resolve (BlockContext ec) + { + expr = expr.Resolve (ec); + if (expr == null) + return false; + + if (expr.IsNull) { + ec.Report.Error (186, loc, "Use of null is not valid in this context"); + return false; + } + + if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.String) { + statement = new ArrayForeach (this, 1); + } else if (expr.Type is ArrayContainer) { + statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank); + } else { + if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) { + ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'", + expr.ExprClassName); + return false; + } + + statement = new CollectionForeach (type, variable, expr, statement, loc); + } + + return statement.Resolve (ec); + } + + protected override void DoEmit (EmitContext ec) + { + Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd; + ec.LoopBegin = ec.DefineLabel (); + ec.LoopEnd = ec.DefineLabel (); + + statement.Emit (ec); + + ec.LoopBegin = old_begin; + ec.LoopEnd = old_end; + } + + protected override void CloneTo (CloneContext clonectx, Statement t) + { + Foreach target = (Foreach) t; + + target.type = type.Clone (clonectx); + target.expr = expr.Clone (clonectx); + target.statement = statement.Clone (clonectx); + } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs new file mode 100644 index 0000000000..c10d13f893 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs @@ -0,0 +1,317 @@ +// +// support.cs: Support routines to work around the fact that System.Reflection.Emit +// can not introspect types that are being constructed +// +// Author: +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Copyright 2001 Ximian, Inc (http://www.ximian.com) +// Copyright 2003-2009 Novell, Inc +// + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Collections.Generic; + +namespace Mono.CSharp { + + sealed class ReferenceEquality : IEqualityComparer where T : class + { + public static readonly IEqualityComparer Default = new ReferenceEquality (); + + private ReferenceEquality () + { + } + + public bool Equals (T x, T y) + { + return ReferenceEquals (x, y); + } + + public int GetHashCode (T obj) + { + return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode (obj); + } + } + + public class Tuple : IEquatable> + { + public Tuple (T1 item1, T2 item2) + { + Item1 = item1; + Item2 = item2; + } + + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + + public override int GetHashCode () + { + return ((object)Item1 ?? 0) .GetHashCode () ^ ((object)Item2 ?? 0).GetHashCode (); + } + + #region IEquatable> Members + + public bool Equals (Tuple other) + { + return EqualityComparer.Default.Equals (Item1, other.Item1) && + EqualityComparer.Default.Equals (Item2, other.Item2); + } + + #endregion + } + + public class Tuple : IEquatable> + { + public Tuple (T1 item1, T2 item2, T3 item3) + { + Item1 = item1; + Item2 = item2; + Item3 = item3; + } + + public T1 Item1 { get; private set; } + public T2 Item2 { get; private set; } + public T3 Item3 { get; private set; } + + public override int GetHashCode () + { + return Item1.GetHashCode () ^ Item2.GetHashCode () ^ Item3.GetHashCode (); + } + + #region IEquatable> Members + + public bool Equals (Tuple other) + { + return EqualityComparer.Default.Equals (Item1, other.Item1) && + EqualityComparer.Default.Equals (Item2, other.Item2) && + EqualityComparer.Default.Equals (Item3, other.Item3); + } + + #endregion + } + + static class Tuple + { + public static Tuple Create (T1 item1, T2 item2) + { + return new Tuple (item1, item2); + } + + public static Tuple Create (T1 item1, T2 item2, T3 item3) + { + return new Tuple (item1, item2, item3); + } + } + + static class ArrayComparer + { + public static bool IsEqual (T[] array1, T[] array2) + { + if (array1 == null || array2 == null) + return array1 == array2; + + var eq = EqualityComparer.Default; + + for (int i = 0; i < array1.Length; ++i) { + if (!eq.Equals (array1[i], array2[i])) { + return false; + } + } + + return true; + } + } + + /// + /// This is an arbitrarily seekable StreamReader wrapper. + /// + /// It uses a self-tuning buffer to cache the seekable data, + /// but if the seek is too far, it may read the underly + /// stream all over from the beginning. + /// + public class SeekableStreamReader : IDisposable + { + StreamReader reader; + Stream stream; + + static char[] buffer; + int read_ahead_length; // the length of read buffer + int buffer_start; // in chars + int char_count; // count of filled characters in buffer[] + int pos; // index into buffer[] + + public SeekableStreamReader (Stream stream, Encoding encoding) + { + this.stream = stream; + + const int default_read_ahead = 2048; + InitializeStream (default_read_ahead); + reader = new StreamReader (stream, encoding, true); + } + + public void Dispose () + { + // Needed to release stream reader buffers + reader.Dispose (); + } + + void InitializeStream (int read_length_inc) + { + read_ahead_length += read_length_inc; + + int required_buffer_size = read_ahead_length * 2; + + if (buffer == null || buffer.Length < required_buffer_size) + buffer = new char [required_buffer_size]; + + stream.Position = 0; + buffer_start = char_count = pos = 0; + } + + /// + /// This value corresponds to the current position in a stream of characters. + /// The StreamReader hides its manipulation of the underlying byte stream and all + /// character set/decoding issues. Thus, we cannot use this position to guess at + /// the corresponding position in the underlying byte stream even though there is + /// a correlation between them. + /// + public int Position { + get { + return buffer_start + pos; + } + + set { + // + // If the lookahead was too small, re-read from the beginning. Increase the buffer size while we're at it + // This should never happen until we are parsing some weird source code + // + if (value < buffer_start) { + InitializeStream (read_ahead_length); + + // + // Discard buffer data after underlying stream changed position + // Cannot use handy reader.DiscardBufferedData () because it for + // some strange reason resets encoding as well + // + reader = new StreamReader (stream, reader.CurrentEncoding, true); + } + + while (value > buffer_start + char_count) { + pos = char_count; + if (!ReadBuffer ()) + throw new InternalErrorException ("Seek beyond end of file: " + (buffer_start + char_count - value)); + } + + pos = value - buffer_start; + } + } + + bool ReadBuffer () + { + int slack = buffer.Length - char_count; + + // + // read_ahead_length is only half of the buffer to deal with + // reads ahead and moves back without re-reading whole buffer + // + if (slack <= read_ahead_length) { + // + // shift the buffer to make room for read_ahead_length number of characters + // + int shift = read_ahead_length - slack; + Array.Copy (buffer, shift, buffer, 0, char_count - shift); + + // Update all counters + pos -= shift; + char_count -= shift; + buffer_start += shift; + slack += shift; + } + + char_count += reader.Read (buffer, char_count, slack); + + return pos < char_count; + } + + public char[] ReadChars (int fromPosition, int toPosition) + { + char[] chars = new char[toPosition - fromPosition]; + if (buffer_start <= fromPosition && toPosition < buffer_start + buffer.Length) { + Array.Copy (buffer, fromPosition - buffer_start, chars, 0, chars.Length); + } else { + throw new NotImplementedException (); + } + + return chars; + } + + public int Peek () + { + if ((pos >= char_count) && !ReadBuffer ()) + return -1; + + return buffer [pos]; + } + + public int Read () + { + if ((pos >= char_count) && !ReadBuffer ()) + return -1; + + return buffer [pos++]; + } + } + + public class UnixUtils { + [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")] + extern static int _isatty (int fd); + + public static bool isatty (int fd) + { + try { + return _isatty (fd) == 1; + } catch { + return false; + } + } + } + + /// + /// An exception used to terminate the compiler resolution phase and provide completions + /// + /// + /// This is thrown when we want to return the completions or + /// terminate the completion process by AST nodes used in + /// the completion process. + /// + public class CompletionResult : Exception { + string [] result; + string base_text; + + public CompletionResult (string base_text, string [] res) + { + if (base_text == null) + throw new ArgumentNullException ("base_text"); + this.base_text = base_text; + + result = res; + Array.Sort (result); + } + + public string [] Result { + get { + return result; + } + } + + public string BaseText { + get { + return base_text; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs new file mode 100644 index 0000000000..ce19cfc492 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs @@ -0,0 +1,245 @@ +// +// symbolwriter.cs: The debug symbol writer +// +// Authors: Martin Baulig (martin@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2003 Ximian, Inc (http://www.ximian.com) +// Copyright 2004-2010 Novell, Inc +// + +using System; + +#if STATIC +using IKVM.Reflection; +using IKVM.Reflection.Emit; +#else +using System.Reflection; +using System.Reflection.Emit; +#endif + +using Mono.CompilerServices.SymbolWriter; + +namespace Mono.CSharp +{ + static class SymbolWriter + { +#if !NET_4_0 && !STATIC + delegate int GetILOffsetFunc (ILGenerator ig); + static GetILOffsetFunc get_il_offset_func; + + delegate Guid GetGuidFunc (ModuleBuilder mb); + static GetGuidFunc get_guid_func; + + static void Initialize () + { + var mi = typeof (ILGenerator).GetMethod ( + "Mono_GetCurrentOffset", + BindingFlags.Static | BindingFlags.NonPublic); + if (mi == null) + throw new MissingMethodException ("Mono_GetCurrentOffset"); + + get_il_offset_func = (GetILOffsetFunc) System.Delegate.CreateDelegate ( + typeof (GetILOffsetFunc), mi); + + mi = typeof (ModuleBuilder).GetMethod ( + "Mono_GetGuid", + BindingFlags.Static | BindingFlags.NonPublic); + if (mi == null) + throw new MissingMethodException ("Mono_GetGuid"); + + get_guid_func = (GetGuidFunc) System.Delegate.CreateDelegate ( + typeof (GetGuidFunc), mi); + } +#endif + + static int GetILOffset (ILGenerator ig) + { +#if NET_4_0 || STATIC + return ig.ILOffset; +#else + if (get_il_offset_func == null) + Initialize (); + + return get_il_offset_func (ig); +#endif + } + + public static Guid GetGuid (ModuleBuilder module) + { +#if NET_4_0 || STATIC + return module.ModuleVersionId; +#else + if (get_guid_func == null) + Initialize (); + + return get_guid_func (module); +#endif + } + + public static bool HasSymbolWriter { + get { return symwriter != null; } + } + + public static MonoSymbolWriter symwriter; + + public static void DefineLocalVariable (string name, LocalBuilder builder) + { + if (symwriter != null) { + symwriter.DefineLocalVariable (builder.LocalIndex, name); + } + } + + public static SourceMethodBuilder OpenMethod (ICompileUnit file, int ns_id, + IMethodDef method) + { + if (symwriter != null) + return symwriter.OpenMethod (file, ns_id, method); + else + return null; + } + + public static void CloseMethod () + { + if (symwriter != null) + symwriter.CloseMethod (); + } + + public static int OpenScope (ILGenerator ig) + { + if (symwriter != null) { + int offset = GetILOffset (ig); + return symwriter.OpenScope (offset); + } else { + return -1; + } + } + + public static void CloseScope (ILGenerator ig) + { + if (symwriter != null) { + int offset = GetILOffset (ig); + symwriter.CloseScope (offset); + } + } + + public static int DefineNamespace (string name, CompileUnitEntry source, + string[] using_clauses, int parent) + { + if (symwriter != null) + return symwriter.DefineNamespace (name, source, using_clauses, parent); + else + return -1; + } + + public static void DefineAnonymousScope (int id) + { + if (symwriter != null) + symwriter.DefineAnonymousScope (id); + } + + public static void DefineScopeVariable (int scope, LocalBuilder builder) + { + if (symwriter != null) { + symwriter.DefineScopeVariable (scope, builder.LocalIndex); + } + } + + public static void DefineScopeVariable (int scope) + { + if (symwriter != null) + symwriter.DefineScopeVariable (scope, -1); + } + + public static void DefineCapturedLocal (int scope_id, string name, + string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedLocal (scope_id, name, captured_name); + } + + public static void DefineCapturedParameter (int scope_id, string name, + string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedParameter (scope_id, name, captured_name); + } + + public static void DefineCapturedThis (int scope_id, string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedThis (scope_id, captured_name); + } + + public static void DefineCapturedScope (int scope_id, int id, string captured_name) + { + if (symwriter != null) + symwriter.DefineCapturedScope (scope_id, id, captured_name); + } + + public static void OpenCompilerGeneratedBlock (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.OpenCompilerGeneratedBlock (offset); + } + } + + public static void CloseCompilerGeneratedBlock (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.CloseCompilerGeneratedBlock (offset); + } + } + + public static void StartIteratorBody (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.StartIteratorBody (offset); + } + } + + public static void EndIteratorBody (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.EndIteratorBody (offset); + } + } + + public static void StartIteratorDispatcher (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.StartIteratorDispatcher (offset); + } + } + + public static void EndIteratorDispatcher (EmitContext ec) + { + if (symwriter != null) { + int offset = GetILOffset (ec.ig); + symwriter.EndIteratorDispatcher (offset); + } + } + + public static void MarkSequencePoint (ILGenerator ig, Location loc) + { + if (symwriter != null) { + SourceFileEntry file = loc.SourceFile.SourceFileEntry; + int offset = GetILOffset (ig); + symwriter.MarkSequencePoint ( + offset, file, loc.Row, loc.Column, loc.Hidden); + } + } + + public static void Reset () + { + symwriter = null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs new file mode 100644 index 0000000000..2e2d17064d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs @@ -0,0 +1,980 @@ +// +// typemanager.cs: C# type manager +// +// Author: Miguel de Icaza (miguel@gnu.org) +// Ravi Pratap (ravi@ximian.com) +// Marek Safar (marek.safar@gmail.com) +// +// 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. +// + +using System; +using System.Globalization; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace Mono.CSharp +{ + // + // All compiler built-in types (they have to exist otherwise the compiler will not work) + // + public class BuiltinTypes + { + public readonly BuiltinTypeSpec Object; + public readonly BuiltinTypeSpec ValueType; + public readonly BuiltinTypeSpec Attribute; + + public readonly BuiltinTypeSpec Int; + public readonly BuiltinTypeSpec UInt; + public readonly BuiltinTypeSpec Long; + public readonly BuiltinTypeSpec ULong; + public readonly BuiltinTypeSpec Float; + public readonly BuiltinTypeSpec Double; + public readonly BuiltinTypeSpec Char; + public readonly BuiltinTypeSpec Short; + public readonly BuiltinTypeSpec Decimal; + public readonly BuiltinTypeSpec Bool; + public readonly BuiltinTypeSpec SByte; + public readonly BuiltinTypeSpec Byte; + public readonly BuiltinTypeSpec UShort; + public readonly BuiltinTypeSpec String; + + public readonly BuiltinTypeSpec Enum; + public readonly BuiltinTypeSpec Delegate; + public readonly BuiltinTypeSpec MulticastDelegate; + public readonly BuiltinTypeSpec Void; + public readonly BuiltinTypeSpec Array; + public readonly BuiltinTypeSpec Type; + public readonly BuiltinTypeSpec IEnumerator; + public readonly BuiltinTypeSpec IEnumerable; + public readonly BuiltinTypeSpec IDisposable; + public readonly BuiltinTypeSpec IntPtr; + public readonly BuiltinTypeSpec UIntPtr; + public readonly BuiltinTypeSpec RuntimeFieldHandle; + public readonly BuiltinTypeSpec RuntimeTypeHandle; + public readonly BuiltinTypeSpec Exception; + + // + // These are internal buil-in types which depend on other + // build-in type (mostly object) + // + public readonly BuiltinTypeSpec Dynamic; + + // Predefined operators tables + public readonly Binary.PredefinedOperator[] OperatorsBinaryStandard; + public readonly Binary.PredefinedOperator[] OperatorsBinaryEquality; + public readonly Binary.PredefinedOperator[] OperatorsBinaryUnsafe; + public readonly TypeSpec[][] OperatorsUnary; + public readonly TypeSpec[] OperatorsUnaryMutator; + + public readonly TypeSpec[] BinaryPromotionsTypes; + public readonly TypeSpec[] SwitchUserTypes; + + readonly BuiltinTypeSpec[] types; + + public BuiltinTypes () + { + Object = new BuiltinTypeSpec (MemberKind.Class, "System", "Object", BuiltinTypeSpec.Type.Object); + ValueType = new BuiltinTypeSpec (MemberKind.Class, "System", "ValueType", BuiltinTypeSpec.Type.ValueType); + Attribute = new BuiltinTypeSpec (MemberKind.Class, "System", "Attribute", BuiltinTypeSpec.Type.Attribute); + + Int = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int32", BuiltinTypeSpec.Type.Int); + Long = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int64", BuiltinTypeSpec.Type.Long); + UInt = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt32", BuiltinTypeSpec.Type.UInt); + ULong = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt64", BuiltinTypeSpec.Type.ULong); + Byte = new BuiltinTypeSpec (MemberKind.Struct, "System", "Byte", BuiltinTypeSpec.Type.Byte); + SByte = new BuiltinTypeSpec (MemberKind.Struct, "System", "SByte", BuiltinTypeSpec.Type.SByte); + Short = new BuiltinTypeSpec (MemberKind.Struct, "System", "Int16", BuiltinTypeSpec.Type.Short); + UShort = new BuiltinTypeSpec (MemberKind.Struct, "System", "UInt16", BuiltinTypeSpec.Type.UShort); + + IEnumerator = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerator", BuiltinTypeSpec.Type.IEnumerator); + IEnumerable = new BuiltinTypeSpec (MemberKind.Interface, "System.Collections", "IEnumerable", BuiltinTypeSpec.Type.IEnumerable); + IDisposable = new BuiltinTypeSpec (MemberKind.Interface, "System", "IDisposable", BuiltinTypeSpec.Type.IDisposable); + + Char = new BuiltinTypeSpec (MemberKind.Struct, "System", "Char", BuiltinTypeSpec.Type.Char); + String = new BuiltinTypeSpec (MemberKind.Class, "System", "String", BuiltinTypeSpec.Type.String); + Float = new BuiltinTypeSpec (MemberKind.Struct, "System", "Single", BuiltinTypeSpec.Type.Float); + Double = new BuiltinTypeSpec (MemberKind.Struct, "System", "Double", BuiltinTypeSpec.Type.Double); + Decimal = new BuiltinTypeSpec (MemberKind.Struct, "System", "Decimal", BuiltinTypeSpec.Type.Decimal); + Bool = new BuiltinTypeSpec (MemberKind.Struct, "System", "Boolean", BuiltinTypeSpec.Type.Bool); + IntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "IntPtr", BuiltinTypeSpec.Type.IntPtr); + UIntPtr = new BuiltinTypeSpec (MemberKind.Struct, "System", "UIntPtr", BuiltinTypeSpec.Type.UIntPtr); + + MulticastDelegate = new BuiltinTypeSpec (MemberKind.Class, "System", "MulticastDelegate", BuiltinTypeSpec.Type.MulticastDelegate); + Delegate = new BuiltinTypeSpec (MemberKind.Class, "System", "Delegate", BuiltinTypeSpec.Type.Delegate); + Enum = new BuiltinTypeSpec (MemberKind.Class, "System", "Enum", BuiltinTypeSpec.Type.Enum); + Array = new BuiltinTypeSpec (MemberKind.Class, "System", "Array", BuiltinTypeSpec.Type.Array); + Void = new BuiltinTypeSpec (MemberKind.Void, "System", "Void", BuiltinTypeSpec.Type.Other); + Type = new BuiltinTypeSpec (MemberKind.Class, "System", "Type", BuiltinTypeSpec.Type.Type); + Exception = new BuiltinTypeSpec (MemberKind.Class, "System", "Exception", BuiltinTypeSpec.Type.Exception); + RuntimeFieldHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeFieldHandle", BuiltinTypeSpec.Type.Other); + RuntimeTypeHandle = new BuiltinTypeSpec (MemberKind.Struct, "System", "RuntimeTypeHandle", BuiltinTypeSpec.Type.Other); + + // TODO: Maybe I should promote it to different kind for faster compares + Dynamic = new BuiltinTypeSpec ("dynamic", BuiltinTypeSpec.Type.Dynamic); + + OperatorsBinaryStandard = Binary.CreateStandardOperatorsTable (this); + OperatorsBinaryEquality = Binary.CreateEqualityOperatorsTable (this); + OperatorsBinaryUnsafe = Binary.CreatePointerOperatorsTable (this); + OperatorsUnary = Unary.CreatePredefinedOperatorsTable (this); + OperatorsUnaryMutator = UnaryMutator.CreatePredefinedOperatorsTable (this); + + BinaryPromotionsTypes = ConstantFold.CreateBinaryPromotionsTypes (this); + SwitchUserTypes = Switch.CreateSwitchUserTypes (this); + + types = new BuiltinTypeSpec[] { + Object, ValueType, Attribute, + Int, UInt, Long, ULong, Float, Double, Char, Short, Decimal, Bool, SByte, Byte, UShort, String, + Enum, Delegate, MulticastDelegate, Void, Array, Type, IEnumerator, IEnumerable, IDisposable, + IntPtr, UIntPtr, RuntimeFieldHandle, RuntimeTypeHandle, Exception }; + } + + public BuiltinTypeSpec[] AllTypes { + get { + return types; + } + } + + public bool CheckDefinitions (ModuleContainer module) + { + var ctx = module.Compiler; + foreach (var p in types) { + var found = PredefinedType.Resolve (module, p.Kind, p.Namespace, p.Name, p.Arity); + if (found == null || found == p) + continue; + + var tc = found.MemberDefinition as TypeContainer; + if (tc != null) { + var ns = module.GlobalRootNamespace.GetNamespace (p.Namespace, false); + ns.SetBuiltinType (p); + + tc.SetPredefinedSpec (p); + p.SetDefinition (found); + } + } + + if (ctx.Report.Errors != 0) + return false; + + // Set internal build-in types + Dynamic.SetDefinition (Object); + + return true; + } + } + + // + // Compiler predefined types. Usually used for compiler generated + // code or for comparison against well known framework type. They + // may not exist as they are optional + // + class PredefinedTypes + { + public readonly PredefinedType ArgIterator; + public readonly PredefinedType TypedReference; + public readonly PredefinedType MarshalByRefObject; + public readonly PredefinedType RuntimeHelpers; + public readonly PredefinedType IAsyncResult; + public readonly PredefinedType AsyncCallback; + public readonly PredefinedType RuntimeArgumentHandle; + public readonly PredefinedType CharSet; + public readonly PredefinedType IsVolatile; + public readonly PredefinedType IEnumeratorGeneric; + public readonly PredefinedType IListGeneric; + public readonly PredefinedType ICollectionGeneric; + public readonly PredefinedType IEnumerableGeneric; + public readonly PredefinedType Nullable; + public readonly PredefinedType Activator; + public readonly PredefinedType Interlocked; + public readonly PredefinedType Monitor; + public readonly PredefinedType NotSupportedException; + public readonly PredefinedType RuntimeFieldHandle; + public readonly PredefinedType RuntimeMethodHandle; + public readonly PredefinedType SecurityAction; + public readonly PredefinedType Dictionary; + public readonly PredefinedType Hashtable; + + // + // C# 3.0 + // + public readonly PredefinedType Expression; + public readonly PredefinedType ExpressionGeneric; + public readonly PredefinedType ParameterExpression; + public readonly PredefinedType FieldInfo; + public readonly PredefinedType MethodBase; + public readonly PredefinedType MethodInfo; + public readonly PredefinedType ConstructorInfo; + + // + // C# 4.0 + // + public readonly PredefinedType Binder; + public readonly PredefinedType CallSite; + public readonly PredefinedType CallSiteGeneric; + public readonly PredefinedType BinderFlags; + + // + // C# 5.0 + // + public readonly PredefinedType AsyncVoidMethodBuilder; + public readonly PredefinedType AsyncTaskMethodBuilder; + public readonly PredefinedType AsyncTaskMethodBuilderGeneric; + public readonly PredefinedType Action; + public readonly PredefinedType Task; + public readonly PredefinedType TaskGeneric; + + public PredefinedTypes (ModuleContainer module) + { + TypedReference = new PredefinedType (module, MemberKind.Struct, "System", "TypedReference"); + ArgIterator = new PredefinedType (module, MemberKind.Struct, "System", "ArgIterator"); + + MarshalByRefObject = new PredefinedType (module, MemberKind.Class, "System", "MarshalByRefObject"); + RuntimeHelpers = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "RuntimeHelpers"); + IAsyncResult = new PredefinedType (module, MemberKind.Interface, "System", "IAsyncResult"); + AsyncCallback = new PredefinedType (module, MemberKind.Delegate, "System", "AsyncCallback"); + RuntimeArgumentHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeArgumentHandle"); + CharSet = new PredefinedType (module, MemberKind.Enum, "System.Runtime.InteropServices", "CharSet"); + IsVolatile = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "IsVolatile"); + IEnumeratorGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerator", 1); + IListGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IList", 1); + ICollectionGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "ICollection", 1); + IEnumerableGeneric = new PredefinedType (module, MemberKind.Interface, "System.Collections.Generic", "IEnumerable", 1); + Nullable = new PredefinedType (module, MemberKind.Struct, "System", "Nullable", 1); + Activator = new PredefinedType (module, MemberKind.Class, "System", "Activator"); + Interlocked = new PredefinedType (module, MemberKind.Class, "System.Threading", "Interlocked"); + Monitor = new PredefinedType (module, MemberKind.Class, "System.Threading", "Monitor"); + NotSupportedException = new PredefinedType (module, MemberKind.Class, "System", "NotSupportedException"); + RuntimeFieldHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeFieldHandle"); + RuntimeMethodHandle = new PredefinedType (module, MemberKind.Struct, "System", "RuntimeMethodHandle"); + SecurityAction = new PredefinedType (module, MemberKind.Enum, "System.Security.Permissions", "SecurityAction"); + Dictionary = new PredefinedType (module, MemberKind.Class, "System.Collections.Generic", "Dictionary", 2); + Hashtable = new PredefinedType (module, MemberKind.Class, "System.Collections", "Hashtable"); + + Expression = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression"); + ExpressionGeneric = new PredefinedType (module, MemberKind.Class, "System.Linq.Expressions", "Expression", 1); + 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"); + MethodInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "MethodInfo"); + ConstructorInfo = new PredefinedType (module, MemberKind.Class, "System.Reflection", "ConstructorInfo"); + + CallSite = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite"); + CallSiteGeneric = new PredefinedType (module, MemberKind.Class, "System.Runtime.CompilerServices", "CallSite", 1); + Binder = new PredefinedType (module, MemberKind.Class, "Microsoft.CSharp.RuntimeBinder", "Binder"); + BinderFlags = new PredefinedType (module, MemberKind.Enum, "Microsoft.CSharp.RuntimeBinder", "CSharpBinderFlags"); + + Action = new PredefinedType (module, MemberKind.Delegate, "System", "Action"); + AsyncVoidMethodBuilder = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncVoidMethodBuilder"); + AsyncTaskMethodBuilder = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder"); + AsyncTaskMethodBuilderGeneric = new PredefinedType (module, MemberKind.Struct, "System.Runtime.CompilerServices", "AsyncTaskMethodBuilder", 1); + Task = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task"); + TaskGeneric = new PredefinedType (module, MemberKind.Class, "System.Threading.Tasks", "Task", 1); + + // + // Define types which are used for comparison. It does not matter + // if they don't exist as no error report is needed + // + if (TypedReference.Define ()) + TypedReference.TypeSpec.IsSpecialRuntimeType = true; + + if (ArgIterator.Define ()) + ArgIterator.TypeSpec.IsSpecialRuntimeType = true; + + if (IEnumerableGeneric.Define ()) + IEnumerableGeneric.TypeSpec.IsGenericIterateInterface = true; + + if (IListGeneric.Define ()) + IListGeneric.TypeSpec.IsGenericIterateInterface = true; + + if (ICollectionGeneric.Define ()) + ICollectionGeneric.TypeSpec.IsGenericIterateInterface = true; + + if (Nullable.Define ()) + Nullable.TypeSpec.IsNullableType = true; + + if (ExpressionGeneric.Define ()) + ExpressionGeneric.TypeSpec.IsExpressionTreeType = true; + + Task.Define (); + if (TaskGeneric.Define ()) + TaskGeneric.TypeSpec.IsGenericTask = true; + } + } + + class PredefinedMembers + { + public readonly PredefinedMember ActivatorCreateInstance; + public readonly PredefinedMember AsyncTaskMethodBuilderCreate; + public readonly PredefinedMember AsyncTaskMethodBuilderSetResult; + public readonly PredefinedMember AsyncTaskMethodBuilderTask; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericCreate; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericSetResult; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericTask; + public readonly PredefinedMember AsyncVoidMethodBuilderCreate; + public readonly PredefinedMember AsyncVoidMethodBuilderSetException; + public readonly PredefinedMember AsyncVoidMethodBuilderSetResult; + public readonly PredefinedMember DecimalCtor; + public readonly PredefinedMember DecimalCtorInt; + public readonly PredefinedMember DecimalCtorLong; + public readonly PredefinedMember DecimalConstantAttributeCtor; + public readonly PredefinedMember DefaultMemberAttributeCtor; + public readonly PredefinedMember DelegateCombine; + public readonly PredefinedMember DelegateEqual; + public readonly PredefinedMember DelegateInequal; + public readonly PredefinedMember DelegateRemove; + public readonly PredefinedMember DynamicAttributeCtor; + public readonly PredefinedMember FieldInfoGetFieldFromHandle; + public readonly PredefinedMember FieldInfoGetFieldFromHandle2; + public readonly PredefinedMember IDisposableDispose; + public readonly PredefinedMember IEnumerableGetEnumerator; + public readonly PredefinedMember InterlockedCompareExchange; + public readonly PredefinedMember InterlockedCompareExchange_T; + public readonly PredefinedMember FixedBufferAttributeCtor; + public readonly PredefinedMember MethodInfoGetMethodFromHandle; + public readonly PredefinedMember MethodInfoGetMethodFromHandle2; + public readonly PredefinedMember MonitorEnter; + public readonly PredefinedMember MonitorEnter_v4; + public readonly PredefinedMember MonitorExit; + public readonly PredefinedMember RuntimeCompatibilityWrapNonExceptionThrows; + public readonly PredefinedMember RuntimeHelpersInitializeArray; + public readonly PredefinedMember RuntimeHelpersOffsetToStringData; + public readonly PredefinedMember SecurityActionRequestMinimum; + public readonly PredefinedMember StringEmpty; + public readonly PredefinedMember StringEqual; + public readonly PredefinedMember StringInequal; + public readonly PredefinedMember StructLayoutAttributeCtor; + public readonly PredefinedMember StructLayoutCharSet; + public readonly PredefinedMember StructLayoutSize; + public readonly PredefinedMember TypeGetTypeFromHandle; + + public PredefinedMembers (ModuleContainer module) + { + var types = module.PredefinedTypes; + var atypes = module.PredefinedAttributes; + var btypes = module.Compiler.BuiltinTypes; + + ActivatorCreateInstance = new PredefinedMember (module, types.Activator, + MemberFilter.Method ("CreateInstance", 1, ParametersCompiled.EmptyReadOnlyParameters, null)); + + AsyncTaskMethodBuilderCreate = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncTaskMethodBuilder.TypeSpec)); + + AsyncTaskMethodBuilderSetResult = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); + + AsyncTaskMethodBuilderTask = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Property ("Task", null)); + + AsyncTaskMethodBuilderGenericCreate = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, + MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); + + AsyncTaskMethodBuilderGenericSetResult = new PredefinedMember (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)); + + AsyncTaskMethodBuilderGenericTask = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, + MemberFilter.Property ("Task", null)); + + AsyncVoidMethodBuilderCreate = new PredefinedMember (module, types.AsyncVoidMethodBuilder, + MemberFilter.Method ("Create", 0, ParametersCompiled.EmptyReadOnlyParameters, types.AsyncVoidMethodBuilder.TypeSpec)); + + AsyncVoidMethodBuilderSetException = new PredefinedMember (module, types.AsyncVoidMethodBuilder, + MemberFilter.Method ("SetException", 0, null, btypes.Void)); + + AsyncVoidMethodBuilderSetResult = new PredefinedMember (module, types.AsyncVoidMethodBuilder, + MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); + + DecimalCtor = new PredefinedMember (module, btypes.Decimal, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved ( + btypes.Int, btypes.Int, btypes.Int, btypes.Bool, btypes.Byte))); + + DecimalCtorInt = new PredefinedMember (module, btypes.Decimal, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Int))); + + DecimalCtorLong = new PredefinedMember (module, btypes.Decimal, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Long))); + + DecimalConstantAttributeCtor = new PredefinedMember (module, atypes.DecimalConstant, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved ( + btypes.Byte, btypes.Byte, btypes.UInt, btypes.UInt, btypes.UInt))); + + DefaultMemberAttributeCtor = new PredefinedMember (module, atypes.DefaultMember, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.String))); + + DelegateCombine = new PredefinedMember (module, btypes.Delegate, "Combine", btypes.Delegate, btypes.Delegate); + DelegateRemove = new PredefinedMember (module, btypes.Delegate, "Remove", btypes.Delegate, btypes.Delegate); + + DelegateEqual = new PredefinedMember (module, btypes.Delegate, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool)); + + DelegateInequal = new PredefinedMember (module, btypes.Delegate, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool)); + + DynamicAttributeCtor = new PredefinedMember (module, atypes.Dynamic, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved ( + ArrayContainer.MakeType (module, btypes.Bool)))); + + FieldInfoGetFieldFromHandle = new PredefinedMember (module, types.FieldInfo, + "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle); + + FieldInfoGetFieldFromHandle2 = new PredefinedMember (module, types.FieldInfo, + "GetFieldFromHandle", MemberKind.Method, types.RuntimeFieldHandle, new PredefinedType (btypes.RuntimeTypeHandle)); + + FixedBufferAttributeCtor = new PredefinedMember (module, atypes.FixedBuffer, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Type, btypes.Int))); + + IDisposableDispose = new PredefinedMember (module, btypes.IDisposable, "Dispose", TypeSpec.EmptyTypes); + + IEnumerableGetEnumerator = new PredefinedMember (module, btypes.IEnumerable, + "GetEnumerator", TypeSpec.EmptyTypes); + + InterlockedCompareExchange = new PredefinedMember (module, types.Interlocked, + MemberFilter.Method ("CompareExchange", 0, + new ParametersImported ( + new[] { + new ParameterData (null, Parameter.Modifier.REF), + new ParameterData (null, Parameter.Modifier.NONE), + new ParameterData (null, Parameter.Modifier.NONE) + }, + new[] { + btypes.Int, btypes.Int, btypes.Int + }, + false), + btypes.Int)); + + InterlockedCompareExchange_T = new PredefinedMember (module, types.Interlocked, + MemberFilter.Method ("CompareExchange", 1, + new ParametersImported ( + new[] { + new ParameterData (null, Parameter.Modifier.REF), + new ParameterData (null, Parameter.Modifier.NONE), + new ParameterData (null, Parameter.Modifier.NONE) + }, + new[] { + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null), + }, false), + null)); + + MethodInfoGetMethodFromHandle = new PredefinedMember (module, types.MethodBase, + "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle); + + MethodInfoGetMethodFromHandle2 = new PredefinedMember (module, types.MethodBase, + "GetMethodFromHandle", MemberKind.Method, types.RuntimeMethodHandle, new PredefinedType (btypes.RuntimeTypeHandle)); + + MonitorEnter = new PredefinedMember (module, types.Monitor, "Enter", btypes.Object); + + MonitorEnter_v4 = new PredefinedMember (module, types.Monitor, + MemberFilter.Method ("Enter", 0, + new ParametersImported (new[] { + new ParameterData (null, Parameter.Modifier.NONE), + new ParameterData (null, Parameter.Modifier.REF) + }, + new[] { + btypes.Object, btypes.Bool + }, false), null)); + + MonitorExit = new PredefinedMember (module, types.Monitor, "Exit", btypes.Object); + + RuntimeCompatibilityWrapNonExceptionThrows = new PredefinedMember (module, atypes.RuntimeCompatibility, + MemberFilter.Property ("WrapNonExceptionThrows", btypes.Bool)); + + RuntimeHelpersInitializeArray = new PredefinedMember (module, types.RuntimeHelpers, + "InitializeArray", btypes.Array, btypes.RuntimeFieldHandle); + + RuntimeHelpersOffsetToStringData = new PredefinedMember (module, types.RuntimeHelpers, + MemberFilter.Property ("OffsetToStringData", btypes.Int)); + + SecurityActionRequestMinimum = new PredefinedMember (module, types.SecurityAction, "RequestMinimum", + MemberKind.Field, types.SecurityAction); + + StringEmpty = new PredefinedMember (module, btypes.String, MemberFilter.Field ("Empty", btypes.String)); + + StringEqual = new PredefinedMember (module, btypes.String, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Equality), 0, MemberKind.Operator, null, btypes.Bool)); + + StringInequal = new PredefinedMember (module, btypes.String, + new MemberFilter (Operator.GetMetadataName (Operator.OpType.Inequality), 0, MemberKind.Operator, null, btypes.Bool)); + + StructLayoutAttributeCtor = new PredefinedMember (module, atypes.StructLayout, + MemberFilter.Constructor (ParametersCompiled.CreateFullyResolved (btypes.Short))); + + StructLayoutCharSet = new PredefinedMember (module, atypes.StructLayout, "CharSet", + MemberKind.Field, types.CharSet); + + StructLayoutSize = new PredefinedMember (module, atypes.StructLayout, + MemberFilter.Field ("Size", btypes.Int)); + + TypeGetTypeFromHandle = new PredefinedMember (module, btypes.Type, "GetTypeFromHandle", btypes.RuntimeTypeHandle); + } + } + + public class PredefinedType + { + readonly string name; + readonly string ns; + readonly int arity; + readonly MemberKind kind; + protected readonly ModuleContainer module; + protected TypeSpec type; + + public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name, int arity) + : this (module, kind, ns, name) + { + this.arity = arity; + } + + public PredefinedType (ModuleContainer module, MemberKind kind, string ns, string name) + { + this.module = module; + this.kind = kind; + this.name = name; + this.ns = ns; + } + + public PredefinedType (BuiltinTypeSpec type) + { + this.kind = type.Kind; + this.name = type.Name; + this.ns = type.Namespace; + this.type = type; + } + + #region Properties + + public int Arity { + get { + return arity; + } + } + + public bool IsDefined { + get { + return type != null; + } + } + + public string Name { + get { + return name; + } + } + + public string Namespace { + get { + return ns; + } + } + + public TypeSpec TypeSpec { + get { + return type; + } + } + + #endregion + + public bool Define () + { + if (type != null) + return true; + + type = Resolve (module, kind, ns, name, arity, false); + return type != null; + } + + public string GetSignatureForError () + { + return ns + "." + name; + } + + public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity) + { + return Resolve (module, kind, ns, name, arity, true); + } + + public static TypeSpec Resolve (ModuleContainer module, MemberKind kind, string ns, string name, int arity, bool reportErrors) + { + Namespace type_ns = module.GlobalRootNamespace.GetNamespace (ns, true); + var found = type_ns.GetAllTypes (name); + if (found == null) { + if (reportErrors) + module.Compiler.Report.Error (518, "The predefined type `{0}.{1}' is not defined or imported", ns, name); + + return null; + } + + TypeSpec best_match = null; + foreach (var candidate in found) { + if (candidate.Kind != kind) { + if (candidate.Kind == MemberKind.Struct && kind == MemberKind.Void && candidate.MemberDefinition is TypeContainer) { + // Void is declared as struct but we keep it internally as + // special kind, the swap will be done by caller + } else { + continue; + } + } + + if (candidate.Arity != arity) + continue; + + if ((candidate.Modifiers & Modifiers.INTERNAL) != 0 && !candidate.MemberDefinition.IsInternalAsPublic (module.DeclaringAssembly)) + continue; + + if (best_match == null) { + best_match = candidate; + continue; + } + + var other_match = best_match; + if (!best_match.MemberDefinition.IsImported && + module.Compiler.BuiltinTypes.Object.MemberDefinition.DeclaringAssembly == candidate.MemberDefinition.DeclaringAssembly) { + best_match = candidate; + } + + string location; + if (best_match.MemberDefinition is MemberCore) { + location = ((MemberCore) best_match.MemberDefinition).Location.Name; + } else { + var assembly = (ImportedAssemblyDefinition) best_match.MemberDefinition.DeclaringAssembly; + location = Path.GetFileName (assembly.Location); + } + + module.Compiler.Report.SymbolRelatedToPreviousError (other_match); + module.Compiler.Report.SymbolRelatedToPreviousError (candidate); + + module.Compiler.Report.Warning (1685, 1, + "The predefined type `{0}.{1}' is defined multiple times. Using definition from `{2}'", + ns, name, location); + + break; + } + + if (best_match == null && reportErrors) { + Location loc; + if (found[0].MemberDefinition is MemberCore) { + loc = ((MemberCore) found[0].MemberDefinition).Location; + } else { + loc = Location.Null; + module.Compiler.Report.SymbolRelatedToPreviousError (found[0]); + } + + module.Compiler.Report.Error (520, loc, "The predefined type `{0}.{1}' is not declared correctly", ns, name); + } + + return best_match; + } + + public TypeSpec Resolve () + { + if (type == null) + type = Resolve (module, kind, ns, name, arity); + + return type; + } + } + + class PredefinedMember where T : MemberSpec + { + readonly ModuleContainer module; + T member; + TypeSpec declaring_type; + readonly PredefinedType declaring_type_predefined; + readonly PredefinedType[] parameters_predefined; + MemberFilter filter; + + public PredefinedMember (ModuleContainer module, PredefinedType type, MemberFilter filter) + { + this.module = module; + this.declaring_type_predefined = type; + this.filter = filter; + } + + public PredefinedMember (ModuleContainer module, TypeSpec type, MemberFilter filter) + { + this.module = module; + this.declaring_type = type; + this.filter = filter; + } + + public PredefinedMember (ModuleContainer module, PredefinedType type, string name, params TypeSpec[] types) + : this (module, type, MemberFilter.Method (name, 0, ParametersCompiled.CreateFullyResolved (types), null)) + { + } + + 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; + } + + public PredefinedMember (ModuleContainer module, BuiltinTypeSpec type, string name, params TypeSpec[] types) + : this (module, type, MemberFilter.Method (name, 0, ParametersCompiled.CreateFullyResolved (types), null)) + { + } + + public T Get () + { + if (member != null) + return member; + + if (declaring_type == null) { + if (!declaring_type_predefined.Define ()) + return null; + + 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.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); + } + + member = MemberCache.FindMember (declaring_type, filter, BindingRestriction.DeclaredOnly) as T; + if (member == null) + return null; + + if (!member.IsAccessible (module)) + return null; + + return member; + } + + public T Resolve (Location loc) + { + if (member != null) + return member; + + if (Get () != null) + return member; + + if (declaring_type == null) { + if (declaring_type_predefined.Resolve () == null) + 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); + } + + string method_args = null; + if (filter.Parameters != null) + method_args = filter.Parameters.GetSignatureForError (); + + module.Compiler.Report.Error (656, loc, "The compiler required member `{0}.{1}{2}' could not be found or is inaccessible", + declaring_type.GetSignatureForError (), filter.Name, method_args); + + return null; + } + } + + partial class TypeManager { + + /// + /// Returns the C# name of a type if possible, or the full type name otherwise + /// + static public string CSharpName (TypeSpec t) + { + return t.GetSignatureForError (); + } + + static public string CSharpName (IList types) + { + if (types.Count == 0) + return string.Empty; + + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < types.Count; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (CSharpName (types [i])); + } + return sb.ToString (); + } + + static public string GetFullNameSignature (MemberSpec mi) + { + return mi.GetSignatureForError (); + } + + static public string CSharpSignature (MemberSpec mb) + { + 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) + { +// TypeParameter tparam = LookupTypeParameter (type); +// TypeParameter pparam = LookupTypeParameter (parent); + + if (type.Kind == MemberKind.TypeParameter && parent.Kind == MemberKind.TypeParameter) { // (tparam != null) && (pparam != null)) { + if (type == parent) + return true; + + throw new NotImplementedException ("net"); +// return tparam.IsSubclassOf (parent); + } + + do { + if (IsInstantiationOfSameGenericType (type, parent)) + return true; + + type = type.BaseType; + } while (type != null); + + return false; + } + + // + // Checks whether `type' is a nested child of `parent'. + // + public static bool IsNestedChildOf (TypeSpec type, ITypeDefinition parent) + { + if (type == null) + return false; + + if (type.MemberDefinition == parent) + return false; + + type = type.DeclaringType; + while (type != null) { + if (type.MemberDefinition == parent) + return true; + + type = type.DeclaringType; + } + + return false; + } + + public static TypeSpec GetElementType (TypeSpec t) + { + return ((ElementTypeSpec)t).Element; + } + + /// + /// This method is not implemented by MS runtime for dynamic types + /// + public static bool HasElementType (TypeSpec t) + { + return t is ElementTypeSpec; + } + + /// + /// Utility function that can be used to probe whether a type + /// is managed or not. + /// + public static bool VerifyUnmanaged (ModuleContainer rc, TypeSpec t, Location loc) + { + while (t.IsPointer) + t = GetElementType (t); + + if (IsUnmanagedType (t)) + return true; + + 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}'", + CSharpName (t)); + + return false; + } +#region Generics + // This method always return false for non-generic compiler, + // while Type.IsGenericParameter is returned if it is supported. + public static bool IsGenericParameter (TypeSpec type) + { + return type.IsGenericParameter; + } + + public static bool IsGenericType (TypeSpec type) + { + return type.IsGeneric; + } + + public static TypeSpec[] GetTypeArguments (TypeSpec t) + { + // TODO: return empty array !! + return t.TypeArguments; + } + + /// + /// Check whether `type' and `parent' are both instantiations of the same + /// generic type. Note that we do not check the type parameters here. + /// + public static bool IsInstantiationOfSameGenericType (TypeSpec type, TypeSpec parent) + { + return type == parent || type.MemberDefinition == parent.MemberDefinition; + } +#endregion +} + +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs new file mode 100644 index 0000000000..8c0a5ddc2f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs @@ -0,0 +1,1759 @@ +// +// typespec.cs: Type specification +// +// Authors: Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright 2010 Novell, Inc +// + +using System; +using System.Collections.Generic; +using System.Text; + +#if STATIC +using MetaType = IKVM.Reflection.Type; +using IKVM.Reflection; +#else +using MetaType = System.Type; +using System.Reflection; +#endif + +namespace Mono.CSharp +{ + public class TypeSpec : MemberSpec + { + protected MetaType info; + protected MemberCache cache; + protected IList ifaces; + TypeSpec base_type; + + Dictionary inflated_instances; + + public static readonly TypeSpec[] EmptyTypes = new TypeSpec[0]; + +#if !STATIC + // Reflection Emit hacking + static readonly Type TypeBuilder; + static readonly Type GenericTypeBuilder; + + static TypeSpec () + { + var assembly = typeof (object).Assembly; + TypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilder"); + GenericTypeBuilder = assembly.GetType ("System.Reflection.MonoGenericClass"); + if (GenericTypeBuilder == null) + GenericTypeBuilder = assembly.GetType ("System.Reflection.Emit.TypeBuilderInstantiation"); + } +#endif + + public TypeSpec (MemberKind kind, TypeSpec declaringType, ITypeDefinition definition, MetaType info, Modifiers modifiers) + : base (kind, declaringType, definition, modifiers) + { + this.declaringType = declaringType; + this.info = info; + + if (definition != null && definition.TypeParametersCount > 0) + state |= StateFlags.IsGeneric; + } + + #region Properties + + public override int Arity { + get { + return MemberDefinition.TypeParametersCount; + } + } + + public virtual TypeSpec BaseType { + get { + return base_type; + } + set { + base_type = value; + } + } + + public virtual BuiltinTypeSpec.Type BuiltinType { + get { + return BuiltinTypeSpec.Type.None; + } + } + + public bool HasDynamicElement { + get { + return (state & StateFlags.HasDynamicElement) != 0; + } + } + + public virtual IList Interfaces { + get { + return ifaces; + } + set { + ifaces = value; + } + } + + public bool IsArray { + get { + return Kind == MemberKind.ArrayType; + } + } + + public bool IsAttribute { + get { + if (!IsClass) + return false; + + var type = this; + do { + if (type.BuiltinType == BuiltinTypeSpec.Type.Attribute) + return true; + + if (type.IsGeneric) + return false; + + type = type.base_type; + } while (type != null); + + return false; + } + } + + public bool IsInterface { + get { + return Kind == MemberKind.Interface; + } + } + + public bool IsClass { + get { + return Kind == MemberKind.Class; + } + } + + public bool IsConstantCompatible { + get { + if ((Kind & (MemberKind.Enum | MemberKind.Class | MemberKind.Interface | MemberKind.Delegate | MemberKind.ArrayType)) != 0) + return true; + + switch (BuiltinType) { + case BuiltinTypeSpec.Type.Int: + case BuiltinTypeSpec.Type.UInt: + case BuiltinTypeSpec.Type.Long: + case BuiltinTypeSpec.Type.ULong: + case BuiltinTypeSpec.Type.Float: + case BuiltinTypeSpec.Type.Double: + case BuiltinTypeSpec.Type.Char: + case BuiltinTypeSpec.Type.Short: + case BuiltinTypeSpec.Type.Decimal: + case BuiltinTypeSpec.Type.Bool: + case BuiltinTypeSpec.Type.SByte: + case BuiltinTypeSpec.Type.Byte: + case BuiltinTypeSpec.Type.UShort: + case BuiltinTypeSpec.Type.Dynamic: + return true; + } + + return false; + } + } + + public bool IsDelegate { + get { + return Kind == MemberKind.Delegate; + } + } + + // + // Returns true for instances of Expression + // + public virtual bool IsExpressionTreeType { + get { + return false; + } + set { + state = value ? state | StateFlags.InflatedExpressionType : state & ~StateFlags.InflatedExpressionType; + } + } + + public bool IsEnum { + get { + return Kind == MemberKind.Enum; + } + } + + // + // Returns true for instances of IList, IEnumerable, ICollection + // + public virtual bool IsGenericIterateInterface { + get { + return false; + } + set { + state = value ? state | StateFlags.GenericIterateInterface : state & ~StateFlags.GenericIterateInterface; + } + } + + // + // Returns true for instances of System.Threading.Tasks.Task + // + public virtual bool IsGenericTask { + get { + return false; + } + set { + state = value ? state | StateFlags.GenericTask : state & ~StateFlags.GenericTask; + } + } + + // TODO: Should probably do + // IsGenericType -- recursive + // HasTypeParameter -- non-recursive + public bool IsGenericOrParentIsGeneric { + get { + var ts = this; + do { + if (ts.IsGeneric) + return true; + ts = ts.declaringType; + } while (ts != null); + + return false; + } + } + + public bool IsGenericParameter { + get { + return Kind == MemberKind.TypeParameter; + } + } + + // + // Returns true for instances of Nullable + // + public virtual bool IsNullableType { + get { + return false; + } + set { + state = value ? state | StateFlags.InflatedNullableType : state & ~StateFlags.InflatedNullableType; + } + } + + public bool IsNested { + get { return declaringType != null && Kind != MemberKind.TypeParameter; } + } + + public bool IsPointer { + get { + return Kind == MemberKind.PointerType; + } + } + + public bool IsSealed { + get { return (Modifiers & Modifiers.SEALED) != 0; } + } + + public bool IsSpecialRuntimeType { + get { + return (state & StateFlags.SpecialRuntimeType) != 0; + } + set { + state = value ? state | StateFlags.SpecialRuntimeType : state & ~StateFlags.SpecialRuntimeType; + } + } + + public bool IsStruct { + get { + return Kind == MemberKind.Struct; + } + } + + public bool IsTypeBuilder { + get { +#if STATIC + return true; +#else + var meta = GetMetaInfo().GetType (); + return meta == TypeBuilder || meta == GenericTypeBuilder; +#endif + } + } + + public MemberCache MemberCache { + get { + if (cache == null || (state & StateFlags.PendingMemberCacheMembers) != 0) + InitializeMemberCache (false); + + return cache; + } + set { + if (cache != null) + throw new InternalErrorException ("Membercache reset"); + + cache = value; + } + } + + public MemberCache MemberCacheTypes { + get { + if (cache == null) + InitializeMemberCache (true); + + return cache; + } + } + + public new ITypeDefinition MemberDefinition { + get { + return (ITypeDefinition) definition; + } + } + + // TODO: Wouldn't be better to rely on cast to InflatedTypeSpec and + // remove the property, YES IT WOULD !!! + public virtual TypeSpec[] TypeArguments { + get { return TypeSpec.EmptyTypes; } + } + + #endregion + + public bool AddInterface (TypeSpec iface) + { + if ((state & StateFlags.InterfacesExpanded) != 0) + throw new InternalErrorException ("Modifying expanded interface list"); + + if (ifaces == null) { + ifaces = new List () { iface }; + return true; + } + + if (!ifaces.Contains (iface)) { + ifaces.Add (iface); + return true; + } + + return false; + } + + public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa) + { + if (Kind != MemberKind.Class) + throw new InternalErrorException (); + + if (!pa.IsDefined) + return Attribute.DefaultUsageAttribute; + + AttributeUsageAttribute aua = null; + var type = this; + while (type != null) { + aua = type.MemberDefinition.GetAttributeUsage (pa); + if (aua != null) + break; + + type = type.BaseType; + } + + return aua; + } + + public virtual MetaType GetMetaInfo () + { + return info; + } + + public virtual TypeSpec GetDefinition () + { + return this; + } + + public override string GetSignatureForDocumentation () + { + StringBuilder sb = new StringBuilder (); + if (IsNested) { + sb.Append (DeclaringType.GetSignatureForDocumentation ()); + } else { + sb.Append (MemberDefinition.Namespace); + } + + if (sb.Length != 0) + sb.Append ("."); + + sb.Append (Name); + if (Arity > 0) { + if (this is InflatedTypeSpec) { + sb.Append ("{"); + for (int i = 0; i < Arity; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (TypeArguments[i].GetSignatureForDocumentation ()); + } + sb.Append ("}"); + } else { + sb.Append ("`"); + sb.Append (Arity.ToString ()); + } + } + + return sb.ToString (); + } + + public string GetExplicitNameSignatureForDocumentation () + { + StringBuilder sb = new StringBuilder (); + if (IsNested) { + sb.Append (DeclaringType.GetExplicitNameSignatureForDocumentation ()); + } else if (MemberDefinition.Namespace != null) { + sb.Append (MemberDefinition.Namespace.Replace ('.', '#')); + } + + if (sb.Length != 0) + sb.Append ("#"); + + sb.Append (Name); + if (Arity > 0) { + sb.Append ("{"); + for (int i = 0; i < Arity; ++i) { + if (i > 0) + sb.Append (","); + + sb.Append (TypeArguments[i].GetExplicitNameSignatureForDocumentation ()); + } + sb.Append ("}"); + } + + return sb.ToString (); + } + + public override string GetSignatureForError () + { + string s; + + if (IsNested) { + s = DeclaringType.GetSignatureForError (); + } else if (MemberDefinition is AnonymousTypeClass) { + return ((AnonymousTypeClass) MemberDefinition).GetSignatureForError (); + } else { + s = MemberDefinition.Namespace; + } + + if (!string.IsNullOrEmpty (s)) + s += "."; + + return s + Name + GetTypeNameSignature (); + } + + public string GetSignatureForErrorIncludingAssemblyName () + { + return string.Format ("{0} [{1}]", GetSignatureForError (), MemberDefinition.DeclaringAssembly.FullName); + } + + protected virtual string GetTypeNameSignature () + { + if (!IsGeneric) + return null; + + return "<" + TypeManager.CSharpName (MemberDefinition.TypeParameters) + ">"; + } + + public bool ImplementsInterface (TypeSpec iface, bool variantly) + { + var t = this; + do { + if (t.Interfaces != null) { + foreach (TypeSpec i in t.Interfaces) { + if (i == iface || TypeSpecComparer.IsEqual (i, iface)) + return true; + + if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface)) + return true; + } + } + + // TODO: Why is it needed when we do it during import + t = t.BaseType; + } while (t != null); + + return false; + } + + protected virtual void InitializeMemberCache (bool onlyTypes) + { + try { + MemberDefinition.LoadMembers (this, onlyTypes, ref cache); + } catch (Exception e) { + throw new InternalErrorException (e, "Unexpected error when loading type `{0}'", GetSignatureForError ()); + } + + if (onlyTypes) + state |= StateFlags.PendingMemberCacheMembers; + else + state &= ~StateFlags.PendingMemberCacheMembers; + } + + // + // Is @baseClass base implementation of @type. With enabled @dynamicIsEqual the slower + // comparison is used to hide differences between `object' and `dynamic' for generic + // types. Should not be used for comparisons where G != G + // + public static bool IsBaseClass (TypeSpec type, TypeSpec baseClass, bool dynamicIsObject) + { + if (dynamicIsObject && baseClass.IsGeneric) { + // + // Returns true for a hierarchies like this when passing baseClass of A + // + // class B : A {} + // + type = type.BaseType; + while (type != null) { + if (TypeSpecComparer.IsEqual (type, baseClass)) + return true; + + type = type.BaseType; + } + + return false; + } + + while (type != null) { + type = type.BaseType; + if (type == baseClass) + return true; + } + + return false; + } + + public static bool IsReferenceType (TypeSpec t) + { + switch (t.Kind) { + case MemberKind.TypeParameter: + return ((TypeParameterSpec) t).IsReferenceType; + case MemberKind.Struct: + case MemberKind.Enum: + return false; + case MemberKind.InternalCompilerType: + // + // Null is considered to be a reference type + // + return t == InternalType.NullLiteral || t.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + default: + return true; + } + } + + public static bool IsValueType (TypeSpec t) + { + switch (t.Kind) { + case MemberKind.TypeParameter: + return ((TypeParameterSpec) t).IsValueType; + case MemberKind.Struct: + case MemberKind.Enum: + return true; + default: + return false; + } + } + + public override MemberSpec InflateMember (TypeParameterInflator inflator) + { + var targs = IsGeneric ? MemberDefinition.TypeParameters : TypeSpec.EmptyTypes; + + // + // When inflating nested type from inside the type instance will be same + // because type parameters are same for all nested types + // + if (DeclaringType == inflator.TypeInstance) { + return MakeGenericType (inflator.Context, targs); + } + + return new InflatedTypeSpec (inflator.Context, this, inflator.TypeInstance, targs); + } + + public InflatedTypeSpec MakeGenericType (IModuleContext context, TypeSpec[] targs) + { + if (targs.Length == 0 && !IsNested) + throw new ArgumentException ("Empty type arguments for type " + GetSignatureForError ()); + + InflatedTypeSpec instance; + + if (inflated_instances == null) { + inflated_instances = new Dictionary (TypeSpecComparer.Default); + + if (IsNested) { + instance = this as InflatedTypeSpec; + if (instance != null) { + // + // Nested types could be inflated on already inflated instances + // Caching this type ensured we are using same instance for + // inside/outside inflation using local type parameters + // + inflated_instances.Add (TypeArguments, instance); + } + } + } + + if (!inflated_instances.TryGetValue (targs, out instance)) { + if (GetDefinition () != this && !IsNested) + throw new InternalErrorException ("`{0}' must be type definition or nested non-inflated type to MakeGenericType", + GetSignatureForError ()); + + instance = new InflatedTypeSpec (context, this, declaringType, targs); + inflated_instances.Add (targs, instance); + } + + return instance; + } + + public virtual TypeSpec Mutate (TypeParameterMutator mutator) + { + return this; + } + + public override List ResolveMissingDependencies () + { + List missing = null; + + if (Kind == MemberKind.MissingType) { + missing = new List (); + missing.Add (this); + return missing; + } + + foreach (var targ in TypeArguments) { + if (targ.Kind == MemberKind.MissingType) { + if (missing == null) + missing = new List (); + + missing.Add (targ); + } + } + + if (Interfaces != null) { + foreach (var iface in Interfaces) { + if (iface.Kind == MemberKind.MissingType) { + if (missing == null) + missing = new List (); + + missing.Add (iface); + } + } + } + + if (missing != null || BaseType == null) + return missing; + + return BaseType.ResolveMissingDependencies (); + } + + public void SetMetaInfo (MetaType info) + { + if (this.info != null) + throw new InternalErrorException ("MetaInfo reset"); + + this.info = info; + } + + public void SetExtensionMethodContainer () + { + modifiers |= Modifiers.METHOD_EXTENSION; + } + } + + public sealed class BuiltinTypeSpec : TypeSpec + { + public enum Type + { + None = 0, + + // Ordered carefully for fast compares + FirstPrimitive = 1, + Bool = 1, + Byte = 2, + SByte = 3, + Char = 4, + Short = 5, + UShort = 6, + Int = 7, + UInt = 8, + Long = 9, + ULong = 10, + Float = 11, + Double = 12, + LastPrimitive = 12, + Decimal = 13, + + IntPtr = 14, + UIntPtr = 15, + + Object = 16, + Dynamic = 17, + String = 18, + Type = 19, + + ValueType = 20, + Enum = 21, + Delegate = 22, + MulticastDelegate = 23, + Array = 24, + + IEnumerator, + IEnumerable, + IDisposable, + Exception, + Attribute, + Other, + } + + readonly Type type; + readonly string ns; + readonly string name; + + public BuiltinTypeSpec (MemberKind kind, string ns, string name, Type builtinKind) + : base (kind, null, null, null, Modifiers.PUBLIC) + { + this.type = builtinKind; + this.ns = ns; + this.name = name; + } + + public BuiltinTypeSpec (string name, Type builtinKind) + : this (MemberKind.InternalCompilerType, "", name, builtinKind) + { + // Make all internal types CLS-compliant, non-obsolete, compact + state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected | StateFlags.MissingDependency_Undetected)) | StateFlags.CLSCompliant; + } + + #region Properties + + public override int Arity { + get { + return 0; + } + } + + public override BuiltinTypeSpec.Type BuiltinType { + get { + return type; + } + } + + public string FullName { + get { + return ns + '.' + name; + } + } + + public override string Name { + get { + return name; + } + } + + public string Namespace { + get { + return ns; + } + } + + #endregion + + public static bool IsPrimitiveType (TypeSpec type) + { + return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.LastPrimitive; + } + + public static bool IsPrimitiveTypeOrDecimal (TypeSpec type) + { + return type.BuiltinType >= Type.FirstPrimitive && type.BuiltinType <= Type.Decimal; + } + + public override string GetSignatureForError () + { + switch (Name) { + case "Int32": return "int"; + case "Int64": return "long"; + case "String": return "string"; + case "Boolean": return "bool"; + case "Void": return "void"; + case "Object": return "object"; + case "UInt32": return "uint"; + case "Int16": return "short"; + case "UInt16": return "ushort"; + case "UInt64": return "ulong"; + case "Single": return "float"; + case "Double": return "double"; + case "Decimal": return "decimal"; + case "Char": return "char"; + case "Byte": return "byte"; + case "SByte": return "sbyte"; + } + + if (ns.Length == 0) + return name; + + return FullName; + } + + // + // Returns the size of type if known, otherwise, 0 + // + public static int GetSize (TypeSpec type) + { + switch (type.BuiltinType) { + case Type.Int: + case Type.UInt: + case Type.Float: + return 4; + case Type.Long: + case Type.ULong: + case Type.Double: + return 8; + case Type.Byte: + case Type.SByte: + case Type.Bool: + return 1; + case Type.Short: + case Type.Char: + case Type.UShort: + return 2; + case Type.Decimal: + return 16; + default: + return 0; + } + } + + public void SetDefinition (ITypeDefinition td, MetaType type, Modifiers mod) + { + this.definition = td; + this.info = type; + this.modifiers |= (mod & ~Modifiers.AccessibilityMask); + } + + public void SetDefinition (TypeSpec ts) + { + this.definition = ts.MemberDefinition; + this.info = ts.GetMetaInfo (); + this.BaseType = ts.BaseType; + this.Interfaces = ts.Interfaces; + this.modifiers = ts.Modifiers; + } + } + + static class TypeSpecComparer + { + // + // Does strict reference comparion only + // + public static readonly DefaultImpl Default = new DefaultImpl (); + + public class DefaultImpl : IEqualityComparer + { + #region IEqualityComparer Members + + bool IEqualityComparer.Equals (TypeSpec[] x, TypeSpec[] y) + { + if (x == y) + return true; + + if (x.Length != y.Length) + return false; + + for (int i = 0; i < x.Length; ++i) + if (x[i] != y[i]) + return false; + + return true; + } + + int IEqualityComparer.GetHashCode (TypeSpec[] obj) + { + int hash = 0; + for (int i = 0; i < obj.Length; ++i) + hash = (hash << 5) - hash + obj[i].GetHashCode (); + + return hash; + } + + #endregion + } + + // + // When comparing type signature of overrides or overloads + // this version tolerates different MVARs at same position + // + public static class Override + { + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a == b) + return true; + + // + // Consider the following example: + // + // public abstract class A + // { + // public abstract T Foo(); + // } + // + // public class B : A + // { + // public override U Foo() { return default (U); } + // } + // + // Here, `T' and `U' are method type parameters from different methods + // (A.Foo and B.Foo), so both `==' and Equals() will fail. + // + // However, since we're determining whether B.Foo() overrides A.Foo(), + // we need to do a signature based comparision and consider them equal. + // + + var tp_a = a as TypeParameterSpec; + if (tp_a != null) { + var tp_b = b as TypeParameterSpec; + return tp_b != null && tp_a.IsMethodOwned == tp_b.IsMethodOwned && tp_a.DeclaredPosition == tp_b.DeclaredPosition; + } + + var ac_a = a as ArrayContainer; + if (ac_a != null) { + var ac_b = b as ArrayContainer; + return ac_b != null && ac_a.Rank == ac_b.Rank && IsEqual (ac_a.Element, ac_b.Element); + } + + if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object; + + if (a.MemberDefinition != b.MemberDefinition) + return false; + + do { + for (int i = 0; i < a.TypeArguments.Length; ++i) { + if (!IsEqual (a.TypeArguments[i], b.TypeArguments[i])) + return false; + } + + a = a.DeclaringType; + b = b.DeclaringType; + } while (a != null); + + return true; + } + + // + // Compares unordered arrays + // + public static bool IsSame (TypeSpec[] a, TypeSpec[] b) + { + if (a == b) + return true; + + if (a == null || b == null || a.Length != b.Length) + return false; + + for (int ai = 0; ai < a.Length; ++ai) { + bool found = false; + for (int bi = 0; bi < b.Length; ++bi) { + if (IsEqual (a[ai], b[bi])) { + found = true; + break; + } + } + + if (!found) + return false; + } + + return true; + } + + public static bool IsEqual (AParametersCollection a, AParametersCollection b) + { + if (a == b) + return true; + + if (a.Count != b.Count) + return false; + + for (int i = 0; i < a.Count; ++i) { + if (!IsEqual (a.Types[i], b.Types[i])) + return false; + + const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT; + if ((a.FixedParameters[i].ModFlags & ref_out) != (b.FixedParameters[i].ModFlags & ref_out)) + return false; + } + + return true; + } + } + + // + // Type variance equality comparison + // + public static class Variant + { + public static bool IsEqual (TypeSpec type1, TypeSpec type2) + { + if (!type1.IsGeneric || !type2.IsGeneric) + return false; + + var target_type_def = type2.MemberDefinition; + if (type1.MemberDefinition != target_type_def) + return false; + + var t1_targs = type1.TypeArguments; + var t2_targs = type2.TypeArguments; + var targs_definition = target_type_def.TypeParameters; + + if (!type1.IsInterface && !type1.IsDelegate) { + return false; + } + + for (int i = 0; i < targs_definition.Length; ++i) { + Variance v = targs_definition[i].Variance; + if (v == Variance.None) { + if (t1_targs[i] == t2_targs[i]) + continue; + return false; + } + + if (v == Variance.Covariant) { + if (!Convert.ImplicitReferenceConversionExists (t1_targs[i], t2_targs[i])) + return false; + } else if (!Convert.ImplicitReferenceConversionExists (t2_targs[i], t1_targs[i])) { + return false; + } + } + + return true; + } + } + + // + // Checks whether two generic instances may become equal for some + // particular instantiation (26.3.1). + // + public static class Unify + { + // + // Either @a or @b must be generic type + // + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a.MemberDefinition != b.MemberDefinition) { + var base_ifaces = a.Interfaces; + if (base_ifaces != null) { + foreach (var base_iface in base_ifaces) { + if (base_iface.Arity > 0 && IsEqual (base_iface, b)) + return true; + } + } + + return false; + } + + var ta = a.TypeArguments; + var tb = b.TypeArguments; + for (int i = 0; i < ta.Length; i++) { + if (!MayBecomeEqualGenericTypes (ta[i], tb[i])) + return false; + } + + return true; + } + + static bool ContainsTypeParameter (TypeSpec tparam, TypeSpec type) + { + TypeSpec[] targs = type.TypeArguments; + for (int i = 0; i < targs.Length; i++) { + if (tparam == targs[i]) + return true; + + if (ContainsTypeParameter (tparam, targs[i])) + return true; + } + + return false; + } + + /// + /// Check whether `a' and `b' may become equal generic types. + /// The algorithm to do that is a little bit complicated. + /// + static bool MayBecomeEqualGenericTypes (TypeSpec a, TypeSpec b) + { + if (a.IsGenericParameter) { + // + // If a is an array of a's type, they may never + // become equal. + // + if (b.IsArray) + return false; + + // + // If b is a generic parameter or an actual type, + // they may become equal: + // + // class X : I, I + // class X : I, I + // + if (b.IsGenericParameter) + return a != b && a.DeclaringType == b.DeclaringType; + + // + // We're now comparing a type parameter with a + // generic instance. They may become equal unless + // the type parameter appears anywhere in the + // generic instance: + // + // class X : I, I> + // -> error because you could instanciate it as + // X,int> + // + // class X : I, I> -> ok + // + + return !ContainsTypeParameter (a, b); + } + + if (b.IsGenericParameter) + return MayBecomeEqualGenericTypes (b, a); + + // + // At this point, neither a nor b are a type parameter. + // + // If one of them is a generic instance, compare them (if the + // other one is not a generic instance, they can never + // become equal). + // + if (TypeManager.IsGenericType (a) || TypeManager.IsGenericType (b)) + return IsEqual (a, b); + + // + // If both of them are arrays. + // + var a_ac = a as ArrayContainer; + if (a_ac != null) { + var b_ac = b as ArrayContainer; + if (b_ac == null || a_ac.Rank != b_ac.Rank) + return false; + + return MayBecomeEqualGenericTypes (a_ac.Element, b_ac.Element); + } + + // + // Ok, two ordinary types. + // + return false; + } + } + + public static bool Equals (TypeSpec[] x, TypeSpec[] y) + { + if (x == y) + return true; + + if (x.Length != y.Length) + return false; + + for (int i = 0; i < x.Length; ++i) + if (!IsEqual (x[i], y[i])) + return false; + + return true; + } + + // + // Identity type conversion + // + // Default reference comparison, it has to be used when comparing + // two possible dynamic/internal types + // + public static bool IsEqual (TypeSpec a, TypeSpec b) + { + if (a == b) { + // This also rejects dynamic == dynamic + return a.Kind != MemberKind.InternalCompilerType || a.BuiltinType == BuiltinTypeSpec.Type.Dynamic; + } + + if (a == null || b == null) + return false; + + if (a.IsArray) { + var a_a = (ArrayContainer) a; + var b_a = b as ArrayContainer; + if (b_a == null) + return false; + + return a_a.Rank == b_a.Rank && IsEqual (a_a.Element, b_a.Element); + } + + if (!a.IsGeneric || !b.IsGeneric) { + // + // object and dynamic are considered equivalent there is an identity conversion + // between object and dynamic, and between constructed types that are the same + // when replacing all occurences of dynamic with object. + // + if (a.BuiltinType == BuiltinTypeSpec.Type.Dynamic || b.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + return b.BuiltinType == BuiltinTypeSpec.Type.Object || a.BuiltinType == BuiltinTypeSpec.Type.Object; + + return false; + } + + if (a.MemberDefinition != b.MemberDefinition) + return false; + + do { + if (!Equals (a.TypeArguments, b.TypeArguments)) + return false; + + a = a.DeclaringType; + b = b.DeclaringType; + } while (a != null); + + return true; + } + } + + public interface ITypeDefinition : IMemberDefinition + { + IAssemblyDefinition DeclaringAssembly { get; } + string Namespace { get; } + int TypeParametersCount { get; } + TypeParameterSpec[] TypeParameters { get; } + + TypeSpec GetAttributeCoClass (); + string GetAttributeDefaultMember (); + AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa); + bool IsInternalAsPublic (IAssemblyDefinition assembly); + void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache); + } + + class InternalType : TypeSpec, ITypeDefinition + { + public static readonly InternalType AnonymousMethod = new InternalType ("anonymous method"); + public static readonly InternalType Arglist = new InternalType ("__arglist"); + public static readonly InternalType MethodGroup = new InternalType ("method group"); + public static readonly InternalType NullLiteral = new InternalType ("null"); + public static readonly InternalType FakeInternalType = new InternalType (""); + public static readonly InternalType Namespace = new InternalType (""); + + readonly string name; + + InternalType (string name, MemberCache cache) + : this (name) + { + this.cache = cache; + } + + InternalType (string name) + : base (MemberKind.InternalCompilerType, null, null, null, Modifiers.PUBLIC) + { + this.name = name; + this.definition = this; + cache = MemberCache.Empty; + + // Make all internal types CLS-compliant, non-obsolete + state = (state & ~(StateFlags.CLSCompliant_Undetected | StateFlags.Obsolete_Undetected)) | StateFlags.CLSCompliant; + } + + #region Properties + + public override int Arity { + get { + return 0; + } + } + + IAssemblyDefinition ITypeDefinition.DeclaringAssembly { + get { + throw new NotImplementedException (); + } + } + + bool IMemberDefinition.IsImported { + get { + return false; + } + } + + public override string Name { + get { + return name; + } + } + + string ITypeDefinition.Namespace { + get { + return null; + } + } + + int ITypeDefinition.TypeParametersCount { + get { + return 0; + } + } + + TypeParameterSpec[] ITypeDefinition.TypeParameters { + get { + return null; + } + } + + #endregion + + public override string GetSignatureForError () + { + return name; + } + + #region ITypeDefinition Members + + TypeSpec ITypeDefinition.GetAttributeCoClass () + { + return null; + } + + string ITypeDefinition.GetAttributeDefaultMember () + { + return null; + } + + AttributeUsageAttribute ITypeDefinition.GetAttributeUsage (PredefinedAttribute pa) + { + return null; + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + throw new NotImplementedException (); + } + + void ITypeDefinition.LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + throw new NotImplementedException (); + } + + string[] IMemberDefinition.ConditionalConditions () + { + return null; + } + + ObsoleteAttribute IMemberDefinition.GetAttributeObsolete () + { + return null; + } + + bool? IMemberDefinition.CLSAttributeValue { + get { + return null; + } + } + + void IMemberDefinition.SetIsAssigned () + { + } + + void IMemberDefinition.SetIsUsed () + { + } + + #endregion + } + + public abstract class ElementTypeSpec : TypeSpec, ITypeDefinition + { + protected ElementTypeSpec (MemberKind kind, TypeSpec element, MetaType info) + : base (kind, element.DeclaringType, null, info, element.Modifiers) + { + this.Element = element; + + // Some flags can be copied directly from the element + const StateFlags shared_flags = StateFlags.CLSCompliant | StateFlags.CLSCompliant_Undetected + | StateFlags.Obsolete | StateFlags.Obsolete_Undetected | StateFlags.HasDynamicElement; + state &= ~shared_flags; + state |= (element.state & shared_flags); + + if (element.BuiltinType == BuiltinTypeSpec.Type.Dynamic) + state |= StateFlags.HasDynamicElement; + + // Has to use its own type definition instead of just element definition to + // correctly identify itself for cases like x.MemberDefininition == predefined.MemberDefinition + this.definition = this; + + cache = MemberCache.Empty; + } + + #region Properties + + public TypeSpec Element { get; private set; } + + public override string Name { + get { + throw new NotSupportedException (); + } + } + + #endregion + + public override ObsoleteAttribute GetAttributeObsolete () + { + return Element.GetAttributeObsolete (); + } + + protected virtual string GetPostfixSignature () + { + return null; + } + + public override string GetSignatureForDocumentation () + { + return Element.GetSignatureForDocumentation () + GetPostfixSignature (); + } + + public override string GetSignatureForError () + { + return Element.GetSignatureForError () + GetPostfixSignature (); + } + + public override TypeSpec Mutate (TypeParameterMutator mutator) + { + var me = Element.Mutate (mutator); + if (me == Element) + return this; + + var mutated = (ElementTypeSpec) MemberwiseClone (); + mutated.Element = me; + mutated.info = null; + return mutated; + } + + #region ITypeDefinition Members + + IAssemblyDefinition ITypeDefinition.DeclaringAssembly { + get { + return Element.MemberDefinition.DeclaringAssembly; + } + } + + bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly) + { + return Element.MemberDefinition.IsInternalAsPublic (assembly); + } + + public string Namespace { + get { throw new NotImplementedException (); } + } + + public int TypeParametersCount { + get { + return 0; + } + } + + public TypeParameterSpec[] TypeParameters { + get { + throw new NotSupportedException (); + } + } + + public TypeSpec GetAttributeCoClass () + { + return Element.MemberDefinition.GetAttributeCoClass (); + } + + public string GetAttributeDefaultMember () + { + return Element.MemberDefinition.GetAttributeDefaultMember (); + } + + public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache) + { + Element.MemberDefinition.LoadMembers (declaringType, onlyTypes, ref cache); + } + + public bool IsImported { + get { + return Element.MemberDefinition.IsImported; + } + } + + public string[] ConditionalConditions () + { + return Element.MemberDefinition.ConditionalConditions (); + } + + bool? IMemberDefinition.CLSAttributeValue { + get { + return Element.MemberDefinition.CLSAttributeValue; + } + } + + public void SetIsAssigned () + { + Element.MemberDefinition.SetIsAssigned (); + } + + public void SetIsUsed () + { + Element.MemberDefinition.SetIsUsed (); + } + + #endregion + } + + public class ArrayContainer : ElementTypeSpec + { + public struct TypeRankPair : IEquatable + { + TypeSpec ts; + int rank; + + public TypeRankPair (TypeSpec ts, int rank) + { + this.ts = ts; + this.rank = rank; + } + + public override int GetHashCode () + { + return ts.GetHashCode () ^ rank.GetHashCode (); + } + + #region IEquatable> Members + + public bool Equals (TypeRankPair other) + { + return other.ts == ts && other.rank == rank; + } + + #endregion + } + + readonly int rank; + readonly ModuleContainer module; + + private ArrayContainer (ModuleContainer module, TypeSpec element, int rank) + : base (MemberKind.ArrayType, element, null) + { + this.module = module; + this.rank = rank; + } + + public int Rank { + get { + return rank; + } + } + + public MethodInfo GetConstructor () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + var ctor = mb.GetArrayMethod ( + GetMetaInfo (), Constructor.ConstructorName, + CallingConventions.HasThis, + null, arg_types); + + return ctor; + } + + public MethodInfo GetAddressMethod () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + var address = mb.GetArrayMethod ( + GetMetaInfo (), "Address", + CallingConventions.HasThis | CallingConventions.Standard, + ReferenceContainer.MakeType (module, Element).GetMetaInfo (), arg_types); + + return address; + } + + public MethodInfo GetGetMethod () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + var get = mb.GetArrayMethod ( + GetMetaInfo (), "Get", + CallingConventions.HasThis | CallingConventions.Standard, + Element.GetMetaInfo (), arg_types); + + return get; + } + + public MethodInfo GetSetMethod () + { + var mb = module.Builder; + + var arg_types = new MetaType[rank + 1]; + for (int i = 0; i < rank; i++) + arg_types[i] = module.Compiler.BuiltinTypes.Int.GetMetaInfo (); + + arg_types[rank] = Element.GetMetaInfo (); + + var set = mb.GetArrayMethod ( + GetMetaInfo (), "Set", + CallingConventions.HasThis | CallingConventions.Standard, + module.Compiler.BuiltinTypes.Void.GetMetaInfo (), arg_types); + + return set; + } + + public override MetaType GetMetaInfo () + { + if (info == null) { + if (rank == 1) + info = Element.GetMetaInfo ().MakeArrayType (); + else + info = Element.GetMetaInfo ().MakeArrayType (rank); + } + + return info; + } + + protected override string GetPostfixSignature() + { + return GetPostfixSignature (rank); + } + + public static string GetPostfixSignature (int rank) + { + StringBuilder sb = new StringBuilder (); + sb.Append ("["); + for (int i = 1; i < rank; i++) { + sb.Append (","); + } + sb.Append ("]"); + + return sb.ToString (); + } + + public override string GetSignatureForDocumentation () + { + StringBuilder sb = new StringBuilder (); + GetElementSignatureForDocumentation (sb); + return sb.ToString (); + } + + void GetElementSignatureForDocumentation (StringBuilder sb) + { + var ac = Element as ArrayContainer; + if (ac == null) + sb.Append (Element.GetSignatureForDocumentation ()); + else + ac.GetElementSignatureForDocumentation (sb); + + sb.Append ("["); + for (int i = 1; i < rank; i++) { + if (i == 1) + sb.Append ("0:"); + + sb.Append (",0:"); + } + sb.Append ("]"); + } + + public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element) + { + return MakeType (module, element, 1); + } + + public static ArrayContainer MakeType (ModuleContainer module, TypeSpec element, int rank) + { + ArrayContainer ac; + var key = new TypeRankPair (element, rank); + if (!module.ArrayTypesCache.TryGetValue (key, out ac)) { + ac = new ArrayContainer (module, element, rank) { + BaseType = module.Compiler.BuiltinTypes.Array + }; + + module.ArrayTypesCache.Add (key, ac); + } + + return ac; + } + } + + class ReferenceContainer : ElementTypeSpec + { + private ReferenceContainer (TypeSpec element) + : base (MemberKind.Class, element, null) // TODO: Kind.Class is most likely wrong + { + } + + public override MetaType GetMetaInfo () + { + if (info == null) { + info = Element.GetMetaInfo ().MakeByRefType (); + } + + return info; + } + + public static ReferenceContainer MakeType (ModuleContainer module, TypeSpec element) + { + ReferenceContainer pc; + if (!module.ReferenceTypesCache.TryGetValue (element, out pc)) { + pc = new ReferenceContainer (element); + module.ReferenceTypesCache.Add (element, pc); + } + + return pc; + } + } + + class PointerContainer : ElementTypeSpec + { + private PointerContainer (TypeSpec element) + : base (MemberKind.PointerType, element, null) + { + // It's never CLS-Compliant + state &= ~StateFlags.CLSCompliant_Undetected; + } + + public override MetaType GetMetaInfo () + { + if (info == null) { + info = Element.GetMetaInfo ().MakePointerType (); + } + + return info; + } + + protected override string GetPostfixSignature() + { + return "*"; + } + + public static PointerContainer MakeType (ModuleContainer module, TypeSpec element) + { + PointerContainer pc; + if (!module.PointerTypesCache.TryGetValue (element, out pc)) { + pc = new PointerContainer (element); + module.PointerTypesCache.Add (element, pc); + } + + return pc; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs new file mode 100644 index 0000000000..0ac678300c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs @@ -0,0 +1,630 @@ +// +// visit.cs: Visitors for parsed dom +// +// Authors: Mike Krüger (mkrueger@novell.com) +// Marek Safar (marek.safar@gmail.com) +// +// Dual licensed under the terms of the MIT X11 or GNU GPL +// +// Copyright (c) 2010 Novell, Inc (http://www.novell.com) +// + +using System; + +namespace Mono.CSharp +{ + public abstract class StructuralVisitor + { + public virtual void Visit (MemberCore member) + { + Console.WriteLine ("unknown member type: " + member.GetType ()); + } + + public virtual void Visit (ModuleContainer mc) + {/* + if (mc.Delegates != null) { + foreach (TypeContainer tc in mc.Delegates) { + tc.Accept (this); + } + }*/ + if (mc.Types != null) { + foreach (TypeContainer tc in mc.Types) { + tc.Accept (this); + } + } + } + + void VisitTypeContainer (TypeContainer tc) + { + foreach (MemberCore member in tc.OrderedAllMembers) { + member.Accept (this); + } + } + + protected void VisitNamespaceUsings (UsingsBag.Namespace nspace) + { + foreach (object u in nspace.usings) { + if (u is UsingsBag.Using) { + ((UsingsBag.Using)u).Accept (this); + } else { + ((UsingsBag.AliasUsing)u).Accept (this); + } + } + } + + protected void VisitNamespaceBody (UsingsBag.Namespace nspace) + { + foreach (object member in nspace.members) { + if (member is MemberCore) { + ((MemberCore)member).Accept (this); + } else { + ((UsingsBag.Namespace)member).Accept (this); + } + } + } + + public virtual void Visit (UsingsBag.Namespace nspace) + { + VisitNamespaceUsings (nspace); + VisitNamespaceBody (nspace); + } + + public virtual void Visit (UsingsBag.Using u) + { + } + + public virtual void Visit (UsingsBag.AliasUsing aliasUsing) + { + } + + public virtual void Visit (UsingsBag.ExternAlias externAlias) + { + } + + public virtual void Visit (Class c) + { + VisitTypeContainer (c); + } + + public virtual void Visit (Struct s) + { + VisitTypeContainer (s); + } + + + public virtual void Visit (Interface i) + { + VisitTypeContainer (i); + } + + public virtual void Visit (Delegate d) + { + } + + public virtual void Visit (Enum e) + { + VisitTypeContainer (e); + } + + public virtual void Visit (FixedField f) + { + } + + public virtual void Visit (Const c) + { + } + + public virtual void Visit (Field f) + { + } + + public virtual void Visit (Operator o) + { + } + + public virtual void Visit (Indexer i) + { + } + + public virtual void Visit (Method m) + { + } + + public virtual void Visit (Property p) + { + } + + public virtual void Visit (Constructor c) + { + } + + public virtual void Visit (Destructor d) + { + } + + public virtual void Visit (EventField e) + { + } + public virtual void Visit (EventProperty ep) + { + } + + public virtual void Visit (EnumMember em) + { + } + + public virtual object Visit (Statement stmt) + { + Console.WriteLine ("unknown statement:" + stmt); + return null; + } + + public virtual object Visit (BlockVariableDeclaration blockVariableDeclaration) + { + return null; + } + + public virtual object Visit (BlockConstantDeclaration blockConstantDeclaration) + { + return null; + } + + public virtual object Visit (EmptyStatement emptyStatement) + { + return null; + } + + public virtual object Visit (EmptyExpressionStatement emptyExpressionStatement) + { + return null; + } + + public virtual object Visit (If ifStatement) + { + return null; + } + + + public virtual object Visit (Do doStatement) + { + return null; + } + + + public virtual object Visit (While whileStatement) + { + return null; + } + + + public virtual object Visit (For forStatement) + { + return null; + } + + + public virtual object Visit (StatementExpression statementExpression) + { + return null; + } + + + public virtual object Visit (Return returnStatement) + { + return null; + } + + + public virtual object Visit (Goto gotoStatement) + { + return null; + } + + + public virtual object Visit (LabeledStatement labeledStatement) + { + return null; + } + + + public virtual object Visit (GotoDefault gotoDefault) + { + return null; + } + + + public virtual object Visit (GotoCase gotoCase) + { + return null; + } + + + public virtual object Visit (Throw throwStatement) + { + return null; + } + + + public virtual object Visit (Break breakStatement) + { + return null; + } + + + public virtual object Visit (Continue continueStatement) + { + return null; + } + + + public virtual object Visit (Block blockStatement) + { + return null; + } + + public virtual object Visit (Switch switchStatement) + { + return null; + } + + public virtual object Visit (StatementList statementList) + { + return null; + } + + public virtual object Visit (Lock lockStatement) + { + return null; + } + + + public virtual object Visit (Unchecked uncheckedStatement) + { + return null; + } + + + public virtual object Visit (Checked checkedStatement) + { + return null; + } + + + public virtual object Visit (Unsafe unsafeStatement) + { + return null; + } + + + public virtual object Visit (Fixed fixedStatement) + { + return null; + } + + + public virtual object Visit (TryFinally tryFinallyStatement) + { + return null; + } + + + public virtual object Visit (TryCatch tryCatchStatement) + { + return null; + } + + public virtual object Visit (Using usingStatement) + { + return null; + } + + public virtual object Visit (Foreach foreachStatement) + { + return null; + } + + public virtual object Visit (Yield yieldStatement) + { + return null; + } + + public virtual object Visit (YieldBreak yieldBreakStatement) + { + return null; + } + + public virtual object Visit (Expression expression) + { + Console.WriteLine ("Visit unknown expression:" + expression); + return null; + } + + public virtual object Visit (MemberAccess memberAccess) + { + return null; + } + + public virtual object Visit (QualifiedAliasMember qualifiedAliasMember) + { + return null; + } + + public virtual object Visit (LocalVariableReference localVariableReference) + { + return null; + } + + public virtual object Visit (Constant constant) + { + return null; + } + + public virtual object Visit (BooleanExpression booleanExpression) + { + return null; + } + + public virtual object Visit (SimpleName simpleName) + { + return null; + } + + public virtual object Visit (ParenthesizedExpression parenthesizedExpression) + { + return null; + } + + public virtual object Visit (Unary unaryExpression) + { + return null; + } + + public virtual object Visit (UnaryMutator unaryMutatorExpression) + { + return null; + } + + // *expr + public virtual object Visit (Indirection indirectionExpression) + { + return null; + } + + public virtual object Visit (Is isExpression) + { + return null; + } + + public virtual object Visit (As asExpression) + { + return null; + } + + public virtual object Visit (Cast castExpression) + { + return null; + } + + public virtual object Visit (ComposedCast composedCast) + { + return null; + } + + public virtual object Visit (DefaultValueExpression defaultValueExpression) + { + return null; + } + + public virtual object Visit (DefaultParameterValueExpression defaultParameterValueExpression) + { + return null; + } + + public virtual object Visit (Binary binaryExpression) + { + return null; + } + + public virtual object Visit (Nullable.NullCoalescingOperator nullCoalescingOperator) + { + return null; + } + + + public virtual object Visit (Conditional conditionalExpression) + { + return null; + } + + public virtual object Visit (Invocation invocationExpression) + { + return null; + } + + public virtual object Visit (New newExpression) + { + return null; + } + + public virtual object Visit (NewAnonymousType newAnonymousType) + { + return null; + } + + public virtual object Visit (NewInitialize newInitializeExpression) + { + return null; + } + + public virtual object Visit (ArrayCreation arrayCreationExpression) + { + return null; + } + + public virtual object Visit (This thisExpression) + { + return null; + } + + public virtual object Visit (ArglistAccess argListAccessExpression) + { + return null; + } + + public virtual object Visit (Arglist argListExpression) + { + return null; + } + + public virtual object Visit (TypeOf typeOfExpression) + { + return null; + } + + public virtual object Visit (SizeOf sizeOfExpression) + { + return null; + } + + public virtual object Visit (CheckedExpr checkedExpression) + { + return null; + } + + public virtual object Visit (UnCheckedExpr uncheckedExpression) + { + return null; + } + + public virtual object Visit (ElementAccess elementAccessExpression) + { + return null; + } + + public virtual object Visit (BaseThis baseAccessExpression) + { + return null; + } + + public virtual object Visit (StackAlloc stackAllocExpression) + { + return null; + } + + public virtual object Visit (SimpleAssign simpleAssign) + { + return null; + } + + public virtual object Visit (CompoundAssign compoundAssign) + { + return null; + } + + public virtual object Visit (TypeExpression typeExpression) + { + return null; + } + + public virtual object Visit (AnonymousMethodExpression anonymousMethodExpression) + { + return null; + } + + public virtual object Visit (LambdaExpression lambdaExpression) + { + return null; + } + + public virtual object Visit (ConstInitializer constInitializer) + { + return null; + } + + public virtual object Visit (ArrayInitializer arrayInitializer) + { + return null; + } + + public virtual object Visit (Linq.QueryExpression queryExpression) + { + return null; + } + + public virtual object Visit (Linq.QueryStartClause queryExpression) + { + return null; + } + + public virtual object Visit (Linq.SelectMany selectMany) + { + return null; + } + + public virtual object Visit (Linq.Select select) + { + return null; + } + + public virtual object Visit (Linq.GroupBy groupBy) + { + return null; + } + + public virtual object Visit (Linq.Let let) + { + return null; + } + + public virtual object Visit (Linq.Where where) + { + return null; + } + + public virtual object Visit (Linq.Join join) + { + return null; + } + + public virtual object Visit (Linq.GroupJoin groupJoin) + { + return null; + } + + public virtual object Visit (Linq.OrderByAscending orderByAscending) + { + return null; + } + + public virtual object Visit (Linq.OrderByDescending orderByDescending) + { + return null; + } + + public virtual object Visit (Linq.ThenByAscending thenByAscending) + { + return null; + } + + public virtual object Visit (Linq.ThenByDescending thenByDescending) + { + return null; + } + + // undocumented expressions + public virtual object Visit (RefValueExpr refValueExpr) + { + return null; + } + + public virtual object Visit (RefTypeExpr refTypeExpr) + { + return null; + } + + public virtual object Visit (MakeRefExpr makeRefExpr) + { + return null; + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output new file mode 100644 index 0000000000..a545cab253 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output @@ -0,0 +1,31920 @@ + 0 $accept : compilation_unit $end + + 1 compilation_unit : outer_declarations opt_EOF + 2 | outer_declarations global_attributes opt_EOF + 3 | global_attributes opt_EOF + 4 | opt_EOF + + 5 $$1 : + + 6 compilation_unit : interactive_parsing $$1 opt_EOF + + 7 opt_EOF : + 8 | EOF + + 9 outer_declarations : outer_declaration + 10 | outer_declarations outer_declaration + + 11 outer_declaration : extern_alias_directive + 12 | using_directive + 13 | namespace_member_declaration + + 14 extern_alias_directives : extern_alias_directive + 15 | extern_alias_directives extern_alias_directive + + 16 extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON + 17 | EXTERN_ALIAS error + + 18 using_directives : using_directive + 19 | using_directives using_directive + + 20 using_directive : using_alias_directive + 21 | using_namespace_directive + + 22 using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON + 23 | USING error + + 24 using_namespace_directive : USING namespace_name SEMICOLON + + 25 $$2 : + + 26 namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 namespace_body opt_semicolon + + 27 qualified_identifier : IDENTIFIER + 28 | qualified_identifier DOT IDENTIFIER + 29 | error + + 30 opt_semicolon : + 31 | SEMICOLON + + 32 opt_comma : + 33 | COMMA + + 34 namespace_name : namespace_or_type_name + + 35 $$3 : + + 36 namespace_body : OPEN_BRACE $$3 namespace_body_body + + 37 namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations CLOSE_BRACE + + 38 $$4 : + + 39 namespace_body_body : error $$4 CLOSE_BRACE + 40 | opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations EOF + + 41 opt_using_directives : + 42 | using_directives + + 43 opt_extern_alias_directives : + 44 | extern_alias_directives + + 45 opt_namespace_member_declarations : + 46 | namespace_member_declarations + + 47 namespace_member_declarations : namespace_member_declaration + 48 | namespace_member_declarations namespace_member_declaration + + 49 namespace_member_declaration : type_declaration + 50 | namespace_declaration + 51 | field_declaration + 52 | method_declaration + + 53 type_declaration : class_declaration + 54 | struct_declaration + 55 | interface_declaration + 56 | enum_declaration + 57 | delegate_declaration + + 58 global_attributes : attribute_sections + + 59 opt_attributes : + 60 | attribute_sections + + 61 attribute_sections : attribute_section + 62 | attribute_sections attribute_section + + 63 attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET + 64 | OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET + + 65 attribute_target_specifier : attribute_target COLON + + 66 attribute_target : IDENTIFIER + 67 | EVENT + 68 | RETURN + 69 | error + + 70 attribute_list : attribute + 71 | attribute_list COMMA attribute + + 72 $$5 : + + 73 attribute : attribute_name $$5 opt_attribute_arguments + + 74 attribute_name : namespace_or_type_name + + 75 opt_attribute_arguments : + 76 | OPEN_PARENS attribute_arguments CLOSE_PARENS + + 77 attribute_arguments : + 78 | positional_or_named_argument + 79 | named_attribute_argument + 80 | attribute_arguments COMMA positional_or_named_argument + 81 | attribute_arguments COMMA named_attribute_argument + + 82 positional_or_named_argument : expression + 83 | named_argument + + 84 $$6 : + + 85 named_attribute_argument : IDENTIFIER ASSIGN $$6 expression + + 86 named_argument : IDENTIFIER COLON opt_named_modifier expression + + 87 opt_named_modifier : + 88 | REF + 89 | OUT + + 90 opt_class_member_declarations : + 91 | class_member_declarations + + 92 class_member_declarations : class_member_declaration + 93 | class_member_declarations class_member_declaration + + 94 class_member_declaration : constant_declaration + 95 | field_declaration + 96 | method_declaration + 97 | property_declaration + 98 | event_declaration + 99 | indexer_declaration + 100 | operator_declaration + 101 | constructor_declaration + 102 | destructor_declaration + 103 | type_declaration + 104 | error + + 105 $$7 : + + 106 $$8 : + + 107 $$9 : + + 108 $$10 : + + 109 struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon + 110 | opt_attributes opt_modifiers opt_partial STRUCT error + + 111 $$11 : + + 112 struct_body : OPEN_BRACE $$11 opt_struct_member_declarations CLOSE_BRACE + + 113 opt_struct_member_declarations : + 114 | struct_member_declarations + + 115 struct_member_declarations : struct_member_declaration + 116 | struct_member_declarations struct_member_declaration + + 117 struct_member_declaration : constant_declaration + 118 | field_declaration + 119 | method_declaration + 120 | property_declaration + 121 | event_declaration + 122 | indexer_declaration + 123 | operator_declaration + 124 | constructor_declaration + 125 | type_declaration + 126 | destructor_declaration + + 127 $$12 : + + 128 constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON + + 129 opt_constant_declarators : + 130 | constant_declarators + + 131 constant_declarators : constant_declarator + 132 | constant_declarators constant_declarator + + 133 constant_declarator : COMMA IDENTIFIER constant_initializer + + 134 $$13 : + + 135 constant_initializer : ASSIGN $$13 constant_initializer_expr + 136 | error + + 137 constant_initializer_expr : constant_expression + 138 | array_initializer + + 139 $$14 : + + 140 field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON + + 141 $$15 : + + 142 field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON + 143 | opt_attributes opt_modifiers FIXED simple_type error SEMICOLON + + 144 opt_field_initializer : + + 145 $$16 : + + 146 opt_field_initializer : ASSIGN $$16 variable_initializer + + 147 opt_field_declarators : + 148 | field_declarators + + 149 field_declarators : field_declarator + 150 | field_declarators field_declarator + + 151 field_declarator : COMMA IDENTIFIER + + 152 $$17 : + + 153 field_declarator : COMMA IDENTIFIER ASSIGN $$17 variable_initializer + + 154 opt_fixed_field_declarators : + 155 | fixed_field_declarators + + 156 fixed_field_declarators : fixed_field_declarator + 157 | fixed_field_declarators fixed_field_declarator + + 158 fixed_field_declarator : COMMA IDENTIFIER fixed_field_size + + 159 $$18 : + + 160 fixed_field_size : OPEN_BRACKET $$18 expression CLOSE_BRACKET + 161 | OPEN_BRACKET error + + 162 local_variable_declarators : local_variable_declarator + 163 | local_variable_declarators COMMA local_variable_declarator + + 164 local_variable_declarator : IDENTIFIER ASSIGN local_variable_initializer + 165 | IDENTIFIER + 166 | IDENTIFIER variable_bad_array + + 167 local_variable_initializer : expression + 168 | array_initializer + 169 | STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET + 170 | ARGLIST + 171 | STACKALLOC simple_type + + 172 variable_bad_array : OPEN_BRACKET_EXPR opt_expression CLOSE_BRACKET + + 173 variable_initializer : expression + 174 | array_initializer + + 175 $$19 : + + 176 method_declaration : method_header $$19 method_body + + 177 $$20 : + + 178 $$21 : + + 179 method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses + + 180 $$22 : + + 181 $$23 : + + 182 method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses + 183 | opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS + + 184 method_body : block + 185 | SEMICOLON + + 186 opt_formal_parameter_list : + 187 | formal_parameter_list + + 188 formal_parameter_list : fixed_parameters + 189 | fixed_parameters COMMA parameter_array + 190 | fixed_parameters COMMA arglist_modifier + 191 | parameter_array COMMA error + 192 | fixed_parameters COMMA parameter_array COMMA error + 193 | arglist_modifier COMMA error + 194 | fixed_parameters COMMA ARGLIST COMMA error + 195 | parameter_array + 196 | arglist_modifier + + 197 fixed_parameters : fixed_parameter + 198 | fixed_parameters COMMA fixed_parameter + + 199 fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER + 200 | opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET + 201 | opt_attributes opt_parameter_modifier parameter_type error + + 202 $$24 : + + 203 fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 constant_expression + + 204 opt_parameter_modifier : + 205 | parameter_modifiers + + 206 parameter_modifiers : parameter_modifier + 207 | parameter_modifiers parameter_modifier + + 208 parameter_modifier : REF + 209 | OUT + 210 | THIS + + 211 parameter_array : opt_attributes params_modifier type IDENTIFIER + 212 | opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression + 213 | opt_attributes params_modifier type error + + 214 params_modifier : PARAMS + 215 | PARAMS parameter_modifier + 216 | PARAMS params_modifier + + 217 arglist_modifier : ARGLIST + + 218 $$25 : + + 219 $$26 : + + 220 $$27 : + + 221 property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE + + 222 $$28 : + + 223 $$29 : + + 224 $$30 : + + 225 indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE + + 226 accessor_declarations : get_accessor_declaration + 227 | get_accessor_declaration accessor_declarations + 228 | set_accessor_declaration + 229 | set_accessor_declaration accessor_declarations + 230 | error + + 231 $$31 : + + 232 get_accessor_declaration : opt_attributes opt_modifiers GET $$31 accessor_body + + 233 $$32 : + + 234 set_accessor_declaration : opt_attributes opt_modifiers SET $$32 accessor_body + + 235 accessor_body : block + 236 | SEMICOLON + 237 | error + + 238 $$33 : + + 239 $$34 : + + 240 $$35 : + + 241 $$36 : + + 242 interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon + 243 | opt_attributes opt_modifiers opt_partial INTERFACE error + + 244 opt_interface_member_declarations : + 245 | interface_member_declarations + + 246 interface_member_declarations : interface_member_declaration + 247 | interface_member_declarations interface_member_declaration + + 248 interface_member_declaration : constant_declaration + 249 | field_declaration + 250 | method_declaration + 251 | property_declaration + 252 | event_declaration + 253 | indexer_declaration + 254 | operator_declaration + 255 | constructor_declaration + 256 | type_declaration + + 257 $$37 : + + 258 operator_declaration : opt_attributes opt_modifiers operator_declarator $$37 operator_body + + 259 operator_body : block + 260 | SEMICOLON + + 261 operator_type : type_expression_or_array + 262 | VOID + + 263 $$38 : + + 264 operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS + 265 | conversion_operator_declarator + + 266 overloadable_operator : BANG + 267 | TILDE + 268 | OP_INC + 269 | OP_DEC + 270 | TRUE + 271 | FALSE + 272 | PLUS + 273 | MINUS + 274 | STAR + 275 | DIV + 276 | PERCENT + 277 | BITWISE_AND + 278 | BITWISE_OR + 279 | CARRET + 280 | OP_SHIFT_LEFT + 281 | OP_SHIFT_RIGHT + 282 | OP_EQ + 283 | OP_NE + 284 | OP_GT + 285 | OP_LT + 286 | OP_GE + 287 | OP_LE + + 288 $$39 : + + 289 conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS + + 290 $$40 : + + 291 conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS + 292 | IMPLICIT error + 293 | EXPLICIT error + + 294 constructor_declaration : constructor_declarator constructor_body + + 295 $$41 : + + 296 $$42 : + + 297 constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer + + 298 constructor_body : block_prepared + 299 | SEMICOLON + + 300 opt_constructor_initializer : + 301 | constructor_initializer + + 302 $$43 : + + 303 constructor_initializer : COLON BASE OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS + + 304 $$44 : + + 305 constructor_initializer : COLON THIS OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS + 306 | COLON error + + 307 $$45 : + + 308 destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body + + 309 $$46 : + + 310 event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON + + 311 $$47 : + + 312 $$48 : + + 313 event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE + + 314 opt_event_initializer : + + 315 $$49 : + + 316 opt_event_initializer : ASSIGN $$49 event_variable_initializer + + 317 opt_event_declarators : + 318 | event_declarators + + 319 event_declarators : event_declarator + 320 | event_declarators event_declarator + + 321 event_declarator : COMMA IDENTIFIER + + 322 $$50 : + + 323 event_declarator : COMMA IDENTIFIER ASSIGN $$50 event_variable_initializer + + 324 $$51 : + + 325 event_variable_initializer : $$51 variable_initializer + + 326 event_accessor_declarations : add_accessor_declaration remove_accessor_declaration + 327 | remove_accessor_declaration add_accessor_declaration + 328 | add_accessor_declaration + 329 | remove_accessor_declaration + 330 | error + + 331 $$52 : + + 332 add_accessor_declaration : opt_attributes opt_modifiers ADD $$52 event_accessor_block + + 333 $$53 : + + 334 remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$53 event_accessor_block + + 335 event_accessor_block : opt_semicolon + 336 | block + + 337 $$54 : + + 338 $$55 : + + 339 $$56 : + + 340 enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon + + 341 opt_enum_base : + 342 | COLON type + 343 | COLON error + + 344 opt_enum_member_declarations : + 345 | enum_member_declarations + 346 | enum_member_declarations COMMA + + 347 enum_member_declarations : enum_member_declaration + 348 | enum_member_declarations COMMA enum_member_declaration + + 349 enum_member_declaration : opt_attributes IDENTIFIER + + 350 $$57 : + + 351 enum_member_declaration : opt_attributes IDENTIFIER $$57 ASSIGN constant_expression + + 352 $$58 : + + 353 $$59 : + + 354 $$60 : + + 355 delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON + + 356 opt_nullable : + 357 | INTERR_NULLABLE + + 358 namespace_or_type_name : member_name + 359 | qualified_alias_member IDENTIFIER opt_type_argument_list + + 360 member_name : type_name + 361 | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list + + 362 type_name : IDENTIFIER opt_type_argument_list + + 363 opt_type_argument_list : + 364 | OP_GENERICS_LT type_arguments OP_GENERICS_GT + 365 | OP_GENERICS_LT error + + 366 type_arguments : type + 367 | type_arguments COMMA type + + 368 $$61 : + + 369 type_declaration_name : IDENTIFIER $$61 opt_type_parameter_list + + 370 member_declaration_name : method_declaration_name + + 371 method_declaration_name : type_declaration_name + 372 | explicit_interface IDENTIFIER opt_type_parameter_list + + 373 indexer_declaration_name : THIS + 374 | explicit_interface THIS + + 375 explicit_interface : IDENTIFIER opt_type_argument_list DOT + 376 | qualified_alias_member IDENTIFIER opt_type_argument_list DOT + 377 | explicit_interface IDENTIFIER opt_type_argument_list DOT + + 378 opt_type_parameter_list : + 379 | OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT + + 380 type_parameters : type_parameter + 381 | type_parameters COMMA type_parameter + + 382 type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER + 383 | error + + 384 type_and_void : type_expression_or_array + 385 | VOID + + 386 member_type : type_and_void + + 387 type : type_expression_or_array + 388 | VOID + + 389 simple_type : type_expression + 390 | VOID + + 391 parameter_type : type_expression_or_array + 392 | VOID + + 393 type_expression_or_array : type_expression + 394 | type_expression rank_specifiers + + 395 type_expression : namespace_or_type_name opt_nullable + 396 | builtin_types opt_nullable + 397 | type_expression STAR + 398 | VOID STAR + + 399 type_list : base_type_name + 400 | type_list COMMA base_type_name + + 401 base_type_name : type + 402 | error + + 403 builtin_types : OBJECT + 404 | STRING + 405 | BOOL + 406 | DECIMAL + 407 | FLOAT + 408 | DOUBLE + 409 | integral_type + + 410 integral_type : SBYTE + 411 | BYTE + 412 | SHORT + 413 | USHORT + 414 | INT + 415 | UINT + 416 | LONG + 417 | ULONG + 418 | CHAR + + 419 primary_expression : primary_expression_no_array_creation + 420 | array_creation_expression + + 421 primary_expression_no_array_creation : literal + 422 | IDENTIFIER opt_type_argument_list + 423 | IDENTIFIER GENERATE_COMPLETION + 424 | parenthesized_expression + 425 | default_value_expression + 426 | member_access + 427 | invocation_expression + 428 | element_access + 429 | this_access + 430 | base_access + 431 | post_increment_expression + 432 | post_decrement_expression + 433 | object_or_delegate_creation_expression + 434 | anonymous_type_expression + 435 | typeof_expression + 436 | sizeof_expression + 437 | checked_expression + 438 | unchecked_expression + 439 | pointer_member_access + 440 | anonymous_method_expression + + 441 literal : boolean_literal + 442 | LITERAL + 443 | NULL + + 444 boolean_literal : TRUE + 445 | FALSE + + 446 open_parens_any : OPEN_PARENS + 447 | OPEN_PARENS_CAST + + 448 close_parens : CLOSE_PARENS + 449 | COMPLETE_COMPLETION + + 450 parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS + 451 | OPEN_PARENS expression COMPLETE_COMPLETION + + 452 member_access : primary_expression DOT IDENTIFIER opt_type_argument_list + 453 | builtin_types DOT IDENTIFIER opt_type_argument_list + 454 | BASE DOT IDENTIFIER opt_type_argument_list + 455 | qualified_alias_member IDENTIFIER opt_type_argument_list + 456 | primary_expression DOT GENERATE_COMPLETION + 457 | primary_expression DOT IDENTIFIER GENERATE_COMPLETION + 458 | builtin_types DOT GENERATE_COMPLETION + 459 | builtin_types DOT IDENTIFIER GENERATE_COMPLETION + + 460 invocation_expression : primary_expression open_parens_any opt_argument_list close_parens + + 461 opt_object_or_collection_initializer : + 462 | object_or_collection_initializer + + 463 object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion + 464 | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE + + 465 opt_member_initializer_list : + 466 | member_initializer_list + + 467 member_initializer_list : member_initializer + 468 | member_initializer_list COMMA member_initializer + 469 | member_initializer_list error + + 470 member_initializer : IDENTIFIER ASSIGN initializer_value + 471 | GENERATE_COMPLETION + 472 | non_assignment_expression opt_COMPLETE_COMPLETION + 473 | OPEN_BRACE expression_list CLOSE_BRACE + 474 | OPEN_BRACE CLOSE_BRACE + + 475 initializer_value : expression + 476 | object_or_collection_initializer + + 477 opt_argument_list : + 478 | argument_list + + 479 argument_list : argument_or_named_argument + 480 | argument_list COMMA argument + 481 | argument_list COMMA named_argument + 482 | argument_list COMMA + 483 | COMMA error + + 484 argument : expression + 485 | non_simple_argument + + 486 argument_or_named_argument : argument + 487 | named_argument + + 488 non_simple_argument : REF variable_reference + 489 | OUT variable_reference + 490 | ARGLIST OPEN_PARENS argument_list CLOSE_PARENS + 491 | ARGLIST OPEN_PARENS CLOSE_PARENS + 492 | ARGLIST + + 493 variable_reference : expression + + 494 element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + + 495 expression_list : expression + 496 | expression_list COMMA expression + 497 | expression_list error + + 498 expression_list_arguments : expression_list_argument + 499 | expression_list_arguments COMMA expression_list_argument + + 500 expression_list_argument : expression + 501 | named_argument + + 502 this_access : THIS + + 503 base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET + 504 | BASE OPEN_BRACKET error + + 505 post_increment_expression : primary_expression OP_INC + + 506 post_decrement_expression : primary_expression OP_DEC + + 507 object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer + 508 | NEW new_expr_type object_or_collection_initializer + + 509 array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer + 510 | NEW new_expr_type rank_specifiers opt_array_initializer + 511 | NEW rank_specifiers array_initializer + 512 | NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET + 513 | NEW new_expr_type error + + 514 $$62 : + + 515 new_expr_type : $$62 simple_type + + 516 anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE + + 517 anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt + 518 | anonymous_type_parameters COMMA + + 519 anonymous_type_parameters_opt : + 520 | anonymous_type_parameters + + 521 anonymous_type_parameters : anonymous_type_parameter + 522 | anonymous_type_parameters COMMA anonymous_type_parameter + + 523 anonymous_type_parameter : IDENTIFIER ASSIGN variable_initializer + 524 | IDENTIFIER + 525 | member_access + 526 | error + + 527 opt_rank_specifier : + 528 | rank_specifiers + + 529 opt_rank_specifier_or_nullable : opt_nullable + 530 | opt_nullable rank_specifiers + + 531 rank_specifiers : rank_specifier + 532 | rank_specifier rank_specifiers + + 533 rank_specifier : OPEN_BRACKET CLOSE_BRACKET + 534 | OPEN_BRACKET dim_separators CLOSE_BRACKET + + 535 dim_separators : COMMA + 536 | dim_separators COMMA + + 537 opt_array_initializer : + 538 | array_initializer + + 539 array_initializer : OPEN_BRACE CLOSE_BRACE + 540 | OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE + + 541 variable_initializer_list : variable_initializer + 542 | variable_initializer_list COMMA variable_initializer + 543 | error + + 544 $$63 : + + 545 typeof_expression : TYPEOF $$63 open_parens_any typeof_type_expression CLOSE_PARENS + + 546 typeof_type_expression : type_and_void + 547 | unbound_type_name + 548 | error + + 549 unbound_type_name : IDENTIFIER generic_dimension + 550 | qualified_alias_member IDENTIFIER generic_dimension + 551 | unbound_type_name DOT IDENTIFIER + 552 | unbound_type_name DOT IDENTIFIER generic_dimension + 553 | namespace_or_type_name DOT IDENTIFIER generic_dimension + + 554 generic_dimension : GENERIC_DIMENSION + + 555 qualified_alias_member : IDENTIFIER DOUBLE_COLON + + 556 sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS + + 557 checked_expression : CHECKED open_parens_any expression CLOSE_PARENS + + 558 unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS + + 559 pointer_member_access : primary_expression OP_PTR IDENTIFIER + + 560 $$64 : + + 561 anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$64 block + + 562 opt_anonymous_method_signature : + 563 | anonymous_method_signature + + 564 $$65 : + + 565 anonymous_method_signature : OPEN_PARENS $$65 opt_formal_parameter_list CLOSE_PARENS + + 566 default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS + + 567 unary_expression : primary_expression + 568 | BANG prefixed_unary_expression + 569 | TILDE prefixed_unary_expression + 570 | cast_expression + + 571 cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression + 572 | OPEN_PARENS builtin_types CLOSE_PARENS prefixed_unary_expression + + 573 prefixed_unary_expression : unary_expression + 574 | PLUS prefixed_unary_expression + 575 | MINUS prefixed_unary_expression + 576 | OP_INC prefixed_unary_expression + 577 | OP_DEC prefixed_unary_expression + 578 | STAR prefixed_unary_expression + 579 | BITWISE_AND prefixed_unary_expression + + 580 multiplicative_expression : prefixed_unary_expression + 581 | multiplicative_expression STAR prefixed_unary_expression + 582 | multiplicative_expression DIV prefixed_unary_expression + 583 | multiplicative_expression PERCENT prefixed_unary_expression + + 584 additive_expression : multiplicative_expression + 585 | additive_expression PLUS multiplicative_expression + 586 | additive_expression MINUS multiplicative_expression + 587 | parenthesized_expression MINUS multiplicative_expression + 588 | additive_expression AS type + 589 | additive_expression IS type + + 590 shift_expression : additive_expression + 591 | shift_expression OP_SHIFT_LEFT additive_expression + 592 | shift_expression OP_SHIFT_RIGHT additive_expression + + 593 relational_expression : shift_expression + 594 | relational_expression OP_LT shift_expression + 595 | relational_expression OP_GT shift_expression + 596 | relational_expression OP_LE shift_expression + 597 | relational_expression OP_GE shift_expression + + 598 equality_expression : relational_expression + 599 | equality_expression OP_EQ relational_expression + 600 | equality_expression OP_NE relational_expression + + 601 and_expression : equality_expression + 602 | and_expression BITWISE_AND equality_expression + + 603 exclusive_or_expression : and_expression + 604 | exclusive_or_expression CARRET and_expression + + 605 inclusive_or_expression : exclusive_or_expression + 606 | inclusive_or_expression BITWISE_OR exclusive_or_expression + + 607 conditional_and_expression : inclusive_or_expression + 608 | conditional_and_expression OP_AND inclusive_or_expression + + 609 conditional_or_expression : conditional_and_expression + 610 | conditional_or_expression OP_OR conditional_and_expression + + 611 null_coalescing_expression : conditional_or_expression + 612 | conditional_or_expression OP_COALESCING null_coalescing_expression + + 613 conditional_expression : null_coalescing_expression + 614 | null_coalescing_expression INTERR expression COLON expression + + 615 assignment_expression : prefixed_unary_expression ASSIGN expression + 616 | prefixed_unary_expression OP_MULT_ASSIGN expression + 617 | prefixed_unary_expression OP_DIV_ASSIGN expression + 618 | prefixed_unary_expression OP_MOD_ASSIGN expression + 619 | prefixed_unary_expression OP_ADD_ASSIGN expression + 620 | prefixed_unary_expression OP_SUB_ASSIGN expression + 621 | prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression + 622 | prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression + 623 | prefixed_unary_expression OP_AND_ASSIGN expression + 624 | prefixed_unary_expression OP_OR_ASSIGN expression + 625 | prefixed_unary_expression OP_XOR_ASSIGN expression + + 626 lambda_parameter_list : lambda_parameter + 627 | lambda_parameter_list COMMA lambda_parameter + + 628 lambda_parameter : parameter_modifier parameter_type IDENTIFIER + 629 | parameter_type IDENTIFIER + 630 | IDENTIFIER + + 631 opt_lambda_parameter_list : + 632 | lambda_parameter_list + + 633 $$66 : + + 634 lambda_expression_body : $$66 expression + 635 | block + + 636 $$67 : + + 637 lambda_expression : IDENTIFIER ARROW $$67 lambda_expression_body + + 638 $$68 : + + 639 $$69 : + + 640 lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body + + 641 expression : assignment_expression + 642 | non_assignment_expression + + 643 non_assignment_expression : conditional_expression + 644 | lambda_expression + 645 | query_expression + + 646 constant_expression : expression + + 647 boolean_expression : expression + + 648 $$70 : + + 649 $$71 : + + 650 $$72 : + + 651 $$73 : + + 652 class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon + + 653 opt_partial : + 654 | PARTIAL + + 655 opt_modifiers : + 656 | modifiers + + 657 modifiers : modifier + 658 | modifiers modifier + + 659 modifier : NEW + 660 | PUBLIC + 661 | PROTECTED + 662 | INTERNAL + 663 | PRIVATE + 664 | ABSTRACT + 665 | SEALED + 666 | STATIC + 667 | READONLY + 668 | VIRTUAL + 669 | OVERRIDE + 670 | EXTERN + 671 | VOLATILE + 672 | UNSAFE + + 673 opt_class_base : + 674 | COLON type_list + + 675 opt_type_parameter_constraints_clauses : + 676 | type_parameter_constraints_clauses + + 677 type_parameter_constraints_clauses : type_parameter_constraints_clause + 678 | type_parameter_constraints_clauses type_parameter_constraints_clause + + 679 type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints + + 680 type_parameter_constraints : type_parameter_constraint + 681 | type_parameter_constraints COMMA type_parameter_constraint + + 682 type_parameter_constraint : type + 683 | NEW OPEN_PARENS CLOSE_PARENS + 684 | CLASS + 685 | STRUCT + + 686 opt_type_parameter_variance : + 687 | type_parameter_variance + + 688 type_parameter_variance : OUT + 689 | IN + + 690 $$74 : + + 691 block : OPEN_BRACE $$74 opt_statement_list block_end + + 692 block_end : CLOSE_BRACE + 693 | COMPLETE_COMPLETION + + 694 $$75 : + + 695 block_prepared : OPEN_BRACE $$75 opt_statement_list CLOSE_BRACE + + 696 opt_statement_list : + 697 | statement_list + + 698 statement_list : statement + 699 | statement_list statement + + 700 statement : declaration_statement + 701 | valid_declaration_statement + 702 | labeled_statement + + 703 interactive_statement_list : interactive_statement + 704 | interactive_statement_list interactive_statement + + 705 interactive_statement : declaration_statement + 706 | interactive_valid_declaration_statement + 707 | labeled_statement + + 708 valid_declaration_statement : block + 709 | empty_statement + 710 | expression_statement + 711 | selection_statement + 712 | iteration_statement + 713 | jump_statement + 714 | try_statement + 715 | checked_statement + 716 | unchecked_statement + 717 | lock_statement + 718 | using_statement + 719 | unsafe_statement + 720 | fixed_statement + + 721 interactive_valid_declaration_statement : block + 722 | empty_statement + 723 | interactive_expression_statement + 724 | selection_statement + 725 | iteration_statement + 726 | jump_statement + 727 | try_statement + 728 | checked_statement + 729 | unchecked_statement + 730 | lock_statement + 731 | using_statement + 732 | unsafe_statement + 733 | fixed_statement + + 734 embedded_statement : valid_declaration_statement + 735 | declaration_statement + 736 | labeled_statement + + 737 empty_statement : SEMICOLON + + 738 $$76 : + + 739 labeled_statement : IDENTIFIER COLON $$76 statement + + 740 declaration_statement : local_variable_declaration SEMICOLON + 741 | local_constant_declaration SEMICOLON + + 742 variable_type : primary_expression_no_array_creation opt_rank_specifier_or_nullable + 743 | builtin_types opt_rank_specifier_or_nullable + 744 | VOID opt_rank_specifier + + 745 local_variable_pointer_type : primary_expression_no_array_creation STAR + 746 | builtin_types STAR + 747 | VOID STAR + 748 | local_variable_pointer_type STAR + + 749 local_variable_type : variable_type + 750 | local_variable_pointer_type opt_rank_specifier + + 751 local_variable_declaration : local_variable_type local_variable_declarators + + 752 local_constant_declaration : CONST variable_type local_constant_declarators + + 753 local_constant_declarators : local_constant_declarator + 754 | local_constant_declarators COMMA local_constant_declarator + + 755 local_constant_declarator : IDENTIFIER ASSIGN constant_initializer_expr + 756 | IDENTIFIER error + + 757 expression_statement : statement_expression SEMICOLON + 758 | statement_expression COMPLETE_COMPLETION + + 759 interactive_expression_statement : interactive_statement_expression SEMICOLON + 760 | interactive_statement_expression COMPLETE_COMPLETION + + 761 statement_expression : expression + 762 | error + + 763 interactive_statement_expression : expression + 764 | error + + 765 selection_statement : if_statement + 766 | switch_statement + + 767 if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement + 768 | IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement + + 769 $$77 : + + 770 switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE + + 771 opt_switch_sections : + 772 | switch_sections + + 773 switch_sections : switch_section + 774 | switch_sections switch_section + + 775 $$78 : + + 776 switch_section : switch_labels $$78 statement_list + + 777 switch_labels : switch_label + 778 | switch_labels switch_label + + 779 switch_label : CASE constant_expression COLON + 780 | DEFAULT_COLON + + 781 iteration_statement : while_statement + 782 | do_statement + 783 | for_statement + 784 | foreach_statement + + 785 while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement + + 786 do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON + + 787 $$79 : + + 788 for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement + + 789 opt_for_initializer : + 790 | for_initializer + + 791 for_initializer : local_variable_declaration + 792 | statement_expression_list + + 793 opt_for_condition : + 794 | boolean_expression + + 795 opt_for_iterator : + 796 | for_iterator + + 797 for_iterator : statement_expression_list + + 798 statement_expression_list : statement_expression + 799 | statement_expression_list COMMA statement_expression + + 800 foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS + + 801 $$80 : + + 802 foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement + + 803 jump_statement : break_statement + 804 | continue_statement + 805 | goto_statement + 806 | return_statement + 807 | throw_statement + 808 | yield_statement + + 809 break_statement : BREAK SEMICOLON + + 810 continue_statement : CONTINUE SEMICOLON + + 811 goto_statement : GOTO IDENTIFIER SEMICOLON + 812 | GOTO CASE constant_expression SEMICOLON + 813 | GOTO DEFAULT SEMICOLON + + 814 return_statement : RETURN opt_expression SEMICOLON + + 815 throw_statement : THROW opt_expression SEMICOLON + + 816 yield_statement : IDENTIFIER RETURN opt_expression SEMICOLON + 817 | IDENTIFIER BREAK SEMICOLON + + 818 opt_expression : + 819 | expression + + 820 try_statement : TRY block catch_clauses + 821 | TRY block FINALLY block + 822 | TRY block catch_clauses FINALLY block + 823 | TRY block error + + 824 catch_clauses : catch_clause + 825 | catch_clauses catch_clause + + 826 opt_identifier : + 827 | IDENTIFIER + + 828 $$81 : + + 829 catch_clause : CATCH opt_catch_args $$81 block + + 830 opt_catch_args : + 831 | catch_args + + 832 catch_args : open_parens_any type opt_identifier CLOSE_PARENS + 833 | open_parens_any CLOSE_PARENS + + 834 checked_statement : CHECKED block + + 835 unchecked_statement : UNCHECKED block + + 836 $$82 : + + 837 unsafe_statement : UNSAFE $$82 block + + 838 $$83 : + + 839 fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement + + 840 fixed_pointer_declarators : fixed_pointer_declarator + 841 | fixed_pointer_declarators COMMA fixed_pointer_declarator + + 842 fixed_pointer_declarator : IDENTIFIER ASSIGN expression + 843 | IDENTIFIER + + 844 lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement + + 845 $$84 : + + 846 using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS $$84 embedded_statement + + 847 $$85 : + + 848 using_statement : USING open_parens_any expression CLOSE_PARENS $$85 embedded_statement + + 849 query_expression : first_from_clause query_body + 850 | nested_from_clause query_body + 851 | first_from_clause COMPLETE_COMPLETION + 852 | nested_from_clause COMPLETE_COMPLETION + + 853 first_from_clause : FROM_FIRST IDENTIFIER IN expression + 854 | FROM_FIRST type IDENTIFIER IN expression + + 855 nested_from_clause : FROM IDENTIFIER IN expression + 856 | FROM type IDENTIFIER IN expression + + 857 $$86 : + + 858 from_clause : FROM IDENTIFIER IN $$86 expression + + 859 $$87 : + + 860 from_clause : FROM type IDENTIFIER IN $$87 expression + + 861 query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation + 862 | opt_query_body_clauses COMPLETE_COMPLETION + + 863 $$88 : + + 864 select_or_group_clause : SELECT $$88 expression + + 865 $$89 : + + 866 $$90 : + + 867 select_or_group_clause : GROUP $$89 expression $$90 BY expression + + 868 opt_query_body_clauses : + 869 | query_body_clauses + + 870 query_body_clauses : query_body_clause + 871 | query_body_clauses query_body_clause + + 872 query_body_clause : from_clause + 873 | let_clause + 874 | where_clause + 875 | join_clause + 876 | orderby_clause + + 877 $$91 : + + 878 let_clause : LET IDENTIFIER ASSIGN $$91 expression + + 879 $$92 : + + 880 where_clause : WHERE $$92 boolean_expression + + 881 $$93 : + + 882 $$94 : + + 883 $$95 : + + 884 join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into + + 885 $$96 : + + 886 $$97 : + + 887 $$98 : + + 888 join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into + + 889 opt_join_into : + 890 | INTO IDENTIFIER + + 891 $$99 : + + 892 orderby_clause : ORDERBY $$99 orderings + + 893 orderings : order_by + + 894 $$100 : + + 895 orderings : order_by COMMA $$100 orderings_then_by + + 896 orderings_then_by : then_by + + 897 $$101 : + + 898 orderings_then_by : orderings_then_by COMMA $$101 then_by + + 899 order_by : expression + 900 | expression ASCENDING + 901 | expression DESCENDING + + 902 then_by : expression + 903 | expression ASCENDING + 904 | expression DESCENDING + + 905 opt_query_continuation : + + 906 $$102 : + + 907 opt_query_continuation : INTO IDENTIFIER $$102 query_body + + 908 interactive_parsing : EVAL_STATEMENT_PARSER EOF + 909 | EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives + + 910 $$103 : + + 911 interactive_parsing : EVAL_STATEMENT_PARSER $$103 interactive_statement_list opt_COMPLETE_COMPLETION + + 912 $$104 : + + 913 interactive_parsing : EVAL_COMPILATION_UNIT_PARSER $$104 interactive_compilation_unit + + 914 interactive_compilation_unit : outer_declarations + 915 | outer_declarations global_attributes + 916 | global_attributes + 917 | + + 918 opt_COMPLETE_COMPLETION : + 919 | COMPLETE_COMPLETION + + 920 close_brace_or_complete_completion : CLOSE_BRACE + 921 | COMPLETE_COMPLETION + +state 0 + $accept : . compilation_unit $end (0) + opt_EOF : . (7) + opt_attributes : . (59) + + EOF shift 1 + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + EVAL_STATEMENT_PARSER shift 5 + EVAL_COMPILATION_UNIT_PARSER shift 6 + EVAL_USING_DECLARATIONS_UNIT_PARSER shift 7 + $end reduce 7 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + compilation_unit goto 8 + outer_declarations goto 9 + opt_EOF goto 10 + global_attributes goto 11 + interactive_parsing goto 12 + outer_declaration goto 13 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + + +state 1 + opt_EOF : EOF . (8) + + . reduce 8 + + +state 2 + using_alias_directive : USING . IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON (22) + using_alias_directive : USING . error (23) + using_namespace_directive : USING . namespace_name SEMICOLON (24) + + error shift 32 + IDENTIFIER shift 33 + . error + + namespace_or_type_name goto 34 + namespace_name goto 35 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 3 + extern_alias_directive : EXTERN_ALIAS . IDENTIFIER IDENTIFIER SEMICOLON (16) + extern_alias_directive : EXTERN_ALIAS . error (17) + + error shift 39 + IDENTIFIER shift 40 + . error + + +state 4 + attribute_section : OPEN_BRACKET . attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET (63) + attribute_section : OPEN_BRACKET . attribute_list opt_comma CLOSE_BRACKET (64) + + error shift 41 + EVENT shift 42 + RETURN shift 43 + IDENTIFIER shift 44 + . error + + namespace_or_type_name goto 45 + attribute_target_specifier goto 46 + attribute_list goto 47 + attribute_target goto 48 + attribute goto 49 + attribute_name goto 50 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 5 + interactive_parsing : EVAL_STATEMENT_PARSER . EOF (908) + interactive_parsing : EVAL_STATEMENT_PARSER . $$103 interactive_statement_list opt_COMPLETE_COMPLETION (911) + $$103 : . (910) + + EOF shift 51 + error reduce 910 + BASE reduce 910 + BOOL reduce 910 + BREAK reduce 910 + BYTE reduce 910 + CHAR reduce 910 + CHECKED reduce 910 + CONST reduce 910 + CONTINUE reduce 910 + DECIMAL reduce 910 + DEFAULT reduce 910 + DELEGATE reduce 910 + DO reduce 910 + DOUBLE reduce 910 + FALSE reduce 910 + FIXED reduce 910 + FLOAT reduce 910 + FOR reduce 910 + FOREACH reduce 910 + GOTO reduce 910 + IF reduce 910 + INT reduce 910 + LOCK reduce 910 + LONG reduce 910 + NEW reduce 910 + NULL reduce 910 + OBJECT reduce 910 + RETURN reduce 910 + SBYTE reduce 910 + SHORT reduce 910 + SIZEOF reduce 910 + STRING reduce 910 + SWITCH reduce 910 + THIS reduce 910 + THROW reduce 910 + TRUE reduce 910 + TRY reduce 910 + TYPEOF reduce 910 + UINT reduce 910 + ULONG reduce 910 + UNCHECKED reduce 910 + UNSAFE reduce 910 + USHORT reduce 910 + USING reduce 910 + VOID reduce 910 + WHILE reduce 910 + FROM reduce 910 + FROM_FIRST reduce 910 + OPEN_BRACE reduce 910 + OPEN_PARENS reduce 910 + SEMICOLON reduce 910 + TILDE reduce 910 + PLUS reduce 910 + MINUS reduce 910 + BANG reduce 910 + BITWISE_AND reduce 910 + STAR reduce 910 + OP_INC reduce 910 + OP_DEC reduce 910 + LITERAL reduce 910 + IDENTIFIER reduce 910 + OPEN_PARENS_LAMBDA reduce 910 + OPEN_PARENS_CAST reduce 910 + + $$103 goto 52 + + +state 6 + interactive_parsing : EVAL_COMPILATION_UNIT_PARSER . $$104 interactive_compilation_unit (913) + $$104 : . (912) + + . reduce 912 + + $$104 goto 53 + + +state 7 + interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER . using_directives (909) + + USING shift 2 + . error + + using_directive goto 54 + using_directives goto 55 + using_alias_directive goto 17 + using_namespace_directive goto 18 + + +state 8 + $accept : compilation_unit . $end (0) + + $end accept + + +state 9 + compilation_unit : outer_declarations . opt_EOF (1) + compilation_unit : outer_declarations . global_attributes opt_EOF (2) + outer_declarations : outer_declarations . outer_declaration (10) + opt_EOF : . (7) + opt_attributes : . (59) + + EOF shift 1 + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + $end reduce 7 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + opt_EOF goto 56 + global_attributes goto 57 + outer_declaration goto 58 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + + +state 10 + compilation_unit : opt_EOF . (4) + + . reduce 4 + + +state 11 + compilation_unit : global_attributes . opt_EOF (3) + opt_EOF : . (7) + + EOF shift 1 + $end reduce 7 + + opt_EOF goto 59 + + +state 12 + compilation_unit : interactive_parsing . $$1 opt_EOF (6) + $$1 : . (5) + + . reduce 5 + + $$1 goto 60 + + +state 13 + outer_declarations : outer_declaration . (9) + + . reduce 9 + + +state 14 + outer_declaration : extern_alias_directive . (11) + + . reduce 11 + + +state 15 + outer_declaration : using_directive . (12) + + . reduce 12 + + +state 16 + outer_declaration : namespace_member_declaration . (13) + + . reduce 13 + + +state 17 + using_directive : using_alias_directive . (20) + + . reduce 20 + + +state 18 + using_directive : using_namespace_directive . (21) + + . reduce 21 + + +state 19 + namespace_member_declaration : namespace_declaration . (50) + + . reduce 50 + + +state 20 + namespace_declaration : opt_attributes . NAMESPACE qualified_identifier $$2 namespace_body opt_semicolon (26) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT error (110) + field_declaration : opt_attributes . opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes . opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes . opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes . opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE error (243) + enum_declaration : opt_attributes . opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes . opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes . opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NAMESPACE shift 64 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + BOOL reduce 655 + BYTE reduce 655 + CHAR reduce 655 + CLASS reduce 655 + DECIMAL reduce 655 + DELEGATE reduce 655 + DOUBLE reduce 655 + ENUM reduce 655 + FIXED reduce 655 + FLOAT reduce 655 + INT reduce 655 + INTERFACE reduce 655 + LONG reduce 655 + OBJECT reduce 655 + SBYTE reduce 655 + SHORT reduce 655 + STRING reduce 655 + STRUCT reduce 655 + UINT reduce 655 + ULONG reduce 655 + USHORT reduce 655 + VOID reduce 655 + PARTIAL reduce 655 + IDENTIFIER reduce 655 + + opt_modifiers goto 76 + modifiers goto 77 + modifier goto 78 + + +state 21 + namespace_member_declaration : type_declaration . (49) + + . reduce 49 + + +state 22 + namespace_member_declaration : field_declaration . (51) + + . reduce 51 + + +state 23 + namespace_member_declaration : method_declaration . (52) + + . reduce 52 + + +state 24 + type_declaration : class_declaration . (53) + + . reduce 53 + + +state 25 + type_declaration : struct_declaration . (54) + + . reduce 54 + + +state 26 + type_declaration : interface_declaration . (55) + + . reduce 55 + + +state 27 + type_declaration : enum_declaration . (56) + + . reduce 56 + + +state 28 + type_declaration : delegate_declaration . (57) + + . reduce 57 + + +state 29 + global_attributes : attribute_sections . (58) + opt_attributes : attribute_sections . (60) + attribute_sections : attribute_sections . attribute_section (62) + + OPEN_BRACKET shift 4 + $end reduce 58 + EOF reduce 58 + ABSTRACT reduce 60 + BOOL reduce 60 + BYTE reduce 60 + CHAR reduce 60 + CLASS reduce 60 + DECIMAL reduce 60 + DELEGATE reduce 60 + DOUBLE reduce 60 + ENUM reduce 60 + EXTERN reduce 60 + FIXED reduce 60 + FLOAT reduce 60 + INT reduce 60 + INTERFACE reduce 60 + INTERNAL reduce 60 + LONG reduce 60 + NAMESPACE reduce 60 + NEW reduce 60 + OBJECT reduce 60 + OVERRIDE reduce 60 + PRIVATE reduce 60 + PROTECTED reduce 60 + PUBLIC reduce 60 + READONLY reduce 60 + SBYTE reduce 60 + SEALED reduce 60 + SHORT reduce 60 + STATIC reduce 60 + STRING reduce 60 + STRUCT reduce 60 + UINT reduce 60 + ULONG reduce 60 + UNSAFE reduce 60 + USHORT reduce 60 + VIRTUAL reduce 60 + VOID reduce 60 + VOLATILE reduce 60 + PARTIAL reduce 60 + IDENTIFIER reduce 60 + + attribute_section goto 79 + + +state 30 + attribute_sections : attribute_section . (61) + + . reduce 61 + + +state 31 + method_declaration : method_header . $$19 method_body (176) + $$19 : . (175) + + . reduce 175 + + $$19 goto 80 + + +state 32 + using_alias_directive : USING error . (23) + + . reduce 23 + + +state 33 + using_alias_directive : USING IDENTIFIER . ASSIGN namespace_or_type_name SEMICOLON (22) + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + ASSIGN shift 82 + DOUBLE_COLON shift 83 + DOT reduce 363 + SEMICOLON reduce 363 + + opt_type_argument_list goto 84 + + +state 34 + namespace_name : namespace_or_type_name . (34) + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + + DOT shift 85 + SEMICOLON reduce 34 + + +state 35 + using_namespace_directive : USING namespace_name . SEMICOLON (24) + + SEMICOLON shift 86 + . error + + +state 36 + namespace_or_type_name : member_name . (358) + + . reduce 358 + + +state 37 + namespace_or_type_name : qualified_alias_member . IDENTIFIER opt_type_argument_list (359) + + IDENTIFIER shift 87 + . error + + +state 38 + member_name : type_name . (360) + + . reduce 360 + + +state 39 + extern_alias_directive : EXTERN_ALIAS error . (17) + + . reduce 17 + + +state 40 + extern_alias_directive : EXTERN_ALIAS IDENTIFIER . IDENTIFIER SEMICOLON (16) + + IDENTIFIER shift 88 + . error + + +state 41 + attribute_target : error . (69) + + . reduce 69 + + +state 42 + attribute_target : EVENT . (67) + + . reduce 67 + + +state 43 + attribute_target : RETURN . (68) + + . reduce 68 + + +state 44 + attribute_target : IDENTIFIER . (66) + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 66 + + opt_type_argument_list goto 84 + + +state 45 + attribute_name : namespace_or_type_name . (74) + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + + DOT shift 85 + CLOSE_BRACKET reduce 74 + OPEN_PARENS reduce 74 + COMMA reduce 74 + + +state 46 + attribute_section : OPEN_BRACKET attribute_target_specifier . attribute_list opt_comma CLOSE_BRACKET (63) + + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 45 + attribute_list goto 90 + attribute goto 49 + attribute_name goto 50 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 47 + attribute_section : OPEN_BRACKET attribute_list . opt_comma CLOSE_BRACKET (64) + attribute_list : attribute_list . COMMA attribute (71) + opt_comma : . (32) + + COMMA shift 91 + CLOSE_BRACKET reduce 32 + + opt_comma goto 92 + + +state 48 + attribute_target_specifier : attribute_target . COLON (65) + + COLON shift 93 + . error + + +state 49 + attribute_list : attribute . (70) + + . reduce 70 + + +state 50 + attribute : attribute_name . $$5 opt_attribute_arguments (73) + $$5 : . (72) + + . reduce 72 + + $$5 goto 94 + + +state 51 + interactive_parsing : EVAL_STATEMENT_PARSER EOF . (908) + + . reduce 908 + + +state 52 + interactive_parsing : EVAL_STATEMENT_PARSER $$103 . interactive_statement_list opt_COMPLETE_COMPLETION (911) + + error shift 95 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 158 + block goto 159 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 204 + labeled_statement goto 205 + interactive_statement_list goto 206 + interactive_statement goto 207 + interactive_valid_declaration_statement goto 208 + empty_statement goto 209 + selection_statement goto 210 + iteration_statement goto 211 + jump_statement goto 212 + try_statement goto 213 + checked_statement goto 214 + unchecked_statement goto 215 + lock_statement goto 216 + using_statement goto 217 + unsafe_statement goto 218 + fixed_statement goto 219 + interactive_expression_statement goto 220 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + interactive_statement_expression goto 226 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 53 + interactive_parsing : EVAL_COMPILATION_UNIT_PARSER $$104 . interactive_compilation_unit (913) + opt_attributes : . (59) + interactive_compilation_unit : . (917) + + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + $end reduce 917 + EOF reduce 917 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + outer_declarations goto 241 + global_attributes goto 242 + outer_declaration goto 13 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + interactive_compilation_unit goto 243 + + +state 54 + using_directives : using_directive . (18) + + . reduce 18 + + +state 55 + using_directives : using_directives . using_directive (19) + interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives . (909) + + USING shift 2 + $end reduce 909 + EOF reduce 909 + + using_directive goto 244 + using_alias_directive goto 17 + using_namespace_directive goto 18 + + +state 56 + compilation_unit : outer_declarations opt_EOF . (1) + + . reduce 1 + + +state 57 + compilation_unit : outer_declarations global_attributes . opt_EOF (2) + opt_EOF : . (7) + + EOF shift 1 + $end reduce 7 + + opt_EOF goto 245 + + +state 58 + outer_declarations : outer_declarations outer_declaration . (10) + + . reduce 10 + + +state 59 + compilation_unit : global_attributes opt_EOF . (3) + + . reduce 3 + + +state 60 + compilation_unit : interactive_parsing $$1 . opt_EOF (6) + opt_EOF : . (7) + + EOF shift 1 + $end reduce 7 + + opt_EOF goto 246 + + +state 61 + modifier : ABSTRACT . (664) + + . reduce 664 + + +state 62 + modifier : EXTERN . (670) + + . reduce 670 + + +state 63 + modifier : INTERNAL . (662) + + . reduce 662 + + +state 64 + namespace_declaration : opt_attributes NAMESPACE . qualified_identifier $$2 namespace_body opt_semicolon (26) + + error shift 247 + IDENTIFIER shift 248 + . error + + qualified_identifier goto 249 + + +state 65 + modifier : NEW . (659) + + . reduce 659 + + +state 66 + modifier : OVERRIDE . (669) + + . reduce 669 + + +state 67 + modifier : PRIVATE . (663) + + . reduce 663 + + +state 68 + modifier : PROTECTED . (661) + + . reduce 661 + + +state 69 + modifier : PUBLIC . (660) + + . reduce 660 + + +state 70 + modifier : READONLY . (667) + + . reduce 667 + + +state 71 + modifier : SEALED . (665) + + . reduce 665 + + +state 72 + modifier : STATIC . (666) + + . reduce 666 + + +state 73 + modifier : UNSAFE . (672) + + . reduce 672 + + +state 74 + modifier : VIRTUAL . (668) + + . reduce 668 + + +state 75 + modifier : VOLATILE . (671) + + . reduce 671 + + +state 76 + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT error (110) + field_declaration : opt_attributes opt_modifiers . member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes opt_modifiers . member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers . PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes opt_modifiers . member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE error (243) + enum_declaration : opt_attributes opt_modifiers . ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes opt_modifiers . DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes opt_modifiers . opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_partial : . (653) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DELEGATE shift 250 + DOUBLE shift 108 + ENUM shift 251 + FIXED shift 252 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + PARTIAL shift 254 + IDENTIFIER shift 89 + CLASS reduce 653 + INTERFACE reduce 653 + STRUCT reduce 653 + + namespace_or_type_name goto 255 + opt_partial goto 256 + member_type goto 257 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 77 + opt_modifiers : modifiers . (656) + modifiers : modifiers . modifier (658) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + ADD reduce 656 + BOOL reduce 656 + BYTE reduce 656 + CHAR reduce 656 + CLASS reduce 656 + CONST reduce 656 + DECIMAL reduce 656 + DELEGATE reduce 656 + DOUBLE reduce 656 + ENUM reduce 656 + EVENT reduce 656 + EXPLICIT reduce 656 + FIXED reduce 656 + FLOAT reduce 656 + IMPLICIT reduce 656 + INT reduce 656 + INTERFACE reduce 656 + LONG reduce 656 + OBJECT reduce 656 + REMOVE reduce 656 + SBYTE reduce 656 + SHORT reduce 656 + STRING reduce 656 + STRUCT reduce 656 + UINT reduce 656 + ULONG reduce 656 + USHORT reduce 656 + VOID reduce 656 + PARTIAL reduce 656 + GET reduce 656 + SET reduce 656 + TILDE reduce 656 + IDENTIFIER reduce 656 + + modifier goto 262 + + +state 78 + modifiers : modifier . (657) + + . reduce 657 + + +state 79 + attribute_sections : attribute_sections attribute_section . (62) + + . reduce 62 + + +state 80 + method_declaration : method_header $$19 . method_body (176) + + OPEN_BRACE shift 143 + SEMICOLON shift 263 + . error + + method_body goto 264 + block goto 265 + + +state 81 + opt_type_argument_list : OP_GENERICS_LT . type_arguments OP_GENERICS_GT (364) + opt_type_argument_list : OP_GENERICS_LT . error (365) + + error shift 266 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 268 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_arguments goto 270 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 82 + using_alias_directive : USING IDENTIFIER ASSIGN . namespace_or_type_name SEMICOLON (22) + + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 271 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 83 + qualified_alias_member : IDENTIFIER DOUBLE_COLON . (555) + + . reduce 555 + + +state 84 + type_name : IDENTIFIER opt_type_argument_list . (362) + + . reduce 362 + + +state 85 + member_name : namespace_or_type_name DOT . IDENTIFIER opt_type_argument_list (361) + + IDENTIFIER shift 272 + . error + + +state 86 + using_namespace_directive : USING namespace_name SEMICOLON . (24) + + . reduce 24 + + +state 87 + namespace_or_type_name : qualified_alias_member IDENTIFIER . opt_type_argument_list (359) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + ABSTRACT reduce 363 + AS reduce 363 + EXTERN reduce 363 + IN reduce 363 + INTERNAL reduce 363 + IS reduce 363 + NEW reduce 363 + OPERATOR reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + THIS reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + OP_GENERICS_GT reduce 363 + OPEN_BRACE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 273 + + +state 88 + extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER . SEMICOLON (16) + + SEMICOLON shift 274 + . error + + +state 89 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + error reduce 363 + ABSTRACT reduce 363 + AS reduce 363 + EXTERN reduce 363 + IN reduce 363 + INTERNAL reduce 363 + IS reduce 363 + NEW reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + OP_GENERICS_GT reduce 363 + OPEN_BRACE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 84 + + +state 90 + attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list . opt_comma CLOSE_BRACKET (63) + attribute_list : attribute_list . COMMA attribute (71) + opt_comma : . (32) + + COMMA shift 91 + CLOSE_BRACKET reduce 32 + + opt_comma goto 275 + + +state 91 + opt_comma : COMMA . (33) + attribute_list : attribute_list COMMA . attribute (71) + + IDENTIFIER shift 89 + CLOSE_BRACKET reduce 33 + + namespace_or_type_name goto 45 + attribute goto 276 + attribute_name goto 50 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + + +state 92 + attribute_section : OPEN_BRACKET attribute_list opt_comma . CLOSE_BRACKET (64) + + CLOSE_BRACKET shift 277 + . error + + +state 93 + attribute_target_specifier : attribute_target COLON . (65) + + . reduce 65 + + +state 94 + attribute : attribute_name $$5 . opt_attribute_arguments (73) + opt_attribute_arguments : . (75) + + OPEN_PARENS shift 278 + CLOSE_BRACKET reduce 75 + COMMA reduce 75 + + opt_attribute_arguments goto 279 + + +state 95 + interactive_statement_expression : error . (764) + + . reduce 764 + + +state 96 + member_access : BASE . DOT IDENTIFIER opt_type_argument_list (454) + base_access : BASE . OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET (503) + base_access : BASE . OPEN_BRACKET error (504) + + OPEN_BRACKET shift 280 + DOT shift 281 + OPEN_BRACKET_EXPR shift 282 + . error + + +state 97 + builtin_types : BOOL . (405) + + . reduce 405 + + +state 98 + break_statement : BREAK . SEMICOLON (809) + + SEMICOLON shift 283 + . error + + +state 99 + integral_type : BYTE . (411) + + . reduce 411 + + +state 100 + integral_type : CHAR . (418) + + . reduce 418 + + +state 101 + checked_expression : CHECKED . open_parens_any expression CLOSE_PARENS (557) + checked_statement : CHECKED . block (834) + + OPEN_BRACE shift 143 + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + block goto 286 + open_parens_any goto 287 + + +state 102 + local_constant_declaration : CONST . variable_type local_constant_declarators (752) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + VOID shift 290 + OPEN_PARENS shift 291 + LITERAL shift 154 + IDENTIFIER shift 292 + . error + + qualified_alias_member goto 160 + builtin_types goto 293 + integral_type goto 162 + primary_expression goto 294 + primary_expression_no_array_creation goto 295 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + variable_type goto 297 + + +state 103 + continue_statement : CONTINUE . SEMICOLON (810) + + SEMICOLON shift 298 + . error + + +state 104 + builtin_types : DECIMAL . (406) + + . reduce 406 + + +state 105 + default_value_expression : DEFAULT . open_parens_any type CLOSE_PARENS (566) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 299 + + +state 106 + anonymous_method_expression : DELEGATE . opt_anonymous_method_signature $$64 block (561) + opt_anonymous_method_signature : . (562) + + OPEN_PARENS shift 300 + OPEN_BRACE reduce 562 + + opt_anonymous_method_signature goto 301 + anonymous_method_signature goto 302 + + +state 107 + do_statement : DO . embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON (786) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 321 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 108 + builtin_types : DOUBLE . (408) + + . reduce 408 + + +state 109 + boolean_literal : FALSE . (445) + + . reduce 445 + + +state 110 + fixed_statement : FIXED . open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement (839) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 323 + + +state 111 + builtin_types : FLOAT . (407) + + . reduce 407 + + +state 112 + for_statement : FOR . open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 324 + + +state 113 + foreach_statement : FOREACH . open_parens_any type IN expression CLOSE_PARENS (800) + foreach_statement : FOREACH . open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement (802) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 325 + + +state 114 + goto_statement : GOTO . IDENTIFIER SEMICOLON (811) + goto_statement : GOTO . CASE constant_expression SEMICOLON (812) + goto_statement : GOTO . DEFAULT SEMICOLON (813) + + CASE shift 326 + DEFAULT shift 327 + IDENTIFIER shift 328 + . error + + +state 115 + if_statement : IF . open_parens_any boolean_expression CLOSE_PARENS embedded_statement (767) + if_statement : IF . open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement (768) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 329 + + +state 116 + integral_type : INT . (414) + + . reduce 414 + + +state 117 + lock_statement : LOCK . open_parens_any expression CLOSE_PARENS embedded_statement (844) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 330 + + +state 118 + integral_type : LONG . (416) + + . reduce 416 + + +state 119 + object_or_delegate_creation_expression : NEW . new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer (507) + object_or_delegate_creation_expression : NEW . new_expr_type object_or_collection_initializer (508) + array_creation_expression : NEW . new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + array_creation_expression : NEW . new_expr_type rank_specifiers opt_array_initializer (510) + array_creation_expression : NEW . rank_specifiers array_initializer (511) + array_creation_expression : NEW . new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + array_creation_expression : NEW . new_expr_type error (513) + anonymous_type_expression : NEW . OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE (516) + $$62 : . (514) + + OPEN_BRACE shift 331 + OPEN_BRACKET shift 332 + BOOL reduce 514 + BYTE reduce 514 + CHAR reduce 514 + DECIMAL reduce 514 + DOUBLE reduce 514 + FLOAT reduce 514 + INT reduce 514 + LONG reduce 514 + OBJECT reduce 514 + SBYTE reduce 514 + SHORT reduce 514 + STRING reduce 514 + UINT reduce 514 + ULONG reduce 514 + USHORT reduce 514 + VOID reduce 514 + IDENTIFIER reduce 514 + + rank_specifiers goto 333 + new_expr_type goto 334 + $$62 goto 335 + rank_specifier goto 336 + + +state 120 + literal : NULL . (443) + + . reduce 443 + + +state 121 + builtin_types : OBJECT . (403) + + . reduce 403 + + +state 122 + return_statement : RETURN . opt_expression SEMICOLON (814) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 818 + + expression goto 338 + opt_expression goto 339 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 123 + integral_type : SBYTE . (410) + + . reduce 410 + + +state 124 + integral_type : SHORT . (412) + + . reduce 412 + + +state 125 + sizeof_expression : SIZEOF . open_parens_any type CLOSE_PARENS (556) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 342 + + +state 126 + builtin_types : STRING . (404) + + . reduce 404 + + +state 127 + switch_statement : SWITCH . open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 343 + + +state 128 + this_access : THIS . (502) + + . reduce 502 + + +state 129 + throw_statement : THROW . opt_expression SEMICOLON (815) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 818 + + expression goto 338 + opt_expression goto 344 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 130 + boolean_literal : TRUE . (444) + + . reduce 444 + + +state 131 + try_statement : TRY . block catch_clauses (820) + try_statement : TRY . block FINALLY block (821) + try_statement : TRY . block catch_clauses FINALLY block (822) + try_statement : TRY . block error (823) + + OPEN_BRACE shift 143 + . error + + block goto 345 + + +state 132 + typeof_expression : TYPEOF . $$63 open_parens_any typeof_type_expression CLOSE_PARENS (545) + $$63 : . (544) + + . reduce 544 + + $$63 goto 346 + + +state 133 + integral_type : UINT . (415) + + . reduce 415 + + +state 134 + integral_type : ULONG . (417) + + . reduce 417 + + +state 135 + unchecked_expression : UNCHECKED . open_parens_any expression CLOSE_PARENS (558) + unchecked_statement : UNCHECKED . block (835) + + OPEN_BRACE shift 143 + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + block goto 347 + open_parens_any goto 348 + + +state 136 + unsafe_statement : UNSAFE . $$82 block (837) + $$82 : . (836) + + . reduce 836 + + $$82 goto 349 + + +state 137 + integral_type : USHORT . (413) + + . reduce 413 + + +state 138 + using_statement : USING . open_parens_any local_variable_declaration CLOSE_PARENS $$84 embedded_statement (846) + using_statement : USING . open_parens_any expression CLOSE_PARENS $$85 embedded_statement (848) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 350 + + +state 139 + variable_type : VOID . opt_rank_specifier (744) + local_variable_pointer_type : VOID . STAR (747) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + STAR shift 351 + IDENTIFIER reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 353 + rank_specifier goto 336 + + +state 140 + while_statement : WHILE . open_parens_any boolean_expression CLOSE_PARENS embedded_statement (785) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 354 + + +state 141 + nested_from_clause : FROM . IDENTIFIER IN expression (855) + nested_from_clause : FROM . type IDENTIFIER IN expression (856) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 355 + . error + + namespace_or_type_name goto 255 + type goto 356 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 142 + first_from_clause : FROM_FIRST . IDENTIFIER IN expression (853) + first_from_clause : FROM_FIRST . type IDENTIFIER IN expression (854) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 357 + . error + + namespace_or_type_name goto 255 + type goto 358 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 143 + block : OPEN_BRACE . $$74 opt_statement_list block_end (691) + $$74 : . (690) + + . reduce 690 + + $$74 goto 359 + + +state 144 + parenthesized_expression : OPEN_PARENS . expression CLOSE_PARENS (450) + parenthesized_expression : OPEN_PARENS . expression COMPLETE_COMPLETION (451) + cast_expression : OPEN_PARENS . builtin_types CLOSE_PARENS prefixed_unary_expression (572) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 360 + qualified_alias_member goto 160 + builtin_types goto 361 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 145 + empty_statement : SEMICOLON . (737) + + . reduce 737 + + +state 146 + unary_expression : TILDE . prefixed_unary_expression (569) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 362 + cast_expression goto 188 + + +state 147 + prefixed_unary_expression : PLUS . prefixed_unary_expression (574) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 363 + cast_expression goto 188 + + +state 148 + prefixed_unary_expression : MINUS . prefixed_unary_expression (575) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 364 + cast_expression goto 188 + + +state 149 + unary_expression : BANG . prefixed_unary_expression (568) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 365 + cast_expression goto 188 + + +state 150 + prefixed_unary_expression : BITWISE_AND . prefixed_unary_expression (579) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 366 + cast_expression goto 188 + + +state 151 + prefixed_unary_expression : STAR . prefixed_unary_expression (578) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 367 + cast_expression goto 188 + + +state 152 + prefixed_unary_expression : OP_INC . prefixed_unary_expression (576) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 368 + cast_expression goto 188 + + +state 153 + prefixed_unary_expression : OP_DEC . prefixed_unary_expression (577) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 369 + cast_expression goto 188 + + +state 154 + literal : LITERAL . (442) + + . reduce 442 + + +state 155 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + labeled_statement : IDENTIFIER . COLON $$76 statement (739) + yield_statement : IDENTIFIER . RETURN opt_expression SEMICOLON (816) + yield_statement : IDENTIFIER . BREAK SEMICOLON (817) + opt_type_argument_list : . (363) + + BREAK shift 370 + RETURN shift 371 + ARROW shift 372 + OP_GENERICS_LT shift 81 + COLON shift 373 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + AS reduce 363 + IS reduce 363 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + OPEN_PARENS reduce 363 + DOT reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 156 + lambda_expression : OPEN_PARENS_LAMBDA . $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body (640) + $$68 : . (638) + + . reduce 638 + + $$68 goto 376 + + +state 157 + cast_expression : OPEN_PARENS_CAST . type CLOSE_PARENS prefixed_unary_expression (571) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 377 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 158 + interactive_statement_expression : expression . (763) + + . reduce 763 + + +state 159 + interactive_valid_declaration_statement : block . (721) + + . reduce 721 + + +state 160 + member_access : qualified_alias_member . IDENTIFIER opt_type_argument_list (455) + + IDENTIFIER shift 378 + . error + + +state 161 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + variable_type : builtin_types . opt_rank_specifier_or_nullable (743) + local_variable_pointer_type : builtin_types . STAR (746) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 380 + STAR shift 381 + OPEN_BRACKET reduce 356 + IDENTIFIER reduce 356 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 383 + + +state 162 + builtin_types : integral_type . (409) + + . reduce 409 + + +state 163 + member_access : primary_expression . DOT IDENTIFIER opt_type_argument_list (452) + member_access : primary_expression . DOT GENERATE_COMPLETION (456) + member_access : primary_expression . DOT IDENTIFIER GENERATE_COMPLETION (457) + invocation_expression : primary_expression . open_parens_any opt_argument_list close_parens (460) + element_access : primary_expression . OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET (494) + post_increment_expression : primary_expression . OP_INC (505) + post_decrement_expression : primary_expression . OP_DEC (506) + pointer_member_access : primary_expression . OP_PTR IDENTIFIER (559) + unary_expression : primary_expression . (567) + + OPEN_PARENS shift 284 + DOT shift 384 + OP_INC shift 385 + OP_DEC shift 386 + OP_PTR shift 387 + OPEN_PARENS_CAST shift 285 + OPEN_BRACKET_EXPR shift 388 + error reduce 567 + AS reduce 567 + IS reduce 567 + WHERE reduce 567 + FROM reduce 567 + JOIN reduce 567 + ON reduce 567 + EQUALS reduce 567 + SELECT reduce 567 + GROUP reduce 567 + BY reduce 567 + LET reduce 567 + ORDERBY reduce 567 + ASCENDING reduce 567 + DESCENDING reduce 567 + INTO reduce 567 + CLOSE_BRACE reduce 567 + CLOSE_BRACKET reduce 567 + CLOSE_PARENS reduce 567 + COMMA reduce 567 + COLON reduce 567 + SEMICOLON reduce 567 + PLUS reduce 567 + MINUS reduce 567 + ASSIGN reduce 567 + OP_LT reduce 567 + OP_GT reduce 567 + BITWISE_AND reduce 567 + BITWISE_OR reduce 567 + STAR reduce 567 + PERCENT reduce 567 + DIV reduce 567 + CARRET reduce 567 + INTERR reduce 567 + OP_SHIFT_LEFT reduce 567 + OP_SHIFT_RIGHT reduce 567 + OP_LE reduce 567 + OP_GE reduce 567 + OP_EQ reduce 567 + OP_NE reduce 567 + OP_AND reduce 567 + OP_OR reduce 567 + OP_MULT_ASSIGN reduce 567 + OP_DIV_ASSIGN reduce 567 + OP_MOD_ASSIGN reduce 567 + OP_ADD_ASSIGN reduce 567 + OP_SUB_ASSIGN reduce 567 + OP_SHIFT_LEFT_ASSIGN reduce 567 + OP_SHIFT_RIGHT_ASSIGN reduce 567 + OP_AND_ASSIGN reduce 567 + OP_XOR_ASSIGN reduce 567 + OP_OR_ASSIGN reduce 567 + OP_COALESCING reduce 567 + COMPLETE_COMPLETION reduce 567 + + open_parens_any goto 389 + + +164: shift/reduce conflict (shift 390, reduce 419) on STAR +state 164 + primary_expression : primary_expression_no_array_creation . (419) + variable_type : primary_expression_no_array_creation . opt_rank_specifier_or_nullable (742) + local_variable_pointer_type : primary_expression_no_array_creation . STAR (745) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + STAR shift 390 + AS reduce 419 + IS reduce 419 + OPEN_BRACKET reduce 356 + OPEN_PARENS reduce 419 + CLOSE_PARENS reduce 419 + DOT reduce 419 + COMMA reduce 419 + SEMICOLON reduce 419 + PLUS reduce 419 + MINUS reduce 419 + ASSIGN reduce 419 + OP_LT reduce 419 + OP_GT reduce 419 + BITWISE_AND reduce 419 + BITWISE_OR reduce 419 + PERCENT reduce 419 + DIV reduce 419 + CARRET reduce 419 + INTERR reduce 419 + OP_INC reduce 419 + OP_DEC reduce 419 + OP_SHIFT_LEFT reduce 419 + OP_SHIFT_RIGHT reduce 419 + OP_LE reduce 419 + OP_GE reduce 419 + OP_EQ reduce 419 + OP_NE reduce 419 + OP_AND reduce 419 + OP_OR reduce 419 + OP_MULT_ASSIGN reduce 419 + OP_DIV_ASSIGN reduce 419 + OP_MOD_ASSIGN reduce 419 + OP_ADD_ASSIGN reduce 419 + OP_SUB_ASSIGN reduce 419 + OP_SHIFT_LEFT_ASSIGN reduce 419 + OP_SHIFT_RIGHT_ASSIGN reduce 419 + OP_AND_ASSIGN reduce 419 + OP_XOR_ASSIGN reduce 419 + OP_OR_ASSIGN reduce 419 + OP_PTR reduce 419 + OP_COALESCING reduce 419 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 419 + OPEN_BRACKET_EXPR reduce 419 + COMPLETE_COMPLETION reduce 419 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 391 + + +state 165 + primary_expression : array_creation_expression . (420) + + . reduce 420 + + +state 166 + primary_expression_no_array_creation : literal . (421) + + . reduce 421 + + +167: shift/reduce conflict (shift 392, reduce 424) on MINUS +state 167 + primary_expression_no_array_creation : parenthesized_expression . (424) + additive_expression : parenthesized_expression . MINUS multiplicative_expression (587) + + MINUS shift 392 + error reduce 424 + AS reduce 424 + IS reduce 424 + WHERE reduce 424 + FROM reduce 424 + JOIN reduce 424 + ON reduce 424 + EQUALS reduce 424 + SELECT reduce 424 + GROUP reduce 424 + BY reduce 424 + LET reduce 424 + ORDERBY reduce 424 + ASCENDING reduce 424 + DESCENDING reduce 424 + INTO reduce 424 + INTERR_NULLABLE reduce 424 + CLOSE_BRACE reduce 424 + OPEN_BRACKET reduce 424 + CLOSE_BRACKET reduce 424 + OPEN_PARENS reduce 424 + CLOSE_PARENS reduce 424 + DOT reduce 424 + COMMA reduce 424 + COLON reduce 424 + SEMICOLON reduce 424 + PLUS reduce 424 + ASSIGN reduce 424 + OP_LT reduce 424 + OP_GT reduce 424 + BITWISE_AND reduce 424 + BITWISE_OR reduce 424 + STAR reduce 424 + PERCENT reduce 424 + DIV reduce 424 + CARRET reduce 424 + INTERR reduce 424 + OP_INC reduce 424 + OP_DEC reduce 424 + OP_SHIFT_LEFT reduce 424 + OP_SHIFT_RIGHT reduce 424 + OP_LE reduce 424 + OP_GE reduce 424 + OP_EQ reduce 424 + OP_NE reduce 424 + OP_AND reduce 424 + OP_OR reduce 424 + OP_MULT_ASSIGN reduce 424 + OP_DIV_ASSIGN reduce 424 + OP_MOD_ASSIGN reduce 424 + OP_ADD_ASSIGN reduce 424 + OP_SUB_ASSIGN reduce 424 + OP_SHIFT_LEFT_ASSIGN reduce 424 + OP_SHIFT_RIGHT_ASSIGN reduce 424 + OP_AND_ASSIGN reduce 424 + OP_XOR_ASSIGN reduce 424 + OP_OR_ASSIGN reduce 424 + OP_PTR reduce 424 + OP_COALESCING reduce 424 + IDENTIFIER reduce 424 + OPEN_PARENS_CAST reduce 424 + OPEN_BRACKET_EXPR reduce 424 + COMPLETE_COMPLETION reduce 424 + + +state 168 + primary_expression_no_array_creation : default_value_expression . (425) + + . reduce 425 + + +state 169 + primary_expression_no_array_creation : member_access . (426) + + . reduce 426 + + +state 170 + primary_expression_no_array_creation : invocation_expression . (427) + + . reduce 427 + + +state 171 + primary_expression_no_array_creation : element_access . (428) + + . reduce 428 + + +state 172 + primary_expression_no_array_creation : this_access . (429) + + . reduce 429 + + +state 173 + primary_expression_no_array_creation : base_access . (430) + + . reduce 430 + + +state 174 + primary_expression_no_array_creation : post_increment_expression . (431) + + . reduce 431 + + +state 175 + primary_expression_no_array_creation : post_decrement_expression . (432) + + . reduce 432 + + +state 176 + primary_expression_no_array_creation : object_or_delegate_creation_expression . (433) + + . reduce 433 + + +state 177 + primary_expression_no_array_creation : anonymous_type_expression . (434) + + . reduce 434 + + +state 178 + primary_expression_no_array_creation : typeof_expression . (435) + + . reduce 435 + + +state 179 + primary_expression_no_array_creation : sizeof_expression . (436) + + . reduce 436 + + +state 180 + primary_expression_no_array_creation : checked_expression . (437) + + . reduce 437 + + +state 181 + primary_expression_no_array_creation : unchecked_expression . (438) + + . reduce 438 + + +state 182 + primary_expression_no_array_creation : pointer_member_access . (439) + + . reduce 439 + + +state 183 + primary_expression_no_array_creation : anonymous_method_expression . (440) + + . reduce 440 + + +state 184 + literal : boolean_literal . (441) + + . reduce 441 + + +state 185 + expression : non_assignment_expression . (642) + + . reduce 642 + + +state 186 + prefixed_unary_expression : unary_expression . (573) + + . reduce 573 + + +state 187 + multiplicative_expression : prefixed_unary_expression . (580) + assignment_expression : prefixed_unary_expression . ASSIGN expression (615) + assignment_expression : prefixed_unary_expression . OP_MULT_ASSIGN expression (616) + assignment_expression : prefixed_unary_expression . OP_DIV_ASSIGN expression (617) + assignment_expression : prefixed_unary_expression . OP_MOD_ASSIGN expression (618) + assignment_expression : prefixed_unary_expression . OP_ADD_ASSIGN expression (619) + assignment_expression : prefixed_unary_expression . OP_SUB_ASSIGN expression (620) + assignment_expression : prefixed_unary_expression . OP_SHIFT_LEFT_ASSIGN expression (621) + assignment_expression : prefixed_unary_expression . OP_SHIFT_RIGHT_ASSIGN expression (622) + assignment_expression : prefixed_unary_expression . OP_AND_ASSIGN expression (623) + assignment_expression : prefixed_unary_expression . OP_OR_ASSIGN expression (624) + assignment_expression : prefixed_unary_expression . OP_XOR_ASSIGN expression (625) + + ASSIGN shift 393 + OP_MULT_ASSIGN shift 394 + OP_DIV_ASSIGN shift 395 + OP_MOD_ASSIGN shift 396 + OP_ADD_ASSIGN shift 397 + OP_SUB_ASSIGN shift 398 + OP_SHIFT_LEFT_ASSIGN shift 399 + OP_SHIFT_RIGHT_ASSIGN shift 400 + OP_AND_ASSIGN shift 401 + OP_XOR_ASSIGN shift 402 + OP_OR_ASSIGN shift 403 + error reduce 580 + AS reduce 580 + IS reduce 580 + WHERE reduce 580 + FROM reduce 580 + JOIN reduce 580 + ON reduce 580 + EQUALS reduce 580 + SELECT reduce 580 + GROUP reduce 580 + BY reduce 580 + LET reduce 580 + ORDERBY reduce 580 + ASCENDING reduce 580 + DESCENDING reduce 580 + INTO reduce 580 + CLOSE_BRACE reduce 580 + CLOSE_BRACKET reduce 580 + CLOSE_PARENS reduce 580 + COMMA reduce 580 + COLON reduce 580 + SEMICOLON reduce 580 + PLUS reduce 580 + MINUS reduce 580 + OP_LT reduce 580 + OP_GT reduce 580 + BITWISE_AND reduce 580 + BITWISE_OR reduce 580 + STAR reduce 580 + PERCENT reduce 580 + DIV reduce 580 + CARRET reduce 580 + INTERR reduce 580 + OP_SHIFT_LEFT reduce 580 + OP_SHIFT_RIGHT reduce 580 + OP_LE reduce 580 + OP_GE reduce 580 + OP_EQ reduce 580 + OP_NE reduce 580 + OP_AND reduce 580 + OP_OR reduce 580 + OP_COALESCING reduce 580 + COMPLETE_COMPLETION reduce 580 + + +state 188 + unary_expression : cast_expression . (570) + + . reduce 570 + + +state 189 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : multiplicative_expression . (584) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 584 + AS reduce 584 + IS reduce 584 + WHERE reduce 584 + FROM reduce 584 + JOIN reduce 584 + ON reduce 584 + EQUALS reduce 584 + SELECT reduce 584 + GROUP reduce 584 + BY reduce 584 + LET reduce 584 + ORDERBY reduce 584 + ASCENDING reduce 584 + DESCENDING reduce 584 + INTO reduce 584 + CLOSE_BRACE reduce 584 + CLOSE_BRACKET reduce 584 + CLOSE_PARENS reduce 584 + COMMA reduce 584 + COLON reduce 584 + SEMICOLON reduce 584 + PLUS reduce 584 + MINUS reduce 584 + OP_LT reduce 584 + OP_GT reduce 584 + BITWISE_AND reduce 584 + BITWISE_OR reduce 584 + CARRET reduce 584 + INTERR reduce 584 + OP_SHIFT_LEFT reduce 584 + OP_SHIFT_RIGHT reduce 584 + OP_LE reduce 584 + OP_GE reduce 584 + OP_EQ reduce 584 + OP_NE reduce 584 + OP_AND reduce 584 + OP_OR reduce 584 + OP_COALESCING reduce 584 + COMPLETE_COMPLETION reduce 584 + + +state 190 + additive_expression : additive_expression . PLUS multiplicative_expression (585) + additive_expression : additive_expression . MINUS multiplicative_expression (586) + additive_expression : additive_expression . AS type (588) + additive_expression : additive_expression . IS type (589) + shift_expression : additive_expression . (590) + + AS shift 407 + IS shift 408 + PLUS shift 409 + MINUS shift 410 + error reduce 590 + WHERE reduce 590 + FROM reduce 590 + JOIN reduce 590 + ON reduce 590 + EQUALS reduce 590 + SELECT reduce 590 + GROUP reduce 590 + BY reduce 590 + LET reduce 590 + ORDERBY reduce 590 + ASCENDING reduce 590 + DESCENDING reduce 590 + INTO reduce 590 + CLOSE_BRACE reduce 590 + CLOSE_BRACKET reduce 590 + CLOSE_PARENS reduce 590 + COMMA reduce 590 + COLON reduce 590 + SEMICOLON reduce 590 + OP_LT reduce 590 + OP_GT reduce 590 + BITWISE_AND reduce 590 + BITWISE_OR reduce 590 + CARRET reduce 590 + INTERR reduce 590 + OP_SHIFT_LEFT reduce 590 + OP_SHIFT_RIGHT reduce 590 + OP_LE reduce 590 + OP_GE reduce 590 + OP_EQ reduce 590 + OP_NE reduce 590 + OP_AND reduce 590 + OP_OR reduce 590 + OP_COALESCING reduce 590 + COMPLETE_COMPLETION reduce 590 + + +state 191 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : shift_expression . (593) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 593 + WHERE reduce 593 + FROM reduce 593 + JOIN reduce 593 + ON reduce 593 + EQUALS reduce 593 + SELECT reduce 593 + GROUP reduce 593 + BY reduce 593 + LET reduce 593 + ORDERBY reduce 593 + ASCENDING reduce 593 + DESCENDING reduce 593 + INTO reduce 593 + CLOSE_BRACE reduce 593 + CLOSE_BRACKET reduce 593 + CLOSE_PARENS reduce 593 + COMMA reduce 593 + COLON reduce 593 + SEMICOLON reduce 593 + OP_LT reduce 593 + OP_GT reduce 593 + BITWISE_AND reduce 593 + BITWISE_OR reduce 593 + CARRET reduce 593 + INTERR reduce 593 + OP_LE reduce 593 + OP_GE reduce 593 + OP_EQ reduce 593 + OP_NE reduce 593 + OP_AND reduce 593 + OP_OR reduce 593 + OP_COALESCING reduce 593 + COMPLETE_COMPLETION reduce 593 + + +state 192 + relational_expression : relational_expression . OP_LT shift_expression (594) + relational_expression : relational_expression . OP_GT shift_expression (595) + relational_expression : relational_expression . OP_LE shift_expression (596) + relational_expression : relational_expression . OP_GE shift_expression (597) + equality_expression : relational_expression . (598) + + OP_LT shift 413 + OP_GT shift 414 + OP_LE shift 415 + OP_GE shift 416 + error reduce 598 + WHERE reduce 598 + FROM reduce 598 + JOIN reduce 598 + ON reduce 598 + EQUALS reduce 598 + SELECT reduce 598 + GROUP reduce 598 + BY reduce 598 + LET reduce 598 + ORDERBY reduce 598 + ASCENDING reduce 598 + DESCENDING reduce 598 + INTO reduce 598 + CLOSE_BRACE reduce 598 + CLOSE_BRACKET reduce 598 + CLOSE_PARENS reduce 598 + COMMA reduce 598 + COLON reduce 598 + SEMICOLON reduce 598 + BITWISE_AND reduce 598 + BITWISE_OR reduce 598 + CARRET reduce 598 + INTERR reduce 598 + OP_EQ reduce 598 + OP_NE reduce 598 + OP_AND reduce 598 + OP_OR reduce 598 + OP_COALESCING reduce 598 + COMPLETE_COMPLETION reduce 598 + + +state 193 + equality_expression : equality_expression . OP_EQ relational_expression (599) + equality_expression : equality_expression . OP_NE relational_expression (600) + and_expression : equality_expression . (601) + + OP_EQ shift 417 + OP_NE shift 418 + error reduce 601 + WHERE reduce 601 + FROM reduce 601 + JOIN reduce 601 + ON reduce 601 + EQUALS reduce 601 + SELECT reduce 601 + GROUP reduce 601 + BY reduce 601 + LET reduce 601 + ORDERBY reduce 601 + ASCENDING reduce 601 + DESCENDING reduce 601 + INTO reduce 601 + CLOSE_BRACE reduce 601 + CLOSE_BRACKET reduce 601 + CLOSE_PARENS reduce 601 + COMMA reduce 601 + COLON reduce 601 + SEMICOLON reduce 601 + BITWISE_AND reduce 601 + BITWISE_OR reduce 601 + CARRET reduce 601 + INTERR reduce 601 + OP_AND reduce 601 + OP_OR reduce 601 + OP_COALESCING reduce 601 + COMPLETE_COMPLETION reduce 601 + + +state 194 + and_expression : and_expression . BITWISE_AND equality_expression (602) + exclusive_or_expression : and_expression . (603) + + BITWISE_AND shift 419 + error reduce 603 + WHERE reduce 603 + FROM reduce 603 + JOIN reduce 603 + ON reduce 603 + EQUALS reduce 603 + SELECT reduce 603 + GROUP reduce 603 + BY reduce 603 + LET reduce 603 + ORDERBY reduce 603 + ASCENDING reduce 603 + DESCENDING reduce 603 + INTO reduce 603 + CLOSE_BRACE reduce 603 + CLOSE_BRACKET reduce 603 + CLOSE_PARENS reduce 603 + COMMA reduce 603 + COLON reduce 603 + SEMICOLON reduce 603 + BITWISE_OR reduce 603 + CARRET reduce 603 + INTERR reduce 603 + OP_AND reduce 603 + OP_OR reduce 603 + OP_COALESCING reduce 603 + COMPLETE_COMPLETION reduce 603 + + +state 195 + exclusive_or_expression : exclusive_or_expression . CARRET and_expression (604) + inclusive_or_expression : exclusive_or_expression . (605) + + CARRET shift 420 + error reduce 605 + WHERE reduce 605 + FROM reduce 605 + JOIN reduce 605 + ON reduce 605 + EQUALS reduce 605 + SELECT reduce 605 + GROUP reduce 605 + BY reduce 605 + LET reduce 605 + ORDERBY reduce 605 + ASCENDING reduce 605 + DESCENDING reduce 605 + INTO reduce 605 + CLOSE_BRACE reduce 605 + CLOSE_BRACKET reduce 605 + CLOSE_PARENS reduce 605 + COMMA reduce 605 + COLON reduce 605 + SEMICOLON reduce 605 + BITWISE_OR reduce 605 + INTERR reduce 605 + OP_AND reduce 605 + OP_OR reduce 605 + OP_COALESCING reduce 605 + COMPLETE_COMPLETION reduce 605 + + +state 196 + inclusive_or_expression : inclusive_or_expression . BITWISE_OR exclusive_or_expression (606) + conditional_and_expression : inclusive_or_expression . (607) + + BITWISE_OR shift 421 + error reduce 607 + WHERE reduce 607 + FROM reduce 607 + JOIN reduce 607 + ON reduce 607 + EQUALS reduce 607 + SELECT reduce 607 + GROUP reduce 607 + BY reduce 607 + LET reduce 607 + ORDERBY reduce 607 + ASCENDING reduce 607 + DESCENDING reduce 607 + INTO reduce 607 + CLOSE_BRACE reduce 607 + CLOSE_BRACKET reduce 607 + CLOSE_PARENS reduce 607 + COMMA reduce 607 + COLON reduce 607 + SEMICOLON reduce 607 + INTERR reduce 607 + OP_AND reduce 607 + OP_OR reduce 607 + OP_COALESCING reduce 607 + COMPLETE_COMPLETION reduce 607 + + +state 197 + conditional_and_expression : conditional_and_expression . OP_AND inclusive_or_expression (608) + conditional_or_expression : conditional_and_expression . (609) + + OP_AND shift 422 + error reduce 609 + WHERE reduce 609 + FROM reduce 609 + JOIN reduce 609 + ON reduce 609 + EQUALS reduce 609 + SELECT reduce 609 + GROUP reduce 609 + BY reduce 609 + LET reduce 609 + ORDERBY reduce 609 + ASCENDING reduce 609 + DESCENDING reduce 609 + INTO reduce 609 + CLOSE_BRACE reduce 609 + CLOSE_BRACKET reduce 609 + CLOSE_PARENS reduce 609 + COMMA reduce 609 + COLON reduce 609 + SEMICOLON reduce 609 + INTERR reduce 609 + OP_OR reduce 609 + OP_COALESCING reduce 609 + COMPLETE_COMPLETION reduce 609 + + +state 198 + conditional_or_expression : conditional_or_expression . OP_OR conditional_and_expression (610) + null_coalescing_expression : conditional_or_expression . (611) + null_coalescing_expression : conditional_or_expression . OP_COALESCING null_coalescing_expression (612) + + OP_OR shift 423 + OP_COALESCING shift 424 + error reduce 611 + WHERE reduce 611 + FROM reduce 611 + JOIN reduce 611 + ON reduce 611 + EQUALS reduce 611 + SELECT reduce 611 + GROUP reduce 611 + BY reduce 611 + LET reduce 611 + ORDERBY reduce 611 + ASCENDING reduce 611 + DESCENDING reduce 611 + INTO reduce 611 + CLOSE_BRACE reduce 611 + CLOSE_BRACKET reduce 611 + CLOSE_PARENS reduce 611 + COMMA reduce 611 + COLON reduce 611 + SEMICOLON reduce 611 + INTERR reduce 611 + COMPLETE_COMPLETION reduce 611 + + +state 199 + conditional_expression : null_coalescing_expression . (613) + conditional_expression : null_coalescing_expression . INTERR expression COLON expression (614) + + INTERR shift 425 + error reduce 613 + WHERE reduce 613 + FROM reduce 613 + JOIN reduce 613 + ON reduce 613 + EQUALS reduce 613 + SELECT reduce 613 + GROUP reduce 613 + BY reduce 613 + LET reduce 613 + ORDERBY reduce 613 + ASCENDING reduce 613 + DESCENDING reduce 613 + INTO reduce 613 + CLOSE_BRACE reduce 613 + CLOSE_BRACKET reduce 613 + CLOSE_PARENS reduce 613 + COMMA reduce 613 + COLON reduce 613 + SEMICOLON reduce 613 + COMPLETE_COMPLETION reduce 613 + + +state 200 + non_assignment_expression : conditional_expression . (643) + + . reduce 643 + + +state 201 + expression : assignment_expression . (641) + + . reduce 641 + + +state 202 + non_assignment_expression : lambda_expression . (644) + + . reduce 644 + + +state 203 + non_assignment_expression : query_expression . (645) + + . reduce 645 + + +state 204 + interactive_statement : declaration_statement . (705) + + . reduce 705 + + +state 205 + interactive_statement : labeled_statement . (707) + + . reduce 707 + + +state 206 + interactive_statement_list : interactive_statement_list . interactive_statement (704) + interactive_parsing : EVAL_STATEMENT_PARSER $$103 interactive_statement_list . opt_COMPLETE_COMPLETION (911) + opt_COMPLETE_COMPLETION : . (918) + + error shift 95 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + COMPLETE_COMPLETION shift 426 + $end reduce 918 + EOF reduce 918 + + expression goto 158 + block goto 159 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + opt_COMPLETE_COMPLETION goto 427 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 204 + labeled_statement goto 205 + interactive_statement goto 428 + interactive_valid_declaration_statement goto 208 + empty_statement goto 209 + selection_statement goto 210 + iteration_statement goto 211 + jump_statement goto 212 + try_statement goto 213 + checked_statement goto 214 + unchecked_statement goto 215 + lock_statement goto 216 + using_statement goto 217 + unsafe_statement goto 218 + fixed_statement goto 219 + interactive_expression_statement goto 220 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + interactive_statement_expression goto 226 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 207 + interactive_statement_list : interactive_statement . (703) + + . reduce 703 + + +state 208 + interactive_statement : interactive_valid_declaration_statement . (706) + + . reduce 706 + + +state 209 + interactive_valid_declaration_statement : empty_statement . (722) + + . reduce 722 + + +state 210 + interactive_valid_declaration_statement : selection_statement . (724) + + . reduce 724 + + +state 211 + interactive_valid_declaration_statement : iteration_statement . (725) + + . reduce 725 + + +state 212 + interactive_valid_declaration_statement : jump_statement . (726) + + . reduce 726 + + +state 213 + interactive_valid_declaration_statement : try_statement . (727) + + . reduce 727 + + +state 214 + interactive_valid_declaration_statement : checked_statement . (728) + + . reduce 728 + + +state 215 + interactive_valid_declaration_statement : unchecked_statement . (729) + + . reduce 729 + + +state 216 + interactive_valid_declaration_statement : lock_statement . (730) + + . reduce 730 + + +state 217 + interactive_valid_declaration_statement : using_statement . (731) + + . reduce 731 + + +state 218 + interactive_valid_declaration_statement : unsafe_statement . (732) + + . reduce 732 + + +state 219 + interactive_valid_declaration_statement : fixed_statement . (733) + + . reduce 733 + + +state 220 + interactive_valid_declaration_statement : interactive_expression_statement . (723) + + . reduce 723 + + +state 221 + declaration_statement : local_variable_declaration . SEMICOLON (740) + + SEMICOLON shift 429 + . error + + +state 222 + declaration_statement : local_constant_declaration . SEMICOLON (741) + + SEMICOLON shift 430 + . error + + +state 223 + local_variable_type : variable_type . (749) + + . reduce 749 + + +state 224 + local_variable_pointer_type : local_variable_pointer_type . STAR (748) + local_variable_type : local_variable_pointer_type . opt_rank_specifier (750) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + STAR shift 431 + IDENTIFIER reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 432 + rank_specifier goto 336 + + +state 225 + local_variable_declaration : local_variable_type . local_variable_declarators (751) + + IDENTIFIER shift 433 + . error + + local_variable_declarators goto 434 + local_variable_declarator goto 435 + + +state 226 + interactive_expression_statement : interactive_statement_expression . SEMICOLON (759) + interactive_expression_statement : interactive_statement_expression . COMPLETE_COMPLETION (760) + + SEMICOLON shift 436 + COMPLETE_COMPLETION shift 437 + . error + + +state 227 + selection_statement : if_statement . (765) + + . reduce 765 + + +state 228 + selection_statement : switch_statement . (766) + + . reduce 766 + + +state 229 + iteration_statement : while_statement . (781) + + . reduce 781 + + +state 230 + iteration_statement : do_statement . (782) + + . reduce 782 + + +state 231 + iteration_statement : for_statement . (783) + + . reduce 783 + + +state 232 + iteration_statement : foreach_statement . (784) + + . reduce 784 + + +state 233 + jump_statement : break_statement . (803) + + . reduce 803 + + +state 234 + jump_statement : continue_statement . (804) + + . reduce 804 + + +state 235 + jump_statement : goto_statement . (805) + + . reduce 805 + + +state 236 + jump_statement : return_statement . (806) + + . reduce 806 + + +state 237 + jump_statement : throw_statement . (807) + + . reduce 807 + + +state 238 + jump_statement : yield_statement . (808) + + . reduce 808 + + +239: shift/reduce conflict (shift 443, reduce 868) on COMPLETE_COMPLETION +state 239 + query_expression : first_from_clause . query_body (849) + query_expression : first_from_clause . COMPLETE_COMPLETION (851) + opt_query_body_clauses : . (868) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + COMPLETE_COMPLETION shift 443 + SELECT reduce 868 + GROUP reduce 868 + + query_body goto 444 + from_clause goto 445 + opt_query_body_clauses goto 446 + query_body_clauses goto 447 + query_body_clause goto 448 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +240: shift/reduce conflict (shift 453, reduce 868) on COMPLETE_COMPLETION +state 240 + query_expression : nested_from_clause . query_body (850) + query_expression : nested_from_clause . COMPLETE_COMPLETION (852) + opt_query_body_clauses : . (868) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + COMPLETE_COMPLETION shift 453 + SELECT reduce 868 + GROUP reduce 868 + + query_body goto 454 + from_clause goto 445 + opt_query_body_clauses goto 446 + query_body_clauses goto 447 + query_body_clause goto 448 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +state 241 + outer_declarations : outer_declarations . outer_declaration (10) + interactive_compilation_unit : outer_declarations . (914) + interactive_compilation_unit : outer_declarations . global_attributes (915) + opt_attributes : . (59) + + USING shift 2 + EXTERN_ALIAS shift 3 + OPEN_BRACKET shift 4 + $end reduce 914 + EOF reduce 914 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + IDENTIFIER reduce 59 + + global_attributes goto 455 + outer_declaration goto 58 + extern_alias_directive goto 14 + using_directive goto 15 + namespace_member_declaration goto 16 + using_alias_directive goto 17 + using_namespace_directive goto 18 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 29 + attribute_section goto 30 + method_header goto 31 + + +state 242 + interactive_compilation_unit : global_attributes . (916) + + . reduce 916 + + +state 243 + interactive_parsing : EVAL_COMPILATION_UNIT_PARSER $$104 interactive_compilation_unit . (913) + + . reduce 913 + + +state 244 + using_directives : using_directives using_directive . (19) + + . reduce 19 + + +state 245 + compilation_unit : outer_declarations global_attributes opt_EOF . (2) + + . reduce 2 + + +state 246 + compilation_unit : interactive_parsing $$1 opt_EOF . (6) + + . reduce 6 + + +state 247 + qualified_identifier : error . (29) + + . reduce 29 + + +state 248 + qualified_identifier : IDENTIFIER . (27) + + . reduce 27 + + +state 249 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier . $$2 namespace_body opt_semicolon (26) + qualified_identifier : qualified_identifier . DOT IDENTIFIER (28) + $$2 : . (25) + + DOT shift 456 + OPEN_BRACE reduce 25 + + $$2 goto 457 + + +state 250 + delegate_declaration : opt_attributes opt_modifiers DELEGATE . member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + member_type goto 458 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 251 + enum_declaration : opt_attributes opt_modifiers ENUM . type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 460 + + +state 252 + field_declaration : opt_attributes opt_modifiers FIXED . simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers FIXED . simple_type error SEMICOLON (143) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 461 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + simple_type goto 462 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 463 + builtin_types goto 261 + integral_type goto 162 + + +state 253 + type_and_void : VOID . (385) + type_expression : VOID . STAR (398) + + STAR shift 464 + ABSTRACT reduce 385 + EXTERN reduce 385 + INTERNAL reduce 385 + NEW reduce 385 + OVERRIDE reduce 385 + PRIVATE reduce 385 + PROTECTED reduce 385 + PUBLIC reduce 385 + READONLY reduce 385 + SEALED reduce 385 + STATIC reduce 385 + UNSAFE reduce 385 + VIRTUAL reduce 385 + VOLATILE reduce 385 + CLOSE_PARENS reduce 385 + IDENTIFIER reduce 385 + + +state 254 + method_header : opt_attributes opt_modifiers PARTIAL . VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + opt_partial : PARTIAL . (654) + + VOID shift 465 + CLASS reduce 654 + INTERFACE reduce 654 + STRUCT reduce 654 + + +state 255 + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + type_expression : namespace_or_type_name . opt_nullable (395) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 85 + error reduce 356 + ABSTRACT reduce 356 + AS reduce 356 + EXTERN reduce 356 + IN reduce 356 + INTERNAL reduce 356 + IS reduce 356 + NEW reduce 356 + OPERATOR reduce 356 + OVERRIDE reduce 356 + PRIVATE reduce 356 + PROTECTED reduce 356 + PUBLIC reduce 356 + READONLY reduce 356 + SEALED reduce 356 + STATIC reduce 356 + THIS reduce 356 + UNSAFE reduce 356 + VIRTUAL reduce 356 + VOLATILE reduce 356 + WHERE reduce 356 + FROM reduce 356 + JOIN reduce 356 + ON reduce 356 + EQUALS reduce 356 + SELECT reduce 356 + GROUP reduce 356 + BY reduce 356 + LET reduce 356 + ORDERBY reduce 356 + ASCENDING reduce 356 + DESCENDING reduce 356 + INTO reduce 356 + OP_GENERICS_GT reduce 356 + OPEN_BRACE reduce 356 + CLOSE_BRACE reduce 356 + OPEN_BRACKET reduce 356 + CLOSE_BRACKET reduce 356 + OPEN_PARENS reduce 356 + CLOSE_PARENS reduce 356 + COMMA reduce 356 + COLON reduce 356 + SEMICOLON reduce 356 + PLUS reduce 356 + MINUS reduce 356 + OP_LT reduce 356 + OP_GT reduce 356 + BITWISE_AND reduce 356 + BITWISE_OR reduce 356 + STAR reduce 356 + CARRET reduce 356 + INTERR reduce 356 + OP_SHIFT_LEFT reduce 356 + OP_SHIFT_RIGHT reduce 356 + OP_LE reduce 356 + OP_GE reduce 356 + OP_EQ reduce 356 + OP_NE reduce 356 + OP_AND reduce 356 + OP_OR reduce 356 + OP_COALESCING reduce 356 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 356 + OPEN_BRACKET_EXPR reduce 356 + COMPLETE_COMPLETION reduce 356 + + opt_nullable goto 466 + + +state 256 + struct_declaration : opt_attributes opt_modifiers opt_partial . STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers opt_partial . STRUCT error (110) + interface_declaration : opt_attributes opt_modifiers opt_partial . INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers opt_partial . INTERFACE error (243) + class_declaration : opt_attributes opt_modifiers opt_partial . CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + + CLASS shift 467 + INTERFACE shift 468 + STRUCT shift 469 + . error + + +state 257 + field_declaration : opt_attributes opt_modifiers member_type . IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + method_header : opt_attributes opt_modifiers member_type . method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers member_type . modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + IDENTIFIER shift 470 + . error + + type_declaration_name goto 471 + method_declaration_name goto 472 + modifiers goto 473 + qualified_alias_member goto 474 + explicit_interface goto 475 + modifier goto 78 + + +state 258 + type_and_void : type_expression_or_array . (384) + + . reduce 384 + + +state 259 + member_type : type_and_void . (386) + + . reduce 386 + + +state 260 + type_expression_or_array : type_expression . (393) + type_expression_or_array : type_expression . rank_specifiers (394) + type_expression : type_expression . STAR (397) + + OPEN_BRACKET shift 332 + STAR shift 476 + error reduce 393 + ABSTRACT reduce 393 + AS reduce 393 + EXTERN reduce 393 + IN reduce 393 + INTERNAL reduce 393 + IS reduce 393 + NEW reduce 393 + OPERATOR reduce 393 + OVERRIDE reduce 393 + PRIVATE reduce 393 + PROTECTED reduce 393 + PUBLIC reduce 393 + READONLY reduce 393 + SEALED reduce 393 + STATIC reduce 393 + THIS reduce 393 + UNSAFE reduce 393 + VIRTUAL reduce 393 + VOLATILE reduce 393 + WHERE reduce 393 + FROM reduce 393 + JOIN reduce 393 + ON reduce 393 + EQUALS reduce 393 + SELECT reduce 393 + GROUP reduce 393 + BY reduce 393 + LET reduce 393 + ORDERBY reduce 393 + ASCENDING reduce 393 + DESCENDING reduce 393 + INTO reduce 393 + OP_GENERICS_GT reduce 393 + OPEN_BRACE reduce 393 + CLOSE_BRACE reduce 393 + CLOSE_BRACKET reduce 393 + OPEN_PARENS reduce 393 + CLOSE_PARENS reduce 393 + COMMA reduce 393 + COLON reduce 393 + SEMICOLON reduce 393 + PLUS reduce 393 + MINUS reduce 393 + OP_LT reduce 393 + OP_GT reduce 393 + BITWISE_AND reduce 393 + BITWISE_OR reduce 393 + CARRET reduce 393 + INTERR reduce 393 + OP_SHIFT_LEFT reduce 393 + OP_SHIFT_RIGHT reduce 393 + OP_LE reduce 393 + OP_GE reduce 393 + OP_EQ reduce 393 + OP_NE reduce 393 + OP_AND reduce 393 + OP_OR reduce 393 + OP_COALESCING reduce 393 + IDENTIFIER reduce 393 + COMPLETE_COMPLETION reduce 393 + + rank_specifiers goto 477 + rank_specifier goto 336 + + +state 261 + type_expression : builtin_types . opt_nullable (396) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + error reduce 356 + ABSTRACT reduce 356 + AS reduce 356 + EXTERN reduce 356 + IN reduce 356 + INTERNAL reduce 356 + IS reduce 356 + NEW reduce 356 + OPERATOR reduce 356 + OVERRIDE reduce 356 + PRIVATE reduce 356 + PROTECTED reduce 356 + PUBLIC reduce 356 + READONLY reduce 356 + SEALED reduce 356 + STATIC reduce 356 + THIS reduce 356 + UNSAFE reduce 356 + VIRTUAL reduce 356 + VOLATILE reduce 356 + WHERE reduce 356 + FROM reduce 356 + JOIN reduce 356 + ON reduce 356 + EQUALS reduce 356 + SELECT reduce 356 + GROUP reduce 356 + BY reduce 356 + LET reduce 356 + ORDERBY reduce 356 + ASCENDING reduce 356 + DESCENDING reduce 356 + INTO reduce 356 + OP_GENERICS_GT reduce 356 + OPEN_BRACE reduce 356 + CLOSE_BRACE reduce 356 + OPEN_BRACKET reduce 356 + CLOSE_BRACKET reduce 356 + OPEN_PARENS reduce 356 + CLOSE_PARENS reduce 356 + COMMA reduce 356 + COLON reduce 356 + SEMICOLON reduce 356 + PLUS reduce 356 + MINUS reduce 356 + OP_LT reduce 356 + OP_GT reduce 356 + BITWISE_AND reduce 356 + BITWISE_OR reduce 356 + STAR reduce 356 + CARRET reduce 356 + INTERR reduce 356 + OP_SHIFT_LEFT reduce 356 + OP_SHIFT_RIGHT reduce 356 + OP_LE reduce 356 + OP_GE reduce 356 + OP_EQ reduce 356 + OP_NE reduce 356 + OP_AND reduce 356 + OP_OR reduce 356 + OP_COALESCING reduce 356 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 356 + OPEN_BRACKET_EXPR reduce 356 + COMPLETE_COMPLETION reduce 356 + + opt_nullable goto 478 + + +state 262 + modifiers : modifiers modifier . (658) + + . reduce 658 + + +state 263 + method_body : SEMICOLON . (185) + + . reduce 185 + + +state 264 + method_declaration : method_header $$19 method_body . (176) + + . reduce 176 + + +state 265 + method_body : block . (184) + + . reduce 184 + + +state 266 + opt_type_argument_list : OP_GENERICS_LT error . (365) + + . reduce 365 + + +state 267 + type : VOID . (388) + type_expression : VOID . STAR (398) + + STAR shift 464 + error reduce 388 + AS reduce 388 + IN reduce 388 + IS reduce 388 + WHERE reduce 388 + FROM reduce 388 + JOIN reduce 388 + ON reduce 388 + EQUALS reduce 388 + SELECT reduce 388 + GROUP reduce 388 + BY reduce 388 + LET reduce 388 + ORDERBY reduce 388 + ASCENDING reduce 388 + DESCENDING reduce 388 + INTO reduce 388 + OP_GENERICS_GT reduce 388 + OPEN_BRACE reduce 388 + CLOSE_BRACE reduce 388 + CLOSE_BRACKET reduce 388 + OPEN_PARENS reduce 388 + CLOSE_PARENS reduce 388 + COMMA reduce 388 + COLON reduce 388 + SEMICOLON reduce 388 + PLUS reduce 388 + MINUS reduce 388 + OP_LT reduce 388 + OP_GT reduce 388 + BITWISE_AND reduce 388 + BITWISE_OR reduce 388 + CARRET reduce 388 + INTERR reduce 388 + OP_SHIFT_LEFT reduce 388 + OP_SHIFT_RIGHT reduce 388 + OP_LE reduce 388 + OP_GE reduce 388 + OP_EQ reduce 388 + OP_NE reduce 388 + OP_AND reduce 388 + OP_OR reduce 388 + OP_COALESCING reduce 388 + IDENTIFIER reduce 388 + COMPLETE_COMPLETION reduce 388 + + +state 268 + type_arguments : type . (366) + + . reduce 366 + + +state 269 + type : type_expression_or_array . (387) + + . reduce 387 + + +state 270 + opt_type_argument_list : OP_GENERICS_LT type_arguments . OP_GENERICS_GT (364) + type_arguments : type_arguments . COMMA type (367) + + OP_GENERICS_GT shift 479 + COMMA shift 480 + . error + + +state 271 + using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name . SEMICOLON (22) + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + + DOT shift 85 + SEMICOLON shift 481 + . error + + +state 272 + member_name : namespace_or_type_name DOT IDENTIFIER . opt_type_argument_list (361) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + ABSTRACT reduce 363 + AS reduce 363 + EXTERN reduce 363 + IN reduce 363 + INTERNAL reduce 363 + IS reduce 363 + NEW reduce 363 + OPERATOR reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + THIS reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + OP_GENERICS_GT reduce 363 + OPEN_BRACE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 482 + + +state 273 + namespace_or_type_name : qualified_alias_member IDENTIFIER opt_type_argument_list . (359) + + . reduce 359 + + +state 274 + extern_alias_directive : EXTERN_ALIAS IDENTIFIER IDENTIFIER SEMICOLON . (16) + + . reduce 16 + + +state 275 + attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma . CLOSE_BRACKET (63) + + CLOSE_BRACKET shift 483 + . error + + +state 276 + attribute_list : attribute_list COMMA attribute . (71) + + . reduce 71 + + +state 277 + attribute_section : OPEN_BRACKET attribute_list opt_comma CLOSE_BRACKET . (64) + + . reduce 64 + + +state 278 + opt_attribute_arguments : OPEN_PARENS . attribute_arguments CLOSE_PARENS (76) + attribute_arguments : . (77) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 484 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 77 + COMMA reduce 77 + + attribute_arguments goto 485 + positional_or_named_argument goto 486 + named_attribute_argument goto 487 + expression goto 488 + named_argument goto 489 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 279 + attribute : attribute_name $$5 opt_attribute_arguments . (73) + + . reduce 73 + + +state 280 + base_access : BASE OPEN_BRACKET . error (504) + + error shift 490 + . error + + +state 281 + member_access : BASE DOT . IDENTIFIER opt_type_argument_list (454) + + IDENTIFIER shift 491 + . error + + +state 282 + base_access : BASE OPEN_BRACKET_EXPR . expression_list_arguments CLOSE_BRACKET (503) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 493 + named_argument goto 494 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list_arguments goto 495 + expression_list_argument goto 496 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 283 + break_statement : BREAK SEMICOLON . (809) + + . reduce 809 + + +state 284 + open_parens_any : OPEN_PARENS . (446) + + . reduce 446 + + +state 285 + open_parens_any : OPEN_PARENS_CAST . (447) + + . reduce 447 + + +state 286 + checked_statement : CHECKED block . (834) + + . reduce 834 + + +state 287 + checked_expression : CHECKED open_parens_any . expression CLOSE_PARENS (557) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 497 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 288 + checked_expression : CHECKED . open_parens_any expression CLOSE_PARENS (557) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 287 + + +state 289 + unchecked_expression : UNCHECKED . open_parens_any expression CLOSE_PARENS (558) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 348 + + +state 290 + variable_type : VOID . opt_rank_specifier (744) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + IDENTIFIER reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 353 + rank_specifier goto 336 + + +state 291 + parenthesized_expression : OPEN_PARENS . expression CLOSE_PARENS (450) + parenthesized_expression : OPEN_PARENS . expression COMPLETE_COMPLETION (451) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 360 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 292 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 293 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + variable_type : builtin_types . opt_rank_specifier_or_nullable (743) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 380 + OPEN_BRACKET reduce 356 + IDENTIFIER reduce 356 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 383 + + +state 294 + member_access : primary_expression . DOT IDENTIFIER opt_type_argument_list (452) + member_access : primary_expression . DOT GENERATE_COMPLETION (456) + member_access : primary_expression . DOT IDENTIFIER GENERATE_COMPLETION (457) + invocation_expression : primary_expression . open_parens_any opt_argument_list close_parens (460) + element_access : primary_expression . OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET (494) + post_increment_expression : primary_expression . OP_INC (505) + post_decrement_expression : primary_expression . OP_DEC (506) + pointer_member_access : primary_expression . OP_PTR IDENTIFIER (559) + + OPEN_PARENS shift 284 + DOT shift 384 + OP_INC shift 385 + OP_DEC shift 386 + OP_PTR shift 387 + OPEN_PARENS_CAST shift 285 + OPEN_BRACKET_EXPR shift 388 + . error + + open_parens_any goto 389 + + +state 295 + primary_expression : primary_expression_no_array_creation . (419) + variable_type : primary_expression_no_array_creation . opt_rank_specifier_or_nullable (742) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + OPEN_BRACKET reduce 356 + OPEN_PARENS reduce 419 + DOT reduce 419 + OP_INC reduce 419 + OP_DEC reduce 419 + OP_PTR reduce 419 + IDENTIFIER reduce 356 + OPEN_PARENS_CAST reduce 419 + OPEN_BRACKET_EXPR reduce 419 + + opt_nullable goto 382 + opt_rank_specifier_or_nullable goto 391 + + +state 296 + primary_expression_no_array_creation : parenthesized_expression . (424) + + . reduce 424 + + +state 297 + local_constant_declaration : CONST variable_type . local_constant_declarators (752) + + IDENTIFIER shift 498 + . error + + local_constant_declarators goto 499 + local_constant_declarator goto 500 + + +state 298 + continue_statement : CONTINUE SEMICOLON . (810) + + . reduce 810 + + +state 299 + default_value_expression : DEFAULT open_parens_any . type CLOSE_PARENS (566) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 501 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 300 + anonymous_method_signature : OPEN_PARENS . $$65 opt_formal_parameter_list CLOSE_PARENS (565) + $$65 : . (564) + + . reduce 564 + + $$65 goto 502 + + +state 301 + anonymous_method_expression : DELEGATE opt_anonymous_method_signature . $$64 block (561) + $$64 : . (560) + + . reduce 560 + + $$64 goto 503 + + +state 302 + opt_anonymous_method_signature : anonymous_method_signature . (563) + + . reduce 563 + + +state 303 + statement_expression : error . (762) + + . reduce 762 + + +state 304 + statement_expression : expression . (761) + + . reduce 761 + + +state 305 + valid_declaration_statement : block . (708) + + . reduce 708 + + +state 306 + embedded_statement : declaration_statement . (735) + + . reduce 735 + + +state 307 + embedded_statement : valid_declaration_statement . (734) + + . reduce 734 + + +state 308 + embedded_statement : labeled_statement . (736) + + . reduce 736 + + +state 309 + valid_declaration_statement : empty_statement . (709) + + . reduce 709 + + +state 310 + valid_declaration_statement : expression_statement . (710) + + . reduce 710 + + +state 311 + valid_declaration_statement : selection_statement . (711) + + . reduce 711 + + +state 312 + valid_declaration_statement : iteration_statement . (712) + + . reduce 712 + + +state 313 + valid_declaration_statement : jump_statement . (713) + + . reduce 713 + + +state 314 + valid_declaration_statement : try_statement . (714) + + . reduce 714 + + +state 315 + valid_declaration_statement : checked_statement . (715) + + . reduce 715 + + +state 316 + valid_declaration_statement : unchecked_statement . (716) + + . reduce 716 + + +state 317 + valid_declaration_statement : lock_statement . (717) + + . reduce 717 + + +state 318 + valid_declaration_statement : using_statement . (718) + + . reduce 718 + + +state 319 + valid_declaration_statement : unsafe_statement . (719) + + . reduce 719 + + +state 320 + valid_declaration_statement : fixed_statement . (720) + + . reduce 720 + + +state 321 + do_statement : DO embedded_statement . WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON (786) + + WHILE shift 504 + . error + + +state 322 + expression_statement : statement_expression . SEMICOLON (757) + expression_statement : statement_expression . COMPLETE_COMPLETION (758) + + SEMICOLON shift 505 + COMPLETE_COMPLETION shift 506 + . error + + +state 323 + fixed_statement : FIXED open_parens_any . type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement (839) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 507 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 324 + for_statement : FOR open_parens_any . opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + opt_for_initializer : . (789) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + VOID shift 139 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 789 + + expression goto 304 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + local_variable_declaration goto 508 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 509 + opt_for_initializer goto 510 + for_initializer goto 511 + statement_expression_list goto 512 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 325 + foreach_statement : FOREACH open_parens_any . type IN expression CLOSE_PARENS (800) + foreach_statement : FOREACH open_parens_any . type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement (802) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 513 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 326 + goto_statement : GOTO CASE . constant_expression SEMICOLON (812) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 515 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 327 + goto_statement : GOTO DEFAULT . SEMICOLON (813) + + SEMICOLON shift 516 + . error + + +state 328 + goto_statement : GOTO IDENTIFIER . SEMICOLON (811) + + SEMICOLON shift 517 + . error + + +state 329 + if_statement : IF open_parens_any . boolean_expression CLOSE_PARENS embedded_statement (767) + if_statement : IF open_parens_any . boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement (768) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 519 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 330 + lock_statement : LOCK open_parens_any . expression CLOSE_PARENS embedded_statement (844) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 520 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 331 + anonymous_type_expression : NEW OPEN_BRACE . anonymous_type_parameters_opt_comma CLOSE_BRACE (516) + anonymous_type_parameters_opt : . (519) + + error shift 521 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 291 + LITERAL shift 154 + IDENTIFIER shift 522 + CLOSE_BRACE reduce 519 + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 294 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 523 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + anonymous_type_parameters_opt_comma goto 524 + anonymous_type_parameters_opt goto 525 + anonymous_type_parameters goto 526 + anonymous_type_parameter goto 527 + + +state 332 + rank_specifier : OPEN_BRACKET . CLOSE_BRACKET (533) + rank_specifier : OPEN_BRACKET . dim_separators CLOSE_BRACKET (534) + + CLOSE_BRACKET shift 528 + COMMA shift 529 + . error + + dim_separators goto 530 + + +state 333 + array_creation_expression : NEW rank_specifiers . array_initializer (511) + + OPEN_BRACE shift 531 + . error + + array_initializer goto 532 + + +state 334 + object_or_delegate_creation_expression : NEW new_expr_type . open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer (507) + object_or_delegate_creation_expression : NEW new_expr_type . object_or_collection_initializer (508) + array_creation_expression : NEW new_expr_type . OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + array_creation_expression : NEW new_expr_type . rank_specifiers opt_array_initializer (510) + array_creation_expression : NEW new_expr_type . OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + array_creation_expression : NEW new_expr_type . error (513) + + error shift 533 + OPEN_BRACE shift 534 + OPEN_BRACKET shift 535 + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + OPEN_BRACKET_EXPR shift 536 + . error + + rank_specifiers goto 537 + open_parens_any goto 538 + object_or_collection_initializer goto 539 + rank_specifier goto 336 + + +state 335 + new_expr_type : $$62 . simple_type (515) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 461 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + simple_type goto 540 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 463 + builtin_types goto 261 + integral_type goto 162 + + +state 336 + rank_specifiers : rank_specifier . (531) + rank_specifiers : rank_specifier . rank_specifiers (532) + + OPEN_BRACKET shift 332 + error reduce 531 + ABSTRACT reduce 531 + AS reduce 531 + EXTERN reduce 531 + IN reduce 531 + INTERNAL reduce 531 + IS reduce 531 + NEW reduce 531 + OPERATOR reduce 531 + OVERRIDE reduce 531 + PRIVATE reduce 531 + PROTECTED reduce 531 + PUBLIC reduce 531 + READONLY reduce 531 + SEALED reduce 531 + STATIC reduce 531 + THIS reduce 531 + UNSAFE reduce 531 + VIRTUAL reduce 531 + VOLATILE reduce 531 + WHERE reduce 531 + FROM reduce 531 + JOIN reduce 531 + ON reduce 531 + EQUALS reduce 531 + SELECT reduce 531 + GROUP reduce 531 + BY reduce 531 + LET reduce 531 + ORDERBY reduce 531 + ASCENDING reduce 531 + DESCENDING reduce 531 + INTO reduce 531 + OP_GENERICS_GT reduce 531 + OPEN_BRACE reduce 531 + CLOSE_BRACE reduce 531 + CLOSE_BRACKET reduce 531 + OPEN_PARENS reduce 531 + CLOSE_PARENS reduce 531 + DOT reduce 531 + COMMA reduce 531 + COLON reduce 531 + SEMICOLON reduce 531 + PLUS reduce 531 + MINUS reduce 531 + ASSIGN reduce 531 + OP_LT reduce 531 + OP_GT reduce 531 + BITWISE_AND reduce 531 + BITWISE_OR reduce 531 + STAR reduce 531 + PERCENT reduce 531 + DIV reduce 531 + CARRET reduce 531 + INTERR reduce 531 + OP_INC reduce 531 + OP_DEC reduce 531 + OP_SHIFT_LEFT reduce 531 + OP_SHIFT_RIGHT reduce 531 + OP_LE reduce 531 + OP_GE reduce 531 + OP_EQ reduce 531 + OP_NE reduce 531 + OP_AND reduce 531 + OP_OR reduce 531 + OP_MULT_ASSIGN reduce 531 + OP_DIV_ASSIGN reduce 531 + OP_MOD_ASSIGN reduce 531 + OP_ADD_ASSIGN reduce 531 + OP_SUB_ASSIGN reduce 531 + OP_SHIFT_LEFT_ASSIGN reduce 531 + OP_SHIFT_RIGHT_ASSIGN reduce 531 + OP_AND_ASSIGN reduce 531 + OP_XOR_ASSIGN reduce 531 + OP_OR_ASSIGN reduce 531 + OP_PTR reduce 531 + OP_COALESCING reduce 531 + IDENTIFIER reduce 531 + OPEN_PARENS_CAST reduce 531 + OPEN_BRACKET_EXPR reduce 531 + COMPLETE_COMPLETION reduce 531 + + rank_specifiers goto 541 + rank_specifier goto 336 + + +state 337 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 338 + opt_expression : expression . (819) + + . reduce 819 + + +state 339 + return_statement : RETURN opt_expression . SEMICOLON (814) + + SEMICOLON shift 542 + . error + + +state 340 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + + DOT shift 380 + . error + + +state 341 + primary_expression : primary_expression_no_array_creation . (419) + + . reduce 419 + + +state 342 + sizeof_expression : SIZEOF open_parens_any . type CLOSE_PARENS (556) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 543 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 343 + switch_statement : SWITCH open_parens_any . $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + $$77 : . (769) + + . reduce 769 + + $$77 goto 544 + + +state 344 + throw_statement : THROW opt_expression . SEMICOLON (815) + + SEMICOLON shift 545 + . error + + +state 345 + try_statement : TRY block . catch_clauses (820) + try_statement : TRY block . FINALLY block (821) + try_statement : TRY block . catch_clauses FINALLY block (822) + try_statement : TRY block . error (823) + + error shift 546 + CATCH shift 547 + FINALLY shift 548 + . error + + catch_clauses goto 549 + catch_clause goto 550 + + +state 346 + typeof_expression : TYPEOF $$63 . open_parens_any typeof_type_expression CLOSE_PARENS (545) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 551 + + +state 347 + unchecked_statement : UNCHECKED block . (835) + + . reduce 835 + + +state 348 + unchecked_expression : UNCHECKED open_parens_any . expression CLOSE_PARENS (558) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 552 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 349 + unsafe_statement : UNSAFE $$82 . block (837) + + OPEN_BRACE shift 143 + . error + + block goto 553 + + +state 350 + using_statement : USING open_parens_any . local_variable_declaration CLOSE_PARENS $$84 embedded_statement (846) + using_statement : USING open_parens_any . expression CLOSE_PARENS $$85 embedded_statement (848) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + VOID shift 139 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 554 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + local_variable_declaration goto 555 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 351 + local_variable_pointer_type : VOID STAR . (747) + + . reduce 747 + + +state 352 + opt_rank_specifier : rank_specifiers . (528) + + . reduce 528 + + +state 353 + variable_type : VOID opt_rank_specifier . (744) + + . reduce 744 + + +state 354 + while_statement : WHILE open_parens_any . boolean_expression CLOSE_PARENS embedded_statement (785) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 556 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 355 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + nested_from_clause : FROM IDENTIFIER . IN expression (855) + opt_type_argument_list : . (363) + + IN shift 557 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 356 + nested_from_clause : FROM type . IDENTIFIER IN expression (856) + + IDENTIFIER shift 558 + . error + + +state 357 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + first_from_clause : FROM_FIRST IDENTIFIER . IN expression (853) + opt_type_argument_list : . (363) + + IN shift 559 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 358 + first_from_clause : FROM_FIRST type . IDENTIFIER IN expression (854) + + IDENTIFIER shift 560 + . error + + +state 359 + block : OPEN_BRACE $$74 . opt_statement_list block_end (691) + opt_statement_list : . (696) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 696 + COMPLETE_COMPLETION reduce 696 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + opt_statement_list goto 561 + statement_list goto 562 + statement goto 563 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 360 + parenthesized_expression : OPEN_PARENS expression . CLOSE_PARENS (450) + parenthesized_expression : OPEN_PARENS expression . COMPLETE_COMPLETION (451) + + CLOSE_PARENS shift 567 + COMPLETE_COMPLETION shift 568 + . error + + +state 361 + member_access : builtin_types . DOT IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types . DOT GENERATE_COMPLETION (458) + member_access : builtin_types . DOT IDENTIFIER GENERATE_COMPLETION (459) + cast_expression : OPEN_PARENS builtin_types . CLOSE_PARENS prefixed_unary_expression (572) + + CLOSE_PARENS shift 569 + DOT shift 380 + . error + + +state 362 + unary_expression : TILDE prefixed_unary_expression . (569) + + . reduce 569 + + +state 363 + prefixed_unary_expression : PLUS prefixed_unary_expression . (574) + + . reduce 574 + + +state 364 + prefixed_unary_expression : MINUS prefixed_unary_expression . (575) + + . reduce 575 + + +state 365 + unary_expression : BANG prefixed_unary_expression . (568) + + . reduce 568 + + +state 366 + prefixed_unary_expression : BITWISE_AND prefixed_unary_expression . (579) + + . reduce 579 + + +state 367 + prefixed_unary_expression : STAR prefixed_unary_expression . (578) + + . reduce 578 + + +state 368 + prefixed_unary_expression : OP_INC prefixed_unary_expression . (576) + + . reduce 576 + + +state 369 + prefixed_unary_expression : OP_DEC prefixed_unary_expression . (577) + + . reduce 577 + + +state 370 + yield_statement : IDENTIFIER BREAK . SEMICOLON (817) + + SEMICOLON shift 570 + . error + + +state 371 + yield_statement : IDENTIFIER RETURN . opt_expression SEMICOLON (816) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 818 + + expression goto 338 + opt_expression goto 571 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 372 + lambda_expression : IDENTIFIER ARROW . $$67 lambda_expression_body (637) + $$67 : . (636) + + . reduce 636 + + $$67 goto 572 + + +state 373 + labeled_statement : IDENTIFIER COLON . $$76 statement (739) + $$76 : . (738) + + . reduce 738 + + $$76 goto 573 + + +state 374 + primary_expression_no_array_creation : IDENTIFIER GENERATE_COMPLETION . (423) + + . reduce 423 + + +state 375 + primary_expression_no_array_creation : IDENTIFIER opt_type_argument_list . (422) + + . reduce 422 + + +state 376 + lambda_expression : OPEN_PARENS_LAMBDA $$68 . opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body (640) + opt_lambda_parameter_list : . (631) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + OUT shift 574 + REF shift 575 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + THIS shift 576 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 578 + CLOSE_PARENS reduce 631 + + namespace_or_type_name goto 255 + parameter_type goto 579 + parameter_modifier goto 580 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + lambda_parameter_list goto 582 + lambda_parameter goto 583 + opt_lambda_parameter_list goto 584 + + +state 377 + cast_expression : OPEN_PARENS_CAST type . CLOSE_PARENS prefixed_unary_expression (571) + + CLOSE_PARENS shift 585 + . error + + +state 378 + member_access : qualified_alias_member IDENTIFIER . opt_type_argument_list (455) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 586 + + +state 379 + opt_nullable : INTERR_NULLABLE . (357) + + . reduce 357 + + +state 380 + member_access : builtin_types DOT . IDENTIFIER opt_type_argument_list (453) + member_access : builtin_types DOT . GENERATE_COMPLETION (458) + member_access : builtin_types DOT . IDENTIFIER GENERATE_COMPLETION (459) + + IDENTIFIER shift 587 + GENERATE_COMPLETION shift 588 + . error + + +state 381 + local_variable_pointer_type : builtin_types STAR . (746) + + . reduce 746 + + +state 382 + opt_rank_specifier_or_nullable : opt_nullable . (529) + opt_rank_specifier_or_nullable : opt_nullable . rank_specifiers (530) + + OPEN_BRACKET shift 332 + IDENTIFIER reduce 529 + + rank_specifiers goto 589 + rank_specifier goto 336 + + +state 383 + variable_type : builtin_types opt_rank_specifier_or_nullable . (743) + + . reduce 743 + + +state 384 + member_access : primary_expression DOT . IDENTIFIER opt_type_argument_list (452) + member_access : primary_expression DOT . GENERATE_COMPLETION (456) + member_access : primary_expression DOT . IDENTIFIER GENERATE_COMPLETION (457) + + IDENTIFIER shift 590 + GENERATE_COMPLETION shift 591 + . error + + +state 385 + post_increment_expression : primary_expression OP_INC . (505) + + . reduce 505 + + +state 386 + post_decrement_expression : primary_expression OP_DEC . (506) + + . reduce 506 + + +state 387 + pointer_member_access : primary_expression OP_PTR . IDENTIFIER (559) + + IDENTIFIER shift 592 + . error + + +state 388 + element_access : primary_expression OPEN_BRACKET_EXPR . expression_list_arguments CLOSE_BRACKET (494) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 493 + named_argument goto 494 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list_arguments goto 593 + expression_list_argument goto 496 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 389 + invocation_expression : primary_expression open_parens_any . opt_argument_list close_parens (460) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + COMPLETE_COMPLETION reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 600 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 390 + local_variable_pointer_type : primary_expression_no_array_creation STAR . (745) + + . reduce 745 + + +state 391 + variable_type : primary_expression_no_array_creation opt_rank_specifier_or_nullable . (742) + + . reduce 742 + + +state 392 + additive_expression : parenthesized_expression MINUS . multiplicative_expression (587) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 606 + + +state 393 + assignment_expression : prefixed_unary_expression ASSIGN . expression (615) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 607 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 394 + assignment_expression : prefixed_unary_expression OP_MULT_ASSIGN . expression (616) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 608 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 395 + assignment_expression : prefixed_unary_expression OP_DIV_ASSIGN . expression (617) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 609 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 396 + assignment_expression : prefixed_unary_expression OP_MOD_ASSIGN . expression (618) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 610 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 397 + assignment_expression : prefixed_unary_expression OP_ADD_ASSIGN . expression (619) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 611 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 398 + assignment_expression : prefixed_unary_expression OP_SUB_ASSIGN . expression (620) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 612 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 399 + assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN . expression (621) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 613 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 400 + assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN . expression (622) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 614 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 401 + assignment_expression : prefixed_unary_expression OP_AND_ASSIGN . expression (623) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 615 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 402 + assignment_expression : prefixed_unary_expression OP_XOR_ASSIGN . expression (625) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 616 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 403 + assignment_expression : prefixed_unary_expression OP_OR_ASSIGN . expression (624) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 617 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 404 + multiplicative_expression : multiplicative_expression STAR . prefixed_unary_expression (581) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 618 + cast_expression goto 188 + + +state 405 + multiplicative_expression : multiplicative_expression PERCENT . prefixed_unary_expression (583) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 619 + cast_expression goto 188 + + +state 406 + multiplicative_expression : multiplicative_expression DIV . prefixed_unary_expression (582) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 620 + cast_expression goto 188 + + +state 407 + additive_expression : additive_expression AS . type (588) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 621 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 408 + additive_expression : additive_expression IS . type (589) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 622 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 409 + additive_expression : additive_expression PLUS . multiplicative_expression (585) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 623 + + +state 410 + additive_expression : additive_expression MINUS . multiplicative_expression (586) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 624 + + +state 411 + shift_expression : shift_expression OP_SHIFT_LEFT . additive_expression (591) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 625 + + +state 412 + shift_expression : shift_expression OP_SHIFT_RIGHT . additive_expression (592) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 626 + + +state 413 + relational_expression : relational_expression OP_LT . shift_expression (594) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 627 + + +state 414 + relational_expression : relational_expression OP_GT . shift_expression (595) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 628 + + +state 415 + relational_expression : relational_expression OP_LE . shift_expression (596) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 629 + + +state 416 + relational_expression : relational_expression OP_GE . shift_expression (597) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 630 + + +state 417 + equality_expression : equality_expression OP_EQ . relational_expression (599) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 631 + + +state 418 + equality_expression : equality_expression OP_NE . relational_expression (600) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 632 + + +state 419 + and_expression : and_expression BITWISE_AND . equality_expression (602) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 633 + + +state 420 + exclusive_or_expression : exclusive_or_expression CARRET . and_expression (604) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 634 + + +state 421 + inclusive_or_expression : inclusive_or_expression BITWISE_OR . exclusive_or_expression (606) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 635 + + +state 422 + conditional_and_expression : conditional_and_expression OP_AND . inclusive_or_expression (608) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 636 + + +state 423 + conditional_or_expression : conditional_or_expression OP_OR . conditional_and_expression (610) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 637 + + +state 424 + null_coalescing_expression : conditional_or_expression OP_COALESCING . null_coalescing_expression (612) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 638 + + +state 425 + conditional_expression : null_coalescing_expression INTERR . expression COLON expression (614) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 639 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 426 + opt_COMPLETE_COMPLETION : COMPLETE_COMPLETION . (919) + + . reduce 919 + + +state 427 + interactive_parsing : EVAL_STATEMENT_PARSER $$103 interactive_statement_list opt_COMPLETE_COMPLETION . (911) + + . reduce 911 + + +state 428 + interactive_statement_list : interactive_statement_list interactive_statement . (704) + + . reduce 704 + + +state 429 + declaration_statement : local_variable_declaration SEMICOLON . (740) + + . reduce 740 + + +state 430 + declaration_statement : local_constant_declaration SEMICOLON . (741) + + . reduce 741 + + +state 431 + local_variable_pointer_type : local_variable_pointer_type STAR . (748) + + . reduce 748 + + +state 432 + local_variable_type : local_variable_pointer_type opt_rank_specifier . (750) + + . reduce 750 + + +state 433 + local_variable_declarator : IDENTIFIER . ASSIGN local_variable_initializer (164) + local_variable_declarator : IDENTIFIER . (165) + local_variable_declarator : IDENTIFIER . variable_bad_array (166) + + ASSIGN shift 640 + OPEN_BRACKET_EXPR shift 641 + CLOSE_PARENS reduce 165 + COMMA reduce 165 + SEMICOLON reduce 165 + + variable_bad_array goto 642 + + +state 434 + local_variable_declarators : local_variable_declarators . COMMA local_variable_declarator (163) + local_variable_declaration : local_variable_type local_variable_declarators . (751) + + COMMA shift 643 + CLOSE_PARENS reduce 751 + SEMICOLON reduce 751 + + +state 435 + local_variable_declarators : local_variable_declarator . (162) + + . reduce 162 + + +state 436 + interactive_expression_statement : interactive_statement_expression SEMICOLON . (759) + + . reduce 759 + + +state 437 + interactive_expression_statement : interactive_statement_expression COMPLETE_COMPLETION . (760) + + . reduce 760 + + +state 438 + where_clause : WHERE . $$92 boolean_expression (880) + $$92 : . (879) + + . reduce 879 + + $$92 goto 644 + + +state 439 + from_clause : FROM . IDENTIFIER IN $$86 expression (858) + from_clause : FROM . type IDENTIFIER IN $$87 expression (860) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 645 + . error + + namespace_or_type_name goto 255 + type goto 646 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 440 + join_clause : JOIN . IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + join_clause : JOIN . type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 647 + . error + + namespace_or_type_name goto 255 + type goto 648 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 441 + let_clause : LET . IDENTIFIER ASSIGN $$91 expression (878) + + IDENTIFIER shift 649 + . error + + +state 442 + orderby_clause : ORDERBY . $$99 orderings (892) + $$99 : . (891) + + . reduce 891 + + $$99 goto 650 + + +state 443 + query_expression : first_from_clause COMPLETE_COMPLETION . (851) + + . reduce 851 + + +state 444 + query_expression : first_from_clause query_body . (849) + + . reduce 849 + + +state 445 + query_body_clause : from_clause . (872) + + . reduce 872 + + +state 446 + query_body : opt_query_body_clauses . select_or_group_clause opt_query_continuation (861) + query_body : opt_query_body_clauses . COMPLETE_COMPLETION (862) + + SELECT shift 651 + GROUP shift 652 + COMPLETE_COMPLETION shift 653 + . error + + select_or_group_clause goto 654 + + +state 447 + opt_query_body_clauses : query_body_clauses . (869) + query_body_clauses : query_body_clauses . query_body_clause (871) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + SELECT reduce 869 + GROUP reduce 869 + COMPLETE_COMPLETION reduce 869 + + from_clause goto 445 + query_body_clause goto 655 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +state 448 + query_body_clauses : query_body_clause . (870) + + . reduce 870 + + +state 449 + query_body_clause : let_clause . (873) + + . reduce 873 + + +state 450 + query_body_clause : where_clause . (874) + + . reduce 874 + + +state 451 + query_body_clause : join_clause . (875) + + . reduce 875 + + +state 452 + query_body_clause : orderby_clause . (876) + + . reduce 876 + + +state 453 + query_expression : nested_from_clause COMPLETE_COMPLETION . (852) + + . reduce 852 + + +state 454 + query_expression : nested_from_clause query_body . (850) + + . reduce 850 + + +state 455 + interactive_compilation_unit : outer_declarations global_attributes . (915) + + . reduce 915 + + +state 456 + qualified_identifier : qualified_identifier DOT . IDENTIFIER (28) + + IDENTIFIER shift 656 + . error + + +state 457 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 . namespace_body opt_semicolon (26) + + OPEN_BRACE shift 657 + . error + + namespace_body goto 658 + + +state 458 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type . type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 659 + + +state 459 + type_declaration_name : IDENTIFIER . $$61 opt_type_parameter_list (369) + $$61 : . (368) + + . reduce 368 + + $$61 goto 660 + + +state 460 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name . opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + opt_enum_base : . (341) + + COLON shift 661 + OPEN_BRACE reduce 341 + + opt_enum_base goto 662 + + +state 461 + simple_type : VOID . (390) + type_expression : VOID . STAR (398) + + STAR shift 464 + error reduce 390 + OPEN_BRACE reduce 390 + OPEN_BRACKET reduce 390 + OPEN_PARENS reduce 390 + CLOSE_PARENS reduce 390 + COMMA reduce 390 + SEMICOLON reduce 390 + IDENTIFIER reduce 390 + OPEN_PARENS_CAST reduce 390 + OPEN_BRACKET_EXPR reduce 390 + + +state 462 + field_declaration : opt_attributes opt_modifiers FIXED simple_type . IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers FIXED simple_type . error SEMICOLON (143) + + error shift 663 + IDENTIFIER shift 664 + . error + + +state 463 + simple_type : type_expression . (389) + type_expression : type_expression . STAR (397) + + STAR shift 476 + error reduce 389 + OPEN_BRACE reduce 389 + OPEN_BRACKET reduce 389 + OPEN_PARENS reduce 389 + CLOSE_PARENS reduce 389 + COMMA reduce 389 + SEMICOLON reduce 389 + IDENTIFIER reduce 389 + OPEN_PARENS_CAST reduce 389 + OPEN_BRACKET_EXPR reduce 389 + + +state 464 + type_expression : VOID STAR . (398) + + . reduce 398 + + +state 465 + method_header : opt_attributes opt_modifiers PARTIAL VOID . method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + + IDENTIFIER shift 665 + . error + + type_declaration_name goto 471 + method_declaration_name goto 666 + qualified_alias_member goto 474 + explicit_interface goto 475 + + +state 466 + type_expression : namespace_or_type_name opt_nullable . (395) + + . reduce 395 + + +state 467 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS . $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + $$70 : . (648) + + . reduce 648 + + $$70 goto 667 + + +state 468 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE . $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE . error (243) + $$33 : . (238) + + error shift 668 + IDENTIFIER reduce 238 + + $$33 goto 669 + + +state 469 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT . $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT . error (110) + $$7 : . (105) + + error shift 670 + IDENTIFIER reduce 105 + + $$7 goto 671 + + +state 470 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER . $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + type_declaration_name : IDENTIFIER . $$61 opt_type_parameter_list (369) + explicit_interface : IDENTIFIER . opt_type_argument_list DOT (375) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + $$14 : . (139) + opt_type_argument_list : . (363) + $$61 : . (368) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + OP_GENERICS_LT_DECL reduce 368 + OPEN_BRACE reduce 368 + OPEN_PARENS reduce 368 + DOT reduce 363 + COMMA reduce 139 + SEMICOLON reduce 139 + ASSIGN reduce 139 + + $$14 goto 672 + opt_type_argument_list goto 673 + $$61 goto 660 + + +state 471 + method_declaration_name : type_declaration_name . (371) + + . reduce 371 + + +state 472 + method_header : opt_attributes opt_modifiers member_type method_declaration_name . OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + + OPEN_PARENS shift 674 + . error + + +state 473 + method_header : opt_attributes opt_modifiers member_type modifiers . method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + modifiers : modifiers . modifier (658) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + IDENTIFIER shift 665 + . error + + type_declaration_name goto 471 + method_declaration_name goto 675 + qualified_alias_member goto 474 + explicit_interface goto 475 + modifier goto 262 + + +state 474 + explicit_interface : qualified_alias_member . IDENTIFIER opt_type_argument_list DOT (376) + + IDENTIFIER shift 676 + . error + + +state 475 + method_declaration_name : explicit_interface . IDENTIFIER opt_type_parameter_list (372) + explicit_interface : explicit_interface . IDENTIFIER opt_type_argument_list DOT (377) + + IDENTIFIER shift 677 + . error + + +state 476 + type_expression : type_expression STAR . (397) + + . reduce 397 + + +state 477 + type_expression_or_array : type_expression rank_specifiers . (394) + + . reduce 394 + + +state 478 + type_expression : builtin_types opt_nullable . (396) + + . reduce 396 + + +state 479 + opt_type_argument_list : OP_GENERICS_LT type_arguments OP_GENERICS_GT . (364) + + . reduce 364 + + +state 480 + type_arguments : type_arguments COMMA . type (367) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 678 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 481 + using_alias_directive : USING IDENTIFIER ASSIGN namespace_or_type_name SEMICOLON . (22) + + . reduce 22 + + +state 482 + member_name : namespace_or_type_name DOT IDENTIFIER opt_type_argument_list . (361) + + . reduce 361 + + +state 483 + attribute_section : OPEN_BRACKET attribute_target_specifier attribute_list opt_comma CLOSE_BRACKET . (63) + + . reduce 63 + + +484: shift/reduce conflict (shift 680, reduce 363) on ASSIGN +state 484 + named_attribute_argument : IDENTIFIER . ASSIGN $$6 expression (85) + named_argument : IDENTIFIER . COLON opt_named_modifier expression (86) + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + COLON shift 679 + ASSIGN shift 680 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + AS reduce 363 + IS reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + + opt_type_argument_list goto 375 + + +state 485 + opt_attribute_arguments : OPEN_PARENS attribute_arguments . CLOSE_PARENS (76) + attribute_arguments : attribute_arguments . COMMA positional_or_named_argument (80) + attribute_arguments : attribute_arguments . COMMA named_attribute_argument (81) + + CLOSE_PARENS shift 681 + COMMA shift 682 + . error + + +state 486 + attribute_arguments : positional_or_named_argument . (78) + + . reduce 78 + + +state 487 + attribute_arguments : named_attribute_argument . (79) + + . reduce 79 + + +state 488 + positional_or_named_argument : expression . (82) + + . reduce 82 + + +state 489 + positional_or_named_argument : named_argument . (83) + + . reduce 83 + + +state 490 + base_access : BASE OPEN_BRACKET error . (504) + + . reduce 504 + + +state 491 + member_access : BASE DOT IDENTIFIER . opt_type_argument_list (454) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 683 + + +state 492 + named_argument : IDENTIFIER . COLON opt_named_modifier expression (86) + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + COLON shift 679 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + AS reduce 363 + IS reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 493 + expression_list_argument : expression . (500) + + . reduce 500 + + +state 494 + expression_list_argument : named_argument . (501) + + . reduce 501 + + +state 495 + expression_list_arguments : expression_list_arguments . COMMA expression_list_argument (499) + base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments . CLOSE_BRACKET (503) + + CLOSE_BRACKET shift 684 + COMMA shift 685 + . error + + +state 496 + expression_list_arguments : expression_list_argument . (498) + + . reduce 498 + + +state 497 + checked_expression : CHECKED open_parens_any expression . CLOSE_PARENS (557) + + CLOSE_PARENS shift 686 + . error + + +state 498 + local_constant_declarator : IDENTIFIER . ASSIGN constant_initializer_expr (755) + local_constant_declarator : IDENTIFIER . error (756) + + error shift 687 + ASSIGN shift 688 + . error + + +state 499 + local_constant_declaration : CONST variable_type local_constant_declarators . (752) + local_constant_declarators : local_constant_declarators . COMMA local_constant_declarator (754) + + COMMA shift 689 + SEMICOLON reduce 752 + + +state 500 + local_constant_declarators : local_constant_declarator . (753) + + . reduce 753 + + +state 501 + default_value_expression : DEFAULT open_parens_any type . CLOSE_PARENS (566) + + CLOSE_PARENS shift 690 + . error + + +state 502 + anonymous_method_signature : OPEN_PARENS $$65 . opt_formal_parameter_list CLOSE_PARENS (565) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 694 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 503 + anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$64 . block (561) + + OPEN_BRACE shift 143 + . error + + block goto 700 + + +state 504 + do_statement : DO embedded_statement WHILE . open_parens_any boolean_expression CLOSE_PARENS SEMICOLON (786) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + . error + + open_parens_any goto 701 + + +state 505 + expression_statement : statement_expression SEMICOLON . (757) + + . reduce 757 + + +state 506 + expression_statement : statement_expression COMPLETE_COMPLETION . (758) + + . reduce 758 + + +state 507 + fixed_statement : FIXED open_parens_any type_and_void . fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement (839) + + IDENTIFIER shift 702 + . error + + fixed_pointer_declarators goto 703 + fixed_pointer_declarator goto 704 + + +state 508 + for_initializer : local_variable_declaration . (791) + + . reduce 791 + + +state 509 + statement_expression_list : statement_expression . (798) + + . reduce 798 + + +state 510 + for_statement : FOR open_parens_any opt_for_initializer . SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + + SEMICOLON shift 705 + . error + + +state 511 + opt_for_initializer : for_initializer . (790) + + . reduce 790 + + +state 512 + for_initializer : statement_expression_list . (792) + statement_expression_list : statement_expression_list . COMMA statement_expression (799) + + COMMA shift 706 + SEMICOLON reduce 792 + + +state 513 + foreach_statement : FOREACH open_parens_any type . IN expression CLOSE_PARENS (800) + foreach_statement : FOREACH open_parens_any type . IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement (802) + + IN shift 707 + IDENTIFIER shift 708 + . error + + +state 514 + constant_expression : expression . (646) + + . reduce 646 + + +state 515 + goto_statement : GOTO CASE constant_expression . SEMICOLON (812) + + SEMICOLON shift 709 + . error + + +state 516 + goto_statement : GOTO DEFAULT SEMICOLON . (813) + + . reduce 813 + + +state 517 + goto_statement : GOTO IDENTIFIER SEMICOLON . (811) + + . reduce 811 + + +state 518 + boolean_expression : expression . (647) + + . reduce 647 + + +state 519 + if_statement : IF open_parens_any boolean_expression . CLOSE_PARENS embedded_statement (767) + if_statement : IF open_parens_any boolean_expression . CLOSE_PARENS embedded_statement ELSE embedded_statement (768) + + CLOSE_PARENS shift 710 + . error + + +state 520 + lock_statement : LOCK open_parens_any expression . CLOSE_PARENS embedded_statement (844) + + CLOSE_PARENS shift 711 + . error + + +state 521 + anonymous_type_parameter : error . (526) + + . reduce 526 + + +state 522 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + anonymous_type_parameter : IDENTIFIER . ASSIGN variable_initializer (523) + anonymous_type_parameter : IDENTIFIER . (524) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + ASSIGN shift 712 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + CLOSE_BRACE reduce 524 + OPEN_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 524 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_PTR reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + + opt_type_argument_list goto 375 + + +state 523 + primary_expression_no_array_creation : member_access . (426) + anonymous_type_parameter : member_access . (525) + + CLOSE_BRACE reduce 525 + OPEN_PARENS reduce 426 + DOT reduce 426 + COMMA reduce 525 + OP_INC reduce 426 + OP_DEC reduce 426 + OP_PTR reduce 426 + OPEN_PARENS_CAST reduce 426 + OPEN_BRACKET_EXPR reduce 426 + + +state 524 + anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma . CLOSE_BRACE (516) + + CLOSE_BRACE shift 713 + . error + + +state 525 + anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt . (517) + + . reduce 517 + + +state 526 + anonymous_type_parameters_opt_comma : anonymous_type_parameters . COMMA (518) + anonymous_type_parameters_opt : anonymous_type_parameters . (520) + anonymous_type_parameters : anonymous_type_parameters . COMMA anonymous_type_parameter (522) + + COMMA shift 714 + CLOSE_BRACE reduce 520 + + +state 527 + anonymous_type_parameters : anonymous_type_parameter . (521) + + . reduce 521 + + +state 528 + rank_specifier : OPEN_BRACKET CLOSE_BRACKET . (533) + + . reduce 533 + + +state 529 + dim_separators : COMMA . (535) + + . reduce 535 + + +state 530 + rank_specifier : OPEN_BRACKET dim_separators . CLOSE_BRACKET (534) + dim_separators : dim_separators . COMMA (536) + + CLOSE_BRACKET shift 715 + COMMA shift 716 + . error + + +state 531 + array_initializer : OPEN_BRACE . CLOSE_BRACE (539) + array_initializer : OPEN_BRACE . variable_initializer_list opt_comma CLOSE_BRACE (540) + + error shift 717 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + CLOSE_BRACE shift 718 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 721 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + variable_initializer_list goto 722 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 532 + array_creation_expression : NEW rank_specifiers array_initializer . (511) + + . reduce 511 + + +state 533 + array_creation_expression : NEW new_expr_type error . (513) + + . reduce 513 + + +state 534 + object_or_collection_initializer : OPEN_BRACE . opt_member_initializer_list close_brace_or_complete_completion (463) + object_or_collection_initializer : OPEN_BRACE . member_initializer_list COMMA CLOSE_BRACE (464) + opt_member_initializer_list : . (465) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 723 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 724 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + GENERATE_COMPLETION shift 725 + CLOSE_BRACE reduce 465 + COMPLETE_COMPLETION reduce 465 + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + opt_member_initializer_list goto 726 + member_initializer_list goto 727 + member_initializer goto 728 + non_assignment_expression goto 729 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 535 + array_creation_expression : NEW new_expr_type OPEN_BRACKET . CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + rank_specifier : OPEN_BRACKET . CLOSE_BRACKET (533) + rank_specifier : OPEN_BRACKET . dim_separators CLOSE_BRACKET (534) + + CLOSE_BRACKET shift 730 + COMMA shift 529 + . error + + dim_separators goto 530 + + +state 536 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR . expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 731 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list goto 732 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 537 + array_creation_expression : NEW new_expr_type rank_specifiers . opt_array_initializer (510) + opt_array_initializer : . (537) + + OPEN_BRACE shift 531 + error reduce 537 + AS reduce 537 + IS reduce 537 + WHERE reduce 537 + FROM reduce 537 + JOIN reduce 537 + ON reduce 537 + EQUALS reduce 537 + SELECT reduce 537 + GROUP reduce 537 + BY reduce 537 + LET reduce 537 + ORDERBY reduce 537 + ASCENDING reduce 537 + DESCENDING reduce 537 + INTO reduce 537 + CLOSE_BRACE reduce 537 + CLOSE_BRACKET reduce 537 + OPEN_PARENS reduce 537 + CLOSE_PARENS reduce 537 + DOT reduce 537 + COMMA reduce 537 + COLON reduce 537 + SEMICOLON reduce 537 + PLUS reduce 537 + MINUS reduce 537 + ASSIGN reduce 537 + OP_LT reduce 537 + OP_GT reduce 537 + BITWISE_AND reduce 537 + BITWISE_OR reduce 537 + STAR reduce 537 + PERCENT reduce 537 + DIV reduce 537 + CARRET reduce 537 + INTERR reduce 537 + OP_INC reduce 537 + OP_DEC reduce 537 + OP_SHIFT_LEFT reduce 537 + OP_SHIFT_RIGHT reduce 537 + OP_LE reduce 537 + OP_GE reduce 537 + OP_EQ reduce 537 + OP_NE reduce 537 + OP_AND reduce 537 + OP_OR reduce 537 + OP_MULT_ASSIGN reduce 537 + OP_DIV_ASSIGN reduce 537 + OP_MOD_ASSIGN reduce 537 + OP_ADD_ASSIGN reduce 537 + OP_SUB_ASSIGN reduce 537 + OP_SHIFT_LEFT_ASSIGN reduce 537 + OP_SHIFT_RIGHT_ASSIGN reduce 537 + OP_AND_ASSIGN reduce 537 + OP_XOR_ASSIGN reduce 537 + OP_OR_ASSIGN reduce 537 + OP_PTR reduce 537 + OP_COALESCING reduce 537 + OPEN_PARENS_CAST reduce 537 + OPEN_BRACKET_EXPR reduce 537 + COMPLETE_COMPLETION reduce 537 + + array_initializer goto 733 + opt_array_initializer goto 734 + + +state 538 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any . opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer (507) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 735 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 539 + object_or_delegate_creation_expression : NEW new_expr_type object_or_collection_initializer . (508) + + . reduce 508 + + +state 540 + new_expr_type : $$62 simple_type . (515) + + . reduce 515 + + +state 541 + rank_specifiers : rank_specifier rank_specifiers . (532) + + . reduce 532 + + +state 542 + return_statement : RETURN opt_expression SEMICOLON . (814) + + . reduce 814 + + +state 543 + sizeof_expression : SIZEOF open_parens_any type . CLOSE_PARENS (556) + + CLOSE_PARENS shift 736 + . error + + +state 544 + switch_statement : SWITCH open_parens_any $$77 . expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 737 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 545 + throw_statement : THROW opt_expression SEMICOLON . (815) + + . reduce 815 + + +state 546 + try_statement : TRY block error . (823) + + . reduce 823 + + +state 547 + catch_clause : CATCH . opt_catch_args $$81 block (829) + opt_catch_args : . (830) + + OPEN_PARENS shift 284 + OPEN_PARENS_CAST shift 285 + OPEN_BRACE reduce 830 + + open_parens_any goto 738 + opt_catch_args goto 739 + catch_args goto 740 + + +state 548 + try_statement : TRY block FINALLY . block (821) + + OPEN_BRACE shift 143 + . error + + block goto 741 + + +state 549 + try_statement : TRY block catch_clauses . (820) + try_statement : TRY block catch_clauses . FINALLY block (822) + catch_clauses : catch_clauses . catch_clause (825) + + CATCH shift 547 + FINALLY shift 742 + $end reduce 820 + error reduce 820 + EOF reduce 820 + BASE reduce 820 + BOOL reduce 820 + BREAK reduce 820 + BYTE reduce 820 + CASE reduce 820 + CHAR reduce 820 + CHECKED reduce 820 + CONST reduce 820 + CONTINUE reduce 820 + DECIMAL reduce 820 + DEFAULT reduce 820 + DELEGATE reduce 820 + DO reduce 820 + DOUBLE reduce 820 + ELSE reduce 820 + FALSE reduce 820 + FIXED reduce 820 + FLOAT reduce 820 + FOR reduce 820 + FOREACH reduce 820 + GOTO reduce 820 + IF reduce 820 + INT reduce 820 + LOCK reduce 820 + LONG reduce 820 + NEW reduce 820 + NULL reduce 820 + OBJECT reduce 820 + RETURN reduce 820 + SBYTE reduce 820 + SHORT reduce 820 + SIZEOF reduce 820 + STRING reduce 820 + SWITCH reduce 820 + THIS reduce 820 + THROW reduce 820 + TRUE reduce 820 + TRY reduce 820 + TYPEOF reduce 820 + UINT reduce 820 + ULONG reduce 820 + UNCHECKED reduce 820 + UNSAFE reduce 820 + USHORT reduce 820 + USING reduce 820 + VOID reduce 820 + WHILE reduce 820 + FROM reduce 820 + FROM_FIRST reduce 820 + OPEN_BRACE reduce 820 + CLOSE_BRACE reduce 820 + OPEN_PARENS reduce 820 + SEMICOLON reduce 820 + TILDE reduce 820 + PLUS reduce 820 + MINUS reduce 820 + BANG reduce 820 + BITWISE_AND reduce 820 + STAR reduce 820 + OP_INC reduce 820 + OP_DEC reduce 820 + LITERAL reduce 820 + IDENTIFIER reduce 820 + OPEN_PARENS_LAMBDA reduce 820 + OPEN_PARENS_CAST reduce 820 + DEFAULT_COLON reduce 820 + COMPLETE_COMPLETION reduce 820 + + catch_clause goto 743 + + +state 550 + catch_clauses : catch_clause . (824) + + . reduce 824 + + +state 551 + typeof_expression : TYPEOF $$63 open_parens_any . typeof_type_expression CLOSE_PARENS (545) + + error shift 744 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 253 + IDENTIFIER shift 745 + . error + + namespace_or_type_name goto 746 + type_expression_or_array goto 258 + member_name goto 36 + qualified_alias_member goto 747 + type_name goto 38 + type_and_void goto 748 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + typeof_type_expression goto 749 + unbound_type_name goto 750 + + +state 552 + unchecked_expression : UNCHECKED open_parens_any expression . CLOSE_PARENS (558) + + CLOSE_PARENS shift 751 + . error + + +state 553 + unsafe_statement : UNSAFE $$82 block . (837) + + . reduce 837 + + +state 554 + using_statement : USING open_parens_any expression . CLOSE_PARENS $$85 embedded_statement (848) + + CLOSE_PARENS shift 752 + . error + + +state 555 + using_statement : USING open_parens_any local_variable_declaration . CLOSE_PARENS $$84 embedded_statement (846) + + CLOSE_PARENS shift 753 + . error + + +state 556 + while_statement : WHILE open_parens_any boolean_expression . CLOSE_PARENS embedded_statement (785) + + CLOSE_PARENS shift 754 + . error + + +state 557 + nested_from_clause : FROM IDENTIFIER IN . expression (855) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 755 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 558 + nested_from_clause : FROM type IDENTIFIER . IN expression (856) + + IN shift 756 + . error + + +state 559 + first_from_clause : FROM_FIRST IDENTIFIER IN . expression (853) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 757 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 560 + first_from_clause : FROM_FIRST type IDENTIFIER . IN expression (854) + + IN shift 758 + . error + + +state 561 + block : OPEN_BRACE $$74 opt_statement_list . block_end (691) + + CLOSE_BRACE shift 759 + COMPLETE_COMPLETION shift 760 + . error + + block_end goto 761 + + +state 562 + opt_statement_list : statement_list . (697) + statement_list : statement_list . statement (699) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 697 + COMPLETE_COMPLETION reduce 697 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement goto 762 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 563 + statement_list : statement . (698) + + . reduce 698 + + +state 564 + statement : declaration_statement . (700) + + . reduce 700 + + +state 565 + statement : valid_declaration_statement . (701) + + . reduce 701 + + +state 566 + statement : labeled_statement . (702) + + . reduce 702 + + +state 567 + parenthesized_expression : OPEN_PARENS expression CLOSE_PARENS . (450) + + . reduce 450 + + +state 568 + parenthesized_expression : OPEN_PARENS expression COMPLETE_COMPLETION . (451) + + . reduce 451 + + +state 569 + cast_expression : OPEN_PARENS builtin_types CLOSE_PARENS . prefixed_unary_expression (572) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 763 + cast_expression goto 188 + + +state 570 + yield_statement : IDENTIFIER BREAK SEMICOLON . (817) + + . reduce 817 + + +state 571 + yield_statement : IDENTIFIER RETURN opt_expression . SEMICOLON (816) + + SEMICOLON shift 764 + . error + + +state 572 + lambda_expression : IDENTIFIER ARROW $$67 . lambda_expression_body (637) + $$66 : . (633) + + OPEN_BRACE shift 143 + BASE reduce 633 + BOOL reduce 633 + BYTE reduce 633 + CHAR reduce 633 + CHECKED reduce 633 + DECIMAL reduce 633 + DEFAULT reduce 633 + DELEGATE reduce 633 + DOUBLE reduce 633 + FALSE reduce 633 + FLOAT reduce 633 + INT reduce 633 + LONG reduce 633 + NEW reduce 633 + NULL reduce 633 + OBJECT reduce 633 + SBYTE reduce 633 + SHORT reduce 633 + SIZEOF reduce 633 + STRING reduce 633 + THIS reduce 633 + TRUE reduce 633 + TYPEOF reduce 633 + UINT reduce 633 + ULONG reduce 633 + UNCHECKED reduce 633 + USHORT reduce 633 + FROM reduce 633 + FROM_FIRST reduce 633 + OPEN_PARENS reduce 633 + TILDE reduce 633 + PLUS reduce 633 + MINUS reduce 633 + BANG reduce 633 + BITWISE_AND reduce 633 + STAR reduce 633 + OP_INC reduce 633 + OP_DEC reduce 633 + LITERAL reduce 633 + IDENTIFIER reduce 633 + OPEN_PARENS_LAMBDA reduce 633 + OPEN_PARENS_CAST reduce 633 + + block goto 765 + lambda_expression_body goto 766 + $$66 goto 767 + + +state 573 + labeled_statement : IDENTIFIER COLON $$76 . statement (739) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement goto 768 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 574 + parameter_modifier : OUT . (209) + + . reduce 209 + + +state 575 + parameter_modifier : REF . (208) + + . reduce 208 + + +state 576 + parameter_modifier : THIS . (210) + + . reduce 210 + + +state 577 + parameter_type : VOID . (392) + type_expression : VOID . STAR (398) + + STAR shift 464 + error reduce 392 + IDENTIFIER reduce 392 + + +state 578 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_parameter : IDENTIFIER . (630) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 630 + DOT reduce 363 + COMMA reduce 630 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 579 + lambda_parameter : parameter_type . IDENTIFIER (629) + + IDENTIFIER shift 769 + . error + + +state 580 + lambda_parameter : parameter_modifier . parameter_type IDENTIFIER (628) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + parameter_type goto 770 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 581 + parameter_type : type_expression_or_array . (391) + + . reduce 391 + + +state 582 + lambda_parameter_list : lambda_parameter_list . COMMA lambda_parameter (627) + opt_lambda_parameter_list : lambda_parameter_list . (632) + + COMMA shift 771 + CLOSE_PARENS reduce 632 + + +state 583 + lambda_parameter_list : lambda_parameter . (626) + + . reduce 626 + + +state 584 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list . CLOSE_PARENS ARROW $$69 lambda_expression_body (640) + + CLOSE_PARENS shift 772 + . error + + +state 585 + cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS . prefixed_unary_expression (571) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 292 + OPEN_PARENS_CAST shift 157 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + unary_expression goto 186 + prefixed_unary_expression goto 773 + cast_expression goto 188 + + +state 586 + member_access : qualified_alias_member IDENTIFIER opt_type_argument_list . (455) + + . reduce 455 + + +state 587 + member_access : builtin_types DOT IDENTIFIER . opt_type_argument_list (453) + member_access : builtin_types DOT IDENTIFIER . GENERATE_COMPLETION (459) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERATE_COMPLETION shift 774 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 775 + + +state 588 + member_access : builtin_types DOT GENERATE_COMPLETION . (458) + + . reduce 458 + + +state 589 + opt_rank_specifier_or_nullable : opt_nullable rank_specifiers . (530) + + . reduce 530 + + +state 590 + member_access : primary_expression DOT IDENTIFIER . opt_type_argument_list (452) + member_access : primary_expression DOT IDENTIFIER . GENERATE_COMPLETION (457) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERATE_COMPLETION shift 776 + error reduce 363 + AS reduce 363 + IS reduce 363 + WHERE reduce 363 + FROM reduce 363 + JOIN reduce 363 + ON reduce 363 + EQUALS reduce 363 + SELECT reduce 363 + GROUP reduce 363 + BY reduce 363 + LET reduce 363 + ORDERBY reduce 363 + ASCENDING reduce 363 + DESCENDING reduce 363 + INTO reduce 363 + INTERR_NULLABLE reduce 363 + CLOSE_BRACE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_BRACKET reduce 363 + OPEN_PARENS reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + COLON reduce 363 + SEMICOLON reduce 363 + PLUS reduce 363 + MINUS reduce 363 + ASSIGN reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_MULT_ASSIGN reduce 363 + OP_DIV_ASSIGN reduce 363 + OP_MOD_ASSIGN reduce 363 + OP_ADD_ASSIGN reduce 363 + OP_SUB_ASSIGN reduce 363 + OP_SHIFT_LEFT_ASSIGN reduce 363 + OP_SHIFT_RIGHT_ASSIGN reduce 363 + OP_AND_ASSIGN reduce 363 + OP_XOR_ASSIGN reduce 363 + OP_OR_ASSIGN reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + IDENTIFIER reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 777 + + +state 591 + member_access : primary_expression DOT GENERATE_COMPLETION . (456) + + . reduce 456 + + +state 592 + pointer_member_access : primary_expression OP_PTR IDENTIFIER . (559) + + . reduce 559 + + +state 593 + element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments . CLOSE_BRACKET (494) + expression_list_arguments : expression_list_arguments . COMMA expression_list_argument (499) + + CLOSE_BRACKET shift 778 + COMMA shift 685 + . error + + +state 594 + non_simple_argument : OUT . variable_reference (489) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 779 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + variable_reference goto 780 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 595 + non_simple_argument : REF . variable_reference (488) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 779 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + variable_reference goto 781 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 596 + non_simple_argument : ARGLIST . OPEN_PARENS argument_list CLOSE_PARENS (490) + non_simple_argument : ARGLIST . OPEN_PARENS CLOSE_PARENS (491) + non_simple_argument : ARGLIST . (492) + + OPEN_PARENS shift 782 + CLOSE_PARENS reduce 492 + COMMA reduce 492 + COMPLETE_COMPLETION reduce 492 + + +state 597 + argument_list : COMMA . error (483) + + error shift 783 + . error + + +state 598 + argument : expression . (484) + + . reduce 484 + + +state 599 + argument_or_named_argument : named_argument . (487) + + . reduce 487 + + +state 600 + invocation_expression : primary_expression open_parens_any opt_argument_list . close_parens (460) + + CLOSE_PARENS shift 784 + COMPLETE_COMPLETION shift 785 + . error + + close_parens goto 786 + + +state 601 + opt_argument_list : argument_list . (478) + argument_list : argument_list . COMMA argument (480) + argument_list : argument_list . COMMA named_argument (481) + argument_list : argument_list . COMMA (482) + + COMMA shift 787 + CLOSE_PARENS reduce 478 + COMPLETE_COMPLETION reduce 478 + + +state 602 + argument_list : argument_or_named_argument . (479) + + . reduce 479 + + +state 603 + argument_or_named_argument : argument . (486) + + . reduce 486 + + +state 604 + argument : non_simple_argument . (485) + + . reduce 485 + + +state 605 + multiplicative_expression : prefixed_unary_expression . (580) + + . reduce 580 + + +state 606 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : parenthesized_expression MINUS multiplicative_expression . (587) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 587 + AS reduce 587 + IS reduce 587 + WHERE reduce 587 + FROM reduce 587 + JOIN reduce 587 + ON reduce 587 + EQUALS reduce 587 + SELECT reduce 587 + GROUP reduce 587 + BY reduce 587 + LET reduce 587 + ORDERBY reduce 587 + ASCENDING reduce 587 + DESCENDING reduce 587 + INTO reduce 587 + CLOSE_BRACE reduce 587 + CLOSE_BRACKET reduce 587 + CLOSE_PARENS reduce 587 + COMMA reduce 587 + COLON reduce 587 + SEMICOLON reduce 587 + PLUS reduce 587 + MINUS reduce 587 + OP_LT reduce 587 + OP_GT reduce 587 + BITWISE_AND reduce 587 + BITWISE_OR reduce 587 + CARRET reduce 587 + INTERR reduce 587 + OP_SHIFT_LEFT reduce 587 + OP_SHIFT_RIGHT reduce 587 + OP_LE reduce 587 + OP_GE reduce 587 + OP_EQ reduce 587 + OP_NE reduce 587 + OP_AND reduce 587 + OP_OR reduce 587 + OP_COALESCING reduce 587 + COMPLETE_COMPLETION reduce 587 + + +state 607 + assignment_expression : prefixed_unary_expression ASSIGN expression . (615) + + . reduce 615 + + +state 608 + assignment_expression : prefixed_unary_expression OP_MULT_ASSIGN expression . (616) + + . reduce 616 + + +state 609 + assignment_expression : prefixed_unary_expression OP_DIV_ASSIGN expression . (617) + + . reduce 617 + + +state 610 + assignment_expression : prefixed_unary_expression OP_MOD_ASSIGN expression . (618) + + . reduce 618 + + +state 611 + assignment_expression : prefixed_unary_expression OP_ADD_ASSIGN expression . (619) + + . reduce 619 + + +state 612 + assignment_expression : prefixed_unary_expression OP_SUB_ASSIGN expression . (620) + + . reduce 620 + + +state 613 + assignment_expression : prefixed_unary_expression OP_SHIFT_LEFT_ASSIGN expression . (621) + + . reduce 621 + + +state 614 + assignment_expression : prefixed_unary_expression OP_SHIFT_RIGHT_ASSIGN expression . (622) + + . reduce 622 + + +state 615 + assignment_expression : prefixed_unary_expression OP_AND_ASSIGN expression . (623) + + . reduce 623 + + +state 616 + assignment_expression : prefixed_unary_expression OP_XOR_ASSIGN expression . (625) + + . reduce 625 + + +state 617 + assignment_expression : prefixed_unary_expression OP_OR_ASSIGN expression . (624) + + . reduce 624 + + +state 618 + multiplicative_expression : multiplicative_expression STAR prefixed_unary_expression . (581) + + . reduce 581 + + +state 619 + multiplicative_expression : multiplicative_expression PERCENT prefixed_unary_expression . (583) + + . reduce 583 + + +state 620 + multiplicative_expression : multiplicative_expression DIV prefixed_unary_expression . (582) + + . reduce 582 + + +state 621 + additive_expression : additive_expression AS type . (588) + + . reduce 588 + + +state 622 + additive_expression : additive_expression IS type . (589) + + . reduce 589 + + +state 623 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : additive_expression PLUS multiplicative_expression . (585) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 585 + AS reduce 585 + IS reduce 585 + WHERE reduce 585 + FROM reduce 585 + JOIN reduce 585 + ON reduce 585 + EQUALS reduce 585 + SELECT reduce 585 + GROUP reduce 585 + BY reduce 585 + LET reduce 585 + ORDERBY reduce 585 + ASCENDING reduce 585 + DESCENDING reduce 585 + INTO reduce 585 + CLOSE_BRACE reduce 585 + CLOSE_BRACKET reduce 585 + CLOSE_PARENS reduce 585 + COMMA reduce 585 + COLON reduce 585 + SEMICOLON reduce 585 + PLUS reduce 585 + MINUS reduce 585 + OP_LT reduce 585 + OP_GT reduce 585 + BITWISE_AND reduce 585 + BITWISE_OR reduce 585 + CARRET reduce 585 + INTERR reduce 585 + OP_SHIFT_LEFT reduce 585 + OP_SHIFT_RIGHT reduce 585 + OP_LE reduce 585 + OP_GE reduce 585 + OP_EQ reduce 585 + OP_NE reduce 585 + OP_AND reduce 585 + OP_OR reduce 585 + OP_COALESCING reduce 585 + COMPLETE_COMPLETION reduce 585 + + +state 624 + multiplicative_expression : multiplicative_expression . STAR prefixed_unary_expression (581) + multiplicative_expression : multiplicative_expression . DIV prefixed_unary_expression (582) + multiplicative_expression : multiplicative_expression . PERCENT prefixed_unary_expression (583) + additive_expression : additive_expression MINUS multiplicative_expression . (586) + + STAR shift 404 + PERCENT shift 405 + DIV shift 406 + error reduce 586 + AS reduce 586 + IS reduce 586 + WHERE reduce 586 + FROM reduce 586 + JOIN reduce 586 + ON reduce 586 + EQUALS reduce 586 + SELECT reduce 586 + GROUP reduce 586 + BY reduce 586 + LET reduce 586 + ORDERBY reduce 586 + ASCENDING reduce 586 + DESCENDING reduce 586 + INTO reduce 586 + CLOSE_BRACE reduce 586 + CLOSE_BRACKET reduce 586 + CLOSE_PARENS reduce 586 + COMMA reduce 586 + COLON reduce 586 + SEMICOLON reduce 586 + PLUS reduce 586 + MINUS reduce 586 + OP_LT reduce 586 + OP_GT reduce 586 + BITWISE_AND reduce 586 + BITWISE_OR reduce 586 + CARRET reduce 586 + INTERR reduce 586 + OP_SHIFT_LEFT reduce 586 + OP_SHIFT_RIGHT reduce 586 + OP_LE reduce 586 + OP_GE reduce 586 + OP_EQ reduce 586 + OP_NE reduce 586 + OP_AND reduce 586 + OP_OR reduce 586 + OP_COALESCING reduce 586 + COMPLETE_COMPLETION reduce 586 + + +state 625 + additive_expression : additive_expression . PLUS multiplicative_expression (585) + additive_expression : additive_expression . MINUS multiplicative_expression (586) + additive_expression : additive_expression . AS type (588) + additive_expression : additive_expression . IS type (589) + shift_expression : shift_expression OP_SHIFT_LEFT additive_expression . (591) + + AS shift 407 + IS shift 408 + PLUS shift 409 + MINUS shift 410 + error reduce 591 + WHERE reduce 591 + FROM reduce 591 + JOIN reduce 591 + ON reduce 591 + EQUALS reduce 591 + SELECT reduce 591 + GROUP reduce 591 + BY reduce 591 + LET reduce 591 + ORDERBY reduce 591 + ASCENDING reduce 591 + DESCENDING reduce 591 + INTO reduce 591 + CLOSE_BRACE reduce 591 + CLOSE_BRACKET reduce 591 + CLOSE_PARENS reduce 591 + COMMA reduce 591 + COLON reduce 591 + SEMICOLON reduce 591 + OP_LT reduce 591 + OP_GT reduce 591 + BITWISE_AND reduce 591 + BITWISE_OR reduce 591 + CARRET reduce 591 + INTERR reduce 591 + OP_SHIFT_LEFT reduce 591 + OP_SHIFT_RIGHT reduce 591 + OP_LE reduce 591 + OP_GE reduce 591 + OP_EQ reduce 591 + OP_NE reduce 591 + OP_AND reduce 591 + OP_OR reduce 591 + OP_COALESCING reduce 591 + COMPLETE_COMPLETION reduce 591 + + +state 626 + additive_expression : additive_expression . PLUS multiplicative_expression (585) + additive_expression : additive_expression . MINUS multiplicative_expression (586) + additive_expression : additive_expression . AS type (588) + additive_expression : additive_expression . IS type (589) + shift_expression : shift_expression OP_SHIFT_RIGHT additive_expression . (592) + + AS shift 407 + IS shift 408 + PLUS shift 409 + MINUS shift 410 + error reduce 592 + WHERE reduce 592 + FROM reduce 592 + JOIN reduce 592 + ON reduce 592 + EQUALS reduce 592 + SELECT reduce 592 + GROUP reduce 592 + BY reduce 592 + LET reduce 592 + ORDERBY reduce 592 + ASCENDING reduce 592 + DESCENDING reduce 592 + INTO reduce 592 + CLOSE_BRACE reduce 592 + CLOSE_BRACKET reduce 592 + CLOSE_PARENS reduce 592 + COMMA reduce 592 + COLON reduce 592 + SEMICOLON reduce 592 + OP_LT reduce 592 + OP_GT reduce 592 + BITWISE_AND reduce 592 + BITWISE_OR reduce 592 + CARRET reduce 592 + INTERR reduce 592 + OP_SHIFT_LEFT reduce 592 + OP_SHIFT_RIGHT reduce 592 + OP_LE reduce 592 + OP_GE reduce 592 + OP_EQ reduce 592 + OP_NE reduce 592 + OP_AND reduce 592 + OP_OR reduce 592 + OP_COALESCING reduce 592 + COMPLETE_COMPLETION reduce 592 + + +state 627 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_LT shift_expression . (594) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 594 + WHERE reduce 594 + FROM reduce 594 + JOIN reduce 594 + ON reduce 594 + EQUALS reduce 594 + SELECT reduce 594 + GROUP reduce 594 + BY reduce 594 + LET reduce 594 + ORDERBY reduce 594 + ASCENDING reduce 594 + DESCENDING reduce 594 + INTO reduce 594 + CLOSE_BRACE reduce 594 + CLOSE_BRACKET reduce 594 + CLOSE_PARENS reduce 594 + COMMA reduce 594 + COLON reduce 594 + SEMICOLON reduce 594 + OP_LT reduce 594 + OP_GT reduce 594 + BITWISE_AND reduce 594 + BITWISE_OR reduce 594 + CARRET reduce 594 + INTERR reduce 594 + OP_LE reduce 594 + OP_GE reduce 594 + OP_EQ reduce 594 + OP_NE reduce 594 + OP_AND reduce 594 + OP_OR reduce 594 + OP_COALESCING reduce 594 + COMPLETE_COMPLETION reduce 594 + + +state 628 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_GT shift_expression . (595) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 595 + WHERE reduce 595 + FROM reduce 595 + JOIN reduce 595 + ON reduce 595 + EQUALS reduce 595 + SELECT reduce 595 + GROUP reduce 595 + BY reduce 595 + LET reduce 595 + ORDERBY reduce 595 + ASCENDING reduce 595 + DESCENDING reduce 595 + INTO reduce 595 + CLOSE_BRACE reduce 595 + CLOSE_BRACKET reduce 595 + CLOSE_PARENS reduce 595 + COMMA reduce 595 + COLON reduce 595 + SEMICOLON reduce 595 + OP_LT reduce 595 + OP_GT reduce 595 + BITWISE_AND reduce 595 + BITWISE_OR reduce 595 + CARRET reduce 595 + INTERR reduce 595 + OP_LE reduce 595 + OP_GE reduce 595 + OP_EQ reduce 595 + OP_NE reduce 595 + OP_AND reduce 595 + OP_OR reduce 595 + OP_COALESCING reduce 595 + COMPLETE_COMPLETION reduce 595 + + +state 629 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_LE shift_expression . (596) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 596 + WHERE reduce 596 + FROM reduce 596 + JOIN reduce 596 + ON reduce 596 + EQUALS reduce 596 + SELECT reduce 596 + GROUP reduce 596 + BY reduce 596 + LET reduce 596 + ORDERBY reduce 596 + ASCENDING reduce 596 + DESCENDING reduce 596 + INTO reduce 596 + CLOSE_BRACE reduce 596 + CLOSE_BRACKET reduce 596 + CLOSE_PARENS reduce 596 + COMMA reduce 596 + COLON reduce 596 + SEMICOLON reduce 596 + OP_LT reduce 596 + OP_GT reduce 596 + BITWISE_AND reduce 596 + BITWISE_OR reduce 596 + CARRET reduce 596 + INTERR reduce 596 + OP_LE reduce 596 + OP_GE reduce 596 + OP_EQ reduce 596 + OP_NE reduce 596 + OP_AND reduce 596 + OP_OR reduce 596 + OP_COALESCING reduce 596 + COMPLETE_COMPLETION reduce 596 + + +state 630 + shift_expression : shift_expression . OP_SHIFT_LEFT additive_expression (591) + shift_expression : shift_expression . OP_SHIFT_RIGHT additive_expression (592) + relational_expression : relational_expression OP_GE shift_expression . (597) + + OP_SHIFT_LEFT shift 411 + OP_SHIFT_RIGHT shift 412 + error reduce 597 + WHERE reduce 597 + FROM reduce 597 + JOIN reduce 597 + ON reduce 597 + EQUALS reduce 597 + SELECT reduce 597 + GROUP reduce 597 + BY reduce 597 + LET reduce 597 + ORDERBY reduce 597 + ASCENDING reduce 597 + DESCENDING reduce 597 + INTO reduce 597 + CLOSE_BRACE reduce 597 + CLOSE_BRACKET reduce 597 + CLOSE_PARENS reduce 597 + COMMA reduce 597 + COLON reduce 597 + SEMICOLON reduce 597 + OP_LT reduce 597 + OP_GT reduce 597 + BITWISE_AND reduce 597 + BITWISE_OR reduce 597 + CARRET reduce 597 + INTERR reduce 597 + OP_LE reduce 597 + OP_GE reduce 597 + OP_EQ reduce 597 + OP_NE reduce 597 + OP_AND reduce 597 + OP_OR reduce 597 + OP_COALESCING reduce 597 + COMPLETE_COMPLETION reduce 597 + + +state 631 + relational_expression : relational_expression . OP_LT shift_expression (594) + relational_expression : relational_expression . OP_GT shift_expression (595) + relational_expression : relational_expression . OP_LE shift_expression (596) + relational_expression : relational_expression . OP_GE shift_expression (597) + equality_expression : equality_expression OP_EQ relational_expression . (599) + + OP_LT shift 413 + OP_GT shift 414 + OP_LE shift 415 + OP_GE shift 416 + error reduce 599 + WHERE reduce 599 + FROM reduce 599 + JOIN reduce 599 + ON reduce 599 + EQUALS reduce 599 + SELECT reduce 599 + GROUP reduce 599 + BY reduce 599 + LET reduce 599 + ORDERBY reduce 599 + ASCENDING reduce 599 + DESCENDING reduce 599 + INTO reduce 599 + CLOSE_BRACE reduce 599 + CLOSE_BRACKET reduce 599 + CLOSE_PARENS reduce 599 + COMMA reduce 599 + COLON reduce 599 + SEMICOLON reduce 599 + BITWISE_AND reduce 599 + BITWISE_OR reduce 599 + CARRET reduce 599 + INTERR reduce 599 + OP_EQ reduce 599 + OP_NE reduce 599 + OP_AND reduce 599 + OP_OR reduce 599 + OP_COALESCING reduce 599 + COMPLETE_COMPLETION reduce 599 + + +state 632 + relational_expression : relational_expression . OP_LT shift_expression (594) + relational_expression : relational_expression . OP_GT shift_expression (595) + relational_expression : relational_expression . OP_LE shift_expression (596) + relational_expression : relational_expression . OP_GE shift_expression (597) + equality_expression : equality_expression OP_NE relational_expression . (600) + + OP_LT shift 413 + OP_GT shift 414 + OP_LE shift 415 + OP_GE shift 416 + error reduce 600 + WHERE reduce 600 + FROM reduce 600 + JOIN reduce 600 + ON reduce 600 + EQUALS reduce 600 + SELECT reduce 600 + GROUP reduce 600 + BY reduce 600 + LET reduce 600 + ORDERBY reduce 600 + ASCENDING reduce 600 + DESCENDING reduce 600 + INTO reduce 600 + CLOSE_BRACE reduce 600 + CLOSE_BRACKET reduce 600 + CLOSE_PARENS reduce 600 + COMMA reduce 600 + COLON reduce 600 + SEMICOLON reduce 600 + BITWISE_AND reduce 600 + BITWISE_OR reduce 600 + CARRET reduce 600 + INTERR reduce 600 + OP_EQ reduce 600 + OP_NE reduce 600 + OP_AND reduce 600 + OP_OR reduce 600 + OP_COALESCING reduce 600 + COMPLETE_COMPLETION reduce 600 + + +state 633 + equality_expression : equality_expression . OP_EQ relational_expression (599) + equality_expression : equality_expression . OP_NE relational_expression (600) + and_expression : and_expression BITWISE_AND equality_expression . (602) + + OP_EQ shift 417 + OP_NE shift 418 + error reduce 602 + WHERE reduce 602 + FROM reduce 602 + JOIN reduce 602 + ON reduce 602 + EQUALS reduce 602 + SELECT reduce 602 + GROUP reduce 602 + BY reduce 602 + LET reduce 602 + ORDERBY reduce 602 + ASCENDING reduce 602 + DESCENDING reduce 602 + INTO reduce 602 + CLOSE_BRACE reduce 602 + CLOSE_BRACKET reduce 602 + CLOSE_PARENS reduce 602 + COMMA reduce 602 + COLON reduce 602 + SEMICOLON reduce 602 + BITWISE_AND reduce 602 + BITWISE_OR reduce 602 + CARRET reduce 602 + INTERR reduce 602 + OP_AND reduce 602 + OP_OR reduce 602 + OP_COALESCING reduce 602 + COMPLETE_COMPLETION reduce 602 + + +state 634 + and_expression : and_expression . BITWISE_AND equality_expression (602) + exclusive_or_expression : exclusive_or_expression CARRET and_expression . (604) + + BITWISE_AND shift 419 + error reduce 604 + WHERE reduce 604 + FROM reduce 604 + JOIN reduce 604 + ON reduce 604 + EQUALS reduce 604 + SELECT reduce 604 + GROUP reduce 604 + BY reduce 604 + LET reduce 604 + ORDERBY reduce 604 + ASCENDING reduce 604 + DESCENDING reduce 604 + INTO reduce 604 + CLOSE_BRACE reduce 604 + CLOSE_BRACKET reduce 604 + CLOSE_PARENS reduce 604 + COMMA reduce 604 + COLON reduce 604 + SEMICOLON reduce 604 + BITWISE_OR reduce 604 + CARRET reduce 604 + INTERR reduce 604 + OP_AND reduce 604 + OP_OR reduce 604 + OP_COALESCING reduce 604 + COMPLETE_COMPLETION reduce 604 + + +state 635 + exclusive_or_expression : exclusive_or_expression . CARRET and_expression (604) + inclusive_or_expression : inclusive_or_expression BITWISE_OR exclusive_or_expression . (606) + + CARRET shift 420 + error reduce 606 + WHERE reduce 606 + FROM reduce 606 + JOIN reduce 606 + ON reduce 606 + EQUALS reduce 606 + SELECT reduce 606 + GROUP reduce 606 + BY reduce 606 + LET reduce 606 + ORDERBY reduce 606 + ASCENDING reduce 606 + DESCENDING reduce 606 + INTO reduce 606 + CLOSE_BRACE reduce 606 + CLOSE_BRACKET reduce 606 + CLOSE_PARENS reduce 606 + COMMA reduce 606 + COLON reduce 606 + SEMICOLON reduce 606 + BITWISE_OR reduce 606 + INTERR reduce 606 + OP_AND reduce 606 + OP_OR reduce 606 + OP_COALESCING reduce 606 + COMPLETE_COMPLETION reduce 606 + + +state 636 + inclusive_or_expression : inclusive_or_expression . BITWISE_OR exclusive_or_expression (606) + conditional_and_expression : conditional_and_expression OP_AND inclusive_or_expression . (608) + + BITWISE_OR shift 421 + error reduce 608 + WHERE reduce 608 + FROM reduce 608 + JOIN reduce 608 + ON reduce 608 + EQUALS reduce 608 + SELECT reduce 608 + GROUP reduce 608 + BY reduce 608 + LET reduce 608 + ORDERBY reduce 608 + ASCENDING reduce 608 + DESCENDING reduce 608 + INTO reduce 608 + CLOSE_BRACE reduce 608 + CLOSE_BRACKET reduce 608 + CLOSE_PARENS reduce 608 + COMMA reduce 608 + COLON reduce 608 + SEMICOLON reduce 608 + INTERR reduce 608 + OP_AND reduce 608 + OP_OR reduce 608 + OP_COALESCING reduce 608 + COMPLETE_COMPLETION reduce 608 + + +state 637 + conditional_and_expression : conditional_and_expression . OP_AND inclusive_or_expression (608) + conditional_or_expression : conditional_or_expression OP_OR conditional_and_expression . (610) + + OP_AND shift 422 + error reduce 610 + WHERE reduce 610 + FROM reduce 610 + JOIN reduce 610 + ON reduce 610 + EQUALS reduce 610 + SELECT reduce 610 + GROUP reduce 610 + BY reduce 610 + LET reduce 610 + ORDERBY reduce 610 + ASCENDING reduce 610 + DESCENDING reduce 610 + INTO reduce 610 + CLOSE_BRACE reduce 610 + CLOSE_BRACKET reduce 610 + CLOSE_PARENS reduce 610 + COMMA reduce 610 + COLON reduce 610 + SEMICOLON reduce 610 + INTERR reduce 610 + OP_OR reduce 610 + OP_COALESCING reduce 610 + COMPLETE_COMPLETION reduce 610 + + +state 638 + null_coalescing_expression : conditional_or_expression OP_COALESCING null_coalescing_expression . (612) + + . reduce 612 + + +state 639 + conditional_expression : null_coalescing_expression INTERR expression . COLON expression (614) + + COLON shift 788 + . error + + +state 640 + local_variable_declarator : IDENTIFIER ASSIGN . local_variable_initializer (164) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STACKALLOC shift 789 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 790 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 791 + array_initializer goto 792 + local_variable_initializer goto 793 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 641 + variable_bad_array : OPEN_BRACKET_EXPR . opt_expression CLOSE_BRACKET (172) + opt_expression : . (818) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACKET reduce 818 + + expression goto 338 + opt_expression goto 794 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 642 + local_variable_declarator : IDENTIFIER variable_bad_array . (166) + + . reduce 166 + + +state 643 + local_variable_declarators : local_variable_declarators COMMA . local_variable_declarator (163) + + IDENTIFIER shift 433 + . error + + local_variable_declarator goto 795 + + +state 644 + where_clause : WHERE $$92 . boolean_expression (880) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 796 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 645 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + from_clause : FROM IDENTIFIER . IN $$86 expression (858) + opt_type_argument_list : . (363) + + IN shift 797 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 646 + from_clause : FROM type . IDENTIFIER IN $$87 expression (860) + + IDENTIFIER shift 798 + . error + + +state 647 + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + join_clause : JOIN IDENTIFIER . IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + opt_type_argument_list : . (363) + + IN shift 799 + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + opt_type_argument_list goto 84 + + +state 648 + join_clause : JOIN type . IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + IDENTIFIER shift 800 + . error + + +state 649 + let_clause : LET IDENTIFIER . ASSIGN $$91 expression (878) + + ASSIGN shift 801 + . error + + +state 650 + orderby_clause : ORDERBY $$99 . orderings (892) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 802 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + orderings goto 803 + order_by goto 804 + + +state 651 + select_or_group_clause : SELECT . $$88 expression (864) + $$88 : . (863) + + . reduce 863 + + $$88 goto 805 + + +state 652 + select_or_group_clause : GROUP . $$89 expression $$90 BY expression (867) + $$89 : . (865) + + . reduce 865 + + $$89 goto 806 + + +state 653 + query_body : opt_query_body_clauses COMPLETE_COMPLETION . (862) + + . reduce 862 + + +654: shift/reduce conflict (shift 807, reduce 905) on INTO +state 654 + query_body : opt_query_body_clauses select_or_group_clause . opt_query_continuation (861) + opt_query_continuation : . (905) + + INTO shift 807 + error reduce 905 + WHERE reduce 905 + FROM reduce 905 + JOIN reduce 905 + ON reduce 905 + EQUALS reduce 905 + SELECT reduce 905 + GROUP reduce 905 + BY reduce 905 + LET reduce 905 + ORDERBY reduce 905 + ASCENDING reduce 905 + DESCENDING reduce 905 + CLOSE_BRACE reduce 905 + CLOSE_BRACKET reduce 905 + CLOSE_PARENS reduce 905 + COMMA reduce 905 + COLON reduce 905 + SEMICOLON reduce 905 + COMPLETE_COMPLETION reduce 905 + + opt_query_continuation goto 808 + + +state 655 + query_body_clauses : query_body_clauses query_body_clause . (871) + + . reduce 871 + + +state 656 + qualified_identifier : qualified_identifier DOT IDENTIFIER . (28) + + . reduce 28 + + +state 657 + namespace_body : OPEN_BRACE . $$3 namespace_body_body (36) + $$3 : . (35) + + . reduce 35 + + $$3 goto 809 + + +state 658 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 namespace_body . opt_semicolon (26) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 811 + + +state 659 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name . OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + OPEN_PARENS shift 812 + . error + + +state 660 + type_declaration_name : IDENTIFIER $$61 . opt_type_parameter_list (369) + opt_type_parameter_list : . (378) + + OP_GENERICS_LT_DECL shift 813 + WHERE reduce 378 + OPEN_BRACE reduce 378 + OPEN_PARENS reduce 378 + COMMA reduce 378 + COLON reduce 378 + SEMICOLON reduce 378 + ASSIGN reduce 378 + + opt_type_parameter_list goto 814 + + +state 661 + opt_enum_base : COLON . type (342) + opt_enum_base : COLON . error (343) + + error shift 815 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 816 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 662 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base . $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + $$54 : . (337) + + . reduce 337 + + $$54 goto 817 + + +state 663 + field_declaration : opt_attributes opt_modifiers FIXED simple_type error . SEMICOLON (143) + + SEMICOLON shift 818 + . error + + +state 664 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER . $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + $$15 : . (141) + + . reduce 141 + + $$15 goto 819 + + +state 665 + type_declaration_name : IDENTIFIER . $$61 opt_type_parameter_list (369) + explicit_interface : IDENTIFIER . opt_type_argument_list DOT (375) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + $$61 : . (368) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + OP_GENERICS_LT_DECL reduce 368 + OPEN_BRACE reduce 368 + OPEN_PARENS reduce 368 + DOT reduce 363 + COMMA reduce 368 + SEMICOLON reduce 368 + ASSIGN reduce 368 + + opt_type_argument_list goto 673 + $$61 goto 660 + + +state 666 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name . OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + + OPEN_PARENS shift 820 + . error + + +state 667 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 . type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 821 + + +state 668 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE error . (243) + + . reduce 243 + + +state 669 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 . type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 822 + + +state 670 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT error . (110) + + . reduce 110 + + +state 671 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 . type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + + IDENTIFIER shift 459 + . error + + type_declaration_name goto 823 + + +state 672 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 . opt_field_initializer opt_field_declarators SEMICOLON (140) + opt_field_initializer : . (144) + + ASSIGN shift 824 + COMMA reduce 144 + SEMICOLON reduce 144 + + opt_field_initializer goto 825 + + +state 673 + explicit_interface : IDENTIFIER opt_type_argument_list . DOT (375) + + DOT shift 826 + . error + + +state 674 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS . $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + $$20 : . (177) + + . reduce 177 + + $$20 goto 827 + + +state 675 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name . OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + + OPEN_PARENS shift 828 + . error + + +state 676 + explicit_interface : qualified_alias_member IDENTIFIER . opt_type_argument_list DOT (376) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOT reduce 363 + + opt_type_argument_list goto 829 + + +state 677 + method_declaration_name : explicit_interface IDENTIFIER . opt_type_parameter_list (372) + explicit_interface : explicit_interface IDENTIFIER . opt_type_argument_list DOT (377) + opt_type_argument_list : . (363) + opt_type_parameter_list : . (378) + + OP_GENERICS_LT shift 81 + OP_GENERICS_LT_DECL shift 813 + OPEN_BRACE reduce 378 + OPEN_PARENS reduce 378 + DOT reduce 363 + COMMA reduce 378 + SEMICOLON reduce 378 + ASSIGN reduce 378 + + opt_type_argument_list goto 830 + opt_type_parameter_list goto 831 + + +state 678 + type_arguments : type_arguments COMMA type . (367) + + . reduce 367 + + +state 679 + named_argument : IDENTIFIER COLON . opt_named_modifier expression (86) + opt_named_modifier : . (87) + + OUT shift 832 + REF shift 833 + BASE reduce 87 + BOOL reduce 87 + BYTE reduce 87 + CHAR reduce 87 + CHECKED reduce 87 + DECIMAL reduce 87 + DEFAULT reduce 87 + DELEGATE reduce 87 + DOUBLE reduce 87 + FALSE reduce 87 + FLOAT reduce 87 + INT reduce 87 + LONG reduce 87 + NEW reduce 87 + NULL reduce 87 + OBJECT reduce 87 + SBYTE reduce 87 + SHORT reduce 87 + SIZEOF reduce 87 + STRING reduce 87 + THIS reduce 87 + TRUE reduce 87 + TYPEOF reduce 87 + UINT reduce 87 + ULONG reduce 87 + UNCHECKED reduce 87 + USHORT reduce 87 + FROM reduce 87 + FROM_FIRST reduce 87 + OPEN_PARENS reduce 87 + TILDE reduce 87 + PLUS reduce 87 + MINUS reduce 87 + BANG reduce 87 + BITWISE_AND reduce 87 + STAR reduce 87 + OP_INC reduce 87 + OP_DEC reduce 87 + LITERAL reduce 87 + IDENTIFIER reduce 87 + OPEN_PARENS_LAMBDA reduce 87 + OPEN_PARENS_CAST reduce 87 + + opt_named_modifier goto 834 + + +state 680 + named_attribute_argument : IDENTIFIER ASSIGN . $$6 expression (85) + $$6 : . (84) + + . reduce 84 + + $$6 goto 835 + + +state 681 + opt_attribute_arguments : OPEN_PARENS attribute_arguments CLOSE_PARENS . (76) + + . reduce 76 + + +state 682 + attribute_arguments : attribute_arguments COMMA . positional_or_named_argument (80) + attribute_arguments : attribute_arguments COMMA . named_attribute_argument (81) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 484 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + positional_or_named_argument goto 836 + named_attribute_argument goto 837 + expression goto 488 + named_argument goto 489 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 683 + member_access : BASE DOT IDENTIFIER opt_type_argument_list . (454) + + . reduce 454 + + +state 684 + base_access : BASE OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET . (503) + + . reduce 503 + + +state 685 + expression_list_arguments : expression_list_arguments COMMA . expression_list_argument (499) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 493 + named_argument goto 494 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list_argument goto 838 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 686 + checked_expression : CHECKED open_parens_any expression CLOSE_PARENS . (557) + + . reduce 557 + + +state 687 + local_constant_declarator : IDENTIFIER error . (756) + + . reduce 756 + + +state 688 + local_constant_declarator : IDENTIFIER ASSIGN . constant_initializer_expr (755) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_initializer_expr goto 839 + constant_expression goto 840 + array_initializer goto 841 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 689 + local_constant_declarators : local_constant_declarators COMMA . local_constant_declarator (754) + + IDENTIFIER shift 498 + . error + + local_constant_declarator goto 842 + + +state 690 + default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS . (566) + + . reduce 566 + + +state 691 + arglist_modifier : ARGLIST . (217) + + . reduce 217 + + +state 692 + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type IDENTIFIER (199) + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type error (201) + fixed_parameter : opt_attributes . opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 constant_expression (203) + parameter_array : opt_attributes . params_modifier type IDENTIFIER (211) + parameter_array : opt_attributes . params_modifier type IDENTIFIER ASSIGN constant_expression (212) + parameter_array : opt_attributes . params_modifier type error (213) + opt_parameter_modifier : . (204) + + OUT shift 574 + PARAMS shift 843 + REF shift 575 + THIS shift 576 + BOOL reduce 204 + BYTE reduce 204 + CHAR reduce 204 + DECIMAL reduce 204 + DOUBLE reduce 204 + FLOAT reduce 204 + INT reduce 204 + LONG reduce 204 + OBJECT reduce 204 + SBYTE reduce 204 + SHORT reduce 204 + STRING reduce 204 + UINT reduce 204 + ULONG reduce 204 + USHORT reduce 204 + VOID reduce 204 + IDENTIFIER reduce 204 + + opt_parameter_modifier goto 844 + parameter_modifiers goto 845 + parameter_modifier goto 846 + params_modifier goto 847 + + +state 693 + opt_attributes : attribute_sections . (60) + attribute_sections : attribute_sections . attribute_section (62) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 60 + ADD reduce 60 + BOOL reduce 60 + BYTE reduce 60 + CHAR reduce 60 + CLASS reduce 60 + CONST reduce 60 + DECIMAL reduce 60 + DELEGATE reduce 60 + DOUBLE reduce 60 + ENUM reduce 60 + EVENT reduce 60 + EXPLICIT reduce 60 + EXTERN reduce 60 + FIXED reduce 60 + FLOAT reduce 60 + IMPLICIT reduce 60 + IN reduce 60 + INT reduce 60 + INTERFACE reduce 60 + INTERNAL reduce 60 + LONG reduce 60 + NAMESPACE reduce 60 + NEW reduce 60 + OBJECT reduce 60 + OUT reduce 60 + OVERRIDE reduce 60 + PARAMS reduce 60 + PRIVATE reduce 60 + PROTECTED reduce 60 + PUBLIC reduce 60 + READONLY reduce 60 + REF reduce 60 + REMOVE reduce 60 + SBYTE reduce 60 + SEALED reduce 60 + SHORT reduce 60 + STATIC reduce 60 + STRING reduce 60 + STRUCT reduce 60 + THIS reduce 60 + UINT reduce 60 + ULONG reduce 60 + UNSAFE reduce 60 + USHORT reduce 60 + VIRTUAL reduce 60 + VOID reduce 60 + VOLATILE reduce 60 + PARTIAL reduce 60 + GET reduce 60 + SET reduce 60 + TILDE reduce 60 + IDENTIFIER reduce 60 + + attribute_section goto 79 + + +state 694 + anonymous_method_signature : OPEN_PARENS $$65 opt_formal_parameter_list . CLOSE_PARENS (565) + + CLOSE_PARENS shift 848 + . error + + +state 695 + opt_formal_parameter_list : formal_parameter_list . (187) + + . reduce 187 + + +state 696 + formal_parameter_list : fixed_parameters . (188) + formal_parameter_list : fixed_parameters . COMMA parameter_array (189) + formal_parameter_list : fixed_parameters . COMMA arglist_modifier (190) + formal_parameter_list : fixed_parameters . COMMA parameter_array COMMA error (192) + formal_parameter_list : fixed_parameters . COMMA ARGLIST COMMA error (194) + fixed_parameters : fixed_parameters . COMMA fixed_parameter (198) + + COMMA shift 849 + CLOSE_BRACKET reduce 188 + CLOSE_PARENS reduce 188 + + +state 697 + formal_parameter_list : parameter_array . COMMA error (191) + formal_parameter_list : parameter_array . (195) + + COMMA shift 850 + CLOSE_BRACKET reduce 195 + CLOSE_PARENS reduce 195 + + +state 698 + formal_parameter_list : arglist_modifier . COMMA error (193) + formal_parameter_list : arglist_modifier . (196) + + COMMA shift 851 + CLOSE_BRACKET reduce 196 + CLOSE_PARENS reduce 196 + + +state 699 + fixed_parameters : fixed_parameter . (197) + + . reduce 197 + + +state 700 + anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$64 block . (561) + + . reduce 561 + + +state 701 + do_statement : DO embedded_statement WHILE open_parens_any . boolean_expression CLOSE_PARENS SEMICOLON (786) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 852 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 702 + fixed_pointer_declarator : IDENTIFIER . ASSIGN expression (842) + fixed_pointer_declarator : IDENTIFIER . (843) + + ASSIGN shift 853 + CLOSE_PARENS reduce 843 + COMMA reduce 843 + + +state 703 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators . CLOSE_PARENS $$83 embedded_statement (839) + fixed_pointer_declarators : fixed_pointer_declarators . COMMA fixed_pointer_declarator (841) + + CLOSE_PARENS shift 854 + COMMA shift 855 + . error + + +state 704 + fixed_pointer_declarators : fixed_pointer_declarator . (840) + + . reduce 840 + + +state 705 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON . $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + $$79 : . (787) + + . reduce 787 + + $$79 goto 856 + + +state 706 + statement_expression_list : statement_expression_list COMMA . statement_expression (799) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement_expression goto 857 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 707 + foreach_statement : FOREACH open_parens_any type IN . expression CLOSE_PARENS (800) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 858 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 708 + foreach_statement : FOREACH open_parens_any type IDENTIFIER . IN expression CLOSE_PARENS $$80 embedded_statement (802) + + IN shift 859 + . error + + +state 709 + goto_statement : GOTO CASE constant_expression SEMICOLON . (812) + + . reduce 812 + + +state 710 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS . embedded_statement (767) + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS . embedded_statement ELSE embedded_statement (768) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 860 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 711 + lock_statement : LOCK open_parens_any expression CLOSE_PARENS . embedded_statement (844) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 861 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 712 + anonymous_type_parameter : IDENTIFIER ASSIGN . variable_initializer (523) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 862 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 713 + anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE . (516) + + . reduce 516 + + +state 714 + anonymous_type_parameters_opt_comma : anonymous_type_parameters COMMA . (518) + anonymous_type_parameters : anonymous_type_parameters COMMA . anonymous_type_parameter (522) + + error shift 521 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + OPEN_PARENS shift 291 + LITERAL shift 154 + IDENTIFIER shift 522 + CLOSE_BRACE reduce 518 + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 294 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 296 + default_value_expression goto 168 + member_access goto 523 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + anonymous_type_parameter goto 863 + + +state 715 + rank_specifier : OPEN_BRACKET dim_separators CLOSE_BRACKET . (534) + + . reduce 534 + + +state 716 + dim_separators : dim_separators COMMA . (536) + + . reduce 536 + + +state 717 + variable_initializer_list : error . (543) + + . reduce 543 + + +state 718 + array_initializer : OPEN_BRACE CLOSE_BRACE . (539) + + . reduce 539 + + +state 719 + variable_initializer : expression . (173) + + . reduce 173 + + +state 720 + variable_initializer : array_initializer . (174) + + . reduce 174 + + +state 721 + variable_initializer_list : variable_initializer . (541) + + . reduce 541 + + +state 722 + array_initializer : OPEN_BRACE variable_initializer_list . opt_comma CLOSE_BRACE (540) + variable_initializer_list : variable_initializer_list . COMMA variable_initializer (542) + opt_comma : . (32) + + COMMA shift 864 + CLOSE_BRACE reduce 32 + + opt_comma goto 865 + + +state 723 + member_initializer : OPEN_BRACE . expression_list CLOSE_BRACE (473) + member_initializer : OPEN_BRACE . CLOSE_BRACE (474) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + CLOSE_BRACE shift 866 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 731 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + expression_list goto 867 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 724 + primary_expression_no_array_creation : IDENTIFIER . opt_type_argument_list (422) + primary_expression_no_array_creation : IDENTIFIER . GENERATE_COMPLETION (423) + member_initializer : IDENTIFIER . ASSIGN initializer_value (470) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + lambda_expression : IDENTIFIER . ARROW $$67 lambda_expression_body (637) + opt_type_argument_list : . (363) + + ARROW shift 372 + OP_GENERICS_LT shift 81 + ASSIGN shift 868 + DOUBLE_COLON shift 83 + GENERATE_COMPLETION shift 374 + error reduce 363 + AS reduce 363 + IS reduce 363 + CLOSE_BRACE reduce 363 + OPEN_PARENS reduce 363 + DOT reduce 363 + COMMA reduce 363 + PLUS reduce 363 + MINUS reduce 363 + OP_LT reduce 363 + OP_GT reduce 363 + BITWISE_AND reduce 363 + BITWISE_OR reduce 363 + STAR reduce 363 + PERCENT reduce 363 + DIV reduce 363 + CARRET reduce 363 + INTERR reduce 363 + OP_INC reduce 363 + OP_DEC reduce 363 + OP_SHIFT_LEFT reduce 363 + OP_SHIFT_RIGHT reduce 363 + OP_LE reduce 363 + OP_GE reduce 363 + OP_EQ reduce 363 + OP_NE reduce 363 + OP_AND reduce 363 + OP_OR reduce 363 + OP_PTR reduce 363 + OP_COALESCING reduce 363 + OPEN_PARENS_CAST reduce 363 + OPEN_BRACKET_EXPR reduce 363 + COMPLETE_COMPLETION reduce 363 + + opt_type_argument_list goto 375 + + +state 725 + member_initializer : GENERATE_COMPLETION . (471) + + . reduce 471 + + +state 726 + object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list . close_brace_or_complete_completion (463) + + CLOSE_BRACE shift 869 + COMPLETE_COMPLETION shift 870 + . error + + close_brace_or_complete_completion goto 871 + + +state 727 + object_or_collection_initializer : OPEN_BRACE member_initializer_list . COMMA CLOSE_BRACE (464) + opt_member_initializer_list : member_initializer_list . (466) + member_initializer_list : member_initializer_list . COMMA member_initializer (468) + member_initializer_list : member_initializer_list . error (469) + + error shift 872 + COMMA shift 873 + CLOSE_BRACE reduce 466 + COMPLETE_COMPLETION reduce 466 + + +state 728 + member_initializer_list : member_initializer . (467) + + . reduce 467 + + +729: shift/reduce conflict (shift 426, reduce 918) on COMPLETE_COMPLETION +state 729 + member_initializer : non_assignment_expression . opt_COMPLETE_COMPLETION (472) + opt_COMPLETE_COMPLETION : . (918) + + COMPLETE_COMPLETION shift 426 + error reduce 918 + CLOSE_BRACE reduce 918 + COMMA reduce 918 + + opt_COMPLETE_COMPLETION goto 874 + + +730: shift/reduce conflict (shift 875, reduce 533) on OPEN_BRACKET_EXPR +state 730 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET . OPEN_BRACKET_EXPR error CLOSE_BRACKET (512) + rank_specifier : OPEN_BRACKET CLOSE_BRACKET . (533) + + OPEN_BRACKET_EXPR shift 875 + error reduce 533 + AS reduce 533 + IS reduce 533 + WHERE reduce 533 + FROM reduce 533 + JOIN reduce 533 + ON reduce 533 + EQUALS reduce 533 + SELECT reduce 533 + GROUP reduce 533 + BY reduce 533 + LET reduce 533 + ORDERBY reduce 533 + ASCENDING reduce 533 + DESCENDING reduce 533 + INTO reduce 533 + OPEN_BRACE reduce 533 + CLOSE_BRACE reduce 533 + OPEN_BRACKET reduce 533 + CLOSE_BRACKET reduce 533 + OPEN_PARENS reduce 533 + CLOSE_PARENS reduce 533 + DOT reduce 533 + COMMA reduce 533 + COLON reduce 533 + SEMICOLON reduce 533 + PLUS reduce 533 + MINUS reduce 533 + ASSIGN reduce 533 + OP_LT reduce 533 + OP_GT reduce 533 + BITWISE_AND reduce 533 + BITWISE_OR reduce 533 + STAR reduce 533 + PERCENT reduce 533 + DIV reduce 533 + CARRET reduce 533 + INTERR reduce 533 + OP_INC reduce 533 + OP_DEC reduce 533 + OP_SHIFT_LEFT reduce 533 + OP_SHIFT_RIGHT reduce 533 + OP_LE reduce 533 + OP_GE reduce 533 + OP_EQ reduce 533 + OP_NE reduce 533 + OP_AND reduce 533 + OP_OR reduce 533 + OP_MULT_ASSIGN reduce 533 + OP_DIV_ASSIGN reduce 533 + OP_MOD_ASSIGN reduce 533 + OP_ADD_ASSIGN reduce 533 + OP_SUB_ASSIGN reduce 533 + OP_SHIFT_LEFT_ASSIGN reduce 533 + OP_SHIFT_RIGHT_ASSIGN reduce 533 + OP_AND_ASSIGN reduce 533 + OP_XOR_ASSIGN reduce 533 + OP_OR_ASSIGN reduce 533 + OP_PTR reduce 533 + OP_COALESCING reduce 533 + OPEN_PARENS_CAST reduce 533 + COMPLETE_COMPLETION reduce 533 + + +state 731 + expression_list : expression . (495) + + . reduce 495 + + +state 732 + expression_list : expression_list . COMMA expression (496) + expression_list : expression_list . error (497) + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list . CLOSE_BRACKET opt_rank_specifier opt_array_initializer (509) + + error shift 876 + CLOSE_BRACKET shift 877 + COMMA shift 878 + . error + + +state 733 + opt_array_initializer : array_initializer . (538) + + . reduce 538 + + +state 734 + array_creation_expression : NEW new_expr_type rank_specifiers opt_array_initializer . (510) + + . reduce 510 + + +state 735 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list . CLOSE_PARENS opt_object_or_collection_initializer (507) + + CLOSE_PARENS shift 879 + . error + + +state 736 + sizeof_expression : SIZEOF open_parens_any type CLOSE_PARENS . (556) + + . reduce 556 + + +state 737 + switch_statement : SWITCH open_parens_any $$77 expression . CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + CLOSE_PARENS shift 880 + . error + + +state 738 + catch_args : open_parens_any . type opt_identifier CLOSE_PARENS (832) + catch_args : open_parens_any . CLOSE_PARENS (833) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + CLOSE_PARENS shift 881 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 882 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 739 + catch_clause : CATCH opt_catch_args . $$81 block (829) + $$81 : . (828) + + . reduce 828 + + $$81 goto 883 + + +state 740 + opt_catch_args : catch_args . (831) + + . reduce 831 + + +state 741 + try_statement : TRY block FINALLY block . (821) + + . reduce 821 + + +state 742 + try_statement : TRY block catch_clauses FINALLY . block (822) + + OPEN_BRACE shift 143 + . error + + block goto 884 + + +state 743 + catch_clauses : catch_clauses catch_clause . (825) + + . reduce 825 + + +state 744 + typeof_type_expression : error . (548) + + . reduce 548 + + +state 745 + type_name : IDENTIFIER . opt_type_argument_list (362) + unbound_type_name : IDENTIFIER . generic_dimension (549) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + GENERIC_DIMENSION shift 885 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + STAR reduce 363 + + opt_type_argument_list goto 84 + generic_dimension goto 886 + + +state 746 + member_name : namespace_or_type_name . DOT IDENTIFIER opt_type_argument_list (361) + type_expression : namespace_or_type_name . opt_nullable (395) + unbound_type_name : namespace_or_type_name . DOT IDENTIFIER generic_dimension (553) + opt_nullable : . (356) + + INTERR_NULLABLE shift 379 + DOT shift 887 + OPEN_BRACKET reduce 356 + CLOSE_PARENS reduce 356 + STAR reduce 356 + + opt_nullable goto 466 + + +state 747 + namespace_or_type_name : qualified_alias_member . IDENTIFIER opt_type_argument_list (359) + unbound_type_name : qualified_alias_member . IDENTIFIER generic_dimension (550) + + IDENTIFIER shift 888 + . error + + +state 748 + typeof_type_expression : type_and_void . (546) + + . reduce 546 + + +state 749 + typeof_expression : TYPEOF $$63 open_parens_any typeof_type_expression . CLOSE_PARENS (545) + + CLOSE_PARENS shift 889 + . error + + +state 750 + typeof_type_expression : unbound_type_name . (547) + unbound_type_name : unbound_type_name . DOT IDENTIFIER (551) + unbound_type_name : unbound_type_name . DOT IDENTIFIER generic_dimension (552) + + DOT shift 890 + CLOSE_PARENS reduce 547 + + +state 751 + unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS . (558) + + . reduce 558 + + +state 752 + using_statement : USING open_parens_any expression CLOSE_PARENS . $$85 embedded_statement (848) + $$85 : . (847) + + . reduce 847 + + $$85 goto 891 + + +state 753 + using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS . $$84 embedded_statement (846) + $$84 : . (845) + + . reduce 845 + + $$84 goto 892 + + +state 754 + while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS . embedded_statement (785) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 893 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 755 + nested_from_clause : FROM IDENTIFIER IN expression . (855) + + . reduce 855 + + +state 756 + nested_from_clause : FROM type IDENTIFIER IN . expression (856) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 894 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 757 + first_from_clause : FROM_FIRST IDENTIFIER IN expression . (853) + + . reduce 853 + + +state 758 + first_from_clause : FROM_FIRST type IDENTIFIER IN . expression (854) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 895 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 759 + block_end : CLOSE_BRACE . (692) + + . reduce 692 + + +state 760 + block_end : COMPLETE_COMPLETION . (693) + + . reduce 693 + + +state 761 + block : OPEN_BRACE $$74 opt_statement_list block_end . (691) + + . reduce 691 + + +state 762 + statement_list : statement_list statement . (699) + + . reduce 699 + + +state 763 + cast_expression : OPEN_PARENS builtin_types CLOSE_PARENS prefixed_unary_expression . (572) + + . reduce 572 + + +state 764 + yield_statement : IDENTIFIER RETURN opt_expression SEMICOLON . (816) + + . reduce 816 + + +state 765 + lambda_expression_body : block . (635) + + . reduce 635 + + +state 766 + lambda_expression : IDENTIFIER ARROW $$67 lambda_expression_body . (637) + + . reduce 637 + + +state 767 + lambda_expression_body : $$66 . expression (634) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 896 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 768 + labeled_statement : IDENTIFIER COLON $$76 statement . (739) + + . reduce 739 + + +state 769 + lambda_parameter : parameter_type IDENTIFIER . (629) + + . reduce 629 + + +state 770 + lambda_parameter : parameter_modifier parameter_type . IDENTIFIER (628) + + IDENTIFIER shift 897 + . error + + +state 771 + lambda_parameter_list : lambda_parameter_list COMMA . lambda_parameter (627) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + OUT shift 574 + REF shift 575 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + THIS shift 576 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 578 + . error + + namespace_or_type_name goto 255 + parameter_type goto 579 + parameter_modifier goto 580 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + lambda_parameter goto 898 + + +state 772 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS . ARROW $$69 lambda_expression_body (640) + + ARROW shift 899 + . error + + +state 773 + cast_expression : OPEN_PARENS_CAST type CLOSE_PARENS prefixed_unary_expression . (571) + + . reduce 571 + + +state 774 + member_access : builtin_types DOT IDENTIFIER GENERATE_COMPLETION . (459) + + . reduce 459 + + +state 775 + member_access : builtin_types DOT IDENTIFIER opt_type_argument_list . (453) + + . reduce 453 + + +state 776 + member_access : primary_expression DOT IDENTIFIER GENERATE_COMPLETION . (457) + + . reduce 457 + + +state 777 + member_access : primary_expression DOT IDENTIFIER opt_type_argument_list . (452) + + . reduce 452 + + +state 778 + element_access : primary_expression OPEN_BRACKET_EXPR expression_list_arguments CLOSE_BRACKET . (494) + + . reduce 494 + + +state 779 + variable_reference : expression . (493) + + . reduce 493 + + +state 780 + non_simple_argument : OUT variable_reference . (489) + + . reduce 489 + + +state 781 + non_simple_argument : REF variable_reference . (488) + + . reduce 488 + + +state 782 + non_simple_argument : ARGLIST OPEN_PARENS . argument_list CLOSE_PARENS (490) + non_simple_argument : ARGLIST OPEN_PARENS . CLOSE_PARENS (491) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + CLOSE_PARENS shift 900 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 598 + named_argument goto 599 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 901 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 783 + argument_list : COMMA error . (483) + + . reduce 483 + + +state 784 + close_parens : CLOSE_PARENS . (448) + + . reduce 448 + + +state 785 + close_parens : COMPLETE_COMPLETION . (449) + + . reduce 449 + + +state 786 + invocation_expression : primary_expression open_parens_any opt_argument_list close_parens . (460) + + . reduce 460 + + +state 787 + argument_list : argument_list COMMA . argument (480) + argument_list : argument_list COMMA . named_argument (481) + argument_list : argument_list COMMA . (482) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 482 + COMMA reduce 482 + COMPLETE_COMPLETION reduce 482 + + expression goto 598 + named_argument goto 902 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument goto 903 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 788 + conditional_expression : null_coalescing_expression INTERR expression COLON . expression (614) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 904 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 789 + local_variable_initializer : STACKALLOC . simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET (169) + local_variable_initializer : STACKALLOC . simple_type (171) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 461 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + simple_type goto 905 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 463 + builtin_types goto 261 + integral_type goto 162 + + +state 790 + local_variable_initializer : ARGLIST . (170) + + . reduce 170 + + +state 791 + local_variable_initializer : expression . (167) + + . reduce 167 + + +state 792 + local_variable_initializer : array_initializer . (168) + + . reduce 168 + + +state 793 + local_variable_declarator : IDENTIFIER ASSIGN local_variable_initializer . (164) + + . reduce 164 + + +state 794 + variable_bad_array : OPEN_BRACKET_EXPR opt_expression . CLOSE_BRACKET (172) + + CLOSE_BRACKET shift 906 + . error + + +state 795 + local_variable_declarators : local_variable_declarators COMMA local_variable_declarator . (163) + + . reduce 163 + + +state 796 + where_clause : WHERE $$92 boolean_expression . (880) + + . reduce 880 + + +state 797 + from_clause : FROM IDENTIFIER IN . $$86 expression (858) + $$86 : . (857) + + . reduce 857 + + $$86 goto 907 + + +state 798 + from_clause : FROM type IDENTIFIER . IN $$87 expression (860) + + IN shift 908 + . error + + +state 799 + join_clause : JOIN IDENTIFIER IN . $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + $$93 : . (881) + + . reduce 881 + + $$93 goto 909 + + +state 800 + join_clause : JOIN type IDENTIFIER . IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + IN shift 910 + . error + + +state 801 + let_clause : LET IDENTIFIER ASSIGN . $$91 expression (878) + $$91 : . (877) + + . reduce 877 + + $$91 goto 911 + + +state 802 + order_by : expression . (899) + order_by : expression . ASCENDING (900) + order_by : expression . DESCENDING (901) + + ASCENDING shift 912 + DESCENDING shift 913 + WHERE reduce 899 + FROM reduce 899 + JOIN reduce 899 + SELECT reduce 899 + GROUP reduce 899 + LET reduce 899 + ORDERBY reduce 899 + COMMA reduce 899 + COMPLETE_COMPLETION reduce 899 + + +state 803 + orderby_clause : ORDERBY $$99 orderings . (892) + + . reduce 892 + + +state 804 + orderings : order_by . (893) + orderings : order_by . COMMA $$100 orderings_then_by (895) + + COMMA shift 914 + WHERE reduce 893 + FROM reduce 893 + JOIN reduce 893 + SELECT reduce 893 + GROUP reduce 893 + LET reduce 893 + ORDERBY reduce 893 + COMPLETE_COMPLETION reduce 893 + + +state 805 + select_or_group_clause : SELECT $$88 . expression (864) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 915 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 806 + select_or_group_clause : GROUP $$89 . expression $$90 BY expression (867) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 916 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 807 + opt_query_continuation : INTO . IDENTIFIER $$102 query_body (907) + + IDENTIFIER shift 917 + . error + + +state 808 + query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation . (861) + + . reduce 861 + + +state 809 + namespace_body : OPEN_BRACE $$3 . namespace_body_body (36) + opt_extern_alias_directives : . (43) + + error shift 918 + EXTERN_ALIAS shift 3 + EOF reduce 43 + ABSTRACT reduce 43 + BOOL reduce 43 + BYTE reduce 43 + CHAR reduce 43 + CLASS reduce 43 + DECIMAL reduce 43 + DELEGATE reduce 43 + DOUBLE reduce 43 + ENUM reduce 43 + EXTERN reduce 43 + FIXED reduce 43 + FLOAT reduce 43 + INT reduce 43 + INTERFACE reduce 43 + INTERNAL reduce 43 + LONG reduce 43 + NAMESPACE reduce 43 + NEW reduce 43 + OBJECT reduce 43 + OVERRIDE reduce 43 + PRIVATE reduce 43 + PROTECTED reduce 43 + PUBLIC reduce 43 + READONLY reduce 43 + SBYTE reduce 43 + SEALED reduce 43 + SHORT reduce 43 + STATIC reduce 43 + STRING reduce 43 + STRUCT reduce 43 + UINT reduce 43 + ULONG reduce 43 + UNSAFE reduce 43 + USHORT reduce 43 + USING reduce 43 + VIRTUAL reduce 43 + VOID reduce 43 + VOLATILE reduce 43 + PARTIAL reduce 43 + CLOSE_BRACE reduce 43 + OPEN_BRACKET reduce 43 + IDENTIFIER reduce 43 + + extern_alias_directive goto 919 + extern_alias_directives goto 920 + namespace_body_body goto 921 + opt_extern_alias_directives goto 922 + + +state 810 + opt_semicolon : SEMICOLON . (31) + + . reduce 31 + + +state 811 + namespace_declaration : opt_attributes NAMESPACE qualified_identifier $$2 namespace_body opt_semicolon . (26) + + . reduce 26 + + +state 812 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS . $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + $$58 : . (352) + + . reduce 352 + + $$58 goto 923 + + +state 813 + opt_type_parameter_list : OP_GENERICS_LT_DECL . type_parameters OP_GENERICS_GT (379) + opt_attributes : . (59) + + error shift 924 + OPEN_BRACKET shift 4 + IN reduce 59 + OUT reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 925 + attribute_sections goto 693 + attribute_section goto 30 + type_parameters goto 926 + type_parameter goto 927 + + +state 814 + type_declaration_name : IDENTIFIER $$61 opt_type_parameter_list . (369) + + . reduce 369 + + +state 815 + opt_enum_base : COLON error . (343) + + . reduce 343 + + +state 816 + opt_enum_base : COLON type . (342) + + . reduce 342 + + +state 817 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 . OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + + OPEN_BRACE shift 928 + . error + + +state 818 + field_declaration : opt_attributes opt_modifiers FIXED simple_type error SEMICOLON . (143) + + . reduce 143 + + +state 819 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 . fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + + OPEN_BRACKET shift 929 + . error + + fixed_field_size goto 930 + + +state 820 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS . $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + $$22 : . (180) + + . reduce 180 + + $$22 goto 931 + + +state 821 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name . $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + $$71 : . (649) + + . reduce 649 + + $$71 goto 932 + + +state 822 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name . $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + $$34 : . (239) + + . reduce 239 + + $$34 goto 933 + + +state 823 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name . $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + $$8 : . (106) + + . reduce 106 + + $$8 goto 934 + + +state 824 + opt_field_initializer : ASSIGN . $$16 variable_initializer (146) + $$16 : . (145) + + . reduce 145 + + $$16 goto 935 + + +state 825 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer . opt_field_declarators SEMICOLON (140) + opt_field_declarators : . (147) + + COMMA shift 936 + SEMICOLON reduce 147 + + opt_field_declarators goto 937 + field_declarators goto 938 + field_declarator goto 939 + + +state 826 + explicit_interface : IDENTIFIER opt_type_argument_list DOT . (375) + + . reduce 375 + + +state 827 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 . opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 940 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 828 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS . opt_formal_parameter_list CLOSE_PARENS (183) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 941 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 829 + explicit_interface : qualified_alias_member IDENTIFIER opt_type_argument_list . DOT (376) + + DOT shift 942 + . error + + +state 830 + explicit_interface : explicit_interface IDENTIFIER opt_type_argument_list . DOT (377) + + DOT shift 943 + . error + + +state 831 + method_declaration_name : explicit_interface IDENTIFIER opt_type_parameter_list . (372) + + . reduce 372 + + +state 832 + opt_named_modifier : OUT . (89) + + . reduce 89 + + +state 833 + opt_named_modifier : REF . (88) + + . reduce 88 + + +state 834 + named_argument : IDENTIFIER COLON opt_named_modifier . expression (86) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 944 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 835 + named_attribute_argument : IDENTIFIER ASSIGN $$6 . expression (85) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 945 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 836 + attribute_arguments : attribute_arguments COMMA positional_or_named_argument . (80) + + . reduce 80 + + +state 837 + attribute_arguments : attribute_arguments COMMA named_attribute_argument . (81) + + . reduce 81 + + +state 838 + expression_list_arguments : expression_list_arguments COMMA expression_list_argument . (499) + + . reduce 499 + + +state 839 + local_constant_declarator : IDENTIFIER ASSIGN constant_initializer_expr . (755) + + . reduce 755 + + +state 840 + constant_initializer_expr : constant_expression . (137) + + . reduce 137 + + +state 841 + constant_initializer_expr : array_initializer . (138) + + . reduce 138 + + +state 842 + local_constant_declarators : local_constant_declarators COMMA local_constant_declarator . (754) + + . reduce 754 + + +state 843 + params_modifier : PARAMS . (214) + params_modifier : PARAMS . parameter_modifier (215) + params_modifier : PARAMS . params_modifier (216) + + OUT shift 574 + PARAMS shift 843 + REF shift 575 + THIS shift 576 + BOOL reduce 214 + BYTE reduce 214 + CHAR reduce 214 + DECIMAL reduce 214 + DOUBLE reduce 214 + FLOAT reduce 214 + INT reduce 214 + LONG reduce 214 + OBJECT reduce 214 + SBYTE reduce 214 + SHORT reduce 214 + STRING reduce 214 + UINT reduce 214 + ULONG reduce 214 + USHORT reduce 214 + VOID reduce 214 + IDENTIFIER reduce 214 + + parameter_modifier goto 946 + params_modifier goto 947 + + +state 844 + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type IDENTIFIER (199) + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type error (201) + fixed_parameter : opt_attributes opt_parameter_modifier . parameter_type IDENTIFIER ASSIGN $$24 constant_expression (203) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 577 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + parameter_type goto 948 + type_expression_or_array goto 581 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 845 + opt_parameter_modifier : parameter_modifiers . (205) + parameter_modifiers : parameter_modifiers . parameter_modifier (207) + + OUT shift 574 + REF shift 575 + THIS shift 576 + BOOL reduce 205 + BYTE reduce 205 + CHAR reduce 205 + DECIMAL reduce 205 + DOUBLE reduce 205 + FLOAT reduce 205 + INT reduce 205 + LONG reduce 205 + OBJECT reduce 205 + SBYTE reduce 205 + SHORT reduce 205 + STRING reduce 205 + UINT reduce 205 + ULONG reduce 205 + USHORT reduce 205 + VOID reduce 205 + IDENTIFIER reduce 205 + + parameter_modifier goto 949 + + +state 846 + parameter_modifiers : parameter_modifier . (206) + + . reduce 206 + + +state 847 + parameter_array : opt_attributes params_modifier . type IDENTIFIER (211) + parameter_array : opt_attributes params_modifier . type IDENTIFIER ASSIGN constant_expression (212) + parameter_array : opt_attributes params_modifier . type error (213) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 950 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 848 + anonymous_method_signature : OPEN_PARENS $$65 opt_formal_parameter_list CLOSE_PARENS . (565) + + . reduce 565 + + +state 849 + formal_parameter_list : fixed_parameters COMMA . parameter_array (189) + formal_parameter_list : fixed_parameters COMMA . arglist_modifier (190) + formal_parameter_list : fixed_parameters COMMA . parameter_array COMMA error (192) + formal_parameter_list : fixed_parameters COMMA . ARGLIST COMMA error (194) + fixed_parameters : fixed_parameters COMMA . fixed_parameter (198) + opt_attributes : . (59) + + ARGLIST shift 951 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + parameter_array goto 952 + arglist_modifier goto 953 + fixed_parameter goto 954 + + +state 850 + formal_parameter_list : parameter_array COMMA . error (191) + + error shift 955 + . error + + +state 851 + formal_parameter_list : arglist_modifier COMMA . error (193) + + error shift 956 + . error + + +state 852 + do_statement : DO embedded_statement WHILE open_parens_any boolean_expression . CLOSE_PARENS SEMICOLON (786) + + CLOSE_PARENS shift 957 + . error + + +state 853 + fixed_pointer_declarator : IDENTIFIER ASSIGN . expression (842) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 958 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 854 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS . $$83 embedded_statement (839) + $$83 : . (838) + + . reduce 838 + + $$83 goto 959 + + +state 855 + fixed_pointer_declarators : fixed_pointer_declarators COMMA . fixed_pointer_declarator (841) + + IDENTIFIER shift 702 + . error + + fixed_pointer_declarator goto 960 + + +state 856 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 . opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + opt_for_condition : . (793) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + SEMICOLON reduce 793 + + expression goto 518 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + boolean_expression goto 961 + opt_for_condition goto 962 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 857 + statement_expression_list : statement_expression_list COMMA statement_expression . (799) + + . reduce 799 + + +state 858 + foreach_statement : FOREACH open_parens_any type IN expression . CLOSE_PARENS (800) + + CLOSE_PARENS shift 963 + . error + + +state 859 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN . expression CLOSE_PARENS $$80 embedded_statement (802) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 964 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +860: shift/reduce conflict (shift 965, reduce 767) on ELSE +state 860 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement . (767) + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement . ELSE embedded_statement (768) + + ELSE shift 965 + $end reduce 767 + error reduce 767 + EOF reduce 767 + BASE reduce 767 + BOOL reduce 767 + BREAK reduce 767 + BYTE reduce 767 + CASE reduce 767 + CHAR reduce 767 + CHECKED reduce 767 + CONST reduce 767 + CONTINUE reduce 767 + DECIMAL reduce 767 + DEFAULT reduce 767 + DELEGATE reduce 767 + DO reduce 767 + DOUBLE reduce 767 + FALSE reduce 767 + FIXED reduce 767 + FLOAT reduce 767 + FOR reduce 767 + FOREACH reduce 767 + GOTO reduce 767 + IF reduce 767 + INT reduce 767 + LOCK reduce 767 + LONG reduce 767 + NEW reduce 767 + NULL reduce 767 + OBJECT reduce 767 + RETURN reduce 767 + SBYTE reduce 767 + SHORT reduce 767 + SIZEOF reduce 767 + STRING reduce 767 + SWITCH reduce 767 + THIS reduce 767 + THROW reduce 767 + TRUE reduce 767 + TRY reduce 767 + TYPEOF reduce 767 + UINT reduce 767 + ULONG reduce 767 + UNCHECKED reduce 767 + UNSAFE reduce 767 + USHORT reduce 767 + USING reduce 767 + VOID reduce 767 + WHILE reduce 767 + FROM reduce 767 + FROM_FIRST reduce 767 + OPEN_BRACE reduce 767 + CLOSE_BRACE reduce 767 + OPEN_PARENS reduce 767 + SEMICOLON reduce 767 + TILDE reduce 767 + PLUS reduce 767 + MINUS reduce 767 + BANG reduce 767 + BITWISE_AND reduce 767 + STAR reduce 767 + OP_INC reduce 767 + OP_DEC reduce 767 + LITERAL reduce 767 + IDENTIFIER reduce 767 + OPEN_PARENS_LAMBDA reduce 767 + OPEN_PARENS_CAST reduce 767 + DEFAULT_COLON reduce 767 + COMPLETE_COMPLETION reduce 767 + + +state 861 + lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement . (844) + + . reduce 844 + + +state 862 + anonymous_type_parameter : IDENTIFIER ASSIGN variable_initializer . (523) + + . reduce 523 + + +state 863 + anonymous_type_parameters : anonymous_type_parameters COMMA anonymous_type_parameter . (522) + + . reduce 522 + + +state 864 + opt_comma : COMMA . (33) + variable_initializer_list : variable_initializer_list COMMA . variable_initializer (542) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 33 + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 966 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 865 + array_initializer : OPEN_BRACE variable_initializer_list opt_comma . CLOSE_BRACE (540) + + CLOSE_BRACE shift 967 + . error + + +state 866 + member_initializer : OPEN_BRACE CLOSE_BRACE . (474) + + . reduce 474 + + +state 867 + member_initializer : OPEN_BRACE expression_list . CLOSE_BRACE (473) + expression_list : expression_list . COMMA expression (496) + expression_list : expression_list . error (497) + + error shift 876 + CLOSE_BRACE shift 968 + COMMA shift 878 + . error + + +state 868 + member_initializer : IDENTIFIER ASSIGN . initializer_value (470) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 534 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 969 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + object_or_collection_initializer goto 970 + initializer_value goto 971 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 869 + close_brace_or_complete_completion : CLOSE_BRACE . (920) + + . reduce 920 + + +state 870 + close_brace_or_complete_completion : COMPLETE_COMPLETION . (921) + + . reduce 921 + + +state 871 + object_or_collection_initializer : OPEN_BRACE opt_member_initializer_list close_brace_or_complete_completion . (463) + + . reduce 463 + + +state 872 + member_initializer_list : member_initializer_list error . (469) + + . reduce 469 + + +state 873 + object_or_collection_initializer : OPEN_BRACE member_initializer_list COMMA . CLOSE_BRACE (464) + member_initializer_list : member_initializer_list COMMA . member_initializer (468) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 723 + CLOSE_BRACE shift 972 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 724 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + GENERATE_COMPLETION shift 725 + . error + + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + member_initializer goto 973 + non_assignment_expression goto 729 + unary_expression goto 186 + prefixed_unary_expression goto 605 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 874 + member_initializer : non_assignment_expression opt_COMPLETE_COMPLETION . (472) + + . reduce 472 + + +state 875 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR . error CLOSE_BRACKET (512) + + error shift 974 + . error + + +state 876 + expression_list : expression_list error . (497) + + . reduce 497 + + +state 877 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET . opt_rank_specifier opt_array_initializer (509) + opt_rank_specifier : . (527) + + OPEN_BRACKET shift 332 + error reduce 527 + AS reduce 527 + IS reduce 527 + WHERE reduce 527 + FROM reduce 527 + JOIN reduce 527 + ON reduce 527 + EQUALS reduce 527 + SELECT reduce 527 + GROUP reduce 527 + BY reduce 527 + LET reduce 527 + ORDERBY reduce 527 + ASCENDING reduce 527 + DESCENDING reduce 527 + INTO reduce 527 + OPEN_BRACE reduce 527 + CLOSE_BRACE reduce 527 + CLOSE_BRACKET reduce 527 + OPEN_PARENS reduce 527 + CLOSE_PARENS reduce 527 + DOT reduce 527 + COMMA reduce 527 + COLON reduce 527 + SEMICOLON reduce 527 + PLUS reduce 527 + MINUS reduce 527 + ASSIGN reduce 527 + OP_LT reduce 527 + OP_GT reduce 527 + BITWISE_AND reduce 527 + BITWISE_OR reduce 527 + STAR reduce 527 + PERCENT reduce 527 + DIV reduce 527 + CARRET reduce 527 + INTERR reduce 527 + OP_INC reduce 527 + OP_DEC reduce 527 + OP_SHIFT_LEFT reduce 527 + OP_SHIFT_RIGHT reduce 527 + OP_LE reduce 527 + OP_GE reduce 527 + OP_EQ reduce 527 + OP_NE reduce 527 + OP_AND reduce 527 + OP_OR reduce 527 + OP_MULT_ASSIGN reduce 527 + OP_DIV_ASSIGN reduce 527 + OP_MOD_ASSIGN reduce 527 + OP_ADD_ASSIGN reduce 527 + OP_SUB_ASSIGN reduce 527 + OP_SHIFT_LEFT_ASSIGN reduce 527 + OP_SHIFT_RIGHT_ASSIGN reduce 527 + OP_AND_ASSIGN reduce 527 + OP_XOR_ASSIGN reduce 527 + OP_OR_ASSIGN reduce 527 + OP_PTR reduce 527 + OP_COALESCING reduce 527 + OPEN_PARENS_CAST reduce 527 + OPEN_BRACKET_EXPR reduce 527 + COMPLETE_COMPLETION reduce 527 + + rank_specifiers goto 352 + opt_rank_specifier goto 975 + rank_specifier goto 336 + + +state 878 + expression_list : expression_list COMMA . expression (496) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 976 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 879 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS . opt_object_or_collection_initializer (507) + opt_object_or_collection_initializer : . (461) + + OPEN_BRACE shift 534 + error reduce 461 + AS reduce 461 + IS reduce 461 + WHERE reduce 461 + FROM reduce 461 + JOIN reduce 461 + ON reduce 461 + EQUALS reduce 461 + SELECT reduce 461 + GROUP reduce 461 + BY reduce 461 + LET reduce 461 + ORDERBY reduce 461 + ASCENDING reduce 461 + DESCENDING reduce 461 + INTO reduce 461 + INTERR_NULLABLE reduce 461 + CLOSE_BRACE reduce 461 + OPEN_BRACKET reduce 461 + CLOSE_BRACKET reduce 461 + OPEN_PARENS reduce 461 + CLOSE_PARENS reduce 461 + DOT reduce 461 + COMMA reduce 461 + COLON reduce 461 + SEMICOLON reduce 461 + PLUS reduce 461 + MINUS reduce 461 + ASSIGN reduce 461 + OP_LT reduce 461 + OP_GT reduce 461 + BITWISE_AND reduce 461 + BITWISE_OR reduce 461 + STAR reduce 461 + PERCENT reduce 461 + DIV reduce 461 + CARRET reduce 461 + INTERR reduce 461 + OP_INC reduce 461 + OP_DEC reduce 461 + OP_SHIFT_LEFT reduce 461 + OP_SHIFT_RIGHT reduce 461 + OP_LE reduce 461 + OP_GE reduce 461 + OP_EQ reduce 461 + OP_NE reduce 461 + OP_AND reduce 461 + OP_OR reduce 461 + OP_MULT_ASSIGN reduce 461 + OP_DIV_ASSIGN reduce 461 + OP_MOD_ASSIGN reduce 461 + OP_ADD_ASSIGN reduce 461 + OP_SUB_ASSIGN reduce 461 + OP_SHIFT_LEFT_ASSIGN reduce 461 + OP_SHIFT_RIGHT_ASSIGN reduce 461 + OP_AND_ASSIGN reduce 461 + OP_XOR_ASSIGN reduce 461 + OP_OR_ASSIGN reduce 461 + OP_PTR reduce 461 + OP_COALESCING reduce 461 + IDENTIFIER reduce 461 + OPEN_PARENS_CAST reduce 461 + OPEN_BRACKET_EXPR reduce 461 + COMPLETE_COMPLETION reduce 461 + + opt_object_or_collection_initializer goto 977 + object_or_collection_initializer goto 978 + + +state 880 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS . OPEN_BRACE opt_switch_sections CLOSE_BRACE (770) + + OPEN_BRACE shift 979 + . error + + +state 881 + catch_args : open_parens_any CLOSE_PARENS . (833) + + . reduce 833 + + +state 882 + catch_args : open_parens_any type . opt_identifier CLOSE_PARENS (832) + opt_identifier : . (826) + + IDENTIFIER shift 980 + CLOSE_PARENS reduce 826 + + opt_identifier goto 981 + + +state 883 + catch_clause : CATCH opt_catch_args $$81 . block (829) + + OPEN_BRACE shift 143 + . error + + block goto 982 + + +state 884 + try_statement : TRY block catch_clauses FINALLY block . (822) + + . reduce 822 + + +state 885 + generic_dimension : GENERIC_DIMENSION . (554) + + . reduce 554 + + +state 886 + unbound_type_name : IDENTIFIER generic_dimension . (549) + + . reduce 549 + + +state 887 + member_name : namespace_or_type_name DOT . IDENTIFIER opt_type_argument_list (361) + unbound_type_name : namespace_or_type_name DOT . IDENTIFIER generic_dimension (553) + + IDENTIFIER shift 983 + . error + + +state 888 + namespace_or_type_name : qualified_alias_member IDENTIFIER . opt_type_argument_list (359) + unbound_type_name : qualified_alias_member IDENTIFIER . generic_dimension (550) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERIC_DIMENSION shift 885 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + STAR reduce 363 + + opt_type_argument_list goto 273 + generic_dimension goto 984 + + +state 889 + typeof_expression : TYPEOF $$63 open_parens_any typeof_type_expression CLOSE_PARENS . (545) + + . reduce 545 + + +state 890 + unbound_type_name : unbound_type_name DOT . IDENTIFIER (551) + unbound_type_name : unbound_type_name DOT . IDENTIFIER generic_dimension (552) + + IDENTIFIER shift 985 + . error + + +state 891 + using_statement : USING open_parens_any expression CLOSE_PARENS $$85 . embedded_statement (848) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 986 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 892 + using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS $$84 . embedded_statement (846) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 987 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 893 + while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement . (785) + + . reduce 785 + + +state 894 + nested_from_clause : FROM type IDENTIFIER IN expression . (856) + + . reduce 856 + + +state 895 + first_from_clause : FROM_FIRST type IDENTIFIER IN expression . (854) + + . reduce 854 + + +state 896 + lambda_expression_body : $$66 expression . (634) + + . reduce 634 + + +state 897 + lambda_parameter : parameter_modifier parameter_type IDENTIFIER . (628) + + . reduce 628 + + +state 898 + lambda_parameter_list : lambda_parameter_list COMMA lambda_parameter . (627) + + . reduce 627 + + +state 899 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW . $$69 lambda_expression_body (640) + $$69 : . (639) + + . reduce 639 + + $$69 goto 988 + + +state 900 + non_simple_argument : ARGLIST OPEN_PARENS CLOSE_PARENS . (491) + + . reduce 491 + + +state 901 + argument_list : argument_list . COMMA argument (480) + argument_list : argument_list . COMMA named_argument (481) + argument_list : argument_list . COMMA (482) + non_simple_argument : ARGLIST OPEN_PARENS argument_list . CLOSE_PARENS (490) + + CLOSE_PARENS shift 989 + COMMA shift 787 + . error + + +state 902 + argument_list : argument_list COMMA named_argument . (481) + + . reduce 481 + + +state 903 + argument_list : argument_list COMMA argument . (480) + + . reduce 480 + + +state 904 + conditional_expression : null_coalescing_expression INTERR expression COLON expression . (614) + + . reduce 614 + + +state 905 + local_variable_initializer : STACKALLOC simple_type . OPEN_BRACKET_EXPR expression CLOSE_BRACKET (169) + local_variable_initializer : STACKALLOC simple_type . (171) + + OPEN_BRACKET_EXPR shift 990 + CLOSE_PARENS reduce 171 + COMMA reduce 171 + SEMICOLON reduce 171 + + +state 906 + variable_bad_array : OPEN_BRACKET_EXPR opt_expression CLOSE_BRACKET . (172) + + . reduce 172 + + +state 907 + from_clause : FROM IDENTIFIER IN $$86 . expression (858) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 991 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 908 + from_clause : FROM type IDENTIFIER IN . $$87 expression (860) + $$87 : . (859) + + . reduce 859 + + $$87 goto 992 + + +state 909 + join_clause : JOIN IDENTIFIER IN $$93 . expression ON $$94 expression EQUALS $$95 expression opt_join_into (884) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 993 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 910 + join_clause : JOIN type IDENTIFIER IN . $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + $$96 : . (885) + + . reduce 885 + + $$96 goto 994 + + +state 911 + let_clause : LET IDENTIFIER ASSIGN $$91 . expression (878) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 995 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 912 + order_by : expression ASCENDING . (900) + + . reduce 900 + + +state 913 + order_by : expression DESCENDING . (901) + + . reduce 901 + + +state 914 + orderings : order_by COMMA . $$100 orderings_then_by (895) + $$100 : . (894) + + . reduce 894 + + $$100 goto 996 + + +state 915 + select_or_group_clause : SELECT $$88 expression . (864) + + . reduce 864 + + +state 916 + select_or_group_clause : GROUP $$89 expression . $$90 BY expression (867) + $$90 : . (866) + + . reduce 866 + + $$90 goto 997 + + +state 917 + opt_query_continuation : INTO IDENTIFIER . $$102 query_body (907) + $$102 : . (906) + + . reduce 906 + + $$102 goto 998 + + +state 918 + namespace_body_body : error . $$4 CLOSE_BRACE (39) + $$4 : . (38) + + . reduce 38 + + $$4 goto 999 + + +state 919 + extern_alias_directives : extern_alias_directive . (14) + + . reduce 14 + + +state 920 + extern_alias_directives : extern_alias_directives . extern_alias_directive (15) + opt_extern_alias_directives : extern_alias_directives . (44) + + EXTERN_ALIAS shift 3 + EOF reduce 44 + ABSTRACT reduce 44 + BOOL reduce 44 + BYTE reduce 44 + CHAR reduce 44 + CLASS reduce 44 + DECIMAL reduce 44 + DELEGATE reduce 44 + DOUBLE reduce 44 + ENUM reduce 44 + EXTERN reduce 44 + FIXED reduce 44 + FLOAT reduce 44 + INT reduce 44 + INTERFACE reduce 44 + INTERNAL reduce 44 + LONG reduce 44 + NAMESPACE reduce 44 + NEW reduce 44 + OBJECT reduce 44 + OVERRIDE reduce 44 + PRIVATE reduce 44 + PROTECTED reduce 44 + PUBLIC reduce 44 + READONLY reduce 44 + SBYTE reduce 44 + SEALED reduce 44 + SHORT reduce 44 + STATIC reduce 44 + STRING reduce 44 + STRUCT reduce 44 + UINT reduce 44 + ULONG reduce 44 + UNSAFE reduce 44 + USHORT reduce 44 + USING reduce 44 + VIRTUAL reduce 44 + VOID reduce 44 + VOLATILE reduce 44 + PARTIAL reduce 44 + CLOSE_BRACE reduce 44 + OPEN_BRACKET reduce 44 + IDENTIFIER reduce 44 + + extern_alias_directive goto 1000 + + +state 921 + namespace_body : OPEN_BRACE $$3 namespace_body_body . (36) + + . reduce 36 + + +state 922 + namespace_body_body : opt_extern_alias_directives . opt_using_directives opt_namespace_member_declarations CLOSE_BRACE (37) + namespace_body_body : opt_extern_alias_directives . opt_using_directives opt_namespace_member_declarations EOF (40) + opt_using_directives : . (41) + + USING shift 2 + EOF reduce 41 + ABSTRACT reduce 41 + BOOL reduce 41 + BYTE reduce 41 + CHAR reduce 41 + CLASS reduce 41 + DECIMAL reduce 41 + DELEGATE reduce 41 + DOUBLE reduce 41 + ENUM reduce 41 + EXTERN reduce 41 + FIXED reduce 41 + FLOAT reduce 41 + INT reduce 41 + INTERFACE reduce 41 + INTERNAL reduce 41 + LONG reduce 41 + NAMESPACE reduce 41 + NEW reduce 41 + OBJECT reduce 41 + OVERRIDE reduce 41 + PRIVATE reduce 41 + PROTECTED reduce 41 + PUBLIC reduce 41 + READONLY reduce 41 + SBYTE reduce 41 + SEALED reduce 41 + SHORT reduce 41 + STATIC reduce 41 + STRING reduce 41 + STRUCT reduce 41 + UINT reduce 41 + ULONG reduce 41 + UNSAFE reduce 41 + USHORT reduce 41 + VIRTUAL reduce 41 + VOID reduce 41 + VOLATILE reduce 41 + PARTIAL reduce 41 + CLOSE_BRACE reduce 41 + OPEN_BRACKET reduce 41 + IDENTIFIER reduce 41 + + using_directive goto 54 + using_directives goto 1001 + using_alias_directive goto 17 + using_namespace_directive goto 18 + opt_using_directives goto 1002 + + +state 923 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 . opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1003 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 924 + type_parameter : error . (383) + + . reduce 383 + + +state 925 + type_parameter : opt_attributes . opt_type_parameter_variance IDENTIFIER (382) + opt_type_parameter_variance : . (686) + + IN shift 1004 + OUT shift 1005 + IDENTIFIER reduce 686 + + opt_type_parameter_variance goto 1006 + type_parameter_variance goto 1007 + + +state 926 + opt_type_parameter_list : OP_GENERICS_LT_DECL type_parameters . OP_GENERICS_GT (379) + type_parameters : type_parameters . COMMA type_parameter (381) + + OP_GENERICS_GT shift 1008 + COMMA shift 1009 + . error + + +state 927 + type_parameters : type_parameter . (380) + + . reduce 380 + + +state 928 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE . $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + $$55 : . (338) + + . reduce 338 + + $$55 goto 1010 + + +state 929 + fixed_field_size : OPEN_BRACKET . $$18 expression CLOSE_BRACKET (160) + fixed_field_size : OPEN_BRACKET . error (161) + $$18 : . (159) + + error shift 1011 + BASE reduce 159 + BOOL reduce 159 + BYTE reduce 159 + CHAR reduce 159 + CHECKED reduce 159 + DECIMAL reduce 159 + DEFAULT reduce 159 + DELEGATE reduce 159 + DOUBLE reduce 159 + FALSE reduce 159 + FLOAT reduce 159 + INT reduce 159 + LONG reduce 159 + NEW reduce 159 + NULL reduce 159 + OBJECT reduce 159 + SBYTE reduce 159 + SHORT reduce 159 + SIZEOF reduce 159 + STRING reduce 159 + THIS reduce 159 + TRUE reduce 159 + TYPEOF reduce 159 + UINT reduce 159 + ULONG reduce 159 + UNCHECKED reduce 159 + USHORT reduce 159 + FROM reduce 159 + FROM_FIRST reduce 159 + OPEN_PARENS reduce 159 + TILDE reduce 159 + PLUS reduce 159 + MINUS reduce 159 + BANG reduce 159 + BITWISE_AND reduce 159 + STAR reduce 159 + OP_INC reduce 159 + OP_DEC reduce 159 + LITERAL reduce 159 + IDENTIFIER reduce 159 + OPEN_PARENS_LAMBDA reduce 159 + OPEN_PARENS_CAST reduce 159 + + $$18 goto 1012 + + +state 930 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size . opt_fixed_field_declarators SEMICOLON (142) + opt_fixed_field_declarators : . (154) + + COMMA shift 1013 + SEMICOLON reduce 154 + + opt_fixed_field_declarators goto 1014 + fixed_field_declarators goto 1015 + fixed_field_declarator goto 1016 + + +state 931 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 . opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1017 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 932 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 . opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_class_base : . (673) + + COLON shift 1018 + WHERE reduce 673 + OPEN_BRACE reduce 673 + + opt_class_base goto 1019 + + +state 933 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 . opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + opt_class_base : . (673) + + COLON shift 1018 + WHERE reduce 673 + OPEN_BRACE reduce 673 + + opt_class_base goto 1020 + + +state 934 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 . opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + opt_class_base : . (673) + + COLON shift 1018 + WHERE reduce 673 + OPEN_BRACE reduce 673 + + opt_class_base goto 1021 + + +state 935 + opt_field_initializer : ASSIGN $$16 . variable_initializer (146) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 1022 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 936 + field_declarator : COMMA . IDENTIFIER (151) + field_declarator : COMMA . IDENTIFIER ASSIGN $$17 variable_initializer (153) + + IDENTIFIER shift 1023 + . error + + +state 937 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators . SEMICOLON (140) + + SEMICOLON shift 1024 + . error + + +state 938 + opt_field_declarators : field_declarators . (148) + field_declarators : field_declarators . field_declarator (150) + + COMMA shift 936 + SEMICOLON reduce 148 + + field_declarator goto 1025 + + +state 939 + field_declarators : field_declarator . (149) + + . reduce 149 + + +state 940 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list . CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + + CLOSE_PARENS shift 1026 + . error + + +state 941 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list . CLOSE_PARENS (183) + + CLOSE_PARENS shift 1027 + . error + + +state 942 + explicit_interface : qualified_alias_member IDENTIFIER opt_type_argument_list DOT . (376) + + . reduce 376 + + +state 943 + explicit_interface : explicit_interface IDENTIFIER opt_type_argument_list DOT . (377) + + . reduce 377 + + +state 944 + named_argument : IDENTIFIER COLON opt_named_modifier expression . (86) + + . reduce 86 + + +state 945 + named_attribute_argument : IDENTIFIER ASSIGN $$6 expression . (85) + + . reduce 85 + + +state 946 + params_modifier : PARAMS parameter_modifier . (215) + + . reduce 215 + + +state 947 + params_modifier : PARAMS params_modifier . (216) + + . reduce 216 + + +state 948 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . IDENTIFIER (199) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . IDENTIFIER OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . error (201) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type . IDENTIFIER ASSIGN $$24 constant_expression (203) + + error shift 1028 + IDENTIFIER shift 1029 + . error + + +state 949 + parameter_modifiers : parameter_modifiers parameter_modifier . (207) + + . reduce 207 + + +state 950 + parameter_array : opt_attributes params_modifier type . IDENTIFIER (211) + parameter_array : opt_attributes params_modifier type . IDENTIFIER ASSIGN constant_expression (212) + parameter_array : opt_attributes params_modifier type . error (213) + + error shift 1030 + IDENTIFIER shift 1031 + . error + + +state 951 + formal_parameter_list : fixed_parameters COMMA ARGLIST . COMMA error (194) + arglist_modifier : ARGLIST . (217) + + COMMA shift 1032 + CLOSE_BRACKET reduce 217 + CLOSE_PARENS reduce 217 + + +state 952 + formal_parameter_list : fixed_parameters COMMA parameter_array . (189) + formal_parameter_list : fixed_parameters COMMA parameter_array . COMMA error (192) + + COMMA shift 1033 + CLOSE_BRACKET reduce 189 + CLOSE_PARENS reduce 189 + + +state 953 + formal_parameter_list : fixed_parameters COMMA arglist_modifier . (190) + + . reduce 190 + + +state 954 + fixed_parameters : fixed_parameters COMMA fixed_parameter . (198) + + . reduce 198 + + +state 955 + formal_parameter_list : parameter_array COMMA error . (191) + + . reduce 191 + + +state 956 + formal_parameter_list : arglist_modifier COMMA error . (193) + + . reduce 193 + + +state 957 + do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS . SEMICOLON (786) + + SEMICOLON shift 1034 + . error + + +state 958 + fixed_pointer_declarator : IDENTIFIER ASSIGN expression . (842) + + . reduce 842 + + +state 959 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 . embedded_statement (839) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1035 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 960 + fixed_pointer_declarators : fixed_pointer_declarators COMMA fixed_pointer_declarator . (841) + + . reduce 841 + + +state 961 + opt_for_condition : boolean_expression . (794) + + . reduce 794 + + +state 962 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition . SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement (788) + + SEMICOLON shift 1036 + . error + + +state 963 + foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS . (800) + + . reduce 800 + + +state 964 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression . CLOSE_PARENS $$80 embedded_statement (802) + + CLOSE_PARENS shift 1037 + . error + + +state 965 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE . embedded_statement (768) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1038 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 966 + variable_initializer_list : variable_initializer_list COMMA variable_initializer . (542) + + . reduce 542 + + +state 967 + array_initializer : OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE . (540) + + . reduce 540 + + +state 968 + member_initializer : OPEN_BRACE expression_list CLOSE_BRACE . (473) + + . reduce 473 + + +state 969 + initializer_value : expression . (475) + + . reduce 475 + + +state 970 + initializer_value : object_or_collection_initializer . (476) + + . reduce 476 + + +state 971 + member_initializer : IDENTIFIER ASSIGN initializer_value . (470) + + . reduce 470 + + +state 972 + object_or_collection_initializer : OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE . (464) + + . reduce 464 + + +state 973 + member_initializer_list : member_initializer_list COMMA member_initializer . (468) + + . reduce 468 + + +state 974 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error . CLOSE_BRACKET (512) + + CLOSE_BRACKET shift 1039 + . error + + +state 975 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier . opt_array_initializer (509) + opt_array_initializer : . (537) + + OPEN_BRACE shift 531 + error reduce 537 + AS reduce 537 + IS reduce 537 + WHERE reduce 537 + FROM reduce 537 + JOIN reduce 537 + ON reduce 537 + EQUALS reduce 537 + SELECT reduce 537 + GROUP reduce 537 + BY reduce 537 + LET reduce 537 + ORDERBY reduce 537 + ASCENDING reduce 537 + DESCENDING reduce 537 + INTO reduce 537 + CLOSE_BRACE reduce 537 + CLOSE_BRACKET reduce 537 + OPEN_PARENS reduce 537 + CLOSE_PARENS reduce 537 + DOT reduce 537 + COMMA reduce 537 + COLON reduce 537 + SEMICOLON reduce 537 + PLUS reduce 537 + MINUS reduce 537 + ASSIGN reduce 537 + OP_LT reduce 537 + OP_GT reduce 537 + BITWISE_AND reduce 537 + BITWISE_OR reduce 537 + STAR reduce 537 + PERCENT reduce 537 + DIV reduce 537 + CARRET reduce 537 + INTERR reduce 537 + OP_INC reduce 537 + OP_DEC reduce 537 + OP_SHIFT_LEFT reduce 537 + OP_SHIFT_RIGHT reduce 537 + OP_LE reduce 537 + OP_GE reduce 537 + OP_EQ reduce 537 + OP_NE reduce 537 + OP_AND reduce 537 + OP_OR reduce 537 + OP_MULT_ASSIGN reduce 537 + OP_DIV_ASSIGN reduce 537 + OP_MOD_ASSIGN reduce 537 + OP_ADD_ASSIGN reduce 537 + OP_SUB_ASSIGN reduce 537 + OP_SHIFT_LEFT_ASSIGN reduce 537 + OP_SHIFT_RIGHT_ASSIGN reduce 537 + OP_AND_ASSIGN reduce 537 + OP_XOR_ASSIGN reduce 537 + OP_OR_ASSIGN reduce 537 + OP_PTR reduce 537 + OP_COALESCING reduce 537 + OPEN_PARENS_CAST reduce 537 + OPEN_BRACKET_EXPR reduce 537 + COMPLETE_COMPLETION reduce 537 + + array_initializer goto 733 + opt_array_initializer goto 1040 + + +state 976 + expression_list : expression_list COMMA expression . (496) + + . reduce 496 + + +state 977 + object_or_delegate_creation_expression : NEW new_expr_type open_parens_any opt_argument_list CLOSE_PARENS opt_object_or_collection_initializer . (507) + + . reduce 507 + + +state 978 + opt_object_or_collection_initializer : object_or_collection_initializer . (462) + + . reduce 462 + + +state 979 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE . opt_switch_sections CLOSE_BRACE (770) + opt_switch_sections : . (771) + + CASE shift 1041 + DEFAULT_COLON shift 1042 + CLOSE_BRACE reduce 771 + + opt_switch_sections goto 1043 + switch_sections goto 1044 + switch_section goto 1045 + switch_labels goto 1046 + switch_label goto 1047 + + +state 980 + opt_identifier : IDENTIFIER . (827) + + . reduce 827 + + +state 981 + catch_args : open_parens_any type opt_identifier . CLOSE_PARENS (832) + + CLOSE_PARENS shift 1048 + . error + + +state 982 + catch_clause : CATCH opt_catch_args $$81 block . (829) + + . reduce 829 + + +state 983 + member_name : namespace_or_type_name DOT IDENTIFIER . opt_type_argument_list (361) + unbound_type_name : namespace_or_type_name DOT IDENTIFIER . generic_dimension (553) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + GENERIC_DIMENSION shift 885 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + CLOSE_PARENS reduce 363 + DOT reduce 363 + STAR reduce 363 + + opt_type_argument_list goto 482 + generic_dimension goto 1049 + + +state 984 + unbound_type_name : qualified_alias_member IDENTIFIER generic_dimension . (550) + + . reduce 550 + + +state 985 + unbound_type_name : unbound_type_name DOT IDENTIFIER . (551) + unbound_type_name : unbound_type_name DOT IDENTIFIER . generic_dimension (552) + + GENERIC_DIMENSION shift 885 + CLOSE_PARENS reduce 551 + DOT reduce 551 + + generic_dimension goto 1050 + + +state 986 + using_statement : USING open_parens_any expression CLOSE_PARENS $$85 embedded_statement . (848) + + . reduce 848 + + +state 987 + using_statement : USING open_parens_any local_variable_declaration CLOSE_PARENS $$84 embedded_statement . (846) + + . reduce 846 + + +state 988 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 . lambda_expression_body (640) + $$66 : . (633) + + OPEN_BRACE shift 143 + BASE reduce 633 + BOOL reduce 633 + BYTE reduce 633 + CHAR reduce 633 + CHECKED reduce 633 + DECIMAL reduce 633 + DEFAULT reduce 633 + DELEGATE reduce 633 + DOUBLE reduce 633 + FALSE reduce 633 + FLOAT reduce 633 + INT reduce 633 + LONG reduce 633 + NEW reduce 633 + NULL reduce 633 + OBJECT reduce 633 + SBYTE reduce 633 + SHORT reduce 633 + SIZEOF reduce 633 + STRING reduce 633 + THIS reduce 633 + TRUE reduce 633 + TYPEOF reduce 633 + UINT reduce 633 + ULONG reduce 633 + UNCHECKED reduce 633 + USHORT reduce 633 + FROM reduce 633 + FROM_FIRST reduce 633 + OPEN_PARENS reduce 633 + TILDE reduce 633 + PLUS reduce 633 + MINUS reduce 633 + BANG reduce 633 + BITWISE_AND reduce 633 + STAR reduce 633 + OP_INC reduce 633 + OP_DEC reduce 633 + LITERAL reduce 633 + IDENTIFIER reduce 633 + OPEN_PARENS_LAMBDA reduce 633 + OPEN_PARENS_CAST reduce 633 + + block goto 765 + lambda_expression_body goto 1051 + $$66 goto 767 + + +state 989 + non_simple_argument : ARGLIST OPEN_PARENS argument_list CLOSE_PARENS . (490) + + . reduce 490 + + +state 990 + local_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR . expression CLOSE_BRACKET (169) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1052 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 991 + from_clause : FROM IDENTIFIER IN $$86 expression . (858) + + . reduce 858 + + +state 992 + from_clause : FROM type IDENTIFIER IN $$87 . expression (860) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1053 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 993 + join_clause : JOIN IDENTIFIER IN $$93 expression . ON $$94 expression EQUALS $$95 expression opt_join_into (884) + + ON shift 1054 + . error + + +state 994 + join_clause : JOIN type IDENTIFIER IN $$96 . expression ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1055 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 995 + let_clause : LET IDENTIFIER ASSIGN $$91 expression . (878) + + . reduce 878 + + +state 996 + orderings : order_by COMMA $$100 . orderings_then_by (895) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1056 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + orderings_then_by goto 1057 + then_by goto 1058 + + +state 997 + select_or_group_clause : GROUP $$89 expression $$90 . BY expression (867) + + BY shift 1059 + . error + + +state 998 + opt_query_continuation : INTO IDENTIFIER $$102 . query_body (907) + opt_query_body_clauses : . (868) + + WHERE shift 438 + FROM shift 439 + JOIN shift 440 + LET shift 441 + ORDERBY shift 442 + SELECT reduce 868 + GROUP reduce 868 + COMPLETE_COMPLETION reduce 868 + + query_body goto 1060 + from_clause goto 445 + opt_query_body_clauses goto 446 + query_body_clauses goto 447 + query_body_clause goto 448 + let_clause goto 449 + where_clause goto 450 + join_clause goto 451 + orderby_clause goto 452 + + +state 999 + namespace_body_body : error $$4 . CLOSE_BRACE (39) + + CLOSE_BRACE shift 1061 + . error + + +state 1000 + extern_alias_directives : extern_alias_directives extern_alias_directive . (15) + + . reduce 15 + + +state 1001 + using_directives : using_directives . using_directive (19) + opt_using_directives : using_directives . (42) + + USING shift 2 + EOF reduce 42 + ABSTRACT reduce 42 + BOOL reduce 42 + BYTE reduce 42 + CHAR reduce 42 + CLASS reduce 42 + DECIMAL reduce 42 + DELEGATE reduce 42 + DOUBLE reduce 42 + ENUM reduce 42 + EXTERN reduce 42 + FIXED reduce 42 + FLOAT reduce 42 + INT reduce 42 + INTERFACE reduce 42 + INTERNAL reduce 42 + LONG reduce 42 + NAMESPACE reduce 42 + NEW reduce 42 + OBJECT reduce 42 + OVERRIDE reduce 42 + PRIVATE reduce 42 + PROTECTED reduce 42 + PUBLIC reduce 42 + READONLY reduce 42 + SBYTE reduce 42 + SEALED reduce 42 + SHORT reduce 42 + STATIC reduce 42 + STRING reduce 42 + STRUCT reduce 42 + UINT reduce 42 + ULONG reduce 42 + UNSAFE reduce 42 + USHORT reduce 42 + VIRTUAL reduce 42 + VOID reduce 42 + VOLATILE reduce 42 + PARTIAL reduce 42 + CLOSE_BRACE reduce 42 + OPEN_BRACKET reduce 42 + IDENTIFIER reduce 42 + + using_directive goto 244 + using_alias_directive goto 17 + using_namespace_directive goto 18 + + +state 1002 + namespace_body_body : opt_extern_alias_directives opt_using_directives . opt_namespace_member_declarations CLOSE_BRACE (37) + namespace_body_body : opt_extern_alias_directives opt_using_directives . opt_namespace_member_declarations EOF (40) + opt_namespace_member_declarations : . (45) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + EOF reduce 45 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 45 + IDENTIFIER reduce 59 + + namespace_member_declaration goto 1062 + namespace_declaration goto 19 + opt_attributes goto 20 + opt_namespace_member_declarations goto 1063 + namespace_member_declarations goto 1064 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + method_header goto 31 + + +state 1003 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list . CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + + CLOSE_PARENS shift 1065 + . error + + +state 1004 + type_parameter_variance : IN . (689) + + . reduce 689 + + +state 1005 + type_parameter_variance : OUT . (688) + + . reduce 688 + + +state 1006 + type_parameter : opt_attributes opt_type_parameter_variance . IDENTIFIER (382) + + IDENTIFIER shift 1066 + . error + + +state 1007 + opt_type_parameter_variance : type_parameter_variance . (687) + + . reduce 687 + + +state 1008 + opt_type_parameter_list : OP_GENERICS_LT_DECL type_parameters OP_GENERICS_GT . (379) + + . reduce 379 + + +state 1009 + type_parameters : type_parameters COMMA . type_parameter (381) + opt_attributes : . (59) + + error shift 924 + OPEN_BRACKET shift 4 + IN reduce 59 + OUT reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 925 + attribute_sections goto 693 + attribute_section goto 30 + type_parameter goto 1067 + + +state 1010 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 . opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + opt_attributes : . (59) + opt_enum_member_declarations : . (344) + + OPEN_BRACKET shift 4 + CLOSE_BRACE reduce 344 + IDENTIFIER reduce 59 + + opt_attributes goto 1068 + attribute_sections goto 693 + attribute_section goto 30 + opt_enum_member_declarations goto 1069 + enum_member_declarations goto 1070 + enum_member_declaration goto 1071 + + +state 1011 + fixed_field_size : OPEN_BRACKET error . (161) + + . reduce 161 + + +state 1012 + fixed_field_size : OPEN_BRACKET $$18 . expression CLOSE_BRACKET (160) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1072 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1013 + fixed_field_declarator : COMMA . IDENTIFIER fixed_field_size (158) + + IDENTIFIER shift 1073 + . error + + +state 1014 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators . SEMICOLON (142) + + SEMICOLON shift 1074 + . error + + +state 1015 + opt_fixed_field_declarators : fixed_field_declarators . (155) + fixed_field_declarators : fixed_field_declarators . fixed_field_declarator (157) + + COMMA shift 1013 + SEMICOLON reduce 155 + + fixed_field_declarator goto 1075 + + +state 1016 + fixed_field_declarators : fixed_field_declarator . (156) + + . reduce 156 + + +state 1017 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list . CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + + CLOSE_PARENS shift 1076 + . error + + +state 1018 + opt_class_base : COLON . type_list (674) + + error shift 1077 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1078 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + type_list goto 1079 + base_type_name goto 1080 + integral_type goto 162 + + +state 1019 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base . opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + + opt_type_parameter_constraints_clauses goto 1082 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1020 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base . opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + + opt_type_parameter_constraints_clauses goto 1085 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1021 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base . opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + + opt_type_parameter_constraints_clauses goto 1086 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1022 + opt_field_initializer : ASSIGN $$16 variable_initializer . (146) + + . reduce 146 + + +state 1023 + field_declarator : COMMA IDENTIFIER . (151) + field_declarator : COMMA IDENTIFIER . ASSIGN $$17 variable_initializer (153) + + ASSIGN shift 1087 + COMMA reduce 151 + SEMICOLON reduce 151 + + +state 1024 + field_declaration : opt_attributes opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON . (140) + + . reduce 140 + + +state 1025 + field_declarators : field_declarators field_declarator . (150) + + . reduce 150 + + +state 1026 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS . $$21 opt_type_parameter_constraints_clauses (179) + $$21 : . (178) + + . reduce 178 + + $$21 goto 1088 + + +state 1027 + method_header : opt_attributes opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS . (183) + + . reduce 183 + + +state 1028 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type error . (201) + + . reduce 201 + + +state 1029 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER . (199) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER . OPEN_BRACKET CLOSE_BRACKET (200) + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER . ASSIGN $$24 constant_expression (203) + + OPEN_BRACKET shift 1089 + ASSIGN shift 1090 + CLOSE_BRACKET reduce 199 + CLOSE_PARENS reduce 199 + COMMA reduce 199 + + +state 1030 + parameter_array : opt_attributes params_modifier type error . (213) + + . reduce 213 + + +state 1031 + parameter_array : opt_attributes params_modifier type IDENTIFIER . (211) + parameter_array : opt_attributes params_modifier type IDENTIFIER . ASSIGN constant_expression (212) + + ASSIGN shift 1091 + CLOSE_BRACKET reduce 211 + CLOSE_PARENS reduce 211 + COMMA reduce 211 + + +state 1032 + formal_parameter_list : fixed_parameters COMMA ARGLIST COMMA . error (194) + + error shift 1092 + . error + + +state 1033 + formal_parameter_list : fixed_parameters COMMA parameter_array COMMA . error (192) + + error shift 1093 + . error + + +state 1034 + do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON . (786) + + . reduce 786 + + +state 1035 + fixed_statement : FIXED open_parens_any type_and_void fixed_pointer_declarators CLOSE_PARENS $$83 embedded_statement . (839) + + . reduce 839 + + +state 1036 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON . opt_for_iterator CLOSE_PARENS embedded_statement (788) + opt_for_iterator : . (795) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 795 + + expression goto 304 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement_expression goto 509 + opt_for_iterator goto 1094 + statement_expression_list goto 1095 + for_iterator goto 1096 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1037 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS . $$80 embedded_statement (802) + $$80 : . (801) + + . reduce 801 + + $$80 goto 1097 + + +state 1038 + if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement . (768) + + . reduce 768 + + +state 1039 + array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET . (512) + + . reduce 512 + + +state 1040 + array_creation_expression : NEW new_expr_type OPEN_BRACKET_EXPR expression_list CLOSE_BRACKET opt_rank_specifier opt_array_initializer . (509) + + . reduce 509 + + +state 1041 + switch_label : CASE . constant_expression COLON (779) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1098 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1042 + switch_label : DEFAULT_COLON . (780) + + . reduce 780 + + +state 1043 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections . CLOSE_BRACE (770) + + CLOSE_BRACE shift 1099 + . error + + +state 1044 + opt_switch_sections : switch_sections . (772) + switch_sections : switch_sections . switch_section (774) + + CASE shift 1041 + DEFAULT_COLON shift 1042 + CLOSE_BRACE reduce 772 + + switch_section goto 1100 + switch_labels goto 1046 + switch_label goto 1047 + + +state 1045 + switch_sections : switch_section . (773) + + . reduce 773 + + +state 1046 + switch_section : switch_labels . $$78 statement_list (776) + switch_labels : switch_labels . switch_label (778) + $$78 : . (775) + + CASE shift 1041 + DEFAULT_COLON shift 1042 + error reduce 775 + BASE reduce 775 + BOOL reduce 775 + BREAK reduce 775 + BYTE reduce 775 + CHAR reduce 775 + CHECKED reduce 775 + CONST reduce 775 + CONTINUE reduce 775 + DECIMAL reduce 775 + DEFAULT reduce 775 + DELEGATE reduce 775 + DO reduce 775 + DOUBLE reduce 775 + FALSE reduce 775 + FIXED reduce 775 + FLOAT reduce 775 + FOR reduce 775 + FOREACH reduce 775 + GOTO reduce 775 + IF reduce 775 + INT reduce 775 + LOCK reduce 775 + LONG reduce 775 + NEW reduce 775 + NULL reduce 775 + OBJECT reduce 775 + RETURN reduce 775 + SBYTE reduce 775 + SHORT reduce 775 + SIZEOF reduce 775 + STRING reduce 775 + SWITCH reduce 775 + THIS reduce 775 + THROW reduce 775 + TRUE reduce 775 + TRY reduce 775 + TYPEOF reduce 775 + UINT reduce 775 + ULONG reduce 775 + UNCHECKED reduce 775 + UNSAFE reduce 775 + USHORT reduce 775 + USING reduce 775 + VOID reduce 775 + WHILE reduce 775 + FROM reduce 775 + FROM_FIRST reduce 775 + OPEN_BRACE reduce 775 + OPEN_PARENS reduce 775 + SEMICOLON reduce 775 + TILDE reduce 775 + PLUS reduce 775 + MINUS reduce 775 + BANG reduce 775 + BITWISE_AND reduce 775 + STAR reduce 775 + OP_INC reduce 775 + OP_DEC reduce 775 + LITERAL reduce 775 + IDENTIFIER reduce 775 + OPEN_PARENS_LAMBDA reduce 775 + OPEN_PARENS_CAST reduce 775 + + $$78 goto 1101 + switch_label goto 1102 + + +state 1047 + switch_labels : switch_label . (777) + + . reduce 777 + + +state 1048 + catch_args : open_parens_any type opt_identifier CLOSE_PARENS . (832) + + . reduce 832 + + +state 1049 + unbound_type_name : namespace_or_type_name DOT IDENTIFIER generic_dimension . (553) + + . reduce 553 + + +state 1050 + unbound_type_name : unbound_type_name DOT IDENTIFIER generic_dimension . (552) + + . reduce 552 + + +state 1051 + lambda_expression : OPEN_PARENS_LAMBDA $$68 opt_lambda_parameter_list CLOSE_PARENS ARROW $$69 lambda_expression_body . (640) + + . reduce 640 + + +state 1052 + local_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR expression . CLOSE_BRACKET (169) + + CLOSE_BRACKET shift 1103 + . error + + +state 1053 + from_clause : FROM type IDENTIFIER IN $$87 expression . (860) + + . reduce 860 + + +state 1054 + join_clause : JOIN IDENTIFIER IN $$93 expression ON . $$94 expression EQUALS $$95 expression opt_join_into (884) + $$94 : . (882) + + . reduce 882 + + $$94 goto 1104 + + +state 1055 + join_clause : JOIN type IDENTIFIER IN $$96 expression . ON $$97 expression EQUALS $$98 expression opt_join_into (888) + + ON shift 1105 + . error + + +state 1056 + then_by : expression . (902) + then_by : expression . ASCENDING (903) + then_by : expression . DESCENDING (904) + + ASCENDING shift 1106 + DESCENDING shift 1107 + WHERE reduce 902 + FROM reduce 902 + JOIN reduce 902 + SELECT reduce 902 + GROUP reduce 902 + LET reduce 902 + ORDERBY reduce 902 + COMMA reduce 902 + COMPLETE_COMPLETION reduce 902 + + +state 1057 + orderings : order_by COMMA $$100 orderings_then_by . (895) + orderings_then_by : orderings_then_by . COMMA $$101 then_by (898) + + COMMA shift 1108 + WHERE reduce 895 + FROM reduce 895 + JOIN reduce 895 + SELECT reduce 895 + GROUP reduce 895 + LET reduce 895 + ORDERBY reduce 895 + COMPLETE_COMPLETION reduce 895 + + +state 1058 + orderings_then_by : then_by . (896) + + . reduce 896 + + +state 1059 + select_or_group_clause : GROUP $$89 expression $$90 BY . expression (867) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1109 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1060 + opt_query_continuation : INTO IDENTIFIER $$102 query_body . (907) + + . reduce 907 + + +state 1061 + namespace_body_body : error $$4 CLOSE_BRACE . (39) + + . reduce 39 + + +state 1062 + namespace_member_declarations : namespace_member_declaration . (47) + + . reduce 47 + + +state 1063 + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations . CLOSE_BRACE (37) + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations . EOF (40) + + EOF shift 1110 + CLOSE_BRACE shift 1111 + . error + + +state 1064 + opt_namespace_member_declarations : namespace_member_declarations . (46) + namespace_member_declarations : namespace_member_declarations . namespace_member_declaration (48) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + EOF reduce 46 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NAMESPACE reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 46 + IDENTIFIER reduce 59 + + namespace_member_declaration goto 1112 + namespace_declaration goto 19 + opt_attributes goto 20 + type_declaration goto 21 + field_declaration goto 22 + method_declaration goto 23 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + method_header goto 31 + + +state 1065 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS . $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + $$59 : . (353) + + . reduce 353 + + $$59 goto 1113 + + +state 1066 + type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER . (382) + + . reduce 382 + + +state 1067 + type_parameters : type_parameters COMMA type_parameter . (381) + + . reduce 381 + + +state 1068 + enum_member_declaration : opt_attributes . IDENTIFIER (349) + enum_member_declaration : opt_attributes . IDENTIFIER $$57 ASSIGN constant_expression (351) + + IDENTIFIER shift 1114 + . error + + +state 1069 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations . $$56 CLOSE_BRACE opt_semicolon (340) + $$56 : . (339) + + . reduce 339 + + $$56 goto 1115 + + +state 1070 + opt_enum_member_declarations : enum_member_declarations . (345) + opt_enum_member_declarations : enum_member_declarations . COMMA (346) + enum_member_declarations : enum_member_declarations . COMMA enum_member_declaration (348) + + COMMA shift 1116 + CLOSE_BRACE reduce 345 + + +state 1071 + enum_member_declarations : enum_member_declaration . (347) + + . reduce 347 + + +state 1072 + fixed_field_size : OPEN_BRACKET $$18 expression . CLOSE_BRACKET (160) + + CLOSE_BRACKET shift 1117 + . error + + +state 1073 + fixed_field_declarator : COMMA IDENTIFIER . fixed_field_size (158) + + OPEN_BRACKET shift 929 + . error + + fixed_field_size goto 1118 + + +state 1074 + field_declaration : opt_attributes opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON . (142) + + . reduce 142 + + +state 1075 + fixed_field_declarators : fixed_field_declarators fixed_field_declarator . (157) + + . reduce 157 + + +state 1076 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS . $$23 opt_type_parameter_constraints_clauses (182) + $$23 : . (181) + + . reduce 181 + + $$23 goto 1119 + + +state 1077 + base_type_name : error . (402) + + . reduce 402 + + +state 1078 + base_type_name : type . (401) + + . reduce 401 + + +state 1079 + type_list : type_list . COMMA base_type_name (400) + opt_class_base : COLON type_list . (674) + + COMMA shift 1120 + WHERE reduce 674 + OPEN_BRACE reduce 674 + + +state 1080 + type_list : base_type_name . (399) + + . reduce 399 + + +state 1081 + type_parameter_constraints_clause : WHERE . IDENTIFIER COLON type_parameter_constraints (679) + + IDENTIFIER shift 1121 + . error + + +state 1082 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses . $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + $$72 : . (650) + + . reduce 650 + + $$72 goto 1122 + + +state 1083 + opt_type_parameter_constraints_clauses : type_parameter_constraints_clauses . (676) + type_parameter_constraints_clauses : type_parameter_constraints_clauses . type_parameter_constraints_clause (678) + + WHERE shift 1081 + OPEN_BRACE reduce 676 + SEMICOLON reduce 676 + + type_parameter_constraints_clause goto 1123 + + +state 1084 + type_parameter_constraints_clauses : type_parameter_constraints_clause . (677) + + . reduce 677 + + +state 1085 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses . $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + $$35 : . (240) + + . reduce 240 + + $$35 goto 1124 + + +state 1086 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses . $$9 struct_body $$10 opt_semicolon (109) + $$9 : . (107) + + . reduce 107 + + $$9 goto 1125 + + +state 1087 + field_declarator : COMMA IDENTIFIER ASSIGN . $$17 variable_initializer (153) + $$17 : . (152) + + . reduce 152 + + $$17 goto 1126 + + +state 1088 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 . opt_type_parameter_constraints_clauses (179) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + SEMICOLON reduce 675 + + opt_type_parameter_constraints_clauses goto 1127 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1089 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET . CLOSE_BRACKET (200) + + CLOSE_BRACKET shift 1128 + . error + + +state 1090 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN . $$24 constant_expression (203) + $$24 : . (202) + + . reduce 202 + + $$24 goto 1129 + + +state 1091 + parameter_array : opt_attributes params_modifier type IDENTIFIER ASSIGN . constant_expression (212) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1130 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1092 + formal_parameter_list : fixed_parameters COMMA ARGLIST COMMA error . (194) + + . reduce 194 + + +state 1093 + formal_parameter_list : fixed_parameters COMMA parameter_array COMMA error . (192) + + . reduce 192 + + +state 1094 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator . CLOSE_PARENS embedded_statement (788) + + CLOSE_PARENS shift 1131 + . error + + +state 1095 + for_iterator : statement_expression_list . (797) + statement_expression_list : statement_expression_list . COMMA statement_expression (799) + + COMMA shift 706 + CLOSE_PARENS reduce 797 + + +state 1096 + opt_for_iterator : for_iterator . (796) + + . reduce 796 + + +state 1097 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 . embedded_statement (802) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1132 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1098 + switch_label : CASE constant_expression . COLON (779) + + COLON shift 1133 + . error + + +state 1099 + switch_statement : SWITCH open_parens_any $$77 expression CLOSE_PARENS OPEN_BRACE opt_switch_sections CLOSE_BRACE . (770) + + . reduce 770 + + +state 1100 + switch_sections : switch_sections switch_section . (774) + + . reduce 774 + + +state 1101 + switch_section : switch_labels $$78 . statement_list (776) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement_list goto 1134 + statement goto 563 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1102 + switch_labels : switch_labels switch_label . (778) + + . reduce 778 + + +state 1103 + local_variable_initializer : STACKALLOC simple_type OPEN_BRACKET_EXPR expression CLOSE_BRACKET . (169) + + . reduce 169 + + +state 1104 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 . expression EQUALS $$95 expression opt_join_into (884) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1135 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1105 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON . $$97 expression EQUALS $$98 expression opt_join_into (888) + $$97 : . (886) + + . reduce 886 + + $$97 goto 1136 + + +state 1106 + then_by : expression ASCENDING . (903) + + . reduce 903 + + +state 1107 + then_by : expression DESCENDING . (904) + + . reduce 904 + + +state 1108 + orderings_then_by : orderings_then_by COMMA . $$101 then_by (898) + $$101 : . (897) + + . reduce 897 + + $$101 goto 1137 + + +state 1109 + select_or_group_clause : GROUP $$89 expression $$90 BY expression . (867) + + . reduce 867 + + +state 1110 + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations EOF . (40) + + . reduce 40 + + +state 1111 + namespace_body_body : opt_extern_alias_directives opt_using_directives opt_namespace_member_declarations CLOSE_BRACE . (37) + + . reduce 37 + + +state 1112 + namespace_member_declarations : namespace_member_declarations namespace_member_declaration . (48) + + . reduce 48 + + +state 1113 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 . opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + SEMICOLON reduce 675 + + opt_type_parameter_constraints_clauses goto 1138 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1114 + enum_member_declaration : opt_attributes IDENTIFIER . (349) + enum_member_declaration : opt_attributes IDENTIFIER . $$57 ASSIGN constant_expression (351) + $$57 : . (350) + + CLOSE_BRACE reduce 349 + COMMA reduce 349 + ASSIGN reduce 350 + + $$57 goto 1139 + + +state 1115 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 . CLOSE_BRACE opt_semicolon (340) + + CLOSE_BRACE shift 1140 + . error + + +state 1116 + opt_enum_member_declarations : enum_member_declarations COMMA . (346) + enum_member_declarations : enum_member_declarations COMMA . enum_member_declaration (348) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + CLOSE_BRACE reduce 346 + IDENTIFIER reduce 59 + + opt_attributes goto 1068 + attribute_sections goto 693 + attribute_section goto 30 + enum_member_declaration goto 1141 + + +state 1117 + fixed_field_size : OPEN_BRACKET $$18 expression CLOSE_BRACKET . (160) + + . reduce 160 + + +state 1118 + fixed_field_declarator : COMMA IDENTIFIER fixed_field_size . (158) + + . reduce 158 + + +state 1119 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 . opt_type_parameter_constraints_clauses (182) + opt_type_parameter_constraints_clauses : . (675) + + WHERE shift 1081 + OPEN_BRACE reduce 675 + SEMICOLON reduce 675 + + opt_type_parameter_constraints_clauses goto 1142 + type_parameter_constraints_clauses goto 1083 + type_parameter_constraints_clause goto 1084 + + +state 1120 + type_list : type_list COMMA . base_type_name (400) + + error shift 1077 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1078 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + base_type_name goto 1143 + integral_type goto 162 + + +state 1121 + type_parameter_constraints_clause : WHERE IDENTIFIER . COLON type_parameter_constraints (679) + + COLON shift 1144 + . error + + +state 1122 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 . OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + + OPEN_BRACE shift 1145 + . error + + +state 1123 + type_parameter_constraints_clauses : type_parameter_constraints_clauses type_parameter_constraints_clause . (678) + + . reduce 678 + + +state 1124 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 . OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + + OPEN_BRACE shift 1146 + . error + + +state 1125 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 . struct_body $$10 opt_semicolon (109) + + OPEN_BRACE shift 1147 + . error + + struct_body goto 1148 + + +state 1126 + field_declarator : COMMA IDENTIFIER ASSIGN $$17 . variable_initializer (153) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 1149 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1127 + method_header : opt_attributes opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses . (179) + + . reduce 179 + + +state 1128 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER OPEN_BRACKET CLOSE_BRACKET . (200) + + . reduce 200 + + +state 1129 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 . constant_expression (203) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1150 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1130 + parameter_array : opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression . (212) + + . reduce 212 + + +state 1131 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS . embedded_statement (788) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + declaration_statement goto 306 + valid_declaration_statement goto 307 + labeled_statement goto 308 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + embedded_statement goto 1151 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1132 + foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$80 embedded_statement . (802) + + . reduce 802 + + +state 1133 + switch_label : CASE constant_expression COLON . (779) + + . reduce 779 + + +state 1134 + statement_list : statement_list . statement (699) + switch_section : switch_labels $$78 statement_list . (776) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CASE reduce 776 + CLOSE_BRACE reduce 776 + DEFAULT_COLON reduce 776 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + statement goto 762 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1135 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression . EQUALS $$95 expression opt_join_into (884) + + EQUALS shift 1152 + . error + + +state 1136 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 . expression EQUALS $$98 expression opt_join_into (888) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1153 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1137 + orderings_then_by : orderings_then_by COMMA $$101 . then_by (898) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1056 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + then_by goto 1154 + + +state 1138 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses . $$60 SEMICOLON (355) + $$60 : . (354) + + . reduce 354 + + $$60 goto 1155 + + +state 1139 + enum_member_declaration : opt_attributes IDENTIFIER $$57 . ASSIGN constant_expression (351) + + ASSIGN shift 1156 + . error + + +state 1140 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE . opt_semicolon (340) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1157 + + +state 1141 + enum_member_declarations : enum_member_declarations COMMA enum_member_declaration . (348) + + . reduce 348 + + +state 1142 + method_header : opt_attributes opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses . (182) + + . reduce 182 + + +state 1143 + type_list : type_list COMMA base_type_name . (400) + + . reduce 400 + + +state 1144 + type_parameter_constraints_clause : WHERE IDENTIFIER COLON . type_parameter_constraints (679) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CLASS shift 1158 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 1159 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + STRUCT shift 1160 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1161 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + type_parameter_constraints goto 1162 + type_parameter_constraint goto 1163 + + +state 1145 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE . opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_attributes : . (59) + opt_class_member_declarations : . (90) + + error shift 1164 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 90 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1166 + field_declaration goto 1167 + method_declaration goto 1168 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + opt_class_member_declarations goto 1169 + class_member_declarations goto 1170 + class_member_declaration goto 1171 + constant_declaration goto 1172 + property_declaration goto 1173 + event_declaration goto 1174 + indexer_declaration goto 1175 + operator_declaration goto 1176 + constructor_declaration goto 1177 + destructor_declaration goto 1178 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1146 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE . opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + opt_attributes : . (59) + opt_interface_member_declarations : . (244) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 244 + IDENTIFIER reduce 59 + + opt_attributes goto 1180 + type_declaration goto 1181 + field_declaration goto 1182 + method_declaration goto 1183 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1184 + property_declaration goto 1185 + event_declaration goto 1186 + indexer_declaration goto 1187 + operator_declaration goto 1188 + constructor_declaration goto 1189 + method_header goto 31 + opt_interface_member_declarations goto 1190 + interface_member_declarations goto 1191 + interface_member_declaration goto 1192 + constructor_declarator goto 1179 + + +state 1147 + struct_body : OPEN_BRACE . $$11 opt_struct_member_declarations CLOSE_BRACE (112) + $$11 : . (111) + + . reduce 111 + + $$11 goto 1193 + + +state 1148 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body . $$10 opt_semicolon (109) + $$10 : . (108) + + . reduce 108 + + $$10 goto 1194 + + +state 1149 + field_declarator : COMMA IDENTIFIER ASSIGN $$17 variable_initializer . (153) + + . reduce 153 + + +state 1150 + fixed_parameter : opt_attributes opt_parameter_modifier parameter_type IDENTIFIER ASSIGN $$24 constant_expression . (203) + + . reduce 203 + + +state 1151 + for_statement : FOR open_parens_any opt_for_initializer SEMICOLON $$79 opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement . (788) + + . reduce 788 + + +state 1152 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS . $$95 expression opt_join_into (884) + $$95 : . (883) + + . reduce 883 + + $$95 goto 1195 + + +state 1153 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression . EQUALS $$98 expression opt_join_into (888) + + EQUALS shift 1196 + . error + + +state 1154 + orderings_then_by : orderings_then_by COMMA $$101 then_by . (898) + + . reduce 898 + + +state 1155 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 . SEMICOLON (355) + + SEMICOLON shift 1197 + . error + + +state 1156 + enum_member_declaration : opt_attributes IDENTIFIER $$57 ASSIGN . constant_expression (351) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_expression goto 1198 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1157 + enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon . (340) + + . reduce 340 + + +state 1158 + type_parameter_constraint : CLASS . (684) + + . reduce 684 + + +state 1159 + type_parameter_constraint : NEW . OPEN_PARENS CLOSE_PARENS (683) + + OPEN_PARENS shift 1199 + . error + + +state 1160 + type_parameter_constraint : STRUCT . (685) + + . reduce 685 + + +state 1161 + type_parameter_constraint : type . (682) + + . reduce 682 + + +state 1162 + type_parameter_constraints_clause : WHERE IDENTIFIER COLON type_parameter_constraints . (679) + type_parameter_constraints : type_parameter_constraints . COMMA type_parameter_constraint (681) + + COMMA shift 1200 + WHERE reduce 679 + OPEN_BRACE reduce 679 + SEMICOLON reduce 679 + + +state 1163 + type_parameter_constraints : type_parameter_constraint . (680) + + . reduce 680 + + +state 1164 + class_member_declaration : error . (104) + + . reduce 104 + + +state 1165 + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT error (110) + constant_declaration : opt_attributes . opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes . opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes . opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes . opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes . opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes . opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes . opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE error (243) + operator_declaration : opt_attributes . opt_modifiers operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes . opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + destructor_declaration : opt_attributes . opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes . opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes . opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes . opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + BOOL reduce 655 + BYTE reduce 655 + CHAR reduce 655 + CLASS reduce 655 + CONST reduce 655 + DECIMAL reduce 655 + DELEGATE reduce 655 + DOUBLE reduce 655 + ENUM reduce 655 + EVENT reduce 655 + EXPLICIT reduce 655 + FIXED reduce 655 + FLOAT reduce 655 + IMPLICIT reduce 655 + INT reduce 655 + INTERFACE reduce 655 + LONG reduce 655 + OBJECT reduce 655 + SBYTE reduce 655 + SHORT reduce 655 + STRING reduce 655 + STRUCT reduce 655 + UINT reduce 655 + ULONG reduce 655 + USHORT reduce 655 + VOID reduce 655 + PARTIAL reduce 655 + TILDE reduce 655 + IDENTIFIER reduce 655 + + opt_modifiers goto 1201 + modifiers goto 77 + modifier goto 78 + + +state 1166 + class_member_declaration : type_declaration . (103) + + . reduce 103 + + +state 1167 + class_member_declaration : field_declaration . (95) + + . reduce 95 + + +state 1168 + class_member_declaration : method_declaration . (96) + + . reduce 96 + + +state 1169 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations . CLOSE_BRACE $$73 opt_semicolon (652) + + CLOSE_BRACE shift 1202 + . error + + +state 1170 + opt_class_member_declarations : class_member_declarations . (91) + class_member_declarations : class_member_declarations . class_member_declaration (93) + opt_attributes : . (59) + + error shift 1164 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 91 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1166 + field_declaration goto 1167 + method_declaration goto 1168 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + class_member_declaration goto 1203 + constant_declaration goto 1172 + property_declaration goto 1173 + event_declaration goto 1174 + indexer_declaration goto 1175 + operator_declaration goto 1176 + constructor_declaration goto 1177 + destructor_declaration goto 1178 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1171 + class_member_declarations : class_member_declaration . (92) + + . reduce 92 + + +state 1172 + class_member_declaration : constant_declaration . (94) + + . reduce 94 + + +state 1173 + class_member_declaration : property_declaration . (97) + + . reduce 97 + + +state 1174 + class_member_declaration : event_declaration . (98) + + . reduce 98 + + +state 1175 + class_member_declaration : indexer_declaration . (99) + + . reduce 99 + + +state 1176 + class_member_declaration : operator_declaration . (100) + + . reduce 100 + + +state 1177 + class_member_declaration : constructor_declaration . (101) + + . reduce 101 + + +state 1178 + class_member_declaration : destructor_declaration . (102) + + . reduce 102 + + +state 1179 + constructor_declaration : constructor_declarator . constructor_body (294) + + OPEN_BRACE shift 1204 + SEMICOLON shift 1205 + . error + + constructor_body goto 1206 + block_prepared goto 1207 + + +state 1180 + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes . opt_modifiers opt_partial STRUCT error (110) + constant_declaration : opt_attributes . opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes . opt_modifiers member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes . opt_modifiers FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes . opt_modifiers member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes . opt_modifiers PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes . opt_modifiers member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes . opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes . opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes . opt_modifiers opt_partial INTERFACE error (243) + operator_declaration : opt_attributes . opt_modifiers operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes . opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes . opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes . opt_modifiers ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes . opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes . opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + BOOL reduce 655 + BYTE reduce 655 + CHAR reduce 655 + CLASS reduce 655 + CONST reduce 655 + DECIMAL reduce 655 + DELEGATE reduce 655 + DOUBLE reduce 655 + ENUM reduce 655 + EVENT reduce 655 + EXPLICIT reduce 655 + FIXED reduce 655 + FLOAT reduce 655 + IMPLICIT reduce 655 + INT reduce 655 + INTERFACE reduce 655 + LONG reduce 655 + OBJECT reduce 655 + SBYTE reduce 655 + SHORT reduce 655 + STRING reduce 655 + STRUCT reduce 655 + UINT reduce 655 + ULONG reduce 655 + USHORT reduce 655 + VOID reduce 655 + PARTIAL reduce 655 + IDENTIFIER reduce 655 + + opt_modifiers goto 1208 + modifiers goto 77 + modifier goto 78 + + +state 1181 + interface_member_declaration : type_declaration . (256) + + . reduce 256 + + +state 1182 + interface_member_declaration : field_declaration . (249) + + . reduce 249 + + +state 1183 + interface_member_declaration : method_declaration . (250) + + . reduce 250 + + +state 1184 + interface_member_declaration : constant_declaration . (248) + + . reduce 248 + + +state 1185 + interface_member_declaration : property_declaration . (251) + + . reduce 251 + + +state 1186 + interface_member_declaration : event_declaration . (252) + + . reduce 252 + + +state 1187 + interface_member_declaration : indexer_declaration . (253) + + . reduce 253 + + +state 1188 + interface_member_declaration : operator_declaration . (254) + + . reduce 254 + + +state 1189 + interface_member_declaration : constructor_declaration . (255) + + . reduce 255 + + +state 1190 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations . CLOSE_BRACE $$36 opt_semicolon (242) + + CLOSE_BRACE shift 1209 + . error + + +state 1191 + opt_interface_member_declarations : interface_member_declarations . (245) + interface_member_declarations : interface_member_declarations . interface_member_declaration (247) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 245 + IDENTIFIER reduce 59 + + opt_attributes goto 1180 + type_declaration goto 1181 + field_declaration goto 1182 + method_declaration goto 1183 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1184 + property_declaration goto 1185 + event_declaration goto 1186 + indexer_declaration goto 1187 + operator_declaration goto 1188 + constructor_declaration goto 1189 + method_header goto 31 + interface_member_declaration goto 1210 + constructor_declarator goto 1179 + + +state 1192 + interface_member_declarations : interface_member_declaration . (246) + + . reduce 246 + + +state 1193 + struct_body : OPEN_BRACE $$11 . opt_struct_member_declarations CLOSE_BRACE (112) + opt_attributes : . (59) + opt_struct_member_declarations : . (113) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 113 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1211 + field_declaration goto 1212 + method_declaration goto 1213 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1214 + property_declaration goto 1215 + event_declaration goto 1216 + indexer_declaration goto 1217 + operator_declaration goto 1218 + constructor_declaration goto 1219 + destructor_declaration goto 1220 + opt_struct_member_declarations goto 1221 + struct_member_declarations goto 1222 + struct_member_declaration goto 1223 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1194 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 . opt_semicolon (109) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1224 + + +state 1195 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 . expression opt_join_into (884) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1225 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1196 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS . $$98 expression opt_join_into (888) + $$98 : . (887) + + . reduce 887 + + $$98 goto 1226 + + +state 1197 + delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON . (355) + + . reduce 355 + + +state 1198 + enum_member_declaration : opt_attributes IDENTIFIER $$57 ASSIGN constant_expression . (351) + + . reduce 351 + + +state 1199 + type_parameter_constraint : NEW OPEN_PARENS . CLOSE_PARENS (683) + + CLOSE_PARENS shift 1227 + . error + + +state 1200 + type_parameter_constraints : type_parameter_constraints COMMA . type_parameter_constraint (681) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CLASS shift 1158 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 1159 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + STRUCT shift 1160 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1161 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + type_parameter_constraint goto 1228 + + +state 1201 + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT error (110) + constant_declaration : opt_attributes opt_modifiers . CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes opt_modifiers . member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes opt_modifiers . member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers . PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes opt_modifiers . member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes opt_modifiers . member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes opt_modifiers . member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE error (243) + operator_declaration : opt_attributes opt_modifiers . operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes opt_modifiers . IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + destructor_declaration : opt_attributes opt_modifiers . TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes opt_modifiers . ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes opt_modifiers . DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes opt_modifiers . opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_partial : . (653) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CONST shift 1229 + DECIMAL shift 104 + DELEGATE shift 250 + DOUBLE shift 108 + ENUM shift 251 + EVENT shift 1230 + EXPLICIT shift 1231 + FIXED shift 252 + FLOAT shift 111 + IMPLICIT shift 1232 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 1233 + PARTIAL shift 254 + TILDE shift 1234 + IDENTIFIER shift 1235 + CLASS reduce 653 + INTERFACE reduce 653 + STRUCT reduce 653 + + namespace_or_type_name goto 255 + opt_partial goto 256 + member_type goto 1236 + operator_declarator goto 1237 + operator_type goto 1238 + type_expression_or_array goto 1239 + conversion_operator_declarator goto 1240 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1202 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE . $$73 opt_semicolon (652) + $$73 : . (651) + + . reduce 651 + + $$73 goto 1241 + + +state 1203 + class_member_declarations : class_member_declarations class_member_declaration . (93) + + . reduce 93 + + +state 1204 + block_prepared : OPEN_BRACE . $$75 opt_statement_list CLOSE_BRACE (695) + $$75 : . (694) + + . reduce 694 + + $$75 goto 1242 + + +state 1205 + constructor_body : SEMICOLON . (299) + + . reduce 299 + + +state 1206 + constructor_declaration : constructor_declarator constructor_body . (294) + + . reduce 294 + + +state 1207 + constructor_body : block_prepared . (298) + + . reduce 298 + + +state 1208 + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon (109) + struct_declaration : opt_attributes opt_modifiers . opt_partial STRUCT error (110) + constant_declaration : opt_attributes opt_modifiers . CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + field_declaration : opt_attributes opt_modifiers . member_type IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type IDENTIFIER $$15 fixed_field_size opt_fixed_field_declarators SEMICOLON (142) + field_declaration : opt_attributes opt_modifiers . FIXED simple_type error SEMICOLON (143) + method_header : opt_attributes opt_modifiers . member_type method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers . PARTIAL VOID method_declaration_name OPEN_PARENS $$22 opt_formal_parameter_list CLOSE_PARENS $$23 opt_type_parameter_constraints_clauses (182) + method_header : opt_attributes opt_modifiers . member_type modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes opt_modifiers . member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes opt_modifiers . member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon (242) + interface_declaration : opt_attributes opt_modifiers . opt_partial INTERFACE error (243) + operator_declaration : opt_attributes opt_modifiers . operator_declarator $$37 operator_body (258) + constructor_declarator : opt_attributes opt_modifiers . IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers . EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + enum_declaration : opt_attributes opt_modifiers . ENUM type_declaration_name opt_enum_base $$54 OPEN_BRACE $$55 opt_enum_member_declarations $$56 CLOSE_BRACE opt_semicolon (340) + delegate_declaration : opt_attributes opt_modifiers . DELEGATE member_type type_declaration_name OPEN_PARENS $$58 opt_formal_parameter_list CLOSE_PARENS $$59 opt_type_parameter_constraints_clauses $$60 SEMICOLON (355) + class_declaration : opt_attributes opt_modifiers . opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon (652) + opt_partial : . (653) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CONST shift 1229 + DECIMAL shift 104 + DELEGATE shift 250 + DOUBLE shift 108 + ENUM shift 251 + EVENT shift 1230 + EXPLICIT shift 1231 + FIXED shift 252 + FLOAT shift 111 + IMPLICIT shift 1232 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 1233 + PARTIAL shift 254 + IDENTIFIER shift 1235 + CLASS reduce 653 + INTERFACE reduce 653 + STRUCT reduce 653 + + namespace_or_type_name goto 255 + opt_partial goto 256 + member_type goto 1236 + operator_declarator goto 1237 + operator_type goto 1238 + type_expression_or_array goto 1239 + conversion_operator_declarator goto 1240 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_and_void goto 259 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1209 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE . $$36 opt_semicolon (242) + $$36 : . (241) + + . reduce 241 + + $$36 goto 1243 + + +state 1210 + interface_member_declarations : interface_member_declarations interface_member_declaration . (247) + + . reduce 247 + + +state 1211 + struct_member_declaration : type_declaration . (125) + + . reduce 125 + + +state 1212 + struct_member_declaration : field_declaration . (118) + + . reduce 118 + + +state 1213 + struct_member_declaration : method_declaration . (119) + + . reduce 119 + + +state 1214 + struct_member_declaration : constant_declaration . (117) + + . reduce 117 + + +state 1215 + struct_member_declaration : property_declaration . (120) + + . reduce 120 + + +state 1216 + struct_member_declaration : event_declaration . (121) + + . reduce 121 + + +state 1217 + struct_member_declaration : indexer_declaration . (122) + + . reduce 122 + + +state 1218 + struct_member_declaration : operator_declaration . (123) + + . reduce 123 + + +state 1219 + struct_member_declaration : constructor_declaration . (124) + + . reduce 124 + + +state 1220 + struct_member_declaration : destructor_declaration . (126) + + . reduce 126 + + +state 1221 + struct_body : OPEN_BRACE $$11 opt_struct_member_declarations . CLOSE_BRACE (112) + + CLOSE_BRACE shift 1244 + . error + + +state 1222 + opt_struct_member_declarations : struct_member_declarations . (114) + struct_member_declarations : struct_member_declarations . struct_member_declaration (116) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + CLASS reduce 59 + CONST reduce 59 + DECIMAL reduce 59 + DELEGATE reduce 59 + DOUBLE reduce 59 + ENUM reduce 59 + EVENT reduce 59 + EXPLICIT reduce 59 + EXTERN reduce 59 + FIXED reduce 59 + FLOAT reduce 59 + IMPLICIT reduce 59 + INT reduce 59 + INTERFACE reduce 59 + INTERNAL reduce 59 + LONG reduce 59 + NEW reduce 59 + OBJECT reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SBYTE reduce 59 + SEALED reduce 59 + SHORT reduce 59 + STATIC reduce 59 + STRING reduce 59 + STRUCT reduce 59 + UINT reduce 59 + ULONG reduce 59 + UNSAFE reduce 59 + USHORT reduce 59 + VIRTUAL reduce 59 + VOID reduce 59 + VOLATILE reduce 59 + PARTIAL reduce 59 + CLOSE_BRACE reduce 114 + TILDE reduce 59 + IDENTIFIER reduce 59 + + opt_attributes goto 1165 + type_declaration goto 1211 + field_declaration goto 1212 + method_declaration goto 1213 + class_declaration goto 24 + struct_declaration goto 25 + interface_declaration goto 26 + enum_declaration goto 27 + delegate_declaration goto 28 + attribute_sections goto 693 + attribute_section goto 30 + constant_declaration goto 1214 + property_declaration goto 1215 + event_declaration goto 1216 + indexer_declaration goto 1217 + operator_declaration goto 1218 + constructor_declaration goto 1219 + destructor_declaration goto 1220 + struct_member_declaration goto 1245 + method_header goto 31 + constructor_declarator goto 1179 + + +state 1223 + struct_member_declarations : struct_member_declaration . (115) + + . reduce 115 + + +state 1224 + struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$7 type_declaration_name $$8 opt_class_base opt_type_parameter_constraints_clauses $$9 struct_body $$10 opt_semicolon . (109) + + . reduce 109 + + +state 1225 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression . opt_join_into (884) + opt_join_into : . (889) + + INTO shift 1246 + WHERE reduce 889 + FROM reduce 889 + JOIN reduce 889 + SELECT reduce 889 + GROUP reduce 889 + LET reduce 889 + ORDERBY reduce 889 + COMPLETE_COMPLETION reduce 889 + + opt_join_into goto 1247 + + +state 1226 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 . expression opt_join_into (888) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 1248 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1227 + type_parameter_constraint : NEW OPEN_PARENS CLOSE_PARENS . (683) + + . reduce 683 + + +state 1228 + type_parameter_constraints : type_parameter_constraints COMMA type_parameter_constraint . (681) + + . reduce 681 + + +state 1229 + constant_declaration : opt_attributes opt_modifiers CONST . type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1249 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1230 + event_declaration : opt_attributes opt_modifiers EVENT . type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers EVENT . type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1250 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1231 + conversion_operator_declarator : EXPLICIT . OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS (291) + conversion_operator_declarator : EXPLICIT . error (293) + + error shift 1251 + OPERATOR shift 1252 + . error + + +state 1232 + conversion_operator_declarator : IMPLICIT . OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS (289) + conversion_operator_declarator : IMPLICIT . error (292) + + error shift 1253 + OPERATOR shift 1254 + . error + + +state 1233 + operator_type : VOID . (262) + type_and_void : VOID . (385) + type_expression : VOID . STAR (398) + + STAR shift 464 + ABSTRACT reduce 385 + EXTERN reduce 385 + INTERNAL reduce 385 + NEW reduce 385 + OPERATOR reduce 262 + OVERRIDE reduce 385 + PRIVATE reduce 385 + PROTECTED reduce 385 + PUBLIC reduce 385 + READONLY reduce 385 + SEALED reduce 385 + STATIC reduce 385 + THIS reduce 385 + UNSAFE reduce 385 + VIRTUAL reduce 385 + VOLATILE reduce 385 + IDENTIFIER reduce 385 + + +state 1234 + destructor_declaration : opt_attributes opt_modifiers TILDE . $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + $$45 : . (307) + + . reduce 307 + + $$45 goto 1255 + + +state 1235 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER . $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + type_name : IDENTIFIER . opt_type_argument_list (362) + qualified_alias_member : IDENTIFIER . DOUBLE_COLON (555) + $$41 : . (295) + opt_type_argument_list : . (363) + + OP_GENERICS_LT shift 81 + DOUBLE_COLON shift 83 + ABSTRACT reduce 363 + EXTERN reduce 363 + INTERNAL reduce 363 + NEW reduce 363 + OPERATOR reduce 363 + OVERRIDE reduce 363 + PRIVATE reduce 363 + PROTECTED reduce 363 + PUBLIC reduce 363 + READONLY reduce 363 + SEALED reduce 363 + STATIC reduce 363 + THIS reduce 363 + UNSAFE reduce 363 + VIRTUAL reduce 363 + VOLATILE reduce 363 + INTERR_NULLABLE reduce 363 + OPEN_BRACKET reduce 363 + OPEN_PARENS reduce 295 + DOT reduce 363 + STAR reduce 363 + IDENTIFIER reduce 363 + + $$41 goto 1256 + opt_type_argument_list goto 84 + + +state 1236 + field_declaration : opt_attributes opt_modifiers member_type . IDENTIFIER $$14 opt_field_initializer opt_field_declarators SEMICOLON (140) + method_header : opt_attributes opt_modifiers member_type . method_declaration_name OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + method_header : opt_attributes opt_modifiers member_type . modifiers method_declaration_name OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS (183) + property_declaration : opt_attributes opt_modifiers member_type . member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + indexer_declaration : opt_attributes opt_modifiers member_type . indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + THIS shift 1257 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + IDENTIFIER shift 470 + . error + + type_declaration_name goto 471 + method_declaration_name goto 1258 + modifiers goto 473 + member_declaration_name goto 1259 + indexer_declaration_name goto 1260 + qualified_alias_member goto 474 + explicit_interface goto 1261 + modifier goto 78 + + +state 1237 + operator_declaration : opt_attributes opt_modifiers operator_declarator . $$37 operator_body (258) + $$37 : . (257) + + . reduce 257 + + $$37 goto 1262 + + +state 1238 + operator_declarator : operator_type . OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS (264) + + OPERATOR shift 1263 + . error + + +state 1239 + operator_type : type_expression_or_array . (261) + type_and_void : type_expression_or_array . (384) + + ABSTRACT reduce 384 + EXTERN reduce 384 + INTERNAL reduce 384 + NEW reduce 384 + OPERATOR reduce 261 + OVERRIDE reduce 384 + PRIVATE reduce 384 + PROTECTED reduce 384 + PUBLIC reduce 384 + READONLY reduce 384 + SEALED reduce 384 + STATIC reduce 384 + THIS reduce 384 + UNSAFE reduce 384 + VIRTUAL reduce 384 + VOLATILE reduce 384 + IDENTIFIER reduce 384 + + +state 1240 + operator_declarator : conversion_operator_declarator . (265) + + . reduce 265 + + +state 1241 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 . opt_semicolon (652) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1264 + + +state 1242 + block_prepared : OPEN_BRACE $$75 . opt_statement_list CLOSE_BRACE (695) + opt_statement_list : . (696) + + error shift 303 + BASE shift 96 + BOOL shift 97 + BREAK shift 98 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 101 + CONST shift 102 + CONTINUE shift 103 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DO shift 107 + DOUBLE shift 108 + FALSE shift 109 + FIXED shift 110 + FLOAT shift 111 + FOR shift 112 + FOREACH shift 113 + GOTO shift 114 + IF shift 115 + INT shift 116 + LOCK shift 117 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + RETURN shift 122 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + SWITCH shift 127 + THIS shift 128 + THROW shift 129 + TRUE shift 130 + TRY shift 131 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 135 + UNSAFE shift 136 + USHORT shift 137 + USING shift 138 + VOID shift 139 + WHILE shift 140 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 143 + OPEN_PARENS shift 144 + SEMICOLON shift 145 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 155 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_BRACE reduce 696 + + expression goto 304 + block goto 305 + qualified_alias_member goto 160 + builtin_types goto 161 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 164 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + opt_statement_list goto 1265 + statement_list goto 562 + statement goto 563 + declaration_statement goto 564 + valid_declaration_statement goto 565 + labeled_statement goto 566 + empty_statement goto 309 + expression_statement goto 310 + selection_statement goto 311 + iteration_statement goto 312 + jump_statement goto 313 + try_statement goto 314 + checked_statement goto 315 + unchecked_statement goto 316 + lock_statement goto 317 + using_statement goto 318 + unsafe_statement goto 319 + fixed_statement goto 320 + local_variable_declaration goto 221 + local_constant_declaration goto 222 + variable_type goto 223 + local_variable_pointer_type goto 224 + local_variable_type goto 225 + statement_expression goto 322 + if_statement goto 227 + switch_statement goto 228 + while_statement goto 229 + do_statement goto 230 + for_statement goto 231 + foreach_statement goto 232 + break_statement goto 233 + continue_statement goto 234 + goto_statement goto 235 + return_statement goto 236 + throw_statement goto 237 + yield_statement goto 238 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1243 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 . opt_semicolon (242) + opt_semicolon : . (30) + + SEMICOLON shift 810 + $end reduce 30 + error reduce 30 + EOF reduce 30 + ABSTRACT reduce 30 + BOOL reduce 30 + BYTE reduce 30 + CHAR reduce 30 + CLASS reduce 30 + CONST reduce 30 + DECIMAL reduce 30 + DELEGATE reduce 30 + DOUBLE reduce 30 + ENUM reduce 30 + EVENT reduce 30 + EXPLICIT reduce 30 + EXTERN reduce 30 + FIXED reduce 30 + FLOAT reduce 30 + IMPLICIT reduce 30 + INT reduce 30 + INTERFACE reduce 30 + INTERNAL reduce 30 + LONG reduce 30 + NAMESPACE reduce 30 + NEW reduce 30 + OBJECT reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SBYTE reduce 30 + SEALED reduce 30 + SHORT reduce 30 + STATIC reduce 30 + STRING reduce 30 + STRUCT reduce 30 + UINT reduce 30 + ULONG reduce 30 + UNSAFE reduce 30 + USHORT reduce 30 + USING reduce 30 + VIRTUAL reduce 30 + VOID reduce 30 + VOLATILE reduce 30 + PARTIAL reduce 30 + EXTERN_ALIAS reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + TILDE reduce 30 + IDENTIFIER reduce 30 + + opt_semicolon goto 1266 + + +state 1244 + struct_body : OPEN_BRACE $$11 opt_struct_member_declarations CLOSE_BRACE . (112) + + . reduce 112 + + +state 1245 + struct_member_declarations : struct_member_declarations struct_member_declaration . (116) + + . reduce 116 + + +state 1246 + opt_join_into : INTO . IDENTIFIER (890) + + IDENTIFIER shift 1267 + . error + + +state 1247 + join_clause : JOIN IDENTIFIER IN $$93 expression ON $$94 expression EQUALS $$95 expression opt_join_into . (884) + + . reduce 884 + + +state 1248 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression . opt_join_into (888) + opt_join_into : . (889) + + INTO shift 1246 + WHERE reduce 889 + FROM reduce 889 + JOIN reduce 889 + SELECT reduce 889 + GROUP reduce 889 + LET reduce 889 + ORDERBY reduce 889 + COMPLETE_COMPLETION reduce 889 + + opt_join_into goto 1268 + + +state 1249 + constant_declaration : opt_attributes opt_modifiers CONST type . IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + + IDENTIFIER shift 1269 + . error + + +state 1250 + event_declaration : opt_attributes opt_modifiers EVENT type . member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers EVENT type . member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + + IDENTIFIER shift 665 + . error + + type_declaration_name goto 471 + method_declaration_name goto 1270 + member_declaration_name goto 1271 + qualified_alias_member goto 474 + explicit_interface goto 475 + + +state 1251 + conversion_operator_declarator : EXPLICIT error . (293) + + . reduce 293 + + +state 1252 + conversion_operator_declarator : EXPLICIT OPERATOR . type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS (291) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1272 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1253 + conversion_operator_declarator : IMPLICIT error . (292) + + . reduce 292 + + +state 1254 + conversion_operator_declarator : IMPLICIT OPERATOR . type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS (289) + + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + DECIMAL shift 104 + DOUBLE shift 108 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + STRING shift 126 + UINT shift 133 + ULONG shift 134 + USHORT shift 137 + VOID shift 267 + IDENTIFIER shift 89 + . error + + namespace_or_type_name goto 255 + type goto 1273 + type_expression_or_array goto 269 + member_name goto 36 + qualified_alias_member goto 37 + type_name goto 38 + type_expression goto 260 + builtin_types goto 261 + integral_type goto 162 + + +state 1255 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 . IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body (308) + + IDENTIFIER shift 1274 + . error + + +state 1256 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 . OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + + OPEN_PARENS shift 1275 + . error + + +state 1257 + indexer_declaration_name : THIS . (373) + + . reduce 373 + + +state 1258 + method_header : opt_attributes opt_modifiers member_type method_declaration_name . OPEN_PARENS $$20 opt_formal_parameter_list CLOSE_PARENS $$21 opt_type_parameter_constraints_clauses (179) + member_declaration_name : method_declaration_name . (370) + + OPEN_PARENS shift 674 + OPEN_BRACE reduce 370 + + +state 1259 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name . $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + $$25 : . (218) + + . reduce 218 + + $$25 goto 1276 + + +state 1260 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name . OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + OPEN_BRACKET shift 1277 + . error + + +state 1261 + method_declaration_name : explicit_interface . IDENTIFIER opt_type_parameter_list (372) + indexer_declaration_name : explicit_interface . THIS (374) + explicit_interface : explicit_interface . IDENTIFIER opt_type_argument_list DOT (377) + + THIS shift 1278 + IDENTIFIER shift 677 + . error + + +state 1262 + operator_declaration : opt_attributes opt_modifiers operator_declarator $$37 . operator_body (258) + + OPEN_BRACE shift 143 + SEMICOLON shift 1279 + . error + + block goto 1280 + operator_body goto 1281 + + +state 1263 + operator_declarator : operator_type OPERATOR . overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS (264) + + FALSE shift 1282 + TRUE shift 1283 + TILDE shift 1284 + PLUS shift 1285 + MINUS shift 1286 + BANG shift 1287 + OP_LT shift 1288 + OP_GT shift 1289 + BITWISE_AND shift 1290 + BITWISE_OR shift 1291 + STAR shift 1292 + PERCENT shift 1293 + DIV shift 1294 + CARRET shift 1295 + OP_INC shift 1296 + OP_DEC shift 1297 + OP_SHIFT_LEFT shift 1298 + OP_SHIFT_RIGHT shift 1299 + OP_LE shift 1300 + OP_GE shift 1301 + OP_EQ shift 1302 + OP_NE shift 1303 + . error + + overloadable_operator goto 1304 + + +state 1264 + class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$70 type_declaration_name $$71 opt_class_base opt_type_parameter_constraints_clauses $$72 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$73 opt_semicolon . (652) + + . reduce 652 + + +state 1265 + block_prepared : OPEN_BRACE $$75 opt_statement_list . CLOSE_BRACE (695) + + CLOSE_BRACE shift 1305 + . error + + +state 1266 + interface_declaration : opt_attributes opt_modifiers opt_partial INTERFACE $$33 type_declaration_name $$34 opt_class_base opt_type_parameter_constraints_clauses $$35 OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE $$36 opt_semicolon . (242) + + . reduce 242 + + +state 1267 + opt_join_into : INTO IDENTIFIER . (890) + + . reduce 890 + + +state 1268 + join_clause : JOIN type IDENTIFIER IN $$96 expression ON $$97 expression EQUALS $$98 expression opt_join_into . (888) + + . reduce 888 + + +state 1269 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER . $$12 constant_initializer opt_constant_declarators SEMICOLON (128) + $$12 : . (127) + + . reduce 127 + + $$12 goto 1306 + + +state 1270 + member_declaration_name : method_declaration_name . (370) + + . reduce 370 + + +state 1271 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name . $$46 opt_event_initializer opt_event_declarators SEMICOLON (310) + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name . OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + $$46 : . (309) + + OPEN_BRACE shift 1307 + COMMA reduce 309 + SEMICOLON reduce 309 + ASSIGN reduce 309 + + $$46 goto 1308 + + +state 1272 + conversion_operator_declarator : EXPLICIT OPERATOR type . OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS (291) + + OPEN_PARENS shift 1309 + . error + + +state 1273 + conversion_operator_declarator : IMPLICIT OPERATOR type . OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS (289) + + OPEN_PARENS shift 1310 + . error + + +state 1274 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER . OPEN_PARENS CLOSE_PARENS method_body (308) + + OPEN_PARENS shift 1311 + . error + + +state 1275 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS . opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer (297) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1312 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1276 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 . OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE (221) + + OPEN_BRACE shift 1313 + . error + + +state 1277 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET . $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + $$28 : . (222) + + . reduce 222 + + $$28 goto 1314 + + +state 1278 + indexer_declaration_name : explicit_interface THIS . (374) + + . reduce 374 + + +state 1279 + operator_body : SEMICOLON . (260) + + . reduce 260 + + +state 1280 + operator_body : block . (259) + + . reduce 259 + + +state 1281 + operator_declaration : opt_attributes opt_modifiers operator_declarator $$37 operator_body . (258) + + . reduce 258 + + +state 1282 + overloadable_operator : FALSE . (271) + + . reduce 271 + + +state 1283 + overloadable_operator : TRUE . (270) + + . reduce 270 + + +state 1284 + overloadable_operator : TILDE . (267) + + . reduce 267 + + +state 1285 + overloadable_operator : PLUS . (272) + + . reduce 272 + + +state 1286 + overloadable_operator : MINUS . (273) + + . reduce 273 + + +state 1287 + overloadable_operator : BANG . (266) + + . reduce 266 + + +state 1288 + overloadable_operator : OP_LT . (285) + + . reduce 285 + + +state 1289 + overloadable_operator : OP_GT . (284) + + . reduce 284 + + +state 1290 + overloadable_operator : BITWISE_AND . (277) + + . reduce 277 + + +state 1291 + overloadable_operator : BITWISE_OR . (278) + + . reduce 278 + + +state 1292 + overloadable_operator : STAR . (274) + + . reduce 274 + + +state 1293 + overloadable_operator : PERCENT . (276) + + . reduce 276 + + +state 1294 + overloadable_operator : DIV . (275) + + . reduce 275 + + +state 1295 + overloadable_operator : CARRET . (279) + + . reduce 279 + + +state 1296 + overloadable_operator : OP_INC . (268) + + . reduce 268 + + +state 1297 + overloadable_operator : OP_DEC . (269) + + . reduce 269 + + +state 1298 + overloadable_operator : OP_SHIFT_LEFT . (280) + + . reduce 280 + + +state 1299 + overloadable_operator : OP_SHIFT_RIGHT . (281) + + . reduce 281 + + +state 1300 + overloadable_operator : OP_LE . (287) + + . reduce 287 + + +state 1301 + overloadable_operator : OP_GE . (286) + + . reduce 286 + + +state 1302 + overloadable_operator : OP_EQ . (282) + + . reduce 282 + + +state 1303 + overloadable_operator : OP_NE . (283) + + . reduce 283 + + +state 1304 + operator_declarator : operator_type OPERATOR overloadable_operator . OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS (264) + + OPEN_PARENS shift 1315 + . error + + +state 1305 + block_prepared : OPEN_BRACE $$75 opt_statement_list CLOSE_BRACE . (695) + + . reduce 695 + + +state 1306 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 . constant_initializer opt_constant_declarators SEMICOLON (128) + + error shift 1316 + ASSIGN shift 1317 + . error + + constant_initializer goto 1318 + + +state 1307 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE . $$47 event_accessor_declarations $$48 CLOSE_BRACE (313) + $$47 : . (311) + + . reduce 311 + + $$47 goto 1319 + + +state 1308 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 . opt_event_initializer opt_event_declarators SEMICOLON (310) + opt_event_initializer : . (314) + + ASSIGN shift 1320 + COMMA reduce 314 + SEMICOLON reduce 314 + + opt_event_initializer goto 1321 + + +state 1309 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS . $$40 opt_formal_parameter_list CLOSE_PARENS (291) + $$40 : . (290) + + . reduce 290 + + $$40 goto 1322 + + +state 1310 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS . $$39 opt_formal_parameter_list CLOSE_PARENS (289) + $$39 : . (288) + + . reduce 288 + + $$39 goto 1323 + + +state 1311 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS . CLOSE_PARENS method_body (308) + + CLOSE_PARENS shift 1324 + . error + + +state 1312 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list . CLOSE_PARENS $$42 opt_constructor_initializer (297) + + CLOSE_PARENS shift 1325 + . error + + +state 1313 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE . $$26 accessor_declarations $$27 CLOSE_BRACE (221) + $$26 : . (219) + + . reduce 219 + + $$26 goto 1326 + + +state 1314 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 . opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_BRACKET reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1327 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1315 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS . $$38 opt_formal_parameter_list CLOSE_PARENS (264) + $$38 : . (263) + + . reduce 263 + + $$38 goto 1328 + + +state 1316 + constant_initializer : error . (136) + + . reduce 136 + + +state 1317 + constant_initializer : ASSIGN . $$13 constant_initializer_expr (135) + $$13 : . (134) + + . reduce 134 + + $$13 goto 1329 + + +state 1318 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer . opt_constant_declarators SEMICOLON (128) + opt_constant_declarators : . (129) + + COMMA shift 1330 + SEMICOLON reduce 129 + + opt_constant_declarators goto 1331 + constant_declarators goto 1332 + constant_declarator goto 1333 + + +state 1319 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 . event_accessor_declarations $$48 CLOSE_BRACE (313) + opt_attributes : . (59) + + error shift 1334 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + ADD reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + REMOVE reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + + opt_attributes goto 1335 + attribute_sections goto 693 + attribute_section goto 30 + event_accessor_declarations goto 1336 + add_accessor_declaration goto 1337 + remove_accessor_declaration goto 1338 + + +state 1320 + opt_event_initializer : ASSIGN . $$49 event_variable_initializer (316) + $$49 : . (315) + + . reduce 315 + + $$49 goto 1339 + + +state 1321 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer . opt_event_declarators SEMICOLON (310) + opt_event_declarators : . (317) + + COMMA shift 1340 + SEMICOLON reduce 317 + + opt_event_declarators goto 1341 + event_declarators goto 1342 + event_declarator goto 1343 + + +state 1322 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 . opt_formal_parameter_list CLOSE_PARENS (291) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1344 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1323 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 . opt_formal_parameter_list CLOSE_PARENS (289) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1345 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1324 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS . method_body (308) + + OPEN_BRACE shift 143 + SEMICOLON shift 263 + . error + + method_body goto 1346 + block goto 265 + + +state 1325 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS . $$42 opt_constructor_initializer (297) + $$42 : . (296) + + . reduce 296 + + $$42 goto 1347 + + +state 1326 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 . accessor_declarations $$27 CLOSE_BRACE (221) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1350 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1327 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list . CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + CLOSE_BRACKET shift 1353 + . error + + +state 1328 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 . opt_formal_parameter_list CLOSE_PARENS (264) + opt_attributes : . (59) + opt_formal_parameter_list : . (186) + + ARGLIST shift 691 + OPEN_BRACKET shift 4 + BOOL reduce 59 + BYTE reduce 59 + CHAR reduce 59 + DECIMAL reduce 59 + DOUBLE reduce 59 + FLOAT reduce 59 + INT reduce 59 + LONG reduce 59 + OBJECT reduce 59 + OUT reduce 59 + PARAMS reduce 59 + REF reduce 59 + SBYTE reduce 59 + SHORT reduce 59 + STRING reduce 59 + THIS reduce 59 + UINT reduce 59 + ULONG reduce 59 + USHORT reduce 59 + VOID reduce 59 + CLOSE_PARENS reduce 186 + IDENTIFIER reduce 59 + + opt_attributes goto 692 + attribute_sections goto 693 + attribute_section goto 30 + opt_formal_parameter_list goto 1354 + formal_parameter_list goto 695 + fixed_parameters goto 696 + parameter_array goto 697 + arglist_modifier goto 698 + fixed_parameter goto 699 + + +state 1329 + constant_initializer : ASSIGN $$13 . constant_initializer_expr (135) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 514 + constant_initializer_expr goto 1355 + constant_expression goto 840 + array_initializer goto 841 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1330 + constant_declarator : COMMA . IDENTIFIER constant_initializer (133) + + IDENTIFIER shift 1356 + . error + + +state 1331 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators . SEMICOLON (128) + + SEMICOLON shift 1357 + . error + + +state 1332 + opt_constant_declarators : constant_declarators . (130) + constant_declarators : constant_declarators . constant_declarator (132) + + COMMA shift 1330 + SEMICOLON reduce 130 + + constant_declarator goto 1358 + + +state 1333 + constant_declarators : constant_declarator . (131) + + . reduce 131 + + +state 1334 + event_accessor_declarations : error . (330) + + . reduce 330 + + +state 1335 + add_accessor_declaration : opt_attributes . opt_modifiers ADD $$52 event_accessor_block (332) + remove_accessor_declaration : opt_attributes . opt_modifiers REMOVE $$53 event_accessor_block (334) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + ADD reduce 655 + REMOVE reduce 655 + + opt_modifiers goto 1359 + modifiers goto 77 + modifier goto 78 + + +state 1336 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations . $$48 CLOSE_BRACE (313) + $$48 : . (312) + + . reduce 312 + + $$48 goto 1360 + + +state 1337 + event_accessor_declarations : add_accessor_declaration . remove_accessor_declaration (326) + event_accessor_declarations : add_accessor_declaration . (328) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + REMOVE reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + CLOSE_BRACE reduce 328 + + opt_attributes goto 1361 + attribute_sections goto 693 + attribute_section goto 30 + remove_accessor_declaration goto 1362 + + +state 1338 + event_accessor_declarations : remove_accessor_declaration . add_accessor_declaration (327) + event_accessor_declarations : remove_accessor_declaration . (329) + opt_attributes : . (59) + + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + ADD reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + CLOSE_BRACE reduce 329 + + opt_attributes goto 1363 + attribute_sections goto 693 + attribute_section goto 30 + add_accessor_declaration goto 1364 + + +state 1339 + opt_event_initializer : ASSIGN $$49 . event_variable_initializer (316) + $$51 : . (324) + + . reduce 324 + + event_variable_initializer goto 1365 + $$51 goto 1366 + + +state 1340 + event_declarator : COMMA . IDENTIFIER (321) + event_declarator : COMMA . IDENTIFIER ASSIGN $$50 event_variable_initializer (323) + + IDENTIFIER shift 1367 + . error + + +state 1341 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators . SEMICOLON (310) + + SEMICOLON shift 1368 + . error + + +state 1342 + opt_event_declarators : event_declarators . (318) + event_declarators : event_declarators . event_declarator (320) + + COMMA shift 1340 + SEMICOLON reduce 318 + + event_declarator goto 1369 + + +state 1343 + event_declarators : event_declarator . (319) + + . reduce 319 + + +state 1344 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list . CLOSE_PARENS (291) + + CLOSE_PARENS shift 1370 + . error + + +state 1345 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list . CLOSE_PARENS (289) + + CLOSE_PARENS shift 1371 + . error + + +state 1346 + destructor_declaration : opt_attributes opt_modifiers TILDE $$45 IDENTIFIER OPEN_PARENS CLOSE_PARENS method_body . (308) + + . reduce 308 + + +state 1347 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 . opt_constructor_initializer (297) + opt_constructor_initializer : . (300) + + COLON shift 1372 + OPEN_BRACE reduce 300 + SEMICOLON reduce 300 + + opt_constructor_initializer goto 1373 + constructor_initializer goto 1374 + + +state 1348 + accessor_declarations : error . (230) + + . reduce 230 + + +state 1349 + get_accessor_declaration : opt_attributes . opt_modifiers GET $$31 accessor_body (232) + set_accessor_declaration : opt_attributes . opt_modifiers SET $$32 accessor_body (234) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + GET reduce 655 + SET reduce 655 + + opt_modifiers goto 1375 + modifiers goto 77 + modifier goto 78 + + +state 1350 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations . $$27 CLOSE_BRACE (221) + $$27 : . (220) + + . reduce 220 + + $$27 goto 1376 + + +state 1351 + accessor_declarations : get_accessor_declaration . (226) + accessor_declarations : get_accessor_declaration . accessor_declarations (227) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + CLOSE_BRACE reduce 226 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1377 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1352 + accessor_declarations : set_accessor_declaration . (228) + accessor_declarations : set_accessor_declaration . accessor_declarations (229) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + CLOSE_BRACE reduce 228 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1378 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1353 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET . OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE (225) + + OPEN_BRACE shift 1379 + . error + + +state 1354 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list . CLOSE_PARENS (264) + + CLOSE_PARENS shift 1380 + . error + + +state 1355 + constant_initializer : ASSIGN $$13 constant_initializer_expr . (135) + + . reduce 135 + + +state 1356 + constant_declarator : COMMA IDENTIFIER . constant_initializer (133) + + error shift 1316 + ASSIGN shift 1317 + . error + + constant_initializer goto 1381 + + +state 1357 + constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$12 constant_initializer opt_constant_declarators SEMICOLON . (128) + + . reduce 128 + + +state 1358 + constant_declarators : constant_declarators constant_declarator . (132) + + . reduce 132 + + +state 1359 + add_accessor_declaration : opt_attributes opt_modifiers . ADD $$52 event_accessor_block (332) + remove_accessor_declaration : opt_attributes opt_modifiers . REMOVE $$53 event_accessor_block (334) + + ADD shift 1382 + REMOVE shift 1383 + . error + + +state 1360 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 . CLOSE_BRACE (313) + + CLOSE_BRACE shift 1384 + . error + + +state 1361 + remove_accessor_declaration : opt_attributes . opt_modifiers REMOVE $$53 event_accessor_block (334) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + REMOVE reduce 655 + + opt_modifiers goto 1385 + modifiers goto 77 + modifier goto 78 + + +state 1362 + event_accessor_declarations : add_accessor_declaration remove_accessor_declaration . (326) + + . reduce 326 + + +state 1363 + add_accessor_declaration : opt_attributes . opt_modifiers ADD $$52 event_accessor_block (332) + opt_modifiers : . (655) + + ABSTRACT shift 61 + EXTERN shift 62 + INTERNAL shift 63 + NEW shift 65 + OVERRIDE shift 66 + PRIVATE shift 67 + PROTECTED shift 68 + PUBLIC shift 69 + READONLY shift 70 + SEALED shift 71 + STATIC shift 72 + UNSAFE shift 73 + VIRTUAL shift 74 + VOLATILE shift 75 + ADD reduce 655 + + opt_modifiers goto 1386 + modifiers goto 77 + modifier goto 78 + + +state 1364 + event_accessor_declarations : remove_accessor_declaration add_accessor_declaration . (327) + + . reduce 327 + + +state 1365 + opt_event_initializer : ASSIGN $$49 event_variable_initializer . (316) + + . reduce 316 + + +state 1366 + event_variable_initializer : $$51 . variable_initializer (325) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_BRACE shift 531 + OPEN_PARENS shift 144 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 337 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + . error + + expression goto 719 + array_initializer goto 720 + variable_initializer goto 1387 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1367 + event_declarator : COMMA IDENTIFIER . (321) + event_declarator : COMMA IDENTIFIER . ASSIGN $$50 event_variable_initializer (323) + + ASSIGN shift 1388 + COMMA reduce 321 + SEMICOLON reduce 321 + + +state 1368 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name $$46 opt_event_initializer opt_event_declarators SEMICOLON . (310) + + . reduce 310 + + +state 1369 + event_declarators : event_declarators event_declarator . (320) + + . reduce 320 + + +state 1370 + conversion_operator_declarator : EXPLICIT OPERATOR type OPEN_PARENS $$40 opt_formal_parameter_list CLOSE_PARENS . (291) + + . reduce 291 + + +state 1371 + conversion_operator_declarator : IMPLICIT OPERATOR type OPEN_PARENS $$39 opt_formal_parameter_list CLOSE_PARENS . (289) + + . reduce 289 + + +state 1372 + constructor_initializer : COLON . BASE OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS (303) + constructor_initializer : COLON . THIS OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS (305) + constructor_initializer : COLON . error (306) + + error shift 1389 + BASE shift 1390 + THIS shift 1391 + . error + + +state 1373 + constructor_declarator : opt_attributes opt_modifiers IDENTIFIER $$41 OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS $$42 opt_constructor_initializer . (297) + + . reduce 297 + + +state 1374 + opt_constructor_initializer : constructor_initializer . (301) + + . reduce 301 + + +state 1375 + get_accessor_declaration : opt_attributes opt_modifiers . GET $$31 accessor_body (232) + set_accessor_declaration : opt_attributes opt_modifiers . SET $$32 accessor_body (234) + + GET shift 1392 + SET shift 1393 + . error + + +state 1376 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 . CLOSE_BRACE (221) + + CLOSE_BRACE shift 1394 + . error + + +state 1377 + accessor_declarations : get_accessor_declaration accessor_declarations . (227) + + . reduce 227 + + +state 1378 + accessor_declarations : set_accessor_declaration accessor_declarations . (229) + + . reduce 229 + + +state 1379 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE . $$29 accessor_declarations $$30 CLOSE_BRACE (225) + $$29 : . (223) + + . reduce 223 + + $$29 goto 1395 + + +state 1380 + operator_declarator : operator_type OPERATOR overloadable_operator OPEN_PARENS $$38 opt_formal_parameter_list CLOSE_PARENS . (264) + + . reduce 264 + + +state 1381 + constant_declarator : COMMA IDENTIFIER constant_initializer . (133) + + . reduce 133 + + +state 1382 + add_accessor_declaration : opt_attributes opt_modifiers ADD . $$52 event_accessor_block (332) + $$52 : . (331) + + . reduce 331 + + $$52 goto 1396 + + +state 1383 + remove_accessor_declaration : opt_attributes opt_modifiers REMOVE . $$53 event_accessor_block (334) + $$53 : . (333) + + . reduce 333 + + $$53 goto 1397 + + +state 1384 + event_declaration : opt_attributes opt_modifiers EVENT type member_declaration_name OPEN_BRACE $$47 event_accessor_declarations $$48 CLOSE_BRACE . (313) + + . reduce 313 + + +state 1385 + remove_accessor_declaration : opt_attributes opt_modifiers . REMOVE $$53 event_accessor_block (334) + + REMOVE shift 1383 + . error + + +state 1386 + add_accessor_declaration : opt_attributes opt_modifiers . ADD $$52 event_accessor_block (332) + + ADD shift 1382 + . error + + +state 1387 + event_variable_initializer : $$51 variable_initializer . (325) + + . reduce 325 + + +state 1388 + event_declarator : COMMA IDENTIFIER ASSIGN . $$50 event_variable_initializer (323) + $$50 : . (322) + + . reduce 322 + + $$50 goto 1398 + + +state 1389 + constructor_initializer : COLON error . (306) + + . reduce 306 + + +state 1390 + constructor_initializer : COLON BASE . OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS (303) + + OPEN_PARENS shift 1399 + . error + + +state 1391 + constructor_initializer : COLON THIS . OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS (305) + + OPEN_PARENS shift 1400 + . error + + +state 1392 + get_accessor_declaration : opt_attributes opt_modifiers GET . $$31 accessor_body (232) + $$31 : . (231) + + . reduce 231 + + $$31 goto 1401 + + +state 1393 + set_accessor_declaration : opt_attributes opt_modifiers SET . $$32 accessor_body (234) + $$32 : . (233) + + . reduce 233 + + $$32 goto 1402 + + +state 1394 + property_declaration : opt_attributes opt_modifiers member_type member_declaration_name $$25 OPEN_BRACE $$26 accessor_declarations $$27 CLOSE_BRACE . (221) + + . reduce 221 + + +state 1395 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 . accessor_declarations $$30 CLOSE_BRACE (225) + opt_attributes : . (59) + + error shift 1348 + OPEN_BRACKET shift 4 + ABSTRACT reduce 59 + EXTERN reduce 59 + INTERNAL reduce 59 + NEW reduce 59 + OVERRIDE reduce 59 + PRIVATE reduce 59 + PROTECTED reduce 59 + PUBLIC reduce 59 + READONLY reduce 59 + SEALED reduce 59 + STATIC reduce 59 + UNSAFE reduce 59 + VIRTUAL reduce 59 + VOLATILE reduce 59 + GET reduce 59 + SET reduce 59 + + opt_attributes goto 1349 + attribute_sections goto 693 + attribute_section goto 30 + accessor_declarations goto 1403 + get_accessor_declaration goto 1351 + set_accessor_declaration goto 1352 + + +state 1396 + add_accessor_declaration : opt_attributes opt_modifiers ADD $$52 . event_accessor_block (332) + opt_semicolon : . (30) + + OPEN_BRACE shift 143 + SEMICOLON shift 810 + ABSTRACT reduce 30 + EXTERN reduce 30 + INTERNAL reduce 30 + NEW reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + REMOVE reduce 30 + SEALED reduce 30 + STATIC reduce 30 + UNSAFE reduce 30 + VIRTUAL reduce 30 + VOLATILE reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + + opt_semicolon goto 1404 + block goto 1405 + event_accessor_block goto 1406 + + +state 1397 + remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$53 . event_accessor_block (334) + opt_semicolon : . (30) + + OPEN_BRACE shift 143 + SEMICOLON shift 810 + ABSTRACT reduce 30 + ADD reduce 30 + EXTERN reduce 30 + INTERNAL reduce 30 + NEW reduce 30 + OVERRIDE reduce 30 + PRIVATE reduce 30 + PROTECTED reduce 30 + PUBLIC reduce 30 + READONLY reduce 30 + SEALED reduce 30 + STATIC reduce 30 + UNSAFE reduce 30 + VIRTUAL reduce 30 + VOLATILE reduce 30 + CLOSE_BRACE reduce 30 + OPEN_BRACKET reduce 30 + + opt_semicolon goto 1404 + block goto 1405 + event_accessor_block goto 1407 + + +state 1398 + event_declarator : COMMA IDENTIFIER ASSIGN $$50 . event_variable_initializer (323) + $$51 : . (324) + + . reduce 324 + + event_variable_initializer goto 1408 + $$51 goto 1366 + + +state 1399 + constructor_initializer : COLON BASE OPEN_PARENS . $$43 opt_argument_list CLOSE_PARENS (303) + $$43 : . (302) + + . reduce 302 + + $$43 goto 1409 + + +state 1400 + constructor_initializer : COLON THIS OPEN_PARENS . $$44 opt_argument_list CLOSE_PARENS (305) + $$44 : . (304) + + . reduce 304 + + $$44 goto 1410 + + +state 1401 + get_accessor_declaration : opt_attributes opt_modifiers GET $$31 . accessor_body (232) + + error shift 1411 + OPEN_BRACE shift 143 + SEMICOLON shift 1412 + . error + + block goto 1413 + accessor_body goto 1414 + + +state 1402 + set_accessor_declaration : opt_attributes opt_modifiers SET $$32 . accessor_body (234) + + error shift 1411 + OPEN_BRACE shift 143 + SEMICOLON shift 1412 + . error + + block goto 1413 + accessor_body goto 1415 + + +state 1403 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations . $$30 CLOSE_BRACE (225) + $$30 : . (224) + + . reduce 224 + + $$30 goto 1416 + + +state 1404 + event_accessor_block : opt_semicolon . (335) + + . reduce 335 + + +state 1405 + event_accessor_block : block . (336) + + . reduce 336 + + +state 1406 + add_accessor_declaration : opt_attributes opt_modifiers ADD $$52 event_accessor_block . (332) + + . reduce 332 + + +state 1407 + remove_accessor_declaration : opt_attributes opt_modifiers REMOVE $$53 event_accessor_block . (334) + + . reduce 334 + + +state 1408 + event_declarator : COMMA IDENTIFIER ASSIGN $$50 event_variable_initializer . (323) + + . reduce 323 + + +state 1409 + constructor_initializer : COLON BASE OPEN_PARENS $$43 . opt_argument_list CLOSE_PARENS (303) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 1417 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1410 + constructor_initializer : COLON THIS OPEN_PARENS $$44 . opt_argument_list CLOSE_PARENS (305) + opt_argument_list : . (477) + + BASE shift 96 + BOOL shift 97 + BYTE shift 99 + CHAR shift 100 + CHECKED shift 288 + DECIMAL shift 104 + DEFAULT shift 105 + DELEGATE shift 106 + DOUBLE shift 108 + FALSE shift 109 + FLOAT shift 111 + INT shift 116 + LONG shift 118 + NEW shift 119 + NULL shift 120 + OBJECT shift 121 + OUT shift 594 + REF shift 595 + SBYTE shift 123 + SHORT shift 124 + SIZEOF shift 125 + STRING shift 126 + THIS shift 128 + TRUE shift 130 + TYPEOF shift 132 + UINT shift 133 + ULONG shift 134 + UNCHECKED shift 289 + USHORT shift 137 + ARGLIST shift 596 + FROM shift 141 + FROM_FIRST shift 142 + OPEN_PARENS shift 144 + COMMA shift 597 + TILDE shift 146 + PLUS shift 147 + MINUS shift 148 + BANG shift 149 + BITWISE_AND shift 150 + STAR shift 151 + OP_INC shift 152 + OP_DEC shift 153 + LITERAL shift 154 + IDENTIFIER shift 492 + OPEN_PARENS_LAMBDA shift 156 + OPEN_PARENS_CAST shift 157 + CLOSE_PARENS reduce 477 + + expression goto 598 + named_argument goto 599 + opt_argument_list goto 1418 + qualified_alias_member goto 160 + builtin_types goto 340 + integral_type goto 162 + primary_expression goto 163 + primary_expression_no_array_creation goto 341 + array_creation_expression goto 165 + literal goto 166 + parenthesized_expression goto 167 + default_value_expression goto 168 + member_access goto 169 + invocation_expression goto 170 + element_access goto 171 + this_access goto 172 + base_access goto 173 + post_increment_expression goto 174 + post_decrement_expression goto 175 + object_or_delegate_creation_expression goto 176 + anonymous_type_expression goto 177 + typeof_expression goto 178 + sizeof_expression goto 179 + checked_expression goto 180 + unchecked_expression goto 181 + pointer_member_access goto 182 + anonymous_method_expression goto 183 + boolean_literal goto 184 + non_assignment_expression goto 185 + argument_list goto 601 + argument_or_named_argument goto 602 + argument goto 603 + non_simple_argument goto 604 + unary_expression goto 186 + prefixed_unary_expression goto 187 + cast_expression goto 188 + multiplicative_expression goto 189 + additive_expression goto 190 + shift_expression goto 191 + relational_expression goto 192 + equality_expression goto 193 + and_expression goto 194 + exclusive_or_expression goto 195 + inclusive_or_expression goto 196 + conditional_and_expression goto 197 + conditional_or_expression goto 198 + null_coalescing_expression goto 199 + conditional_expression goto 200 + assignment_expression goto 201 + lambda_expression goto 202 + query_expression goto 203 + first_from_clause goto 239 + nested_from_clause goto 240 + + +state 1411 + accessor_body : error . (237) + + . reduce 237 + + +state 1412 + accessor_body : SEMICOLON . (236) + + . reduce 236 + + +state 1413 + accessor_body : block . (235) + + . reduce 235 + + +state 1414 + get_accessor_declaration : opt_attributes opt_modifiers GET $$31 accessor_body . (232) + + . reduce 232 + + +state 1415 + set_accessor_declaration : opt_attributes opt_modifiers SET $$32 accessor_body . (234) + + . reduce 234 + + +state 1416 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 . CLOSE_BRACE (225) + + CLOSE_BRACE shift 1419 + . error + + +state 1417 + constructor_initializer : COLON BASE OPEN_PARENS $$43 opt_argument_list . CLOSE_PARENS (303) + + CLOSE_PARENS shift 1420 + . error + + +state 1418 + constructor_initializer : COLON THIS OPEN_PARENS $$44 opt_argument_list . CLOSE_PARENS (305) + + CLOSE_PARENS shift 1421 + . error + + +state 1419 + indexer_declaration : opt_attributes opt_modifiers member_type indexer_declaration_name OPEN_BRACKET $$28 opt_formal_parameter_list CLOSE_BRACKET OPEN_BRACE $$29 accessor_declarations $$30 CLOSE_BRACE . (225) + + . reduce 225 + + +state 1420 + constructor_initializer : COLON BASE OPEN_PARENS $$43 opt_argument_list CLOSE_PARENS . (303) + + . reduce 303 + + +state 1421 + constructor_initializer : COLON THIS OPEN_PARENS $$44 opt_argument_list CLOSE_PARENS . (305) + + . reduce 305 + + +State 164 contains 1 shift/reduce conflict. +State 167 contains 1 shift/reduce conflict. +State 239 contains 1 shift/reduce conflict. +State 240 contains 1 shift/reduce conflict. +State 484 contains 1 shift/reduce conflict. +State 654 contains 1 shift/reduce conflict. +State 729 contains 1 shift/reduce conflict. +State 730 contains 1 shift/reduce conflict. +State 860 contains 1 shift/reduce conflict. + + +170 terminals, 432 nonterminals +922 grammar rules, 1422 states diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs new file mode 100644 index 0000000000..4a99ef1625 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs @@ -0,0 +1,55 @@ +// +// Change.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + /// + /// This is the base class for all refactoring operations that are performed. + /// + public abstract class Action + { + /// + /// Gets or sets the description. + /// + /// + /// A brief description of the refactoring change. + /// + public string Description { + get; + set; + } + + /// + /// Performs the change. + /// + /// + /// The context on which the change should perform on. + /// + public abstract void Perform (Script script); + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs new file mode 100644 index 0000000000..f934917d9a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs @@ -0,0 +1,89 @@ +// +// AddAnotherAccessor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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. + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Add another accessor to a property declaration that has only one. + /// + public class AddAnotherAccessor : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var pdecl = GetPropertyDeclaration (context); + if (pdecl == null) + return false; + var type = pdecl.Parent as TypeDeclaration; + if (type != null && type.ClassType == ICSharpCode.NRefactory.TypeSystem.ClassType.Interface) + return false; + + return pdecl.Setter.IsNull || pdecl.Getter.IsNull; + } + + public void Run (RefactoringContext context) + { + var pdecl = GetPropertyDeclaration (context); + var accessorStatement = BuildAccessorStatement (context, pdecl); + + Accessor accessor = new Accessor () { + Body = new BlockStatement { accessorStatement } + }; + + pdecl.AddChild (accessor, pdecl.Setter.IsNull ? PropertyDeclaration.SetterRole : PropertyDeclaration.GetterRole); + + using (var script = context.StartScript ()) { + script.InsertBefore (pdecl.RBraceToken, accessor); + script.Select (accessorStatement); + script.FormatText (ctx => GetPropertyDeclaration (context)); + } + } + + static Statement BuildAccessorStatement (RefactoringContext context, PropertyDeclaration pdecl) + { + if (pdecl.Setter.IsNull && !pdecl.Getter.IsNull) { + var field = RemoveBackingStore.ScanGetter (context, pdecl); + if (field != null) + return new ExpressionStatement (new AssignmentExpression (new IdentifierExpression (field.Name), AssignmentOperatorType.Assign, new IdentifierExpression ("value"))); + } + + if (!pdecl.Setter.IsNull && pdecl.Getter.IsNull) { + var field = RemoveBackingStore.ScanSetter (context, pdecl); + if (field != null) + return new ReturnStatement (new IdentifierExpression (field.Name)); + } + + return new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "NotImplementedException"))); + } + + static PropertyDeclaration GetPropertyDeclaration (RefactoringContext context) + { + var node = context.GetNode (); + if (node == null) + return null; + return node.Parent as PropertyDeclaration; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs new file mode 100644 index 0000000000..3c52562aa6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs @@ -0,0 +1,112 @@ +// +// CheckIfParameterIsNull.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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 ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Creates a 'if (param == null) throw new System.ArgumentNullException ();' contruct for a parameter. + /// + public class CheckIfParameterIsNull : IContextAction + { + //TODO: Create 'multiple' null checks when more than 1 parameter is selected. + public bool IsValid (RefactoringContext context) + { + var parameter = GetParameterDeclaration (context); + if (parameter == null) + return false; + + var bodyStatement = parameter.Parent.GetChildByRole (AstNode.Roles.Body); + + if (bodyStatement == null) + return false; + + if (parameter.Type is PrimitiveType) + return (((PrimitiveType)parameter.Type).Keyword == "object" || ((PrimitiveType)parameter.Type).Keyword == "string") && !HasNullCheck (parameter); + + // TODO: check for structs + return !HasNullCheck (parameter); + } + + public void Run (RefactoringContext context) + { + var parameter = GetParameterDeclaration (context); + + var bodyStatement = parameter.Parent.GetChildByRole (AstNode.Roles.Body); + + var statement = new IfElseStatement () { + Condition = new BinaryOperatorExpression (new IdentifierExpression (parameter.Name), BinaryOperatorType.Equality, new NullReferenceExpression ()), + TrueStatement = new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "ArgumentNullException"), new PrimitiveExpression (parameter.Name))) + }; + + using (var script = context.StartScript ()) { + script.AddTo (bodyStatement, statement); + } + } + + static ParameterDeclaration GetParameterDeclaration (RefactoringContext context) + { + return context.GetNode (); + } + + static bool HasNullCheck (ParameterDeclaration parameter) + { + var visitor = new CheckNullVisitor (parameter); + parameter.Parent.AcceptVisitor (visitor, null); + return visitor.ContainsNullCheck; + } + + class CheckNullVisitor : DepthFirstAstVisitor + { + ParameterDeclaration parameter; + + public bool ContainsNullCheck { + get; + set; + } + + public CheckNullVisitor (ParameterDeclaration parameter) + { + this.parameter = parameter; + } + + public object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) + { + if (ifElseStatement.Condition is BinaryOperatorExpression) { + var binOp = ifElseStatement.Condition as BinaryOperatorExpression; + if ((binOp.Operator == BinaryOperatorType.Equality || binOp.Operator == BinaryOperatorType.InEquality) && + binOp.Left.IsMatch (new IdentifierExpression (parameter.Name)) && binOp.Right.IsMatch (new NullReferenceExpression ()) || + binOp.Right.IsMatch (new IdentifierExpression (parameter.Name)) && binOp.Left.IsMatch (new NullReferenceExpression ())) { + ContainsNullCheck = true; + } + } + + return base.VisitIfElseStatement (ifElseStatement, data); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs new file mode 100644 index 0000000000..c1ec0fa06f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs @@ -0,0 +1,52 @@ +// +// ConvertDecToHex.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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. + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Convert a dec numer to hex. For example: 16 -> 0x10 + /// + public class ConvertDecToHex : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var pexpr = context.GetNode (); + if (pexpr == null || pexpr.LiteralValue.StartsWith ("0X", System.StringComparison.OrdinalIgnoreCase)) + return false; + return (pexpr.Value is int) || (pexpr.Value is long) || (pexpr.Value is short) || (pexpr.Value is sbyte) || + (pexpr.Value is uint) || (pexpr.Value is ulong) || (pexpr.Value is ushort) || (pexpr.Value is byte); + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + + using (var script = context.StartScript ()) { + script.Replace (pexpr, new PrimitiveExpression (pexpr.Value, string.Format ("0x{0:x}", pexpr.Value))); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs new file mode 100644 index 0000000000..b3f38e7cbc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs @@ -0,0 +1,95 @@ +// +// ConvertForeachToFor.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Converts a foreach loop to for. + /// + public class ConvertForeachToFor : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetForeachStatement (context) != null; + } + + static string GetCountProperty (IType type) + { +// if (!type.) +// return "Length"; + return "Count"; + } + + public void Run (RefactoringContext context) + { + var foreachStatement = GetForeachStatement (context); + + var result = context.Resolve (foreachStatement.InExpression); + var countProperty = GetCountProperty (result.Type); + + var initializer = new VariableDeclarationStatement (new PrimitiveType ("int"), "i", new PrimitiveExpression (0)); + var id1 = new IdentifierExpression ("i"); + var id2 = id1.Clone (); + var id3 = id1.Clone (); + + var forStatement = new ForStatement () { + Initializers = { initializer }, + Condition = new BinaryOperatorExpression (id1, BinaryOperatorType.LessThan, new MemberReferenceExpression (foreachStatement.InExpression.Clone (), countProperty)), + Iterators = { new ExpressionStatement (new UnaryOperatorExpression (UnaryOperatorType.PostIncrement, id2)) }, + EmbeddedStatement = new BlockStatement { + new VariableDeclarationStatement (foreachStatement.VariableType.Clone (), foreachStatement.VariableName, new IndexerExpression (foreachStatement.InExpression.Clone (), id3)) + } + }; + + if (foreachStatement.EmbeddedStatement is BlockStatement) { + foreach (var child in ((BlockStatement)foreachStatement.EmbeddedStatement).Statements) { + forStatement.EmbeddedStatement.AddChild (child.Clone (), BlockStatement.StatementRole); + } + } else { + forStatement.EmbeddedStatement.AddChild (foreachStatement.EmbeddedStatement.Clone (), BlockStatement.StatementRole); + } + + using (var script = context.StartScript ()) { + script.Replace (foreachStatement, forStatement); + script.Link (initializer.Variables.First ().NameToken, id1, id2, id3); + } + } + + static ForeachStatement GetForeachStatement (RefactoringContext context) + { + var astNode = context.GetNode (); + if (astNode == null) + return null; + var result = (astNode as ForeachStatement) ?? astNode.Parent as ForeachStatement; + if (result == null || context.Resolve (result.InExpression) == null) + return null; + return result; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs new file mode 100644 index 0000000000..3c653c1c12 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs @@ -0,0 +1,52 @@ +// +// ConvertHexToDec.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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. + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Convert a hex numer to dec. For example: 0x10 -> 16 + /// + public class ConvertHexToDec: IContextAction + { + public bool IsValid (RefactoringContext context) + { + var pexpr = context.GetNode (); + if (pexpr == null || !pexpr.LiteralValue.StartsWith ("0X", System.StringComparison.OrdinalIgnoreCase)) + return false; + return (pexpr.Value is int) || (pexpr.Value is long) || (pexpr.Value is short) || (pexpr.Value is sbyte) || + (pexpr.Value is uint) || (pexpr.Value is ulong) || (pexpr.Value is ushort) || (pexpr.Value is byte); + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + + using (var script = context.StartScript ()) { + script.Replace (pexpr, new PrimitiveExpression (pexpr.Value)); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs new file mode 100644 index 0000000000..db6598a877 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs @@ -0,0 +1,73 @@ +// +// CreateBackingStore.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public class CreateBackingStore : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var propertyDeclaration = context.GetNode (); + return propertyDeclaration != null && + !propertyDeclaration.Getter.IsNull && !propertyDeclaration.Setter.IsNull && // automatic properties always need getter & setter + propertyDeclaration.Getter.Body.IsNull && + propertyDeclaration.Setter.Body.IsNull; + } + + public void Run (RefactoringContext context) + { + var property = context.GetNode (); + + string backingStoreName = context.GetNameProposal (property.Name); + + // create field + var backingStore = new FieldDeclaration (); + backingStore.ReturnType = property.ReturnType.Clone (); + + var initializer = new VariableInitializer (backingStoreName); + backingStore.Variables.Add (initializer); + + // create new property & implement the get/set bodies + var newProperty = (PropertyDeclaration)property.Clone (); + var id1 = new IdentifierExpression (backingStoreName); + var id2 = new IdentifierExpression (backingStoreName); + newProperty.Getter.Body = new BlockStatement () { + new ReturnStatement (id1) + }; + newProperty.Setter.Body = new BlockStatement () { + new ExpressionStatement (new AssignmentExpression (id2, AssignmentOperatorType.Assign, new IdentifierExpression ("value"))) + }; + + using (var script = context.StartScript ()) { + script.Replace (property, newProperty); + script.InsertBefore (property, backingStore); + script.Link (initializer, id1, id2); + } + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs new file mode 100644 index 0000000000..e8473bdd9b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs @@ -0,0 +1,109 @@ +// +// CreateEventInvocator.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateEventInvocator : IContextAction + { + public bool IsValid (RefactoringContext context) + { + VariableInitializer initializer; + var eventDeclaration = GetEventDeclaration (context, out initializer); + if (eventDeclaration == null) + return false; + var type = (TypeDeclaration)eventDeclaration.Parent; + return !type.Members.Any (m => m is MethodDeclaration && ((MethodDeclaration)m).Name == "On" + initializer.Name); + } + + public void Run (RefactoringContext context) + { + VariableInitializer initializer; + var eventDeclaration = GetEventDeclaration (context, out initializer); + var type = context.Resolve (eventDeclaration.ReturnType).Type; + if (type == null) + return; + var invokeMethod = type.GetDelegateInvokeMethod (); + if (invokeMethod == null) + return; + + bool hasSenderParam = false; + IEnumerable pars = invokeMethod.Parameters; + if (invokeMethod.Parameters.Any ()) { + var first = invokeMethod.Parameters [0]; + if (first.Name == "sender" /*&& first.Type == "System.Object"*/) { + hasSenderParam = true; + pars = invokeMethod.Parameters.Skip (1); + } + } + const string handlerName = "handler"; + + var arguments = new List (); + if (hasSenderParam) + arguments.Add (new ThisReferenceExpression ()); + foreach (var par in pars) + arguments.Add (new IdentifierExpression (par.Name)); + + var methodDeclaration = new MethodDeclaration () { + Name = "On" + initializer.Name, + ReturnType = new PrimitiveType ("void"), + Modifiers = ICSharpCode.NRefactory.CSharp.Modifiers.Protected | ICSharpCode.NRefactory.CSharp.Modifiers.Virtual, + Body = new BlockStatement () { + new VariableDeclarationStatement (context.CreateShortType (eventDeclaration.ReturnType), handlerName, new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name)), + new IfElseStatement () { + Condition = new BinaryOperatorExpression (new IdentifierExpression (handlerName), BinaryOperatorType.InEquality, new PrimitiveExpression (null)), + TrueStatement = new ExpressionStatement (new InvocationExpression (new IdentifierExpression (handlerName), arguments)) + } + } + }; + + foreach (var par in pars) { + var typeName = context.CreateShortType (par.Type.Resolve (context.TypeResolveContext)); + var decl = new ParameterDeclaration (typeName, par.Name); + methodDeclaration.Parameters.Add (decl); + } + + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create event invocator", methodDeclaration, Script.InsertPosition.After); + } + } + + static EventDeclaration GetEventDeclaration (RefactoringContext context, out VariableInitializer initializer) + { + var result = context.GetNode (); + if (result == null) { + initializer = null; + return null; + } + initializer = result.Variables.First (v => v.NameToken.Contains (context.Location)); + return initializer != null ? result : null; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs new file mode 100644 index 0000000000..831dfe121e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs @@ -0,0 +1,77 @@ +// +// CreateField.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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.PatternMatching; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateField : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var identifier = GetIdentifier (context); + if (identifier == null) + return false; + return context.Resolve (identifier) == null && GuessType (context, identifier) != null; + } + + public void Run (RefactoringContext context) + { + var identifier = GetIdentifier (context); + + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create field", GenerateFieldDeclaration (context, identifier), Script.InsertPosition.Before); + } + } + + static AstNode GenerateFieldDeclaration (RefactoringContext context, IdentifierExpression identifier) + { + return new FieldDeclaration () { + ReturnType = GuessType (context, identifier), + Variables = { new VariableInitializer (identifier.Identifier) } + }; + } + + internal static AstType GuessType (RefactoringContext context, IdentifierExpression identifier) + { + if (identifier.Parent is AssignmentExpression) { + var assign = (AssignmentExpression)identifier.Parent; + var other = assign.Left == identifier ? assign.Right : assign.Left; + return context.Resolve (other).Type.ConvertToAstType (); + } + return null; + } + + public static IdentifierExpression GetIdentifier (RefactoringContext context) + { + return context.GetNode (); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs new file mode 100644 index 0000000000..f5927a2d89 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs @@ -0,0 +1,129 @@ +// +// CreateLocalVariable.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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.PatternMatching; +using System.Linq; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateLocalVariable : IContextAction + { + public List GetUnresolvedArguments (RefactoringContext context) + { + var expressions = new List (); + + var invocation = GetInvocation (context); + if (invocation != null) { + foreach (var arg in invocation.Arguments) { + IdentifierExpression identifier; + if (arg is DirectionExpression) { + identifier = ((DirectionExpression)arg).Expression as IdentifierExpression; + } else if (arg is NamedArgumentExpression) { + identifier = ((NamedArgumentExpression)arg).Expression as IdentifierExpression; + } else { + identifier = arg as IdentifierExpression; + } + if (identifier == null) + continue; + + if (context.Resolve (identifier) == null && GuessType (context, identifier) != null) + expressions.Insert (0, identifier); + } + } + return expressions; + } + + public bool IsValid (RefactoringContext context) + { + if (GetUnresolvedArguments (context).Count > 0) + return true; + var identifier = CreateField.GetIdentifier (context); + if (identifier == null) + return false; + if (context.GetNode () == null) + return false; + return context.Resolve (identifier) == null && GuessType (context, identifier) != null; + } + + public void Run (RefactoringContext context) + { + var stmt = context.GetNode (); + var unresolvedArguments = GetUnresolvedArguments (context); + if (unresolvedArguments.Count > 0) { + using (var script = context.StartScript ()) { + foreach (var id in unresolvedArguments) { + script.InsertBefore (stmt, GenerateLocalVariableDeclaration (context, id)); + } + } + return; + } + + using (var script = context.StartScript ()) { + script.InsertBefore (stmt, GenerateLocalVariableDeclaration (context, CreateField.GetIdentifier (context))); + } + } + + AstNode GenerateLocalVariableDeclaration (RefactoringContext context, IdentifierExpression identifier) + { + return new VariableDeclarationStatement () { + Type = GuessType (context, identifier), + Variables = { new VariableInitializer (identifier.Identifier) } + }; + } + + InvocationExpression GetInvocation (RefactoringContext context) + { + return context.GetNode (); + } + + AstType GuessType (RefactoringContext context, IdentifierExpression identifier) + { + var type = CreateField.GuessType (context, identifier); + if (type != null) + return type; + + if (identifier != null && (identifier.Parent is InvocationExpression || identifier.Parent.Parent is InvocationExpression)) { + var invocation = (identifier.Parent as InvocationExpression) ?? (identifier.Parent.Parent as InvocationExpression); + var result = context.Resolve (invocation).Type.GetDelegateInvokeMethod (); + if (result == null) + return null; + int i = 0; + foreach (var arg in invocation.Arguments) { + if (arg.Contains (identifier.StartLocation)) + break; + i++; + } + if (result.Parameters.Count < i) + return null; + return context.CreateShortType (result.Parameters[i].Type.Resolve (context.TypeResolveContext)); + } + return null; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs new file mode 100644 index 0000000000..5dfd3d3599 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs @@ -0,0 +1,66 @@ +// +// CreateProperty.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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.PatternMatching; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class CreateProperty : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var identifier = CreateField.GetIdentifier (context); + if (identifier == null) + return false; + return context.Resolve (identifier) == null && CreateField.GuessType (context, identifier) != null; + } + + public void Run (RefactoringContext context) + { + var identifier = GetIdentifier (context); + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create property", GeneratePropertyDeclaration (context, identifier), Script.InsertPosition.Before); + } + } + + AstNode GeneratePropertyDeclaration (RefactoringContext context, IdentifierExpression identifier) + { + return new PropertyDeclaration () { + ReturnType = CreateField.GuessType (context, identifier), + Name = identifier.Identifier, + Getter = new Accessor (), + Setter = new Accessor () + }; + } + + IdentifierExpression GetIdentifier (RefactoringContext context) + { + return context.GetNode (); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs new file mode 100644 index 0000000000..9a11da7b07 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs @@ -0,0 +1,59 @@ +// +// FlipOperatorArguments.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public class FlipOperatorArguments : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetBinaryOperatorExpression (context) != null; + } + + public void Run (RefactoringContext context) + { + var binop = GetBinaryOperatorExpression (context); + + using (var script = context.StartScript ()) { + script.Replace (binop.Left, binop.Right); + script.Replace (binop.Right, binop.Left); + } + } + + public static BinaryOperatorExpression GetBinaryOperatorExpression (RefactoringContext context) + { + var node = context.GetNode (); + + if (node == null || !node.OperatorToken.Contains (context.Location)) + return null; + var result = node as BinaryOperatorExpression; + if (result == null || (result.Operator != BinaryOperatorType.Equality && result.Operator != BinaryOperatorType.InEquality)) + return null; + return result; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs new file mode 100644 index 0000000000..5919da6564 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs @@ -0,0 +1,95 @@ +// +// GenerateGetter.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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.PatternMatching; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class GenerateGetter : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var initializer = GetVariableInitializer (context); + if (initializer == null || !initializer.NameToken.Contains (context.Location.Line, context.Location.Column)) + return false; + var type = initializer.Parent.Parent as TypeDeclaration; + if (type == null) + return false; + foreach (var member in type.Members) { + if (member is PropertyDeclaration && ContainsGetter ((PropertyDeclaration)member, initializer)) + return false; + } + return initializer.Parent is FieldDeclaration; + } + + public void Run (RefactoringContext context) + { + var initializer = GetVariableInitializer (context); + var field = initializer.Parent as FieldDeclaration; + + using (var script = context.StartScript ()) { + script.InsertWithCursor ("Create getter", GeneratePropertyDeclaration (context, field, initializer), Script.InsertPosition.After); + } + } + + static PropertyDeclaration GeneratePropertyDeclaration (RefactoringContext context, FieldDeclaration field, VariableInitializer initializer) + { + var mod = ICSharpCode.NRefactory.CSharp.Modifiers.Public; + if (field.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Static)) + mod |= ICSharpCode.NRefactory.CSharp.Modifiers.Static; + + return new PropertyDeclaration () { + Modifiers = mod, + Name = context.GetNameProposal (initializer.Name, false), + ReturnType = field.ReturnType.Clone (), + Getter = new Accessor () { + Body = new BlockStatement () { + new ReturnStatement (new IdentifierExpression (initializer.Name)) + } + } + }; + } + + bool ContainsGetter (PropertyDeclaration property, VariableInitializer initializer) + { + if (property.Getter.IsNull || property.Getter.Body.Statements.Count () != 1) + return false; + var ret = property.Getter.Body.Statements.Single () as ReturnStatement; + if (ret == null) + return false; + return ret.Expression.IsMatch (new IdentifierExpression (initializer.Name)) || + ret.Expression.IsMatch (new MemberReferenceExpression (new ThisReferenceExpression (), initializer.Name)); + } + + VariableInitializer GetVariableInitializer (RefactoringContext context) + { + return context.GetNode (); + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs new file mode 100644 index 0000000000..28ce57cf4b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs @@ -0,0 +1,88 @@ +// +// GenerateSwitchLabels.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class GenerateSwitchLabels : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var switchStatement = GetSwitchStatement (context); + if (switchStatement == null) + return false; + var result = context.Resolve (switchStatement.Expression); + if (result == null) + return false; + return result.Type.IsEnum (); + } + + public void Run (RefactoringContext context) + { + var switchStatement = GetSwitchStatement (context); + + var result = context.Resolve (switchStatement.Expression); + 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)) { + if (field.IsSynthetic || !field.IsConst) + continue; + newSwitch.SwitchSections.Add (new SwitchSection () { + CaseLabels = { + new CaseLabel (new MemberReferenceExpression (target.Clone (), field.Name)) + }, + Statements = { + new BreakStatement () + } + }); + } + + newSwitch.SwitchSections.Add (new SwitchSection () { + CaseLabels = { + new CaseLabel () + }, + Statements = { + new ThrowStatement (new ObjectCreateExpression (context.CreateShortType ("System", "ArgumentOutOfRangeException"))) + } + }); + + using (var script = context.StartScript ()) { + script.Replace (switchStatement, newSwitch); + } + } + + static SwitchStatement GetSwitchStatement (RefactoringContext context) + { + var switchStatment = context.GetNode (); + if (switchStatment != null && switchStatment.SwitchSections.Count == 0) + return switchStatment; + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs new file mode 100644 index 0000000000..503899bd90 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs @@ -0,0 +1,94 @@ +// +// InsertAnonymousMethodSignature.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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 System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class InsertAnonymousMethodSignature : IContextAction + { + public bool IsValid (RefactoringContext context) + { + IType type; + return GetAnonymousMethodExpression (context, out type) != null; + } + + public void Run (RefactoringContext context) + { + IType type; + var anonymousMethodExpression = GetAnonymousMethodExpression (context, out type); + + var delegateMethod = type.GetDelegateInvokeMethod (); + + var sb = new StringBuilder ("("); + for (int k = 0; k < delegateMethod.Parameters.Count; k++) { + if (k > 0) + sb.Append (", "); + + var paramType = delegateMethod.Parameters [k].Type; + + sb.Append (paramType.ToString ()); + sb.Append (" "); + sb.Append (delegateMethod.Parameters [k].Name); + } + sb.Append (")"); + + using (var script = context.StartScript ()) { + script.InsertText (context.GetOffset (anonymousMethodExpression.DelegateToken.EndLocation), sb.ToString ()); + } + } + + static AnonymousMethodExpression GetAnonymousMethodExpression (RefactoringContext context, out IType delegateType) + { + delegateType = null; + + var anonymousMethodExpression = context.GetNode (); + if (anonymousMethodExpression == null || !anonymousMethodExpression.DelegateToken.Contains (context.Location.Line, context.Location.Column) || anonymousMethodExpression.HasParameterList) + return null; + + IType resolvedType = null; + var parent = anonymousMethodExpression.Parent; + if (parent is AssignmentExpression) { + resolvedType = context.Resolve (((AssignmentExpression)parent).Left).Type; + } else if (parent is VariableDeclarationStatement) { + resolvedType = context.Resolve (((VariableDeclarationStatement)parent).Type).Type; + } else if (parent is InvocationExpression) { + // TODO: handle invocations + } + + if (resolvedType == null) + return null; + delegateType = resolvedType; + if (!delegateType.IsDelegate ()) + return null; + + return anonymousMethodExpression; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs new file mode 100644 index 0000000000..d1530b90de --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs @@ -0,0 +1,100 @@ +// +// IntroduceFormatItem.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Novell, Inc (http://www.novell.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.PatternMatching; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Introduce format item. Works on strings that contain selections. + /// "this is string" => string.Format ("this is {0} string", ) + /// + public class IntroduceFormatItem : IContextAction + { + readonly static MemberReferenceExpression PrototypeFormatReference = new MemberReferenceExpression (new TypeReferenceExpression (new PrimitiveType ("string")), "Format"); + + public bool IsValid (RefactoringContext context) + { + if (!context.IsSomethingSelected) + return false; + var pexpr = context.GetNode (); + if (pexpr == null || !(pexpr.Value is string)) + return false; + if (pexpr.LiteralValue.StartsWith ("@")) + return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 1) && + new AstLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; + return pexpr.StartLocation < context.Location && context.Location < pexpr.EndLocation; + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + var invocation = context.GetNode (); + if (invocation != null && invocation.Target.IsMatch (PrototypeFormatReference)) { + AddFormatCallToInvocation (context, pexpr, invocation); + return; + } + + var arg = CreateFormatArgument (context); + var newInvocation = new InvocationExpression (PrototypeFormatReference.Clone ()) { + Arguments = { CreateFormatString (context, pexpr, 0), arg } + }; + + using (var script = context.StartScript ()) { + script.Replace (pexpr, newInvocation); + script.Select (arg); + } + } + + void AddFormatCallToInvocation (RefactoringContext context, PrimitiveExpression pExpr, InvocationExpression invocation) + { + var newInvocation = (InvocationExpression)invocation.Clone (); + + newInvocation.Arguments.First ().ReplaceWith (CreateFormatString (context, pExpr, newInvocation.Arguments.Count () - 1)); + newInvocation.Arguments.Add (CreateFormatArgument (context)); + + using (var script = context.StartScript ()) { + script.Replace (invocation, newInvocation); + } + } + + static PrimitiveExpression CreateFormatArgument (RefactoringContext context) + { + return new PrimitiveExpression (context.SelectedText); + } + + static PrimitiveExpression CreateFormatString (RefactoringContext context, PrimitiveExpression pExpr, int argumentNumber) + { + var start = context.GetOffset (pExpr.StartLocation); + var end = context.GetOffset (pExpr.EndLocation); + + return new PrimitiveExpression ("", context.GetText (start, context.SelectionStart - start) + "{" + argumentNumber + "}" + context.GetText (context.SelectionEnd, end - context.SelectionEnd)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs new file mode 100644 index 0000000000..79a59c32ae --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs @@ -0,0 +1,61 @@ +// +// InvertIf.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public class InvertIf : IContextAction + { + public bool IsValid (RefactoringContext context) + { + var ifStatement = GetIfElseStatement (context); + return ifStatement != null && !ifStatement.TrueStatement.IsNull && !ifStatement.FalseStatement.IsNull; + } + + // TODO: Invert if without else + // ex. if (cond) DoSomething () == if (!cond) return; DoSomething () + // beware of loop contexts return should be continue then. + public void Run (RefactoringContext context) + { + var ifStatement = GetIfElseStatement (context); + + using (var script = context.StartScript ()) { + script.Replace (ifStatement.Condition, CSharpUtil.InvertCondition (ifStatement.Condition)); + script.Replace (ifStatement.TrueStatement, ifStatement.FalseStatement); + script.Replace (ifStatement.FalseStatement, ifStatement.TrueStatement); + script.FormatText (ctx => GetIfElseStatement (ctx)); + } + } + + static IfElseStatement GetIfElseStatement (RefactoringContext context) + { + var result = context.GetNode (); + if (result != null && result.IfToken.Contains (context.Location)) + return result; + return null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs new file mode 100644 index 0000000000..6655656bca --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs @@ -0,0 +1,123 @@ +// +// RemoveBackingStore.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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 System.Linq; +using ICSharpCode.NRefactory.CSharp.Resolver; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class RemoveBackingStore : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetBackingField (context) != null; + } + + public void Run (RefactoringContext context) + { + var property = context.GetNode (); + var field = GetBackingField (context); + + context.ReplaceReferences (field, property); + + // create new auto property + var newProperty = (PropertyDeclaration)property.Clone (); + newProperty.Getter.Body = BlockStatement.Null; + newProperty.Setter.Body = BlockStatement.Null; + + using (var script = context.StartScript ()) { + script.Remove (context.Unit.GetNodeAt (field.Region.BeginLine, field.Region.BeginColumn)); + script.Replace (property, newProperty); + } + + } + +// void ReplaceBackingFieldReferences (MDRefactoringContext context, IField backingStore, PropertyDeclaration property) +// { +// using (var monitor = IdeApp.Workbench.ProgressMonitors.GetSearchProgressMonitor (true, true)) { +// foreach (var memberRef in MonoDevelop.Ide.FindInFiles.ReferenceFinder.FindReferences (backingStore, monitor)) { +// if (property.Contains (memberRef.Line, memberRef.Column)) +// continue; +// if (backingStore.Location.Line == memberRef.Line && backingStore.Location.Column == memberRef.Column) +// continue; +// context.Do (new TextReplaceChange () { +// FileName = memberRef.FileName, +// Offset = memberRef.Position, +// RemovedChars = memberRef.Name.Length, +// InsertedText = property.Name +// }); +// } +// } +// } +// + static IField GetBackingField (RefactoringContext context) + { + var propertyDeclaration = context.GetNode (); + // automatic properties always need getter & setter + if (propertyDeclaration == null || propertyDeclaration.Getter.IsNull || propertyDeclaration.Setter.IsNull || propertyDeclaration.Getter.Body.IsNull || propertyDeclaration.Setter.Body.IsNull) + return null; + if (!context.HasCSharp3Support || propertyDeclaration.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Abstract) || ((TypeDeclaration)propertyDeclaration.Parent).ClassType == ICSharpCode.NRefactory.TypeSystem.ClassType.Interface) + return null; + var getterField = ScanGetter (context, propertyDeclaration); + if (getterField == null) + return null; + var setterField = ScanSetter (context, propertyDeclaration); + if (setterField == null) + return null; + if (getterField.Region != setterField.Region) + return null; + return getterField; + } + + internal static IField ScanGetter (RefactoringContext context, PropertyDeclaration propertyDeclaration) + { + if (propertyDeclaration.Getter.Body.Statements.Count != 1) + return null; + var returnStatement = propertyDeclaration.Getter.Body.Statements.First () as ReturnStatement; + + var result = context.Resolve (returnStatement.Expression); + if (result == null || !(result is MemberResolveResult)) + return null; + return ((MemberResolveResult)result).Member as IField; + } + + internal static IField ScanSetter (RefactoringContext context, PropertyDeclaration propertyDeclaration) + { + if (propertyDeclaration.Setter.Body.Statements.Count != 1) + return null; + var setAssignment = propertyDeclaration.Setter.Body.Statements.First () as ExpressionStatement; + var assignment = setAssignment != null ? setAssignment.Expression as AssignmentExpression : null; + if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign) + return null; + var result = context.Resolve (assignment.Left); + if (result == null || !(result is MemberResolveResult)) + return null; + return ((MemberResolveResult)result).Member as IField; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs new file mode 100644 index 0000000000..eed2e429f0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs @@ -0,0 +1,61 @@ +// +// RemoveBraces.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class RemoveBraces : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetBlockStatement (context) != null; + } + + public void Run (RefactoringContext context) + { + var block = GetBlockStatement (context); + + using (var script = context.StartScript ()) { + script.Remove (block.LBraceToken); + script.Remove (block.RBraceToken); + script.FormatText (ctx => ctx.Unit.GetNodeAt (block.Parent.StartLocation)); + } + } + + static BlockStatement GetBlockStatement (RefactoringContext context) + { + var block = context.GetNode (); + if (block == null || block.LBraceToken.IsNull || block.RBraceToken.IsNull) + return null; + if (block.Parent.Role == TypeDeclaration.MemberRole) + return null; + if (block.Statements.Count () != 1) + return null; + return block; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs new file mode 100644 index 0000000000..4e91b866b3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs @@ -0,0 +1,53 @@ +// +// ReplaceEmptyString.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public class ReplaceEmptyString : IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetEmptyString (context) != null; + } + + public void Run (RefactoringContext context) + { + var expr = GetEmptyString (context); + using (var script = context.StartScript ()) { + script.Replace (expr, new MemberReferenceExpression (new TypeReferenceExpression (new PrimitiveType ("string")), "Empty")); + } + } + + static PrimitiveExpression GetEmptyString (RefactoringContext context) + { + var node = context.GetNode (); + if (node == null || !(node.Value is string) || node.Value.ToString () != "") + return null; + return node; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs new file mode 100644 index 0000000000..4142280531 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs @@ -0,0 +1,74 @@ +// +// SplitDeclarationAndAssignment.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class SplitDeclarationAndAssignment : IContextAction + { + public bool IsValid (RefactoringContext context) + { + AstType type; + return GetVariableDeclarationStatement (context, out type) != null; + } + + public void Run (RefactoringContext context) + { + AstType type; + var varDecl = GetVariableDeclarationStatement (context, out type); + + var assign = new AssignmentExpression (new IdentifierExpression (varDecl.Variables.First ().Name), AssignmentOperatorType.Assign, varDecl.Variables.First ().Initializer.Clone ()); + + var newVarDecl = (VariableDeclarationStatement)varDecl.Clone (); + + if (newVarDecl.Type.IsMatch (new SimpleType ("var"))) + newVarDecl.Type = type; + + newVarDecl.Variables.First ().Initializer = Expression.Null; + + using (var script = context.StartScript ()) { + script.InsertBefore (varDecl, newVarDecl); + script.Replace (varDecl, varDecl.Parent is ForStatement ? (AstNode)assign : new ExpressionStatement (assign)); + } + } + + static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context, out AstType resolvedType) + { + var result = context.GetNode (); + if (result != null && result.Variables.Count == 1 && !result.Variables.First ().Initializer.IsNull && result.Variables.First ().NameToken.Contains (context.Location.Line, context.Location.Column)) { + resolvedType = context.Resolve (result.Variables.First ().Initializer).Type.ConvertToAstType (); + if (resolvedType == null) + return null; + return result; + } + resolvedType = null; + return null; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs new file mode 100644 index 0000000000..425f54ca32 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs @@ -0,0 +1,55 @@ +// +// SplitString.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public class SplitString: IContextAction + { + public bool IsValid (RefactoringContext context) + { + if (context.IsSomethingSelected) + return false; + var pexpr = context.GetNode (); + if (pexpr == null || !(pexpr.Value is string)) + return false; + if (pexpr.LiteralValue.StartsWith ("@")) + return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 2) && + new AstLocation (context.Location.Line, context.Location.Column + 2) < pexpr.EndLocation; + return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 1) && + new AstLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; + } + + public void Run (RefactoringContext context) + { + var pexpr = context.GetNode (); + int offset = context.GetOffset (context.Location); + using (var script = context.StartScript ()) { + script.InsertText (offset, pexpr.LiteralValue.StartsWith ("@") ? "\" + @\"" : "\" + \""); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs new file mode 100644 index 0000000000..b31bf78cb3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs @@ -0,0 +1,67 @@ +// +// UseExplicitType.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.TypeSystem; + + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class UseExplicitType: IContextAction + { + 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); + } + + 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)); + } + } + + static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context) + { + var result = context.GetNode (); + 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 (context.Resolve (result.Variables.First ().Initializer) == null) + return null; + return result; + } + return null; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs new file mode 100644 index 0000000000..8aa9c8b66e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs @@ -0,0 +1,56 @@ +// +// UseVarKeyword.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class UseVarKeyword: IContextAction + { + public bool IsValid (RefactoringContext context) + { + return GetVariableDeclarationStatement (context) != null; + } + + public void Run (RefactoringContext context) + { + var varDecl = GetVariableDeclarationStatement (context); + using (var script = context.StartScript ()) { + script.Replace (varDecl.Type, new SimpleType ("var")); + } + } + + static VariableDeclarationStatement GetVariableDeclarationStatement (RefactoringContext context) + { + var result = context.GetNode (); + 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"))) + return result; + return null; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs new file mode 100644 index 0000000000..11212a1c9a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs @@ -0,0 +1,44 @@ +// +// CreateLinkAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class CreateLinkAction : Action + { + public IEnumerable Linked { + get; + private set; + } + + public CreateLinkAction (IEnumerable linked) + { + this.Linked = linked; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs new file mode 100644 index 0000000000..8b7fde6615 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs @@ -0,0 +1,39 @@ +// +// FormatTextAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public abstract class FormatTextAction : Action + { + public Func Callback { get; private set; } + + public FormatTextAction (Func callback) + { + this.Callback = callback; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs new file mode 100644 index 0000000000..f801a1c9b9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs @@ -0,0 +1,75 @@ +// +// IChangeFactory.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// A factory that creates the changes. + /// + public interface IActionFactory + { + TextReplaceAction CreateTextReplaceAction (int offset, int removedChars, string insertedText); + NodeOutputAction CreateNodeOutputAction (int offset, int removedChars, NodeOutput output); + NodeSelectionAction CreateNodeSelectionAction (AstNode node); + FormatTextAction CreateFormatTextAction (Func callback); + CreateLinkAction CreateLinkAction (IEnumerable linkedNodes); + } + + public abstract class AbstractActionFactory : IActionFactory + { + #region IActionFactory implementation + public virtual TextReplaceAction CreateTextReplaceAction (int offset, int removedChars, string insertedText) + { + throw new NotImplementedException (); + } + + public virtual NodeOutputAction CreateNodeOutputAction (int offset, int removedChars, NodeOutput output) + { + throw new NotImplementedException (); + } + + public virtual NodeSelectionAction CreateNodeSelectionAction (AstNode node) + { + throw new NotImplementedException (); + } + + public virtual FormatTextAction CreateFormatTextAction (Func callback) + { + throw new NotImplementedException (); + } + + public virtual CreateLinkAction CreateLinkAction (IEnumerable linkedNodes) + { + throw new NotImplementedException (); + } + #endregion + + } + +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs new file mode 100644 index 0000000000..8c2b64ce23 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs @@ -0,0 +1,36 @@ +// +// ContextAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public interface IContextAction + { + bool IsValid (RefactoringContext context); + void Run (RefactoringContext context); + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs new file mode 100644 index 0000000000..47d5e7ba70 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs @@ -0,0 +1,136 @@ +// +// NodeOutputChange.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// This is the node that should be outputted at a position. + /// + public class NodeOutput + { + public readonly Dictionary NodeSegments = new Dictionary (); + + public string Text { + get; + set; + } + + public void Trim () + { + for (int i = 0; i < Text.Length; i++) { + char ch = Text [i]; + if (ch != ' ' && ch != '\t') { + if (i > 0) { + Text = Text.Substring (i); + foreach (var seg in NodeSegments.Values) { + seg.Offset -= i; + } + } + break; + } + } + } + + public class Segment : ISegment + { + public int Offset { + get; + set; + } + + public int Length { + get { + return EndOffset - Offset; + } + } + + public int EndOffset { + get; + set; + } + + public Segment (int offset) + { + this.Offset = offset; + } + } + } + + + /// + /// Outputs an Ast node at a specific offset. + /// + public abstract class NodeOutputAction : TextReplaceAction + { + public NodeOutput NodeOutput { + get; + private set; + } + + public override string InsertedText { + get { + return NodeOutput.Text; + } + set { + throw new NotSupportedException ("Changing text with this propery is not supported on NodeOutputChange."); + } + } + + public NodeOutputAction (int offset, int removedChars, NodeOutput output) : base (offset, removedChars) + { + if (output == null) + throw new ArgumentNullException ("output"); + this.NodeOutput = output; + } + } + + + /// + /// An (Offset,Length)-pair. + /// + public interface ISegment + { + /// + /// Gets the start offset of the segment. + /// + int Offset { get; } + + /// + /// Gets the length of the segment. + /// + /// Must not be negative. + int Length { get; } + + /// + /// Gets the end offset of the segment. + /// + /// EndOffset = Offset + Length; + int EndOffset { get; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs new file mode 100644 index 0000000000..b7df34b951 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs @@ -0,0 +1,40 @@ +// +// SelectionAction.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + public abstract class NodeSelectionAction : Action + { + public AstNode AstNode { get; private set; } + + public NodeSelectionAction (AstNode astNode) + { + this.AstNode = astNode; + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs new file mode 100644 index 0000000000..a73d973733 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs @@ -0,0 +1,141 @@ +// +// RefactoringContext.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp.Resolver; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class RefactoringContext : AbstractActionFactory + { + public CompilationUnit Unit { + get; + protected set; + } + + public virtual ITypeResolveContext TypeResolveContext { + get { + return null; + } + } + + public AstLocation Location { + get; + protected set; + } + + public abstract bool HasCSharp3Support { + get; + } + + public abstract CSharpFormattingOptions FormattingOptions { + get; + } + + public abstract AstType CreateShortType (IType fullType); + + public AstType CreateShortType (string ns, string typeName) + { + return CreateShortType (TypeResolveContext.GetTypeDefinition (ns, typeName, 0, StringComparer.Ordinal)); + } + + public virtual AstType CreateShortType (AstType fullType) + { + return CreateShortType (Resolve (fullType).Type.Resolve (TypeResolveContext)); + } + +// public abstract IType GetDefinition (AstType resolvedType); + + public abstract void ReplaceReferences (IMember member, MemberDeclaration replaceWidth); + + public AstNode GetNode () + { + return Unit.GetNodeAt (Location); + } + + public T GetNode () where T : AstNode + { + return Unit.GetNodeAt (Location); + } + + public abstract Script StartScript (); + + #region Text stuff + public abstract string EolMarker { get; } + public abstract bool IsSomethingSelected { get; } + public abstract string SelectedText { get; } + public abstract int SelectionStart { get; } + public abstract int SelectionEnd { get; } + public abstract int SelectionLength { get; } + public abstract int GetOffset (AstLocation location); + public int GetOffset (int line, int col) + { + return GetOffset (new AstLocation (line, col)); + } + public abstract AstLocation GetLocation (int offset); + public abstract string GetText (int offset, int length); + #endregion + + #region Resolving + public abstract ResolveResult Resolve (AstNode expression); + #endregion + + public string GetNameProposal (string name, bool camelCase = true) + { + string baseName = (camelCase ? char.ToLower (name [0]) : char.ToUpper (name [0])) + name.Substring (1); + + var type = GetNode (); + if (type == null) + return baseName; + + int number = -1; + string proposedName; + do { + proposedName = AppendNumberToName (baseName, number++); + } while (type.Members.Select (m => m.GetChildByRole (AstNode.Roles.Identifier)).Any (n => n.Name == proposedName)); + return proposedName; + } + + static string AppendNumberToName (string baseName, int number) + { + return baseName + (number > 0 ? (number + 1).ToString () : ""); + } + } + + public static class ExtensionMethods + { + #region ConvertTypes + public static ICSharpCode.NRefactory.CSharp.AstType ConvertToAstType (this IType type) + { + var builder = new TypeSystemAstBuilder (); + return builder.ConvertType (type); + } + #endregion + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs new file mode 100644 index 0000000000..db6be31899 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs @@ -0,0 +1,180 @@ +// +// Script.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public abstract class Script : IDisposable + { + public RefactoringContext Context { + get; + private set; + } + + protected readonly List changes = new List (); + + public IEnumerable Actions { + get { + return changes; + } + } + + public Script (RefactoringContext context) + { + if (context == null) + throw new ArgumentNullException ("context"); + this.Context = context; + } + + public void Queue (Action change) + { + changes.Add (change); + } + + public void InsertText (int offset, string text) + { + Queue (Context.CreateTextReplaceAction (offset, 0, text)); + } + + public void InsertBefore (AstNode node, AstNode insertNode) + { + var startOffset = Context.GetOffset (node.StartLocation.Line, 1); + var output = OutputNode (GetIndentLevelAt (startOffset), insertNode); + + if (!(insertNode is Expression || insertNode is AstType)) + output.Text += Context.EolMarker; + + Queue (Context.CreateNodeOutputAction (startOffset, 0, output)); + } + + public void AddTo (BlockStatement bodyStatement, AstNode insertNode) + { + var startOffset = Context.GetOffset (bodyStatement.LBraceToken.StartLocation) + 1; + var output = OutputNode (GetIndentLevelAt (startOffset), insertNode, true); + Queue (Context.CreateNodeOutputAction (startOffset, 0, output)); + } + + public void Link (params AstNode[] nodes) + { + Queue (Context.CreateLinkAction (nodes)); + } + + public void Link (IEnumerable nodes) + { + Queue (Context.CreateLinkAction (nodes)); + } + + public void Remove (AstNode node) + { + var startOffset = Context.GetOffset (node.StartLocation); + var endOffset = Context.GetOffset (node.EndLocation); + Remove (startOffset, endOffset - startOffset); + } + + void Remove (int offset, int length) + { + Queue (Context.CreateTextReplaceAction (offset, length, null)); + } + + void Replace (int offset, int length, string text) + { + Queue (Context.CreateTextReplaceAction (offset, length, text)); + } + + public void Replace (AstNode node, AstNode replaceWith) + { + var startOffset = Context.GetOffset (node.StartLocation); + var endOffset = Context.GetOffset (node.EndLocation); + int level = 0; + if (!(replaceWith is Expression) && !(replaceWith is AstType)) + level = GetIndentLevelAt (startOffset); + NodeOutput output = OutputNode (level, replaceWith); + output.Trim (); + Queue (Context.CreateNodeOutputAction (startOffset, endOffset - startOffset, output)); + } + + public void FormatText (Func callback) + { + Queue (Context.CreateFormatTextAction (callback)); + } + + public void Select (AstNode node) + { + Queue (Context.CreateNodeSelectionAction (node)); + } + + public enum InsertPosition { + Start, + Before, + After, + End + } + + public abstract void InsertWithCursor (string operation, AstNode node, InsertPosition defaultPosition); + + protected int GetIndentLevelAt (int offset) + { + var node = Context.Unit.GetNodeAt (Context.GetLocation (offset)); + int level = 0; + while (node != null) { + if (node is BlockStatement || node is TypeDeclaration || node is NamespaceDeclaration) + level++; + node = node.Parent; + } + return level; + } + + protected NodeOutput OutputNode (int indentLevel, AstNode node, bool startWithNewLine = false) + { + var result = new NodeOutput (); + var stringWriter = new System.IO.StringWriter (); + var formatter = new TextWriterOutputFormatter (stringWriter); + formatter.Indentation = indentLevel; + stringWriter.NewLine = Context.EolMarker; + if (startWithNewLine) + formatter.NewLine (); + var visitor = new OutputVisitor (formatter, Context.FormattingOptions); + visitor.OutputStarted += (sender, e) => { + result.NodeSegments [e.AstNode] = new NodeOutput.Segment (stringWriter.GetStringBuilder ().Length); + }; + visitor.OutputFinished += (sender, e) => { + result.NodeSegments [e.AstNode].EndOffset = stringWriter.GetStringBuilder ().Length; + }; + node.AcceptVisitor (visitor, null); + result.Text = stringWriter.ToString ().TrimEnd (); + if (node is FieldDeclaration) + result.Text += Context.EolMarker; + + return result; + } + + #region IDisposable implementation + public abstract void Dispose (); + #endregion + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs new file mode 100644 index 0000000000..63830b47a0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs @@ -0,0 +1,158 @@ +// +// StringBuilderOutputFormatter.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Text; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + public class StringBuilderOutputFormatter : IOutputFormatter + { + readonly StringBuilder sb = new StringBuilder (); + int indentation; + bool needsIndent = true; + + public int Length { + get { + WriteIndentation (); + return sb.Length; + } + } + + public int Indentation { + get { + return this.indentation; + } + set { + indentation = value; + } + } + + public string EolMarker { + get; + set; + } + + public override string ToString () + { + return sb.ToString (); + } + + public void WriteIdentifier (string ident) + { + WriteIndentation (); + sb.Append (ident); + } + + public void WriteKeyword (string keyword) + { + WriteIndentation (); + sb.Append (keyword); + } + + public void WriteToken (string token) + { + WriteIndentation (); + sb.Append (token); + } + + public void Space () + { + WriteIndentation (); + sb.Append (' '); + } + + public void OpenBrace (BraceStyle style) + { + WriteIndentation (); + sb.Append (' '); + sb.Append ('{'); + Indent (); + NewLine (); + } + + public void CloseBrace (BraceStyle style) + { + Unindent (); + WriteIndentation (); + sb.Append ('}'); + } + + void WriteIndentation () + { + if (needsIndent) { + needsIndent = false; + for (int i = 0; i < indentation; i++) { + sb.Append ('\t'); + } + } + } + + public void NewLine () + { + sb.Append (EolMarker); + needsIndent = true; + } + + public void Indent () + { + indentation++; + } + + public void Unindent () + { + indentation--; + } + + public void WriteComment (CommentType commentType, string content) + { + WriteIndentation (); + switch (commentType) { + case CommentType.SingleLine: + sb.Append ("//"); + sb.AppendLine (content); + break; + case CommentType.MultiLine: + sb.Append ("/*"); + sb.Append (content); + sb.Append ("*/"); + break; + case CommentType.Documentation: + sb.Append ("///"); + sb.AppendLine (content); + break; + } + } + + public virtual void StartNode (AstNode node) + { + } + + public virtual void EndNode (AstNode node) + { + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs new file mode 100644 index 0000000000..d2bc29f585 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs @@ -0,0 +1,134 @@ +// +// TextReplaceChange.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.Refactoring +{ + /// + /// This is the base action for changes in a text document. + /// + public abstract class TextReplaceAction : Action + { + /// + /// Gets or sets the offset. + /// + /// + /// The offset of the replace. + /// + public int Offset { + get; + set; + } + + int removedChars; + /// + /// Gets or sets the numer of chars to removed. + /// + /// + /// The numer of chars to remove. + /// + /// + /// Is thrown when an argument passed to a method is invalid because it is outside the allowable range of values as + /// specified by the method. + /// + public int RemovedChars { + get { + return removedChars; + } + set { + if (value < 0) + throw new ArgumentOutOfRangeException ("RemovedChars", "needs to be >= 0"); + removedChars = value; + } + } + + /// + /// Gets or sets the inserted text. + /// + /// + /// The text to insert. + /// + public virtual string InsertedText { + get; + set; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The offset of the replace. + /// + /// + /// The numer of chars to remove. + /// + /// + /// Is thrown when an argument passed to a method is invalid because it is outside the allowable range of values as + /// specified by the method. + /// + protected TextReplaceAction (int offset, int removedChars) + { + if (removedChars < 0) + throw new ArgumentOutOfRangeException ("removedChars", "removedChars needs to be >= 0"); + if (offset < 0) + throw new ArgumentOutOfRangeException ("offset", "offset needs to be >= 0"); + this.removedChars = removedChars; + this.Offset = offset; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The offset of the replace. + /// + /// + /// The numer of chars to remove. + /// + /// + /// The text to insert. + /// + /// + /// Is thrown when an argument passed to a method is invalid because it is outside the allowable range of values as + /// specified by the method. + public TextReplaceAction (int offset, int removedChars, string insertedText) : this (offset, removedChars) + { + this.InsertedText = insertedText; + } + + /// + /// Returns a that represents the current . + /// + /// + /// A that represents the current . + /// + public override string ToString () + { + return string.Format ("[TextReplaceAction: Offset={0}, RemovedChars={1}, InsertedText={2}]", Offset, RemovedChars, InsertedText == null ? "" : InsertedText.Replace ("\t", "\\t").Replace ("\n", "\\n")); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs new file mode 100644 index 0000000000..6bd0c98309 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -0,0 +1,218 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Converts from type system to the C# AST. + /// + public class TypeSystemAstBuilder + { + readonly CSharpResolver resolver; + + /// + /// Creates a new TypeSystemAstBuilder. + /// + /// + /// A resolver initialized for the position where the type will be inserted. + /// + public TypeSystemAstBuilder(CSharpResolver resolver = null) + { + this.resolver = resolver; + } + + public AstType ConvertType(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + TypeWithElementType typeWithElementType = type as TypeWithElementType; + if (typeWithElementType != null) { + if (typeWithElementType is PointerType) { + return ConvertType(typeWithElementType.ElementType).MakePointerType(); + } else if (typeWithElementType is ArrayType) { + return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); + } else { + // e.g. ByReferenceType; not supported as type in C# + return ConvertType(typeWithElementType.ElementType); + } + } + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) { + return ConvertType(pt.TypeArguments[0]).MakeNullableType(); + } + return ConvertTypeDefinition(pt.GetDefinition(), pt.TypeArguments); + } + ITypeDefinition typeDef = type as ITypeDefinition; + if (typeDef != null) { + if (typeDef.TypeParameterCount > 0) { + // Create an unbound type + IType[] typeArguments = new IType[typeDef.TypeParameterCount]; + for (int i = 0; i < typeArguments.Length; i++) { + typeArguments[i] = SharedTypes.UnknownType; + } + return ConvertTypeDefinition(typeDef, typeArguments); + } else { + return ConvertTypeDefinition(typeDef, EmptyList.Instance); + } + } + return new SimpleType(type.Name); + } + + AstType ConvertTypeDefinition(ITypeDefinition typeDef, IList typeArguments) + { + Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); + switch (ReflectionHelper.GetTypeCode(typeDef)) { + case TypeCode.Object: + return new PrimitiveType("object"); + case TypeCode.Boolean: + return new PrimitiveType("bool"); + case TypeCode.Char: + return new PrimitiveType("char"); + case TypeCode.SByte: + return new PrimitiveType("sbyte"); + case TypeCode.Byte: + return new PrimitiveType("byte"); + case TypeCode.Int16: + return new PrimitiveType("short"); + case TypeCode.UInt16: + return new PrimitiveType("ushort"); + case TypeCode.Int32: + return new PrimitiveType("int"); + case TypeCode.UInt32: + return new PrimitiveType("uint"); + case TypeCode.Int64: + return new PrimitiveType("long"); + case TypeCode.UInt64: + return new PrimitiveType("ulong"); + case TypeCode.Single: + return new PrimitiveType("float"); + case TypeCode.Double: + return new PrimitiveType("double"); + case TypeCode.Decimal: + return new PrimitiveType("decimal"); + case TypeCode.String: + return new PrimitiveType("string"); + } + // There is no type code for System.Void + if (typeDef != null && typeDef.Namespace == "System" && typeDef.Name == "Void" && typeDef.TypeParameterCount == 0) + return new PrimitiveType("void"); + if (resolver != null && TypeArgumentsTrivial(typeArguments, OuterTypeParameterCount(typeDef))) { + TypeResolveResult trr = resolver.ResolveSimpleName(typeDef.Name, typeArguments) as TypeResolveResult; + if (trr != null && !trr.IsError && trr.Type.GetDefinition() == typeDef) { + // We can use the short type name + SimpleType shortResult = new SimpleType(typeDef.Name); + AddTypeArguments(shortResult, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount); + return shortResult; + } + } + + MemberType result = new MemberType(); + if (typeDef.DeclaringTypeDefinition != null) { + // Handle nested types + result.Target = ConvertTypeDefinition(typeDef.DeclaringTypeDefinition, typeArguments); + } else { + // Handle top-level types + if (string.IsNullOrEmpty(typeDef.Namespace)) { + result.Target = new SimpleType("global"); + result.IsDoubleColon = true; + } else { + result.Target = ConvertNamespace(typeDef.Namespace); + } + } + result.MemberName = typeDef.Name; + AddTypeArguments(result, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount); + return result; + } + + /// + /// Gets the number of type parameters belonging to outer classes. + /// + int OuterTypeParameterCount(ITypeDefinition typeDef) + { + if (typeDef.DeclaringType != null) + return typeDef.DeclaringType.TypeParameterCount; + else + return 0; + } + + /// + /// Gets whether the first type arguments are trivial, + /// that is, they point to a type parameter with the same index. + /// + bool TypeArgumentsTrivial(IList typeArguments, int num) + { + for (int i = 0; i < num; i++) { + ITypeParameter tp = typeArguments[i] as ITypeParameter; + if (!(tp != null && tp.OwnerType == EntityType.TypeDefinition && tp.Index == i)) + return false; + } + return true; + } + + /// + /// Adds type arguments to the result type. + /// + /// The result AST node (a SimpleType or MemberType) + /// The list of type arguments + /// Index of first type argument to add + /// Index after last type argument to add + void AddTypeArguments(AstType result, IList typeArguments, int startIndex, int endIndex) + { + for (int i = startIndex; i < endIndex; i++) { + result.AddChild(ConvertType(typeArguments[i]), AstType.Roles.TypeArgument); + } + } + + AstType ConvertNamespace(string ns) + { + if (resolver != null) { + // Look if there's an alias to the target namespace + for (UsingScope usingScope = resolver.UsingScope; 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); + if (nrr != null && nrr.NamespaceName == ns) + return new SimpleType(pair.Key); + } + } + } + + int pos = ns.LastIndexOf('.'); + if (pos < 0) { + if (IsValidNamespace(ns)) { + return new SimpleType(ns); + } else { + return new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = ns + }; + } + } else { + string parentNamespace = ns.Substring(0, pos); + string localNamespace = ns.Substring(pos + 1); + return new MemberType { + Target = ConvertNamespace(parentNamespace), + MemberName = localNamespace + }; + } + } + + bool IsValidNamespace(string firstNamespacePart) + { + if (resolver == null) + return true; // just assume namespaces are valid if we don't have a resolver + NamespaceResolveResult nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList.Instance) as NamespaceResolveResult; + return nrr != null && !nrr.IsError && nrr.NamespaceName == firstNamespacePart; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs new file mode 100644 index 0000000000..49acbf90d5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Looks up an alias (identifier in front of :: operator). + /// + /// + /// The member lookup performed by the :: operator is handled + /// by . + /// + public class AliasNamespaceReference : ITypeOrNamespaceReference + { + readonly UsingScope parentUsingScope; + readonly string identifier; + + public AliasNamespaceReference(string identifier, UsingScope parentUsingScope) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.identifier = identifier; + this.parentUsingScope = parentUsingScope; + } + + public ResolveResult DoResolve(ITypeResolveContext context) + { + CSharpResolver r = new CSharpResolver(context); + r.UsingScope = parentUsingScope; + return r.ResolveAlias(identifier); + } + + public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) + { + return DoResolve(context) as NamespaceResolveResult; + } + + public IType Resolve(ITypeResolveContext context) + { + return SharedTypes.UnknownType; + } + + public override string ToString() + { + return identifier + "::"; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs new file mode 100644 index 0000000000..3c17dd65f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents an ambiguous type resolve result. + /// + public class AmbiguousTypeResolveResult : TypeResolveResult + { + public AmbiguousTypeResolveResult(IType type) : base(type) + { + } + + public override bool IsError { + get { return true; } + } + } + + public class AmbiguousMemberResultResult : MemberResolveResult + { + public AmbiguousMemberResultResult(IMember member, IType returnType) : base(member, returnType) + { + } + + public override bool IsError { + get { return true; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs new file mode 100644 index 0000000000..2056fe4c35 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs @@ -0,0 +1,32 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents the resolve result of an 'ref x' or 'out x' expression. + /// + public class ByReferenceResolveResult : ResolveResult + { + public bool IsOut { get; private set; } + public bool IsRef { get { return !IsOut;} } + + public ByReferenceResolveResult(IType elementType, bool isOut) + : base(new ByReferenceType(elementType)) + { + this.IsOut = isOut; + } + + public IType ElementType { + get { return ((ByReferenceType)this.Type).ElementType; } + } + + public override string ToString() + { + return string.Format("[{0} {1} {2}]", GetType().Name, IsOut ? "out" : "ref", ElementType); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs new file mode 100644 index 0000000000..f2f5dba1f7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs @@ -0,0 +1,144 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public sealed class CSharpAttribute : Immutable, IAttribute + { + ITypeReference attributeType; + DomRegion region; + IList positionalArguments; + IList> namedCtorArguments; + IList> namedArguments; + + public CSharpAttribute(ITypeReference attributeType, DomRegion region, + IList positionalArguments, + IList> namedCtorArguments, + IList> namedArguments) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + this.attributeType = attributeType; + this.region = region; + this.positionalArguments = positionalArguments; + this.namedCtorArguments = namedCtorArguments; + this.namedArguments = namedArguments; + } + + public DomRegion Region { + get { return region; } + } + + public ITypeReference AttributeType { + get { return attributeType; } + } + + public IMethod ResolveConstructor(ITypeResolveContext context) + { + IType type = attributeType.Resolve(context); + throw new NotImplementedException(); + } + + public IList GetPositionalArguments(ITypeResolveContext context) + { + if (namedCtorArguments == null || namedCtorArguments.Count == 0) { + // no namedCtorArguments: just return the positionalArguments + if (positionalArguments != null) + return new ReadOnlyCollection(positionalArguments); + else + return EmptyList.Instance; + } + // we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments + List result = new List(this.positionalArguments); + IMethod method = ResolveConstructor(context); + if (method != null) { + for (int i = result.Count; i < method.Parameters.Count; i++) { + IParameter p = method.Parameters[i]; + bool found = false; + foreach (var pair in namedCtorArguments) { + if (pair.Key == p.Name) { + result.Add(pair.Value); + found = true; + } + } + if (!found) { + // add the parameter's default value: + result.Add(p.DefaultValue ?? new SimpleConstantValue(p.Type, CSharpResolver.GetDefaultValue(p.Type.Resolve(context)))); + } + } + } + return result.AsReadOnly(); + } + + public IList> GetNamedArguments(ITypeResolveContext context) + { + if (namedArguments != null) + return new ReadOnlyCollection>(namedArguments); + else + return EmptyList>.Instance; + } + } + + /// + /// Type reference used within an attribute. + /// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists. + /// + public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning + { + ITypeReference withoutSuffix, withSuffix; + + public AttributeTypeReference(ITypeReference withoutSuffix, ITypeReference withSuffix) + { + if (withoutSuffix == null) + throw new ArgumentNullException("withoutSuffix"); + if (withSuffix == null) + throw new ArgumentNullException("withSuffix"); + this.withoutSuffix = withoutSuffix; + this.withSuffix = withSuffix; + } + + public IType Resolve(ITypeResolveContext context) + { + // If both types exist, C# considers that to be an ambiguity, but we are less strict. + IType type = withoutSuffix.Resolve(context); + var attrType = context.GetTypeDefinition (typeof(System.Attribute)); + if (attrType == null) + return SharedTypes.UnknownType; + + if (type == SharedTypes.UnknownType || !(type.GetDefinition () != null && type.GetDefinition ().IsDerivedFrom (attrType, context))) + type = withSuffix.Resolve(context); + + return type; + } + + public override string ToString() + { + return withoutSuffix.ToString() + "[Attribute]"; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + withoutSuffix = provider.Intern(withoutSuffix); + withSuffix = provider.Intern(withSuffix); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return withoutSuffix.GetHashCode() + 715613 * withSuffix.GetHashCode(); + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + AttributeTypeReference atr = other as AttributeTypeReference; + return atr != null && this.withoutSuffix == atr.withoutSuffix && this.withSuffix == atr.withSuffix; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs new file mode 100644 index 0000000000..31dbf0f869 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -0,0 +1,2185 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Contains the main resolver logic. + /// + public class CSharpResolver + { + static readonly ResolveResult ErrorResult = new ErrorResolveResult(SharedTypes.UnknownType); + static readonly ResolveResult DynamicResult = new ResolveResult(SharedTypes.Dynamic); + static readonly ResolveResult NullResult = new ResolveResult(SharedTypes.Null); + + readonly ITypeResolveContext context; + internal readonly CancellationToken cancellationToken; + + #region Constructor + public CSharpResolver(ITypeResolveContext context) : this (context, CancellationToken.None) + { + } + + public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + this.cancellationToken = cancellationToken; + } + #endregion + + #region Properties + /// + /// Gets the type resolve context used by the resolver. + /// + public ITypeResolveContext Context { + get { return context; } + } + + /// + /// Gets/Sets whether the current context is checked. + /// + public bool CheckForOverflow { get; set; } + + /// + /// Gets/Sets the current member definition that is used to look up identifiers as parameters + /// or type parameters. + /// + /// Don't forget to also set CurrentTypeDefinition when setting CurrentMember; + /// setting one of the properties does not automatically set the other. + public IMember CurrentMember { get; set; } + + /// + /// Gets/Sets the current type definition that is used to look up identifiers as simple members. + /// + public ITypeDefinition CurrentTypeDefinition { get; set; } + + /// + /// Gets/Sets the current using scope that is used to look up identifiers as class names. + /// + public UsingScope UsingScope { get; set; } + #endregion + + #region Local Variable Management + sealed class LocalVariable : IVariable + { + // We store the local variable in a linked list + // and provide a stack-like API. + // The beginning of a stack frame is marked by a dummy local variable + // with type==null and name==null. + + // This data structure is used to allow efficient cloning of the resolver with its local variable context. + + internal readonly LocalVariable prev; + internal readonly ITypeReference type; + internal readonly DomRegion region; + internal readonly string name; + internal readonly IConstantValue constantValue; + + public LocalVariable(LocalVariable prev, ITypeReference type, DomRegion region, string name, IConstantValue constantValue) + { + this.prev = prev; + this.region = region; + this.type = type; + this.name = name; + this.constantValue = constantValue; + } + + public string Name { + get { return name; } + } + + public DomRegion DeclarationRegion { + get { return region; } + } + + public ITypeReference Type { + get { return type; } + } + public bool IsConst { + get { return constantValue != null; } + } + public IConstantValue ConstantValue { + get { return constantValue; } + } + + public override string ToString() + { + if (name == null) + return ""; + else + return name + ":" + type; + } + } + + LocalVariable localVariableStack; + + /// + /// Opens a new scope for local variables. + /// + public void PushBlock() + { + localVariableStack = new LocalVariable(localVariableStack, null, DomRegion.Empty, null, null); + } + + /// + /// Closes the current scope for local variables; removing all variables in that scope. + /// + public void PopBlock() + { + LocalVariable removedVar; + do { + removedVar = localVariableStack; + if (removedVar == null) + throw new InvalidOperationException("Cannot execute PopBlock() without corresponding PushBlock()"); + localVariableStack = removedVar.prev; + } while (removedVar.name != null); + } + + /// + /// Adds a new variable to the current block. + /// + public IVariable AddVariable(ITypeReference type, DomRegion declarationRegion, string name, IConstantValue constantValue = null) + { + if (type == null) + throw new ArgumentNullException("type"); + if (name == null) + throw new ArgumentNullException("name"); + return localVariableStack = new LocalVariable(localVariableStack, type, declarationRegion, name, constantValue); + } + + /// + /// Gets all currently visible local variables. + /// + public IEnumerable LocalVariables { + get { + for (LocalVariable v = localVariableStack; v != null; v = v.prev) { + if (v.name != null) + yield return v; + } + } + } + #endregion + + #region Clone + /// + /// Creates a copy of this CSharp resolver. + /// + public CSharpResolver Clone() + { + return (CSharpResolver)MemberwiseClone(); + } + #endregion + + #region class OperatorMethod + static OperatorMethod[] Lift(params OperatorMethod[] methods) + { + List result = new List(methods); + foreach (OperatorMethod method in methods) { + OperatorMethod lifted = method.Lift(); + if (lifted != null) + result.Add(lifted); + } + return result.ToArray(); + } + + class OperatorMethod : Immutable, IParameterizedMember + { + static readonly IParameter[] normalParameters = new IParameter[(int)(TypeCode.String + 1 - TypeCode.Object)]; + static readonly IParameter[] nullableParameters = new IParameter[(int)(TypeCode.Decimal + 1 - TypeCode.Boolean)]; + + static OperatorMethod() + { + for (TypeCode i = TypeCode.Object; i <= TypeCode.String; i++) { + normalParameters[i - TypeCode.Object] = new DefaultParameter(i.ToTypeReference(), string.Empty); + } + for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { + nullableParameters[i - TypeCode.Boolean] = new DefaultParameter(NullableType.Create(i.ToTypeReference()), string.Empty); + } + } + + protected static IParameter MakeParameter(TypeCode code) + { + return normalParameters[code - TypeCode.Object]; + } + + protected static IParameter MakeNullableParameter(IParameter normalParameter) + { + for (TypeCode i = TypeCode.Boolean; i <= TypeCode.Decimal; i++) { + if (normalParameter == normalParameters[i - TypeCode.Object]) + return nullableParameters[i - TypeCode.Boolean]; + } + throw new ArgumentException(); + } + + readonly IList parameters = new List(); + + public IList Parameters { + get { return parameters; } + } + + public ITypeReference ReturnType { + get; set; + } + + public virtual OperatorMethod Lift() + { + return null; + } + + ITypeDefinition IEntity.DeclaringTypeDefinition { + get { throw new NotSupportedException(); } + } + + IType IMember.DeclaringType { + get { return SharedTypes.UnknownType; } + } + + IMember IMember.MemberDefinition { + get { return null; } + } + + IList IMember.InterfaceImplementations { + get { return EmptyList.Instance; } + } + + bool IMember.IsVirtual { + get { return false; } + } + + bool IMember.IsOverride { + get { return false; } + } + + bool IMember.IsOverridable { + get { return false; } + } + + EntityType IEntity.EntityType { + get { return EntityType.Operator; } + } + + DomRegion IEntity.Region { + get { return DomRegion.Empty; } + } + + DomRegion IEntity.BodyRegion { + get { return DomRegion.Empty; } + } + + IList IEntity.Attributes { + get { return EmptyList.Instance; } + } + + string IEntity.Documentation { + get { return null; } + } + + Accessibility IEntity.Accessibility { + get { return Accessibility.Public; } + } + + bool IEntity.IsStatic { + get { return true; } + } + + bool IEntity.IsAbstract { + get { return false; } + } + + bool IEntity.IsSealed { + get { return false; } + } + + bool IEntity.IsShadowing { + get { return false; } + } + + bool IEntity.IsSynthetic { + get { return true; } + } + + bool IEntity.IsPrivate { + get { return false; } + } + + bool IEntity.IsPublic { + get { return true; } + } + + bool IEntity.IsProtected { + get { return false; } + } + + bool IEntity.IsInternal { + get { return false; } + } + + bool IEntity.IsProtectedOrInternal { + get { return false; } + } + + bool IEntity.IsProtectedAndInternal { + get { return false; } + } + + IProjectContent IEntity.ProjectContent { + get { throw new NotSupportedException(); } + } + + string INamedElement.FullName { + get { return "operator"; } + } + + string INamedElement.Name { + get { return "operator"; } + } + + string INamedElement.Namespace { + get { return string.Empty; } + } + + string INamedElement.ReflectionName { + get { return "operator"; } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append(ReturnType + " operator("); + for (int i = 0; i < parameters.Count; i++) { + if (i > 0) + b.Append(", "); + b.Append(parameters[i].Type); + } + b.Append(')'); + return b.ToString(); + } + } + #endregion + + #region ResolveUnaryOperator + #region ResolveUnaryOperator method + public ResolveResult ResolveUnaryOperator(UnaryOperatorType op, ResolveResult expression) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (expression.Type == SharedTypes.Dynamic) + return DynamicResult; + + // C# 4.0 spec: §7.3.3 Unary operator overload resolution + string overloadableOperatorName = GetOverloadableOperatorName(op); + if (overloadableOperatorName == null) { + switch (op) { + case UnaryOperatorType.Dereference: + PointerType p = expression.Type as PointerType; + if (p != null) + return new ResolveResult(p.ElementType); + else + return ErrorResult; + case UnaryOperatorType.AddressOf: + return new ResolveResult(new PointerType(expression.Type)); + default: + throw new ArgumentException("Invalid value for UnaryOperatorType", "op"); + } + } + // If the type is nullable, get the underlying type: + IType type = NullableType.GetUnderlyingType(expression.Type); + bool isNullable = NullableType.IsNullable(expression.Type); + + // the operator is overloadable: + // TODO: implicit support for user operators + //var candidateSet = GetUnaryOperatorCandidates(); + + expression = UnaryNumericPromotion(op, ref type, isNullable, expression); + OperatorMethod[] methodGroup; + switch (op) { + case UnaryOperatorType.Increment: + case UnaryOperatorType.Decrement: + case UnaryOperatorType.PostIncrement: + case UnaryOperatorType.PostDecrement: + // C# 4.0 spec: §7.6.9 Postfix increment and decrement operators + // C# 4.0 spec: §7.7.5 Prefix increment and decrement operators + TypeCode code = ReflectionHelper.GetTypeCode(type); + if ((code >= TypeCode.SByte && code <= TypeCode.Decimal) || type.IsEnum() || type is PointerType) + return new ResolveResult(expression.Type); + else + return new ErrorResolveResult(expression.Type); + case UnaryOperatorType.Plus: + methodGroup = unaryPlusOperators; + break; + case UnaryOperatorType.Minus: + methodGroup = CheckForOverflow ? checkedUnaryMinusOperators : uncheckedUnaryMinusOperators; + break; + case UnaryOperatorType.Not: + methodGroup = logicalNegationOperator; + break; + case UnaryOperatorType.BitNot: + if (type.IsEnum()) { + if (expression.IsCompileTimeConstant && !isNullable) { + // evaluate as (E)(~(U)x); + var U = expression.ConstantValue.GetType().ToTypeReference().Resolve(context); + var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue); + return CheckErrorAndResolveCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum)); + } else { + return new ResolveResult(expression.Type); + } + } else { + methodGroup = bitwiseComplementOperators; + break; + } + default: + throw new InvalidOperationException(); + } + OverloadResolution r = new OverloadResolution(context, new[] { expression }); + foreach (var candidate in methodGroup) { + r.AddCandidate(candidate); + } + UnaryOperatorMethod m = (UnaryOperatorMethod)r.BestCandidate; + IType resultType = m.ReturnType.Resolve(context); + if (r.BestCandidateErrors != OverloadResolutionErrors.None) { + return new ErrorResolveResult(resultType); + } else if (expression.IsCompileTimeConstant && !isNullable) { + object val; + try { + val = m.Invoke(this, expression.ConstantValue); + } catch (ArithmeticException) { + return new ErrorResolveResult(resultType); + } + return new ConstantResolveResult(resultType, val); + } else { + return new ResolveResult(resultType); + } + } + #endregion + + #region UnaryNumericPromotion + ResolveResult UnaryNumericPromotion(UnaryOperatorType op, ref IType type, bool isNullable, ResolveResult expression) + { + // C# 4.0 spec: §7.3.6.1 + TypeCode code = ReflectionHelper.GetTypeCode(type); + if (isNullable && type == SharedTypes.Null) + code = TypeCode.SByte; // cause promotion of null to int32 + switch (op) { + case UnaryOperatorType.Minus: + if (code == TypeCode.UInt32) { + IType targetType = KnownTypeReference.Int64.Resolve(context); + type = targetType; + if (isNullable) targetType = NullableType.Create(targetType, context); + return ResolveCast(targetType, expression); + } + goto case UnaryOperatorType.Plus; + case UnaryOperatorType.Plus: + case UnaryOperatorType.BitNot: + if (code >= TypeCode.Char && code <= TypeCode.UInt16) { + IType targetType = KnownTypeReference.Int32.Resolve(context); + type = targetType; + if (isNullable) targetType = NullableType.Create(targetType, context); + return ResolveCast(targetType, expression); + } + break; + } + return expression; + } + #endregion + + #region GetOverloadableOperatorName + static string GetOverloadableOperatorName(UnaryOperatorType op) + { + switch (op) { + case UnaryOperatorType.Not: + return "op_LogicalNot"; + case UnaryOperatorType.BitNot: + return "op_OnesComplement"; + case UnaryOperatorType.Minus: + return "op_UnaryNegation"; + case UnaryOperatorType.Plus: + return "op_UnaryPlus"; + case UnaryOperatorType.Increment: + case UnaryOperatorType.PostIncrement: + return "op_Increment"; + case UnaryOperatorType.Decrement: + case UnaryOperatorType.PostDecrement: + return "op_Decrement"; + default: + return null; + } + } + #endregion + + #region Unary operator class definitions + abstract class UnaryOperatorMethod : OperatorMethod + { + public abstract object Invoke(CSharpResolver resolver, object input); + } + + sealed class LambdaUnaryOperatorMethod : UnaryOperatorMethod + { + readonly Func func; + + public LambdaUnaryOperatorMethod(Func func) + { + TypeCode t = Type.GetTypeCode(typeof(T)); + this.ReturnType = t.ToTypeReference(); + this.Parameters.Add(MakeParameter(t)); + this.func = func; + } + + public override object Invoke(CSharpResolver resolver, object input) + { + return func((T)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T)), input)); + } + + public override OperatorMethod Lift() + { + return new LiftedUnaryOperatorMethod(this); + } + } + + sealed class LiftedUnaryOperatorMethod : UnaryOperatorMethod, OverloadResolution.ILiftedOperator + { + UnaryOperatorMethod baseMethod; + + public LiftedUnaryOperatorMethod(UnaryOperatorMethod baseMethod) + { + this.baseMethod = baseMethod; + this.ReturnType = NullableType.Create(baseMethod.ReturnType); + this.Parameters.Add(MakeNullableParameter(baseMethod.Parameters[0])); + } + + public override object Invoke(CSharpResolver resolver, object input) + { + if (input == null) + return null; + else + return baseMethod.Invoke(resolver, input); + } + + public IList NonLiftedParameters { + get { return baseMethod.Parameters; } + } + } + #endregion + + #region Unary operator definitions + // C# 4.0 spec: §7.7.1 Unary plus operator + static readonly OperatorMethod[] unaryPlusOperators = Lift( + new LambdaUnaryOperatorMethod(i => +i), + new LambdaUnaryOperatorMethod(i => +i), + new LambdaUnaryOperatorMethod(i => +i), + new LambdaUnaryOperatorMethod(i => +i), + new LambdaUnaryOperatorMethod(i => +i), + new LambdaUnaryOperatorMethod(i => +i), + new LambdaUnaryOperatorMethod(i => +i) + ); + + // C# 4.0 spec: §7.7.2 Unary minus operator + static readonly OperatorMethod[] uncheckedUnaryMinusOperators = Lift( + new LambdaUnaryOperatorMethod(i => unchecked(-i)), + new LambdaUnaryOperatorMethod(i => unchecked(-i)), + new LambdaUnaryOperatorMethod(i => -i), + new LambdaUnaryOperatorMethod(i => -i), + new LambdaUnaryOperatorMethod(i => -i) + ); + static readonly OperatorMethod[] checkedUnaryMinusOperators = Lift( + new LambdaUnaryOperatorMethod(i => checked(-i)), + new LambdaUnaryOperatorMethod(i => checked(-i)), + new LambdaUnaryOperatorMethod(i => -i), + new LambdaUnaryOperatorMethod(i => -i), + new LambdaUnaryOperatorMethod(i => -i) + ); + + // C# 4.0 spec: §7.7.3 Logical negation operator + static readonly OperatorMethod[] logicalNegationOperator = Lift(new LambdaUnaryOperatorMethod(b => !b)); + + // C# 4.0 spec: §7.7.4 Bitwise complement operator + static readonly OperatorMethod[] bitwiseComplementOperators = Lift( + new LambdaUnaryOperatorMethod(i => ~i), + new LambdaUnaryOperatorMethod(i => ~i), + new LambdaUnaryOperatorMethod(i => ~i), + new LambdaUnaryOperatorMethod(i => ~i) + ); + #endregion + + object GetUserUnaryOperatorCandidates() + { + // C# 4.0 spec: §7.3.5 Candidate user-defined operators + // TODO: implement user-defined operators + throw new NotImplementedException(); + } + #endregion + + #region ResolveBinaryOperator + #region ResolveBinaryOperator method + public ResolveResult ResolveBinaryOperator(BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (lhs.Type == SharedTypes.Dynamic || rhs.Type == SharedTypes.Dynamic) + return DynamicResult; + + // C# 4.0 spec: §7.3.4 Binary operator overload resolution + string overloadableOperatorName = GetOverloadableOperatorName(op); + if (overloadableOperatorName == null) { + + // Handle logical and/or exactly as bitwise and/or: + // - If the user overloads a bitwise operator, that implicitly creates the corresponding logical operator. + // - If both inputs are compile-time constants, it doesn't matter that we don't short-circuit. + // - If inputs aren't compile-time constants, we don't evaluate anything, so again it doesn't matter that we don't short-circuit + if (op == BinaryOperatorType.ConditionalAnd) { + overloadableOperatorName = GetOverloadableOperatorName(BinaryOperatorType.BitwiseAnd); + } else if (op == BinaryOperatorType.ConditionalOr) { + overloadableOperatorName = GetOverloadableOperatorName(BinaryOperatorType.BitwiseOr); + } else if (op == BinaryOperatorType.NullCoalescing) { + // null coalescing operator is not overloadable and needs to be handled separately + return ResolveNullCoalescingOperator(lhs, rhs); + } else { + throw new ArgumentException("Invalid value for BinaryOperatorType", "op"); + } + } + + // If the type is nullable, get the underlying type: + bool isNullable = NullableType.IsNullable(lhs.Type) || NullableType.IsNullable(rhs.Type); + IType lhsType = NullableType.GetUnderlyingType(lhs.Type); + IType rhsType = NullableType.GetUnderlyingType(rhs.Type); + + // TODO: find user-defined operators + + if (lhsType == SharedTypes.Null && rhsType.IsReferenceType(context) == false + || lhsType.IsReferenceType(context) == false && rhsType == SharedTypes.Null) + { + isNullable = true; + } + if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) { + // special case: the shift operators allow "var x = null << null", producing int?. + if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null) + isNullable = true; + // for shift operators, do unary promotion independently on both arguments + lhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref lhsType, isNullable, lhs); + rhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref rhsType, isNullable, rhs); + } else { + bool allowNullableConstants = op == BinaryOperatorType.Equality || op == BinaryOperatorType.InEquality; + if (!BinaryNumericPromotion(isNullable, ref lhs, ref rhs, allowNullableConstants)) + return new ErrorResolveResult(lhs.Type); + } + // re-read underlying types after numeric promotion + lhsType = NullableType.GetUnderlyingType(lhs.Type); + rhsType = NullableType.GetUnderlyingType(rhs.Type); + + IEnumerable methodGroup; + switch (op) { + case BinaryOperatorType.Multiply: + methodGroup = CheckForOverflow ? checkedMultiplicationOperators : uncheckedMultiplicationOperators; + break; + case BinaryOperatorType.Divide: + methodGroup = CheckForOverflow ? checkedDivisionOperators : uncheckedDivisionOperators; + break; + case BinaryOperatorType.Modulus: + methodGroup = CheckForOverflow ? checkedRemainderOperators : uncheckedRemainderOperators; + break; + case BinaryOperatorType.Add: + methodGroup = CheckForOverflow ? checkedAdditionOperators : uncheckedAdditionOperators; + { + Conversions conversions = new Conversions(context); + if (lhsType.IsEnum() && conversions.ImplicitConversion(rhsType, lhsType.GetEnumUnderlyingType(context))) { + // E operator +(E x, U y); + return HandleEnumAdditionOrSubtraction(isNullable, lhsType, op, lhs, rhs); + } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhsType, rhsType.GetEnumUnderlyingType(context))) { + // E operator +(U x, E y); + return ResolveBinaryOperator(op, rhs, lhs); // swap arguments + } + if (lhsType.IsDelegate() && conversions.ImplicitConversion(rhsType, lhsType)) { + return new ResolveResult(lhsType); + } else if (rhsType.IsDelegate() && conversions.ImplicitConversion(lhsType, rhsType)) { + return new ResolveResult(rhsType); + } + if (lhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(rhsType))) { + return new ResolveResult(lhsType); + } else if (rhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(lhsType))) { + return new ResolveResult(rhsType); + } + if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null) + return new ErrorResolveResult(SharedTypes.Null); + } + break; + case BinaryOperatorType.Subtract: + methodGroup = CheckForOverflow ? checkedSubtractionOperators : uncheckedSubtractionOperators; + { + Conversions conversions = new Conversions(context); + if (lhsType.IsEnum() && conversions.ImplicitConversion(rhsType, lhsType.GetEnumUnderlyingType(context))) { + // E operator –(E x, U y); + return HandleEnumAdditionOrSubtraction(isNullable, lhsType, op, lhs, rhs); + } else if (lhsType.IsEnum() && conversions.ImplicitConversion(rhs, lhs.Type)) { + // U operator –(E x, E y); + return HandleEnumSubtraction(isNullable, lhsType, lhs, rhs); + } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhs, rhs.Type)) { + // U operator –(E x, E y); + return HandleEnumSubtraction(isNullable, lhsType, lhs, rhs); + } + if (lhsType.IsDelegate() && conversions.ImplicitConversion(rhsType, lhsType)) { + return new ResolveResult(lhsType); + } else if (rhsType.IsDelegate() && conversions.ImplicitConversion(lhsType, rhsType)) { + return new ResolveResult(rhsType); + } + if (lhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(rhsType))) { + return new ResolveResult(lhsType); + } else if (lhsType is PointerType && lhsType.Equals(rhsType)) { + return new ResolveResult(KnownTypeReference.Int64.Resolve(context)); + } + if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null) + return new ErrorResolveResult(SharedTypes.Null); + } + break; + case BinaryOperatorType.ShiftLeft: + methodGroup = shiftLeftOperators; + break; + case BinaryOperatorType.ShiftRight: + methodGroup = shiftRightOperators; + break; + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + case BinaryOperatorType.LessThan: + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.LessThanOrEqual: + case BinaryOperatorType.GreaterThanOrEqual: + { + Conversions conversions = new Conversions(context); + if (lhsType.IsEnum() && conversions.ImplicitConversion(rhs, lhs.Type)) { + // bool operator op(E x, E y); + return HandleEnumComparison(op, lhsType, isNullable, lhs, rhs); + } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhs, rhs.Type)) { + // bool operator op(E x, E y); + return HandleEnumComparison(op, rhsType, isNullable, lhs, rhs); + } else if (lhsType is PointerType && rhsType is PointerType) { + return new ResolveResult(KnownTypeReference.Boolean.Resolve(context)); + } + switch (op) { + case BinaryOperatorType.Equality: + methodGroup = equalityOperators; + break; + case BinaryOperatorType.InEquality: + methodGroup = inequalityOperators; + break; + case BinaryOperatorType.LessThan: + methodGroup = lessThanOperators; + break; + case BinaryOperatorType.GreaterThan: + methodGroup = greaterThanOperators; + break; + case BinaryOperatorType.LessThanOrEqual: + methodGroup = lessThanOrEqualOperators; + break; + case BinaryOperatorType.GreaterThanOrEqual: + methodGroup = greaterThanOrEqualOperators; + break; + default: + throw new InvalidOperationException(); + } + } + break; + case BinaryOperatorType.BitwiseAnd: + case BinaryOperatorType.BitwiseOr: + case BinaryOperatorType.ExclusiveOr: + { + Conversions conversions = new Conversions(context); + if (lhsType.IsEnum() && conversions.ImplicitConversion(rhs, lhs.Type)) { + // E operator op(E x, E y); + return HandleEnumAdditionOrSubtraction(isNullable, lhsType, op, lhs, rhs); + } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhs, rhs.Type)) { + // E operator op(E x, E y); + return HandleEnumAdditionOrSubtraction(isNullable, rhsType, op, lhs, rhs); + } + switch (op) { + case BinaryOperatorType.BitwiseAnd: + methodGroup = bitwiseAndOperators; + break; + case BinaryOperatorType.BitwiseOr: + methodGroup = bitwiseOrOperators; + break; + case BinaryOperatorType.ExclusiveOr: + methodGroup = bitwiseXorOperators; + break; + default: + throw new InvalidOperationException(); + } + } + break; + case BinaryOperatorType.ConditionalAnd: + methodGroup = logicalAndOperator; + break; + case BinaryOperatorType.ConditionalOr: + methodGroup = logicalOrOperator; + break; + default: + throw new InvalidOperationException(); + } + OverloadResolution r = new OverloadResolution(context, new[] { lhs, rhs }); + foreach (var candidate in methodGroup) { + r.AddCandidate(candidate); + } + BinaryOperatorMethod m = (BinaryOperatorMethod)r.BestCandidate; + IType resultType = m.ReturnType.Resolve(context); + if (r.BestCandidateErrors != OverloadResolutionErrors.None) { + return new ErrorResolveResult(resultType); + } else if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { + object val; + try { + val = m.Invoke(this, lhs.ConstantValue, rhs.ConstantValue); + } catch (ArithmeticException) { + return new ErrorResolveResult(resultType); + } + return new ConstantResolveResult(resultType, val); + } else { + return new ResolveResult(resultType); + } + } + #endregion + + #region Enum helper methods + /// + /// Handle the case where an enum value is compared with another enum value + /// bool operator op(E x, E y); + /// + ResolveResult HandleEnumComparison(BinaryOperatorType op, IType enumType, bool isNullable, ResolveResult lhs, ResolveResult rhs) + { + // evaluate as ((U)x op (U)y) + IType elementType = enumType.GetEnumUnderlyingType(context); + if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { + lhs = ResolveCast(elementType, lhs); + if (lhs.IsError) + return lhs; + rhs = ResolveCast(elementType, rhs); + if (rhs.IsError) + return rhs; + return ResolveBinaryOperator(op, lhs, rhs); + } + return new ResolveResult(KnownTypeReference.Boolean.Resolve(context)); + } + + /// + /// Handle the case where an enum value is subtracted from another enum value + /// U operator –(E x, E y); + /// + ResolveResult HandleEnumSubtraction(bool isNullable, IType enumType, ResolveResult lhs, ResolveResult rhs) + { + // evaluate as (U)((U)x – (U)y) + IType elementType = enumType.GetEnumUnderlyingType(context); + if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { + lhs = ResolveCast(elementType, lhs); + if (lhs.IsError) + return lhs; + rhs = ResolveCast(elementType, rhs); + if (rhs.IsError) + return rhs; + return CheckErrorAndResolveCast(elementType, ResolveBinaryOperator(BinaryOperatorType.Subtract, lhs, rhs)); + } + return new ResolveResult(isNullable ? NullableType.Create(elementType, context) : elementType); + } + + /// + /// Handle the case where an integral value is added to or subtracted from an enum value, + /// or when two enum values of the same type are combined using a bitwise operator. + /// E operator +(E x, U y); + /// E operator –(E x, U y); + /// E operator &(E x, E y); + /// E operator |(E x, E y); + /// E operator ^(E x, E y); + /// + ResolveResult HandleEnumAdditionOrSubtraction(bool isNullable, IType enumType, BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs) + { + // evaluate as (E)((U)x op (U)y) + if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { + IType elementType = enumType.GetEnumUnderlyingType(context); + lhs = ResolveCast(elementType, lhs); + if (lhs.IsError) + return lhs; + rhs = ResolveCast(elementType, rhs); + if (rhs.IsError) + return rhs; + return CheckErrorAndResolveCast(enumType, ResolveBinaryOperator(op, lhs, rhs)); + } + return new ResolveResult(isNullable ? NullableType.Create(enumType, context) : enumType); + } + #endregion + + #region BinaryNumericPromotion + bool BinaryNumericPromotion(bool isNullable, ref ResolveResult lhs, ref ResolveResult rhs, bool allowNullableConstants) + { + // C# 4.0 spec: §7.3.6.2 + TypeCode lhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(lhs.Type)); + TypeCode rhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rhs.Type)); + // if one of the inputs is the null literal, promote that to the type of the other operand + if (isNullable && lhs.Type == SharedTypes.Null) { + lhs = CastTo(rhsCode, isNullable, lhs, allowNullableConstants); + lhsCode = rhsCode; + } else if (isNullable && rhs.Type == SharedTypes.Null) { + rhs = CastTo(lhsCode, isNullable, rhs, allowNullableConstants); + rhsCode = lhsCode; + } + bool bindingError = false; + if (lhsCode >= TypeCode.Char && lhsCode <= TypeCode.Decimal + && rhsCode >= TypeCode.Char && rhsCode <= TypeCode.Decimal) + { + TypeCode targetType; + if (lhsCode == TypeCode.Decimal || rhsCode == TypeCode.Decimal) { + targetType = TypeCode.Decimal; + bindingError = (lhsCode == TypeCode.Single || lhsCode == TypeCode.Double + || rhsCode == TypeCode.Single || rhsCode == TypeCode.Double); + } else if (lhsCode == TypeCode.Double || rhsCode == TypeCode.Double) { + targetType = TypeCode.Double; + } else if (lhsCode == TypeCode.Single || rhsCode == TypeCode.Single) { + targetType = TypeCode.Single; + } else if (lhsCode == TypeCode.UInt64 || rhsCode == TypeCode.UInt64) { + targetType = TypeCode.UInt64; + bindingError = IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs); + } else if (lhsCode == TypeCode.Int64 || rhsCode == TypeCode.Int64) { + targetType = TypeCode.Int64; + } else if (lhsCode == TypeCode.UInt32 || rhsCode == TypeCode.UInt32) { + targetType = (IsSigned(lhsCode, lhs) || IsSigned(rhsCode, rhs)) ? TypeCode.Int64 : TypeCode.UInt32; + } else { + targetType = TypeCode.Int32; + } + lhs = CastTo(targetType, isNullable, lhs, allowNullableConstants); + rhs = CastTo(targetType, isNullable, rhs, allowNullableConstants); + } + return !bindingError; + } + + bool IsSigned(TypeCode code, ResolveResult rr) + { + // Determine whether the rr with code==ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rr.Type)) + // is a signed primitive type. + switch (code) { + case TypeCode.SByte: + case TypeCode.Int16: + return true; + case TypeCode.Int32: + // for int, consider implicit constant expression conversion + if (rr.IsCompileTimeConstant && rr.ConstantValue != null && (int)rr.ConstantValue >= 0) + return false; + else + return true; + case TypeCode.Int64: + // for long, consider implicit constant expression conversion + if (rr.IsCompileTimeConstant && rr.ConstantValue != null && (long)rr.ConstantValue >= 0) + return false; + else + return true; + default: + return false; + } + } + + static bool IsInteger(TypeCode code) + { + return code >= TypeCode.SByte && code <= TypeCode.UInt64; + } + + ResolveResult CastTo(TypeCode targetType, bool isNullable, ResolveResult expression, bool allowNullableConstants) + { + IType elementType = targetType.ToTypeReference().Resolve(context); + IType nullableType = isNullable ? NullableType.Create(elementType, context) : elementType; + if (allowNullableConstants && expression.IsCompileTimeConstant) { + if (expression.ConstantValue == null) + return new ConstantResolveResult(nullableType, null); + ResolveResult rr = ResolveCast(elementType, expression); + if (rr.IsError) + return rr; + Debug.Assert(rr.IsCompileTimeConstant); + return new ConstantResolveResult(nullableType, rr.ConstantValue); + } else { + return ResolveCast(nullableType, expression); + } + } + #endregion + + #region GetOverloadableOperatorName + static string GetOverloadableOperatorName(BinaryOperatorType op) + { + switch (op) { + case BinaryOperatorType.Add: + return "op_Addition"; + case BinaryOperatorType.Subtract: + return "op_Subtraction"; + case BinaryOperatorType.Multiply: + return "op_Multiply"; + case BinaryOperatorType.Divide: + return "op_Division"; + case BinaryOperatorType.Modulus: + return "op_Modulus"; + case BinaryOperatorType.BitwiseAnd: + return "op_BitwiseAnd"; + case BinaryOperatorType.BitwiseOr: + return "op_BitwiseOr"; + case BinaryOperatorType.ExclusiveOr: + return "op_ExclusiveOr"; + case BinaryOperatorType.ShiftLeft: + return "op_LeftShift"; + case BinaryOperatorType.ShiftRight: + return "op_RightShift"; + case BinaryOperatorType.Equality: + return "op_Equality"; + case BinaryOperatorType.InEquality: + return "op_Inequality"; + case BinaryOperatorType.GreaterThan: + return "op_GreaterThan"; + case BinaryOperatorType.LessThan: + return "op_LessThan"; + case BinaryOperatorType.GreaterThanOrEqual: + return "op_GreaterThanOrEqual"; + case BinaryOperatorType.LessThanOrEqual: + return "op_LessThanOrEqual"; + default: + return null; + } + } + #endregion + + #region Binary operator class definitions + abstract class BinaryOperatorMethod : OperatorMethod + { + public virtual bool CanEvaluateAtCompileTime { get { return true; } } + public abstract object Invoke(CSharpResolver resolver, object lhs, object rhs); + } + + sealed class LambdaBinaryOperatorMethod : BinaryOperatorMethod + { + readonly Func func; + + public LambdaBinaryOperatorMethod(Func func) + { + TypeCode t1 = Type.GetTypeCode(typeof(T1)); + this.ReturnType = t1.ToTypeReference(); + this.Parameters.Add(MakeParameter(t1)); + this.Parameters.Add(MakeParameter(Type.GetTypeCode(typeof(T2)))); + this.func = func; + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), + (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); + } + + public override OperatorMethod Lift() + { + return new LiftedBinaryOperatorMethod(this); + } + } + + sealed class LiftedBinaryOperatorMethod : BinaryOperatorMethod, OverloadResolution.ILiftedOperator + { + readonly BinaryOperatorMethod baseMethod; + + public LiftedBinaryOperatorMethod(BinaryOperatorMethod baseMethod) + { + this.baseMethod = baseMethod; + this.ReturnType = NullableType.Create(baseMethod.ReturnType); + this.Parameters.Add(MakeNullableParameter(baseMethod.Parameters[0])); + this.Parameters.Add(MakeNullableParameter(baseMethod.Parameters[1])); + } + + public override bool CanEvaluateAtCompileTime { + get { return false; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + throw new NotSupportedException(); // cannot use nullables at compile time + } + + public IList NonLiftedParameters { + get { return baseMethod.Parameters; } + } + } + #endregion + + #region Arithmetic operators + // C# 4.0 spec: §7.8.1 Multiplication operator + static readonly OperatorMethod[] checkedMultiplicationOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a * b)), + new LambdaBinaryOperatorMethod((a, b) => checked(a * b)) + ); + static readonly OperatorMethod[] uncheckedMultiplicationOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a * b)), + new LambdaBinaryOperatorMethod((a, b) => unchecked(a * b)) + ); + + // C# 4.0 spec: §7.8.2 Division operator + static readonly OperatorMethod[] checkedDivisionOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a / b)), + new LambdaBinaryOperatorMethod((a, b) => checked(a / b)) + ); + static readonly OperatorMethod[] uncheckedDivisionOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a / b)), + new LambdaBinaryOperatorMethod((a, b) => unchecked(a / b)) + ); + + // C# 4.0 spec: §7.8.3 Remainder operator + static readonly OperatorMethod[] checkedRemainderOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a % b)), + new LambdaBinaryOperatorMethod((a, b) => checked(a % b)) + ); + static readonly OperatorMethod[] uncheckedRemainderOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a % b)), + new LambdaBinaryOperatorMethod((a, b) => unchecked(a % b)) + ); + + // C# 4.0 spec: §7.8.3 Addition operator + static readonly OperatorMethod[] checkedAdditionOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a + b)), + new LambdaBinaryOperatorMethod((a, b) => checked(a + b)), + new StringConcatenation(TypeCode.String, TypeCode.String), + new StringConcatenation(TypeCode.String, TypeCode.Object), + new StringConcatenation(TypeCode.Object, TypeCode.String) + ); + static readonly OperatorMethod[] uncheckedAdditionOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a + b)), + new LambdaBinaryOperatorMethod((a, b) => unchecked(a + b)), + new StringConcatenation(TypeCode.String, TypeCode.String), + new StringConcatenation(TypeCode.String, TypeCode.Object), + new StringConcatenation(TypeCode.Object, TypeCode.String) + ); + // not in this list, but handled manually: enum addition, delegate combination + sealed class StringConcatenation : BinaryOperatorMethod + { + bool canEvaluateAtCompileTime; + + public StringConcatenation(TypeCode p1, TypeCode p2) + { + this.canEvaluateAtCompileTime = p1 == TypeCode.String && p2 == TypeCode.String; + this.ReturnType = KnownTypeReference.String; + this.Parameters.Add(MakeParameter(p1)); + this.Parameters.Add(MakeParameter(p2)); + } + + public override bool CanEvaluateAtCompileTime { + get { return canEvaluateAtCompileTime; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + return string.Concat(lhs, rhs); + } + } + + // C# 4.0 spec: §7.8.4 Subtraction operator + static readonly OperatorMethod[] checkedSubtractionOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => checked(a - b)), + new LambdaBinaryOperatorMethod((a, b) => checked(a - b)) + ); + static readonly OperatorMethod[] uncheckedSubtractionOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod ((a, b) => unchecked(a - b)), + new LambdaBinaryOperatorMethod((a, b) => unchecked(a - b)) + ); + + // C# 4.0 spec: §7.8.5 Shift operators + static readonly OperatorMethod[] shiftLeftOperators = Lift( + new LambdaBinaryOperatorMethod((a, b) => a << b), + new LambdaBinaryOperatorMethod((a, b) => a << b), + new LambdaBinaryOperatorMethod((a, b) => a << b), + new LambdaBinaryOperatorMethod((a, b) => a << b) + ); + static readonly OperatorMethod[] shiftRightOperators = Lift( + new LambdaBinaryOperatorMethod((a, b) => a >> b), + new LambdaBinaryOperatorMethod((a, b) => a >> b), + new LambdaBinaryOperatorMethod((a, b) => a >> b), + new LambdaBinaryOperatorMethod((a, b) => a >> b) + ); + #endregion + + #region Equality operators + sealed class EqualityOperatorMethod : BinaryOperatorMethod + { + public readonly TypeCode Type; + public readonly bool Negate; + + public EqualityOperatorMethod(TypeCode type, bool negate) + { + this.Negate = negate; + this.Type = type; + this.ReturnType = KnownTypeReference.Boolean; + this.Parameters.Add(MakeParameter(type)); + this.Parameters.Add(MakeParameter(type)); + } + + public override bool CanEvaluateAtCompileTime { + get { return Type != TypeCode.Object; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + lhs = resolver.CSharpPrimitiveCast(Type, lhs); + rhs = resolver.CSharpPrimitiveCast(Type, rhs); + bool equal; + if (Type == TypeCode.Single) { + equal = (float)lhs == (float)rhs; + } else if (Type == TypeCode.Double) { + equal = (double)lhs == (double)rhs; + } else { + equal = object.Equals(lhs, rhs); + } + return equal ^ Negate; + } + + public override OperatorMethod Lift() + { + if (Type == TypeCode.Object || Type == TypeCode.String) + return null; + else + return new LiftedEqualityOperatorMethod(this); + } + } + + sealed class LiftedEqualityOperatorMethod : BinaryOperatorMethod, OverloadResolution.ILiftedOperator + { + readonly EqualityOperatorMethod baseMethod; + + public LiftedEqualityOperatorMethod(EqualityOperatorMethod baseMethod) + { + this.baseMethod = baseMethod; + this.ReturnType = baseMethod.ReturnType; + IParameter p = MakeNullableParameter(baseMethod.Parameters[0]); + this.Parameters.Add(p); + this.Parameters.Add(p); + } + + public override bool CanEvaluateAtCompileTime { + get { return baseMethod.CanEvaluateAtCompileTime; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + if (lhs == null && rhs == null) + return !baseMethod.Negate; // ==: true; !=: false + if (lhs == null || rhs == null) + return baseMethod.Negate; // ==: false; !=: true + return baseMethod.Invoke(resolver, lhs, rhs); + } + + public IList NonLiftedParameters { + get { return baseMethod.Parameters; } + } + } + + // C# 4.0 spec: §7.10 Relational and type-testing operators + static readonly TypeCode[] equalityOperatorsFor = { + TypeCode.Int32, TypeCode.UInt32, + TypeCode.Int64, TypeCode.UInt64, + TypeCode.Single, TypeCode.Double, + TypeCode.Decimal, + TypeCode.Boolean, + TypeCode.String, TypeCode.Object + }; + + static readonly OperatorMethod[] equalityOperators = Lift(equalityOperatorsFor.Select(c => new EqualityOperatorMethod(c, false)).ToArray()); + static readonly OperatorMethod[] inequalityOperators = Lift(equalityOperatorsFor.Select(c => new EqualityOperatorMethod(c, true)).ToArray()); + #endregion + + #region Relational Operators + sealed class RelationalOperatorMethod : BinaryOperatorMethod + { + readonly Func func; + + public RelationalOperatorMethod(Func func) + { + this.ReturnType = KnownTypeReference.Boolean; + this.Parameters.Add(MakeParameter(Type.GetTypeCode(typeof(T1)))); + this.Parameters.Add(MakeParameter(Type.GetTypeCode(typeof(T2)))); + this.func = func; + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + return func((T1)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T1)), lhs), + (T2)resolver.CSharpPrimitiveCast(Type.GetTypeCode(typeof(T2)), rhs)); + } + + public override OperatorMethod Lift() + { + return new LiftedBinaryOperatorMethod(this); + } + } + + static readonly OperatorMethod[] lessThanOperators = Lift( + new RelationalOperatorMethod ((a, b) => a < b), + new RelationalOperatorMethod ((a, b) => a < b), + new RelationalOperatorMethod ((a, b) => a < b), + new RelationalOperatorMethod ((a, b) => a < b), + new RelationalOperatorMethod ((a, b) => a < b), + new RelationalOperatorMethod ((a, b) => a < b), + new RelationalOperatorMethod((a, b) => a < b) + ); + + static readonly OperatorMethod[] lessThanOrEqualOperators = Lift( + new RelationalOperatorMethod ((a, b) => a <= b), + new RelationalOperatorMethod ((a, b) => a <= b), + new RelationalOperatorMethod ((a, b) => a <= b), + new RelationalOperatorMethod ((a, b) => a <= b), + new RelationalOperatorMethod ((a, b) => a <= b), + new RelationalOperatorMethod ((a, b) => a <= b), + new RelationalOperatorMethod((a, b) => a <= b) + ); + + static readonly OperatorMethod[] greaterThanOperators = Lift( + new RelationalOperatorMethod ((a, b) => a > b), + new RelationalOperatorMethod ((a, b) => a > b), + new RelationalOperatorMethod ((a, b) => a > b), + new RelationalOperatorMethod ((a, b) => a > b), + new RelationalOperatorMethod ((a, b) => a > b), + new RelationalOperatorMethod ((a, b) => a > b), + new RelationalOperatorMethod((a, b) => a > b) + ); + + static readonly OperatorMethod[] greaterThanOrEqualOperators = Lift( + new RelationalOperatorMethod ((a, b) => a >= b), + new RelationalOperatorMethod ((a, b) => a >= b), + new RelationalOperatorMethod ((a, b) => a >= b), + new RelationalOperatorMethod ((a, b) => a >= b), + new RelationalOperatorMethod ((a, b) => a >= b), + new RelationalOperatorMethod ((a, b) => a >= b), + new RelationalOperatorMethod((a, b) => a >= b) + ); + #endregion + + #region Bitwise operators + static readonly OperatorMethod[] logicalAndOperator = { + new LambdaBinaryOperatorMethod ((a, b) => a & b) + }; + + static readonly OperatorMethod[] bitwiseAndOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => a & b), + new LambdaBinaryOperatorMethod ((a, b) => a & b), + new LambdaBinaryOperatorMethod ((a, b) => a & b), + new LambdaBinaryOperatorMethod((a, b) => a & b), + logicalAndOperator[0] + ); + + static readonly OperatorMethod[] logicalOrOperator = { + new LambdaBinaryOperatorMethod ((a, b) => a | b) + }; + + static readonly OperatorMethod[] bitwiseOrOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => a | b), + new LambdaBinaryOperatorMethod ((a, b) => a | b), + new LambdaBinaryOperatorMethod ((a, b) => a | b), + new LambdaBinaryOperatorMethod((a, b) => a | b), + logicalOrOperator[0] + ); + // Note: the logic for the lifted bool? bitwise operators is wrong; + // we produce "true | null" = "null" when it should be true. However, this is irrelevant + // because bool? cannot be a compile-time type. + + static readonly OperatorMethod[] bitwiseXorOperators = Lift( + new LambdaBinaryOperatorMethod ((a, b) => a ^ b), + new LambdaBinaryOperatorMethod ((a, b) => a ^ b), + new LambdaBinaryOperatorMethod ((a, b) => a ^ b), + new LambdaBinaryOperatorMethod((a, b) => a ^ b), + new LambdaBinaryOperatorMethod ((a, b) => a ^ b) + ); + #endregion + + #region Null coalescing operator + ResolveResult ResolveNullCoalescingOperator(ResolveResult lhs, ResolveResult rhs) + { + Conversions conversions = new Conversions(context); + if (NullableType.IsNullable(lhs.Type)) { + IType a0 = NullableType.GetUnderlyingType(lhs.Type); + if (conversions.ImplicitConversion(rhs, a0)) + return new ResolveResult(a0); + } + if (conversions.ImplicitConversion(rhs, lhs.Type)) + return new ResolveResult(lhs.Type); + if (conversions.ImplicitConversion(lhs, rhs.Type)) + return new ResolveResult(rhs.Type); + else + return new ErrorResolveResult(lhs.Type); + } + #endregion + + object GetUserBinaryOperatorCandidates() + { + // C# 4.0 spec: §7.3.5 Candidate user-defined operators + // TODO: implement user-defined operators + throw new NotImplementedException(); + } + #endregion + + #region ResolveCast + public ResolveResult ResolveCast(IType targetType, ResolveResult expression) + { + cancellationToken.ThrowIfCancellationRequested(); + + // C# 4.0 spec: §7.7.6 Cast expressions + if (expression.IsCompileTimeConstant) { + TypeCode code = ReflectionHelper.GetTypeCode(targetType); + if (code >= TypeCode.Boolean && code <= TypeCode.Decimal && expression.ConstantValue != null) { + try { + return new ConstantResolveResult(targetType, CSharpPrimitiveCast(code, expression.ConstantValue)); + } catch (OverflowException) { + return new ErrorResolveResult(targetType); + } + } else if (code == TypeCode.String) { + if (expression.ConstantValue == null || expression.ConstantValue is string) + return new ConstantResolveResult(targetType, expression.ConstantValue); + else + return new ErrorResolveResult(targetType); + } else if (targetType.IsEnum()) { + code = ReflectionHelper.GetTypeCode(targetType.GetEnumUnderlyingType(context)); + if (code >= TypeCode.SByte && code <= TypeCode.UInt64 && expression.ConstantValue != null) { + try { + return new ConstantResolveResult(targetType, CSharpPrimitiveCast(code, expression.ConstantValue)); + } catch (OverflowException) { + return new ErrorResolveResult(targetType); + } + } + } + } + return new ResolveResult(targetType); + } + + object CSharpPrimitiveCast(TypeCode targetType, object input) + { + return Utils.CSharpPrimitiveCast.Cast(targetType, input, this.CheckForOverflow); + } + + ResolveResult CheckErrorAndResolveCast(IType targetType, ResolveResult expression) + { + if (expression.IsError) + return expression; + else + return ResolveCast(targetType, expression); + } + #endregion + + #region ResolveSimpleName + enum SimpleNameLookupMode + { + Expression, + InvocationTarget, + Type, + TypeInUsingDeclaration + } + + public ResolveResult ResolveSimpleName(string identifier, IList typeArguments, bool isInvocationTarget = false) + { + // C# 4.0 spec: §7.6.2 Simple Names + + if (identifier == null) + throw new ArgumentNullException("identifier"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + + if (typeArguments.Count == 0) { + foreach (IVariable v in this.LocalVariables) { + if (v.Name == identifier) { + object constantValue = v.IsConst ? v.ConstantValue.GetValue(context) : null; + return new LocalResolveResult(v, v.Type.Resolve(context), constantValue); + } + } + IParameterizedMember parameterizedMember = this.CurrentMember as IParameterizedMember; + if (parameterizedMember != null) { + foreach (IParameter p in parameterizedMember.Parameters) { + if (p.Name == identifier) { + return new LocalResolveResult(p, p.Type.Resolve(context)); + } + } + } + } + + return LookupSimpleNameOrTypeName( + identifier, typeArguments, + isInvocationTarget ? SimpleNameLookupMode.InvocationTarget : SimpleNameLookupMode.Expression); + } + + public ResolveResult LookupSimpleNamespaceOrTypeName(string identifier, IList typeArguments, bool isUsingDeclaration = false) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + + return LookupSimpleNameOrTypeName(identifier, typeArguments, + isUsingDeclaration ? SimpleNameLookupMode.TypeInUsingDeclaration : SimpleNameLookupMode.Type); + } + + ResolveResult LookupSimpleNameOrTypeName(string identifier, IList typeArguments, SimpleNameLookupMode lookupMode) + { + // C# 4.0 spec: §3.8 Namespace and type names; §7.6.2 Simple Names + + cancellationToken.ThrowIfCancellationRequested(); + + int k = typeArguments.Count; + + // look in type parameters of current method + if (k == 0) { + IMethod m = this.CurrentMember as IMethod; + if (m != null) { + foreach (ITypeParameter tp in m.TypeParameters) { + if (tp.Name == identifier) + return new TypeResolveResult(tp); + } + } + } + + // look in current type definitions + for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { + if (k == 0) { + // look for type parameter with that name + var typeParameters = t.TypeParameters; + // only look at type parameters defined directly on this type, not at those copied from outer classes + for (int i = (t.DeclaringTypeDefinition != null ? t.DeclaringTypeDefinition.TypeParameterCount : 0); i < typeParameters.Count; i++) { + if (typeParameters[i].Name == identifier) + return new TypeResolveResult(typeParameters[i]); + } + } + + MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent); + ResolveResult r; + if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) { + r = lookup.Lookup(t, identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget); + } else { + r = lookup.LookupType(t, identifier, typeArguments); + } + if (!(r is UnknownMemberResolveResult)) // but do return AmbiguousMemberResolveResult + return r; + } + // look in current namespace definitions + for (UsingScope n = this.UsingScope; n != null; n = n.Parent) { + // first look for a namespace + if (k == 0) { + string fullName = NamespaceDeclaration.BuildQualifiedName(n.NamespaceName, identifier); + if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) { + if (n.HasAlias(identifier)) + return new AmbiguousTypeResolveResult(SharedTypes.UnknownType); + return new NamespaceResolveResult(fullName); + } + } + // then look for a type + ITypeDefinition def = context.GetTypeDefinition(n.NamespaceName, identifier, k, StringComparer.Ordinal); + if (def != null) { + IType result = def; + if (k != 0) { + result = new ParameterizedType(def, typeArguments); + } + if (n.HasAlias(identifier)) + return new AmbiguousTypeResolveResult(result); + else + return new TypeResolveResult(result); + } + // then look for aliases: + if (k == 0) { + if (n.ExternAliases.Contains(identifier)) { + return ResolveExternAlias(identifier); + } + if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.UsingScope) { + foreach (var pair in n.UsingAliases) { + if (pair.Key == identifier) { + NamespaceResolveResult ns = pair.Value.ResolveNamespace(context); + if (ns != null) + return ns; + else + return new TypeResolveResult(pair.Value.Resolve(context)); + } + } + } + } + // finally, look in the imported namespaces: + if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.UsingScope) { + IType firstResult = null; + foreach (var u in n.Usings) { + NamespaceResolveResult ns = u.ResolveNamespace(context); + if (ns != null) { + def = context.GetTypeDefinition(ns.NamespaceName, identifier, k, StringComparer.Ordinal); + if (def != null) { + if (firstResult == null) { + if (k == 0) + firstResult = def; + else + firstResult = new ParameterizedType(def, typeArguments); + } else { + return new AmbiguousTypeResolveResult(firstResult); + } + } + } + } + if (firstResult != null) + return new TypeResolveResult(firstResult); + } + // if we didn't find anything: repeat lookup with parent namespace + } + if (typeArguments.Count == 0) { + if (identifier == "dynamic") + return new TypeResolveResult(SharedTypes.Dynamic); + else + return new UnknownIdentifierResolveResult(identifier); + } else { + return ErrorResult; + } + } + + /// + /// Looks up an alias (identifier in front of :: operator) + /// + public ResolveResult ResolveAlias(string identifier) + { + if (identifier == "global") + return new NamespaceResolveResult(string.Empty); + + for (UsingScope n = this.UsingScope; n != null; n = n.Parent) { + if (n.ExternAliases.Contains(identifier)) { + return ResolveExternAlias(identifier); + } + foreach (var pair in n.UsingAliases) { + if (pair.Key == identifier) { + return pair.Value.ResolveNamespace(context) ?? ErrorResult; + } + } + } + return ErrorResult; + } + + ResolveResult ResolveExternAlias(string alias) + { + // TODO: implement extern alias support + return new NamespaceResolveResult(string.Empty); + } + #endregion + + #region ResolveMemberAccess + public ResolveResult ResolveMemberAccess(ResolveResult target, string identifier, IList typeArguments, bool isInvocationTarget = false) + { + // C# 4.0 spec: §7.6.4 + + cancellationToken.ThrowIfCancellationRequested(); + + NamespaceResolveResult nrr = target as NamespaceResolveResult; + if (nrr != null) { + if (typeArguments.Count == 0) { + string fullName = NamespaceDeclaration.BuildQualifiedName(nrr.NamespaceName, identifier); + if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) + return new NamespaceResolveResult(fullName); + } + ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal); + if (def != null) + return new TypeResolveResult(def); + return ErrorResult; + } + + if (target.Type == SharedTypes.Dynamic) + return DynamicResult; + + MemberLookup lookup = CreateMemberLookup(); + ResolveResult result = lookup.Lookup(target.Type, identifier, typeArguments, isInvocationTarget); + if (result is UnknownMemberResolveResult) { + var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments.Count); + if (extensionMethods.Count > 0) { + return new MethodGroupResolveResult(target.Type, identifier, EmptyList.Instance, typeArguments) { + ExtensionMethods = extensionMethods + }; + } + } + return result; + } + + MemberLookup CreateMemberLookup() + { + return new MemberLookup(context, this.CurrentTypeDefinition, this.UsingScope != null ? this.UsingScope.ProjectContent : null); + } + #endregion + + #region GetExtensionMethods + /// + /// Gets the extension methods that are called 'name', and can be called with 'typeArgumentCount' explicit type arguments; + /// and are applicable with a first argument type of 'targetType'. + /// + List> GetExtensionMethods(IType targetType, string name, int typeArgumentCount) + { + List> extensionMethodGroups = new List>(); + foreach (var inputGroup in GetAllExtensionMethods()) { + List outputGroup = new List(); + foreach (var method in inputGroup) { + if (method.Name == name && (typeArgumentCount == 0 || method.TypeParameters.Count == typeArgumentCount)) { + // TODO: verify targetType + outputGroup.Add(method); + } + } + if (outputGroup.Count > 0) + extensionMethodGroups.Add(outputGroup); + } + return extensionMethodGroups; + } + + List> GetAllExtensionMethods() + { + // TODO: maybe cache the result? + List> extensionMethodGroups = new List>(); + List m; + for (UsingScope scope = this.UsingScope; scope != null; scope = scope.Parent) { + m = GetExtensionMethods(scope.NamespaceName).ToList(); + if (m.Count > 0) + extensionMethodGroups.Add(m); + + m = ( + from u in scope.Usings + select u.ResolveNamespace(context) into ns + where ns != null + select ns.NamespaceName + ).Distinct().SelectMany(ns => GetExtensionMethods(ns)).ToList(); + if (m.Count > 0) + extensionMethodGroups.Add(m); + } + return extensionMethodGroups; + } + + IEnumerable GetExtensionMethods(string namespaceName) + { + return + from c in context.GetTypes(namespaceName, StringComparer.Ordinal) + where c.IsStatic && c.HasExtensionMethods + from m in c.Methods + where m.IsExtensionMethod + select m; + } + #endregion + + #region ResolveInvocation + public ResolveResult ResolveInvocation(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null) + { + // C# 4.0 spec: §7.6.5 + + cancellationToken.ThrowIfCancellationRequested(); + + if (target.Type == SharedTypes.Dynamic) + return DynamicResult; + + MethodGroupResolveResult mgrr = target as MethodGroupResolveResult; + if (mgrr != null) { + var typeArgumentArray = mgrr.TypeArguments.ToArray(); + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, typeArgumentArray); + foreach (IMethod method in mgrr.Methods) { + // TODO: grouping by class definition? + or.AddCandidate(method); + } + if (!or.FoundApplicableCandidate) { + // No applicable match found, so let's try extension methods. + + var extensionMethods = mgrr.ExtensionMethods; + // Look in extension methods pre-calcalculated by ResolveMemberAccess if possible; + // otherwise call GetExtensionMethods(). + if (extensionMethods == null) + extensionMethods = GetExtensionMethods(mgrr.TargetType, mgrr.MethodName, mgrr.TypeArguments.Count); + + if (extensionMethods.Count > 0) { + ResolveResult[] extArguments = new ResolveResult[arguments.Length + 1]; + extArguments[0] = new ResolveResult(mgrr.TargetType); + arguments.CopyTo(extArguments, 1); + string[] extArgumentNames = null; + if (argumentNames != null) { + extArgumentNames = new string[argumentNames.Length + 1]; + argumentNames.CopyTo(extArgumentNames, 1); + } + var extOr = new OverloadResolution(context, extArguments, extArgumentNames, typeArgumentArray); + + foreach (var g in extensionMethods) { + foreach (var m in g) { + extOr.AddCandidate(m); + } + if (extOr.FoundApplicableCandidate) + break; + } + // For the lack of a better comparison function (the one within OverloadResolution + // cannot be used as it depends on the argument set): + if (extOr.FoundApplicableCandidate || or.BestCandidate == null) { + // Consider an extension method result better than the normal result only + // if it's applicable; or if there is no normal result. + or = extOr; + } + } + } + if (or.BestCandidate != null) { + IType returnType = or.BestCandidate.ReturnType.Resolve(context); + returnType = returnType.AcceptVisitor(new MethodTypeParameterSubstitution(or.InferredTypeArguments)); + return new MemberResolveResult(or.BestCandidate, returnType); + } else { + // No candidate found at all (not even an inapplicable one). + // This can happen with empty method groups (as sometimes used with extension methods) + return new UnknownMethodResolveResult( + mgrr.TargetType, mgrr.MethodName, mgrr.TypeArguments, CreateParameters(arguments, argumentNames)); + } + } + UnknownMemberResolveResult umrr = target as UnknownMemberResolveResult; + if (umrr != null) { + return new UnknownMethodResolveResult(umrr.TargetType, umrr.MemberName, umrr.TypeArguments, CreateParameters(arguments, argumentNames)); + } + UnknownIdentifierResolveResult uirr = target as UnknownIdentifierResolveResult; + if (uirr != null && CurrentTypeDefinition != null) { + return new UnknownMethodResolveResult(CurrentTypeDefinition, uirr.Identifier, EmptyList.Instance, CreateParameters(arguments, argumentNames)); + } + IMethod invokeMethod = target.Type.GetDelegateInvokeMethod(); + if (invokeMethod != null) { + return new ResolveResult(invokeMethod.ReturnType.Resolve(context)); + } + return ErrorResult; + } + + static List CreateParameters(ResolveResult[] arguments, string[] argumentNames) + { + List list = new List(); + if (argumentNames == null) { + argumentNames = new string[arguments.Length]; + } else { + if (argumentNames.Length != arguments.Length) + throw new ArgumentException(); + argumentNames = (string[])argumentNames.Clone(); + } + for (int i = 0; i < arguments.Length; i++) { + // invent argument names where necessary: + if (argumentNames[i] == null) { + string newArgumentName = GuessParameterName(arguments[i]); + if (argumentNames.Contains(newArgumentName)) { + // disambiguate argument name (e.g. add a number) + int num = 1; + string newName; + do { + newName = newArgumentName + num.ToString(); + num++; + } while(argumentNames.Contains(newName)); + newArgumentName = newName; + } + argumentNames[i] = newArgumentName; + } + + // create the parameter: + ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; + if (brrr != null) { + list.Add(new DefaultParameter(arguments[i].Type, argumentNames[i]) { + IsRef = brrr.IsRef, + IsOut = brrr.IsOut + }); + } else { + // argument might be a lambda or delegate type, so we have to try to guess the delegate type + IType type = arguments[i].Type; + if (type == SharedTypes.Null || type == SharedTypes.UnknownType) { + list.Add(new DefaultParameter(KnownTypeReference.Object, argumentNames[i])); + } else { + list.Add(new DefaultParameter(type, argumentNames[i])); + } + } + } + return list; + } + + static string GuessParameterName(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + if (mrr != null) + return mrr.Member.Name; + + UnknownMemberResolveResult umrr = rr as UnknownMemberResolveResult; + if (umrr != null) + return umrr.MemberName; + + MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult; + if (mgrr != null && mgrr.Methods.Count > 0) + return mgrr.Methods[0].Name; + + LocalResolveResult vrr = rr as LocalResolveResult; + if (vrr != null) + return MakeParameterName(vrr.Variable.Name); + + if (rr.Type != SharedTypes.UnknownType && !string.IsNullOrEmpty(rr.Type.Name)) { + return MakeParameterName(rr.Type.Name); + } else { + return "parameter"; + } + } + + static string MakeParameterName(string variableName) + { + if (string.IsNullOrEmpty(variableName)) + return "parameter"; + if (variableName.Length > 1 && variableName[0] == '_') + variableName = variableName.Substring(1); + return char.ToLower(variableName[0]) + variableName.Substring(1); + } + #endregion + + #region ResolveIndexer + public ResolveResult ResolveIndexer(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (target.Type == SharedTypes.Dynamic) + return DynamicResult; + + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]); + MemberLookup lookup = CreateMemberLookup(); + bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(target.Type); + var indexers = target.Type.GetProperties(context, p => p.IsIndexer && lookup.IsAccessible(p, allowProtectedAccess)); + // TODO: filter indexers hiding other indexers? + foreach (IProperty p in indexers) { + // TODO: grouping by class definition? + or.AddCandidate(p); + } + if (or.BestCandidate != null) { + return new MemberResolveResult(or.BestCandidate, or.BestCandidate.ReturnType.Resolve(context)); + } else { + return ErrorResult; + } + } + #endregion + + #region ResolveObjectCreation + public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null) + { + cancellationToken.ThrowIfCancellationRequested(); + + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]); + MemberLookup lookup = CreateMemberLookup(); + bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(type); + var constructors = type.GetConstructors(context, m => lookup.IsAccessible(m, allowProtectedAccess)); + foreach (IMethod ctor in constructors) { + or.AddCandidate(ctor); + } + if (or.BestCandidate != null) { + return new MemberResolveResult(or.BestCandidate, type); + } else { + return new ErrorResolveResult(type); + } + } + #endregion + + #region ResolveSizeOf + /// + /// Resolves 'sizeof(type)'. + /// + public ResolveResult ResolveSizeOf(IType type) + { + IType int32 = KnownTypeReference.Int32.Resolve(context); + int size; + switch (ReflectionHelper.GetTypeCode(type)) { + case TypeCode.Boolean: + case TypeCode.SByte: + case TypeCode.Byte: + size = 1; + break; + case TypeCode.Char: + case TypeCode.Int16: + case TypeCode.UInt16: + size = 2; + break; + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Single: + size = 4; + break; + case TypeCode.Int64: + case TypeCode.UInt64: + case TypeCode.Double: + size = 8; + break; + default: + return new ResolveResult(int32); + } + return new ConstantResolveResult(int32, size); + } + #endregion + + #region Resolve This/Base Reference + /// + /// Resolves 'this'. + /// + public ResolveResult ResolveThisReference() + { + ITypeDefinition t = CurrentTypeDefinition; + if (t != null) { + return new ResolveResult(t); + } + return ErrorResult; + } + + /// + /// Resolves 'base'. + /// + public ResolveResult ResolveBaseReference() + { + ITypeDefinition t = CurrentTypeDefinition; + if (t != null) { + foreach (IType baseType in t.GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && baseTypeDef.ClassType != ClassType.Interface) { + return new ResolveResult(baseType); + } + } + } + return ErrorResult; + } + #endregion + + #region ResolveConditional + public ResolveResult ResolveConditional(ResolveResult condition, ResolveResult trueExpression, ResolveResult falseExpression) + { + // C# 4.0 spec §7.14: Conditional operator + + cancellationToken.ThrowIfCancellationRequested(); + + Conversions c = new Conversions(context); + bool isValid; + IType resultType; + if (trueExpression.Type == SharedTypes.Dynamic || falseExpression.Type == SharedTypes.Dynamic) { + resultType = SharedTypes.Dynamic; + isValid = true; + } else if (HasType(trueExpression) && HasType(falseExpression)) { + bool t2f = c.ImplicitConversion(trueExpression.Type, falseExpression.Type); + bool f2t = c.ImplicitConversion(falseExpression.Type, trueExpression.Type); + resultType = (f2t && !t2f) ? trueExpression.Type : falseExpression.Type; + // The operator is valid: + // a) if there's a conversion in one direction but not the other + // b) if there are conversions in both directions, and the types are equivalent + isValid = (t2f != f2t) || (t2f && f2t && trueExpression.Type.Equals(falseExpression.Type)); + } else if (HasType(trueExpression)) { + resultType = trueExpression.Type; + isValid = c.ImplicitConversion(falseExpression, resultType); + } else if (HasType(falseExpression)) { + resultType = falseExpression.Type; + isValid = c.ImplicitConversion(trueExpression, resultType); + } else { + return ErrorResult; + } + if (isValid) { + if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) { + bool? val = condition.ConstantValue as bool?; + if (val == true) + return ResolveCast(resultType, trueExpression); + else if (val == false) + return ResolveCast(resultType, falseExpression); + } + return new ResolveResult(resultType); + } else { + return new ErrorResolveResult(resultType); + } + } + + bool HasType(ResolveResult r) + { + return r.Type != SharedTypes.UnknownType && r.Type != SharedTypes.Null; + } + #endregion + + #region ResolvePrimitive + public ResolveResult ResolvePrimitive(object value) + { + if (value == null) { + return NullResult; + } else { + TypeCode typeCode = Type.GetTypeCode(value.GetType()); + IType type = typeCode.ToTypeReference().Resolve(context); + return new ConstantResolveResult(type, value); + } + } + #endregion + + #region ResolveDefaultValue + public ResolveResult ResolveDefaultValue(IType type) + { + return new ConstantResolveResult(type, GetDefaultValue(type)); + } + + public static object GetDefaultValue(IType type) + { + switch (ReflectionHelper.GetTypeCode(type)) { + case TypeCode.Boolean: + return false; + case TypeCode.Char: + return '\0'; + case TypeCode.SByte: + return (sbyte)0; + case TypeCode.Byte: + return (byte)0; + case TypeCode.Int16: + return (short)0; + case TypeCode.UInt16: + return (ushort)0; + case TypeCode.Int32: + return 0; + case TypeCode.UInt32: + return 0U; + case TypeCode.Int64: + return 0L; + case TypeCode.UInt64: + return 0UL; + case TypeCode.Single: + return 0f; + case TypeCode.Double: + return 0.0; + case TypeCode.Decimal: + return 0m; + default: + return null; + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs new file mode 100644 index 0000000000..32489a1d8b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs @@ -0,0 +1,34 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// ResolveResult representing a compile-time constant. + /// + public class ConstantResolveResult : ResolveResult + { + object constantValue; + + public ConstantResolveResult(IType type, object constantValue) : base(type) + { + this.constantValue = constantValue; + } + + public override bool IsCompileTimeConstant { + get { return true; } + } + + public override object ConstantValue { + get { return constantValue; } + } + + public override string ToString() + { + return string.Format("[{0} {1} = {2}]", GetType().Name, this.Type, constantValue); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs new file mode 100644 index 0000000000..5c59905173 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs @@ -0,0 +1,638 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.CSharp.Analysis; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues +{ + // Contains representations for constant C# expressions. + // We use these instead of storing the full AST to reduce the memory usage. + + public sealed class CSharpConstantValue : Immutable, IConstantValue, ISupportsInterning + { + ConstantExpression expression; + UsingScope parentUsingScope; + ITypeDefinition parentTypeDefinition; + + public CSharpConstantValue(ConstantExpression expression, UsingScope parentUsingScope, ITypeDefinition parentTypeDefinition) + { + if (expression == null) + throw new ArgumentNullException("expression"); + this.expression = expression; + this.parentUsingScope = parentUsingScope; + this.parentTypeDefinition = parentTypeDefinition; + } + + CSharpResolver CreateResolver(ITypeResolveContext context) + { + // Because constants are evaluated by the compiler, we need to evaluate them in the resolve context + // of the project where they are defined, not in that where the constant value is used. + // TODO: how do we get the correct resolve context? + return new CSharpResolver(context) { + CheckForOverflow = false, // TODO: get project-wide overflow setting + CurrentTypeDefinition = parentTypeDefinition, + UsingScope = parentUsingScope + }; + } + + public IType GetValueType(ITypeResolveContext context) + { + CSharpResolver resolver = CreateResolver(context); + IType type = expression.Resolve(resolver).Type; + if (resolver.Context != context) { + // Retrieve the equivalent type in the new resolve context. + // E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0. + // However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0. + return type.AcceptVisitor(new MapTypeIntoNewContext(context)); + } + return type; + } + + public object GetValue(ITypeResolveContext context) + { + CSharpResolver resolver = CreateResolver(context); + object val = expression.Resolve(resolver).ConstantValue; + if (resolver.Context != context) { + // If 'val' is a type or an array containing types, we need to map it to the new context. + val = MapToNewContext(val, context); + } + return val; + } + + static object MapToNewContext(object val, ITypeResolveContext context) + { + IType type = val as IType; + if (type != null) { + return type.AcceptVisitor(new MapTypeIntoNewContext(context)); + } + object[] arr = val as object[]; + if (arr != null) { + object[] newArr = new object[arr.Length]; + bool modified = false; + for (int i = 0; i < arr.Length; i++) { + newArr[i] = MapToNewContext(arr[i], context); + modified |= arr[i] != newArr[i]; + } + if (modified) + return newArr; + } + return val; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return expression.GetHashCode() + ^ (parentUsingScope != null ? parentUsingScope.GetHashCode() : 0) + ^ (parentTypeDefinition != null ? parentTypeDefinition.GetHashCode() : 0); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + CSharpConstantValue cv = other as CSharpConstantValue; + return cv != null + && expression == cv.expression + && parentUsingScope == cv.parentUsingScope + && parentTypeDefinition == cv.parentTypeDefinition; + } + } + + /// + /// Increments an integer by a fixed amount without changing the type. + /// + public sealed class IncrementConstantValue : Immutable, IConstantValue, ISupportsInterning + { + IConstantValue baseValue; + int incrementAmount; + + public IncrementConstantValue(IConstantValue baseValue, int incrementAmount = 1) + { + if (baseValue == null) + throw new ArgumentNullException("baseValue"); + IncrementConstantValue icv = baseValue as IncrementConstantValue; + if (icv != null) { + this.baseValue = icv.baseValue; + this.incrementAmount = icv.incrementAmount + incrementAmount; + } else { + this.baseValue = baseValue; + this.incrementAmount = incrementAmount; + } + } + + public IType GetValueType(ITypeResolveContext context) + { + return baseValue.GetValueType(context); + } + + public object GetValue(ITypeResolveContext context) + { + object val = baseValue.GetValue(context); + if (val == null) + return null; + TypeCode typeCode = Type.GetTypeCode(val.GetType()); + if (!(typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64)) + return null; + long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false); + return CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + baseValue = provider.Intern(baseValue); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return baseValue.GetHashCode() ^ incrementAmount; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + IncrementConstantValue o = other as IncrementConstantValue; + return o != null && baseValue == o.baseValue && incrementAmount == o.incrementAmount; + } + } + + public abstract class ConstantExpression + { + public abstract ResolveResult Resolve(CSharpResolver resolver); + } + + /// + /// C#'s equivalent to the SimpleConstantValue. + /// + public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning + { + ITypeReference type; + object value; + + public ITypeReference Type { + get { return type; } + } + + public object Value { + get { return value; } + } + + public PrimitiveConstantExpression(ITypeReference type, object value) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + this.value = value; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + object val = value; + if (val is ITypeReference) + val = ((ITypeReference)val).Resolve(resolver.Context); + return new ConstantResolveResult(type.Resolve(resolver.Context), val); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + value = provider.Intern(value); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + PrimitiveConstantExpression scv = other as PrimitiveConstantExpression; + return scv != null && type == scv.type && value == scv.value; + } + } + + public sealed class ConstantCast : ConstantExpression, ISupportsInterning + { + ITypeReference targetType; + ConstantExpression expression; + + public ConstantCast(ITypeReference targetType, ConstantExpression expression) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + if (expression == null) + throw new ArgumentNullException("expression"); + this.targetType = targetType; + this.expression = expression; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveCast(targetType.Resolve(resolver.Context), expression.Resolve(resolver)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + targetType = provider.Intern(targetType); + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return targetType.GetHashCode() + expression.GetHashCode() * 1018829; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantCast cast = other as ConstantCast; + return cast != null + && this.targetType == cast.targetType && this.expression == cast.expression; + } + } + + public sealed class ConstantIdentifierReference : ConstantExpression, ISupportsInterning + { + string identifier; + IList typeArguments; + + public ConstantIdentifierReference(string identifier, IList typeArguments = null) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.identifier = identifier; + this.typeArguments = typeArguments; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveSimpleName(identifier, ResolveTypes(resolver, typeArguments)); + } + + internal static IList ResolveTypes(CSharpResolver resolver, IList typeArguments) + { + if (typeArguments == null) + return EmptyList.Instance; + IType[] types = new IType[typeArguments.Count]; + for (int i = 0; i < types.Length; i++) { + types[i] = typeArguments[i].Resolve(resolver.Context); + } + return types; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + identifier = provider.Intern(identifier); + typeArguments = provider.InternList(typeArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + int hashCode = identifier.GetHashCode(); + if (typeArguments != null) + hashCode ^= typeArguments.GetHashCode(); + return hashCode; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantIdentifierReference cir = other as ConstantIdentifierReference; + return cir != null && + this.identifier == cir.identifier && this.typeArguments == cir.typeArguments; + } + } + + public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning + { + ITypeReference targetType; + ConstantExpression targetExpression; + string memberName; + IList typeArguments; + + public ConstantMemberReference(ITypeReference targetType, string memberName, IList typeArguments = null) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + if (memberName == null) + throw new ArgumentNullException("memberName"); + this.targetType = targetType; + this.memberName = memberName; + this.typeArguments = typeArguments; + } + + public ConstantMemberReference(ConstantExpression targetExpression, string memberName, IList typeArguments = null) + { + if (targetExpression == null) + throw new ArgumentNullException("targetExpression"); + if (memberName == null) + throw new ArgumentNullException("memberName"); + this.targetExpression = targetExpression; + this.memberName = memberName; + this.typeArguments = typeArguments; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + ResolveResult rr; + if (targetType != null) + rr = new TypeResolveResult(targetType.Resolve(resolver.Context)); + else + rr = targetExpression.Resolve(resolver); + return resolver.ResolveMemberAccess(rr, memberName, ConstantIdentifierReference.ResolveTypes(resolver, typeArguments)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + targetType = provider.Intern(targetType); + targetExpression = provider.Intern(targetExpression); + memberName = provider.Intern(memberName); + typeArguments = provider.InternList(typeArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + int hashCode; + if (targetType != null) + hashCode = targetType.GetHashCode(); + else + hashCode = targetExpression.GetHashCode(); + hashCode ^= memberName.GetHashCode(); + if (typeArguments != null) + hashCode ^= typeArguments.GetHashCode(); + return hashCode; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantMemberReference cmr = other as ConstantMemberReference; + return cmr != null + && this.targetType == cmr.targetType && this.targetExpression == cmr.targetExpression + && this.memberName == cmr.memberName && this.typeArguments == cmr.typeArguments; + } + } + + public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning + { + bool checkForOverflow; + ConstantExpression expression; + + public ConstantCheckedExpression(bool checkForOverflow, ConstantExpression expression) + { + if (expression == null) + throw new ArgumentNullException("expression"); + this.checkForOverflow = checkForOverflow; + this.expression = expression; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = this.checkForOverflow; + return expression.Resolve(resolver); + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return expression.GetHashCode() ^ (checkForOverflow ? 161851612 : 75163517); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantCheckedExpression cce = other as ConstantCheckedExpression; + return cce != null + && this.expression == cce.expression + && this.checkForOverflow == cce.checkForOverflow; + } + } + + public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning + { + ITypeReference type; + + public ConstantDefaultValue(ITypeReference type) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveDefaultValue(type.Resolve(resolver.Context)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantDefaultValue o = other as ConstantDefaultValue; + return o != null && this.type == o.type; + } + } + + public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning + { + UnaryOperatorType operatorType; + ConstantExpression expression; + + public ConstantUnaryOperator(UnaryOperatorType operatorType, ConstantExpression expression) + { + if (expression == null) + throw new ArgumentNullException("expression"); + this.operatorType = operatorType; + this.expression = expression; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveUnaryOperator(operatorType, expression.Resolve(resolver)); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + expression = provider.Intern(expression); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return expression.GetHashCode() * 811 + operatorType.GetHashCode(); + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantUnaryOperator uop = other as ConstantUnaryOperator; + return uop != null + && this.operatorType == uop.operatorType + && this.expression == uop.expression; + } + } + + public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning + { + ConstantExpression left; + BinaryOperatorType operatorType; + ConstantExpression right; + + public ConstantBinaryOperator(ConstantExpression left, BinaryOperatorType operatorType, ConstantExpression right) + { + if (left == null) + throw new ArgumentNullException("left"); + if (right == null) + throw new ArgumentNullException("right"); + this.left = left; + this.operatorType = operatorType; + this.right = right; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + ResolveResult lhs = left.Resolve(resolver); + ResolveResult rhs = right.Resolve(resolver); + return resolver.ResolveBinaryOperator(operatorType, lhs, rhs); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + left = provider.Intern(left); + right = provider.Intern(right); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return left.GetHashCode() * 811 + operatorType.GetHashCode() + right.GetHashCode() * 91781; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantBinaryOperator bop = other as ConstantBinaryOperator; + return bop != null + && this.operatorType == bop.operatorType + && this.left == bop.left && this.right == bop.right; + } + } + + public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning + { + ConstantExpression condition, trueExpr, falseExpr; + + public ConstantConditionalOperator(ConstantExpression condition, ConstantExpression trueExpr, ConstantExpression falseExpr) + { + if (condition == null) + throw new ArgumentNullException("condition"); + if (trueExpr == null) + throw new ArgumentNullException("trueExpr"); + if (falseExpr == null) + throw new ArgumentNullException("falseExpr"); + this.condition = condition; + this.trueExpr = trueExpr; + this.falseExpr = falseExpr; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + return resolver.ResolveConditional( + condition.Resolve(resolver), + trueExpr.Resolve(resolver), + falseExpr.Resolve(resolver) + ); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + condition = provider.Intern(condition); + trueExpr = provider.Intern(trueExpr); + falseExpr = provider.Intern(falseExpr); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + return condition.GetHashCode() * 182981713 + + trueExpr.GetHashCode() * 917517169 + + falseExpr.GetHashCode() * 611651; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantConditionalOperator coo = other as ConstantConditionalOperator; + return coo != null + && this.condition == coo.condition + && this.trueExpr == coo.trueExpr + && this.falseExpr == coo.falseExpr; + } + } + + /// + /// Represents an array creation (as used within an attribute argument) + /// + public sealed class ConstantArrayCreation : ConstantExpression, ISupportsInterning + { + // type may be null when the element is being inferred + ITypeReference type; + IList arrayElements; + + public ConstantArrayCreation(ITypeReference type, IList arrayElements) + { + if (arrayElements == null) + throw new ArgumentNullException("arrayElements"); + this.type = type; + this.arrayElements = arrayElements; + } + + public override ResolveResult Resolve(CSharpResolver resolver) + { + throw new NotImplementedException(); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + arrayElements = provider.InternList(arrayElements); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return (type != null ? type.GetHashCode() : 0) ^ arrayElements.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ConstantArrayCreation cac = other as ConstantArrayCreation; + return cac != null && this.type == cac.type && this.arrayElements == cac.arrayElements; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs new file mode 100644 index 0000000000..3109fb8f8e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs @@ -0,0 +1,466 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Contains logic that determines whether an implicit conversion exists between two types. + /// + public class Conversions : IConversions + { + readonly ITypeResolveContext context; + readonly IType objectType; + + public Conversions(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + this.objectType = KnownTypeReference.Object.Resolve(context); + this.dynamicErasure = new DynamicErasure(this); + } + + #region ImplicitConversion + public bool ImplicitConversion(ResolveResult resolveResult, IType toType) + { + if (resolveResult == null) + throw new ArgumentNullException("resolveResult"); + if (resolveResult.IsCompileTimeConstant) { + if (ImplicitEnumerationConversion(resolveResult, toType)) + return true; + if (ImplicitConstantExpressionConversion(resolveResult, toType)) + return true; + } + if (ImplicitConversion(resolveResult.Type, toType)) + return true; + // TODO: Anonymous function conversions + // TODO: Method group conversions + return false; + } + + public bool ImplicitConversion(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + // C# 4.0 spec: §6.1 + if (IdentityConversion(fromType, toType)) + return true; + if (ImplicitNumericConversion(fromType, toType)) + return true; + if (ImplicitNullableConversion(fromType, toType)) + return true; + if (NullLiteralConversion(fromType, toType)) + return true; + if (ImplicitReferenceConversion(fromType, toType)) + return true; + if (BoxingConversion(fromType, toType)) + return true; + if (ImplicitDynamicConversion(fromType, toType)) + return true; + if (ImplicitTypeParameterConversion(fromType, toType)) + return true; + if (ImplicitPointerConversion(fromType, toType)) + return true; + if (ImplicitUserDefinedConversion(fromType, toType)) + return true; + return false; + } + + public bool StandardImplicitConversion(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + // C# 4.0 spec: §6.3.1 + if (IdentityConversion(fromType, toType)) + return true; + if (ImplicitNumericConversion(fromType, toType)) + return true; + if (ImplicitNullableConversion(fromType, toType)) + return true; + if (ImplicitReferenceConversion(fromType, toType)) + return true; + if (ImplicitTypeParameterConversion(fromType, toType)) + return true; + if (BoxingConversion(fromType, toType)) + return true; + return false; + } + #endregion + + #region IdentityConversion + /// + /// Gets whether there is an identity conversion from to + /// + public bool IdentityConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.1 + return fromType.AcceptVisitor(dynamicErasure).Equals(toType.AcceptVisitor(dynamicErasure)); + } + + readonly DynamicErasure dynamicErasure; + + sealed class DynamicErasure : TypeVisitor + { + readonly IType objectType; + + public DynamicErasure(Conversions conversions) + { + this.objectType = conversions.objectType; + } + + public override IType VisitOtherType(IType type) + { + if (type == SharedTypes.Dynamic) + return objectType; + else + return base.VisitOtherType(type); + } + } + #endregion + + #region ImplicitNumericConversion + static readonly bool[,] implicitNumericConversionLookup = { + // to: short ushort int uint long ulong + // from: + /* char */ { false, true , true , true , true , true }, + /* sbyte */ { true , false, true , false, true , false }, + /* byte */ { true , true , true , true , true , true }, + /* short */ { false, false, true , false, true , false }, + /* ushort */ { false, false, true , true , true , true }, + /* int */ { false, false, false, false, true , false }, + /* uint */ { false, false, false, false, true , true }, + }; + + bool ImplicitNumericConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.2 + + TypeCode from = ReflectionHelper.GetTypeCode(fromType); + TypeCode to = ReflectionHelper.GetTypeCode(toType); + if (to >= TypeCode.Single && to <= TypeCode.Decimal) { + // Conversions to float/double/decimal exist from all integral types, + // and there's a conversion from float to double. + return from >= TypeCode.Char && from <= TypeCode.UInt64 + || from == TypeCode.Single && to == TypeCode.Double; + } else { + // Conversions to integral types: look at the table + return from >= TypeCode.Char && from <= TypeCode.UInt32 + && to >= TypeCode.Int16 && to <= TypeCode.UInt64 + && implicitNumericConversionLookup[from - TypeCode.Char, to - TypeCode.Int16]; + } + } + #endregion + + #region ImplicitEnumerationConversion + bool ImplicitEnumerationConversion(ResolveResult rr, IType toType) + { + // C# 4.0 spec: §6.1.3 + TypeCode constantType = ReflectionHelper.GetTypeCode(rr.Type); + if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) { + return NullableType.GetUnderlyingType(toType).IsEnum(); + } + return false; + } + #endregion + + #region ImplicitNullableConversion + bool ImplicitNullableConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.4 + if (NullableType.IsNullable(toType)) { + IType t = NullableType.GetUnderlyingType(toType); + IType s = NullableType.GetUnderlyingType(fromType); // might or might not be nullable + return IdentityConversion(s, t) || ImplicitNumericConversion(s, t); + } else { + return false; + } + } + #endregion + + #region NullLiteralConversion + bool NullLiteralConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.5 + return fromType == SharedTypes.Null && NullableType.IsNullable(toType); + // This function only handles the conversion from the null literal to nullable value types, + // reference types are handled by ImplicitReferenceConversion instead. + } + #endregion + + #region ImplicitReferenceConversion + public bool ImplicitReferenceConversion(IType fromType, IType toType) + { + // 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)) + return false; + + // conversion from null literal is always possible + if (fromType == SharedTypes.Null) + return true; + + ArrayType fromArray = fromType as ArrayType; + if (fromArray != null) { + ArrayType toArray = toType as ArrayType; + if (toArray != null) { + // array covariance (the broken kind) + return fromArray.Dimensions == toArray.Dimensions + && ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType); + } + // conversion from single-dimensional array S[] to IList: + ParameterizedType toPT = toType as ParameterizedType; + if (fromArray.Dimensions == 1 && toPT != null && toPT.TypeArguments.Count == 1 + && toPT.Namespace == "System.Collections.Generic" + && (toPT.Name == "IList" || toPT.Name == "ICollection" || toPT.Name == "IEnumerable")) + { + // array covariance plays a part here as well (string[] is IList) + return IdentityConversion(fromArray.ElementType, toPT.TypeArguments[0]) + || ImplicitReferenceConversion(fromArray.ElementType, toPT.TypeArguments[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)); + } + + // now comes the hard part: traverse the inheritance chain and figure out generics+variance + return IsSubtypeOf(fromType, toType); + } + + // Determines whether s is a subtype of t. + // Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion + bool IsSubtypeOf(IType s, IType t) + { + // conversion to dynamic + object are always possible + if (t == SharedTypes.Dynamic || t.Equals(objectType)) + return true; + + // let GetAllBaseTypes do the work for us + foreach (IType baseType in s.GetAllBaseTypes(context)) { + if (IdentityOrVarianceConversion(baseType, t)) + return true; + } + return false; + } + + bool IdentityOrVarianceConversion(IType s, IType t) + { + ITypeDefinition def = s.GetDefinition(); + if (def != null && def.Equals(t.GetDefinition())) { + ParameterizedType ps = s as ParameterizedType; + ParameterizedType pt = t as ParameterizedType; + if (ps != null && pt != null + && ps.TypeArguments.Count == pt.TypeArguments.Count + && ps.TypeArguments.Count == def.TypeParameters.Count) + { + // C# 4.0 spec: §13.1.3.2 Variance Conversion + for (int i = 0; i < def.TypeParameters.Count; i++) { + IType si = ps.TypeArguments[i]; + IType ti = pt.TypeArguments[i]; + if (IdentityConversion(si, ti)) + continue; + ITypeParameter xi = def.TypeParameters[i]; + switch (xi.Variance) { + case VarianceModifier.Covariant: + if (!ImplicitReferenceConversion(si, ti)) + return false; + break; + case VarianceModifier.Contravariant: + if (!ImplicitReferenceConversion(ti, si)) + return false; + break; + default: + return false; + } + } + } else if (ps != null || pt != null) { + return false; // only of of them is parameterized, or counts don't match? -> not valid conversion + } + return true; + } + return false; + } + #endregion + + #region BoxingConversion + bool BoxingConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.7 + fromType = NullableType.GetUnderlyingType(fromType); + return fromType.IsReferenceType(context) == false && toType.IsReferenceType(context) == true && IsSubtypeOf(fromType, toType); + } + #endregion + + #region ImplicitDynamicConversion + bool ImplicitDynamicConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.8 + return fromType == SharedTypes.Dynamic; + } + #endregion + + #region ImplicitConstantExpressionConversion + bool ImplicitConstantExpressionConversion(ResolveResult rr, IType toType) + { + // C# 4.0 spec: §6.1.9 + TypeCode fromTypeCode = ReflectionHelper.GetTypeCode(rr.Type); + TypeCode toTypeCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(toType)); + if (fromTypeCode == TypeCode.Int64) { + long val = (long)rr.ConstantValue; + return val >= 0 && toTypeCode == TypeCode.UInt64; + } else if (fromTypeCode == TypeCode.Int32) { + int val = (int)rr.ConstantValue; + switch (toTypeCode) { + case TypeCode.SByte: + return val >= SByte.MinValue && val <= SByte.MaxValue; + case TypeCode.Byte: + return val >= Byte.MinValue && val <= Byte.MaxValue; + case TypeCode.Int16: + return val >= Int16.MinValue && val <= Int16.MaxValue; + case TypeCode.UInt16: + return val >= UInt16.MinValue && val <= UInt16.MaxValue; + case TypeCode.UInt32: + return val >= 0; + case TypeCode.UInt64: + return val >= 0; + } + } + return false; + } + #endregion + + #region ImplicitTypeParameterConversion + /// + /// Implicit conversions involving type parameters. + /// + bool ImplicitTypeParameterConversion(IType fromType, IType toType) + { + ITypeParameter t = fromType as ITypeParameter; + if (t == null) + return false; // not a type parameter + if (t.IsReferenceType(context) == true) + return false; // already handled by ImplicitReferenceConversion + return IsSubtypeOf(t, toType); + } + #endregion + + #region ImplicitPointerConversion + bool ImplicitPointerConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §18.4 Pointer conversions + if (fromType is PointerType && toType is PointerType && toType.ReflectionName == "System.Void*") + return true; + if (fromType == SharedTypes.Null && toType is PointerType) + return true; + return false; + } + #endregion + + #region ImplicitUserDefinedConversion + bool ImplicitUserDefinedConversion(IType fromType, IType toType) + { + // C# 4.0 spec §6.4.4 User-defined implicit conversions + // Currently we only test whether an applicable implicit conversion exists, + // we do not resolve which conversion is the most specific and gets used. + + // Find the candidate operators: + Predicate opImplicitFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1; + var operators = NullableType.GetUnderlyingType(fromType).GetMethods(context, opImplicitFilter) + .Concat(NullableType.GetUnderlyingType(toType).GetMethods(context, opImplicitFilter)); + // Determine whether one of them is applicable: + foreach (IMethod op in operators) { + IType sourceType = op.Parameters[0].Type.Resolve(context); + IType targetType = op.ReturnType.Resolve(context); + // Try if the operator is applicable: + if (StandardImplicitConversion(fromType, sourceType) && StandardImplicitConversion(targetType, toType)) { + return true; + } + // Try if the operator is applicable in lifted form: + if (sourceType.IsReferenceType(context) == false && targetType.IsReferenceType(context) == false) { + IType liftedSourceType = NullableType.Create(sourceType, context); + IType liftedTargetType = NullableType.Create(targetType, context); + if (StandardImplicitConversion(fromType, liftedSourceType) && StandardImplicitConversion(liftedTargetType, toType)) { + return true; + } + } + } + return false; + } + #endregion + + #region BetterConversion + /// + /// Gets the better conversion (C# 4.0 spec, §7.5.3.3) + /// + /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better + public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) + { + // TODO: implement the special logic for anonymous functions + return BetterConversion(resolveResult.Type, t1, t2); + } + + /// + /// Gets the better conversion (C# 4.0 spec, §7.5.3.4) + /// + /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better + public int BetterConversion(IType s, IType t1, IType t2) + { + bool ident1 = IdentityConversion(s, t1); + bool ident2 = IdentityConversion(s, t2); + if (ident1 && !ident2) + return 1; + if (ident2 && !ident1) + return 2; + return BetterConversionTarget(t1, t2); + } + + /// + /// Gets the better conversion target (C# 4.0 spec, §7.5.3.5) + /// + /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better + int BetterConversionTarget(IType t1, IType t2) + { + bool t1To2 = ImplicitConversion(t1, t2); + bool t2To1 = ImplicitConversion(t2, t1); + if (t1To2 && !t2To1) + return 1; + if (t2To1 && !t1To2) + return 2; + TypeCode t1Code = ReflectionHelper.GetTypeCode(t1); + TypeCode t2Code = ReflectionHelper.GetTypeCode(t2); + if (IsBetterIntegralType(t1Code, t2Code)) + return 1; + if (IsBetterIntegralType(t2Code, t1Code)) + return 2; + return 0; + } + + bool IsBetterIntegralType(TypeCode t1, TypeCode t2) + { + // signed types are better than unsigned types + switch (t1) { + case TypeCode.SByte: + return t2 == TypeCode.Byte || t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; + case TypeCode.Int16: + return t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; + case TypeCode.Int32: + return t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; + case TypeCode.Int64: + return t2 == TypeCode.UInt64; + default: + return false; + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs new file mode 100644 index 0000000000..75a36470fc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a resolve error. + /// + public class ErrorResolveResult : ResolveResult + { + public ErrorResolveResult(IType type) : base(type) + { + } + + public override bool IsError { + get { return true; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs new file mode 100644 index 0000000000..be956b22fa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Allows controlling which nodes are resolved by the resolve visitor. + /// + /// + public interface IResolveVisitorNavigator + { + ResolveVisitorNavigationMode Scan(AstNode node); + } + + /// + /// Represents the operation mode of the resolve visitor. + /// + /// + public enum ResolveVisitorNavigationMode + { + /// + /// Scan into the children of the current node, without resolving the current node. + /// + Scan, + /// + /// Skip the current node - do not scan into it; do not resolve it. + /// + Skip, + /// + /// Resolve the current node; but only scan subnodes which are not required for resolving the current node. + /// + Resolve, + /// + /// Resolves all nodes in the current subtree. + /// + ResolveAll + } + + sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator + { + ResolveVisitorNavigationMode mode; + + public static readonly IResolveVisitorNavigator Skip = new ConstantModeResolveVisitorNavigator { mode = ResolveVisitorNavigationMode.Skip }; + + ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node) + { + return mode; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs new file mode 100644 index 0000000000..fdca6acb3e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs @@ -0,0 +1,24 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a reference which could point to a type or namespace. + /// + public interface ITypeOrNamespaceReference : ITypeReference + { + /// + /// Resolves the reference and returns the ResolveResult. + /// + ResolveResult DoResolve(ITypeResolveContext context); + + /// + /// Returns the namespace that is referenced; or null if no such namespace is found. + /// + NamespaceResolveResult ResolveNamespace(ITypeResolveContext context); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs new file mode 100644 index 0000000000..1309466700 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs @@ -0,0 +1,47 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a local variable. + /// + public class LocalResolveResult : ResolveResult + { + readonly IVariable variable; + readonly object constantValue; + + public LocalResolveResult(IVariable variable, IType type, object constantValue = null) + : base(type) + { + if (variable == null) + throw new ArgumentNullException("variable"); + this.variable = variable; + this.constantValue = constantValue; + } + + public IVariable Variable { + get { return variable; } + } + + public bool IsParameter { + get { return variable is IParameter; } + } + + public override bool IsCompileTimeConstant { + get { return variable.IsConst; } + } + + public override object ConstantValue { + get { return constantValue; } + } + + public override string ToString() + { + return string.Format("[VariableResolveResult {0}]", variable); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs new file mode 100644 index 0000000000..14cc7ccb1b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs @@ -0,0 +1,49 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Converts a type by replacing all type definitions with the equivalent definitions in the new context. + /// + sealed class MapTypeIntoNewContext : TypeVisitor + { + readonly ITypeResolveContext context; + + public MapTypeIntoNewContext(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + } + + public override IType VisitTypeDefinition(ITypeDefinition type) + { + if (type.DeclaringTypeDefinition != null) { + ITypeDefinition decl = type.DeclaringTypeDefinition.AcceptVisitor(this) as ITypeDefinition; + if (decl != null) { + foreach (ITypeDefinition c in decl.NestedTypes) { + if (c.Name == type.Name && c.TypeParameterCount == type.TypeParameterCount) + return c; + } + } + return type; + } else { + return context.GetTypeDefinition(type.Namespace, type.Name, type.TypeParameterCount, StringComparer.Ordinal) ?? type; + } + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + // TODO: how to map type parameters? + // It might have constraints, and those constraints might be mutually recursive. + // Maybe reintroduce ITypeParameter.Owner? + throw new NotImplementedException(); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs new file mode 100644 index 0000000000..06c1e67bcb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs @@ -0,0 +1,274 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Implementation of member lookup (C# 4.0 spec, §7.4). + /// + public class MemberLookup + { + #region Static helper methods + /// + /// Gets whether the member is considered to be invocable. + /// + public static bool IsInvocable(IMember member, ITypeResolveContext context) + { + if (member == null) + throw new ArgumentNullException("member"); + // C# 4.0 spec, §7.4 member lookup + if (member is IEvent || member is IMethod) + return true; + IType returnType = member.ReturnType.Resolve(context); + if (returnType == SharedTypes.Dynamic) + return true; + return returnType.IsDelegate(); + } + #endregion + + ITypeResolveContext context; + ITypeDefinition currentTypeDefinition; + IProjectContent currentProject; + + public MemberLookup(ITypeResolveContext context, ITypeDefinition currentTypeDefinition, IProjectContent currentProject) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + this.currentTypeDefinition = currentTypeDefinition; + this.currentProject = currentProject; + } + + #region IsAccessible + public bool IsProtectedAccessAllowed(IType targetType) + { + ITypeDefinition typeDef = targetType.GetDefinition(); + return typeDef != null && typeDef.IsDerivedFrom(currentTypeDefinition, context); + } + + /// + /// Gets whether is accessible in the current class. + /// + /// The entity to test + /// Whether protected access is allowed. + /// True if the type of the reference is derived from the current class. + public bool IsAccessible(IEntity entity, bool allowProtectedAccess) + { + if (entity == null) + throw new ArgumentNullException("entity"); + // C# 4.0 spec, §3.5.2 Accessiblity domains + switch (entity.Accessibility) { + case Accessibility.None: + return false; + case Accessibility.Private: + // check for members of outer classes (private members of outer classes can be accessed) + var lookupTypeDefinition = currentTypeDefinition; + while (lookupTypeDefinition != null) { + if (entity.DeclaringTypeDefinition.Equals (lookupTypeDefinition)) + return true; + lookupTypeDefinition = lookupTypeDefinition.DeclaringTypeDefinition; + } + return false; + case Accessibility.Public: + return true; + case Accessibility.Protected: + return allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition); + case Accessibility.Internal: + return IsInternalAccessible(entity.ProjectContent); + case Accessibility.ProtectedOrInternal: + return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) + || IsInternalAccessible(entity.ProjectContent); + case Accessibility.ProtectedAndInternal: + return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) + && IsInternalAccessible(entity.ProjectContent); + default: + throw new Exception("Invalid value for Accessibility"); + } + } + + bool IsInternalAccessible(IProjectContent declaringProject) + { + return declaringProject != null && currentProject != null && declaringProject.InternalsVisibleTo(currentProject, context); + } + + bool IsProtectedAccessible(ITypeDefinition declaringType) + { + if (declaringType.Equals (currentTypeDefinition)) + return true; + // PERF: this might hurt performance as this method is called several times (once for each member) + // make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance + return currentTypeDefinition != null && currentTypeDefinition.IsDerivedFrom(declaringType, context); + } + #endregion + + public ResolveResult LookupType(IType declaringType, string name, IList typeArguments) + { + int typeArgumentCount = typeArguments.Count; + Predicate typeFilter = delegate (ITypeDefinition d) { + return d.TypeParameterCount == typeArgumentCount && d.Name == name && IsAccessible(d, true); + }; + List types = declaringType.GetNestedTypes(context, typeFilter).ToList(); + RemoveTypesHiddenByOtherTypes(types); + if (types.Count > 0) + return CreateTypeResolveResult(types[0], types.Count > 1, typeArguments); + else + return new UnknownMemberResolveResult(declaringType, name, typeArguments); + } + + void RemoveTypesHiddenByOtherTypes(List types) + { + for (int i = types.Count - 1; i >= 0; i--) { + ITypeDefinition d = GetDeclaringTypeDef(types[i]); + if (d == null) + continue; + // nested loop depends on the fact that the members of more derived classes appear later in the list + for (int j = i + 1; j < types.Count; j++) { + if (types[i].TypeParameterCount != types[j].TypeParameterCount) + continue; + ITypeDefinition s = GetDeclaringTypeDef(types[j]); + if (s != null && s != d && s.IsDerivedFrom(d, context)) { + // types[j] hides types[i] + types.RemoveAt(i); + break; + } + } + } + } + + ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList typeArguments) + { + if (typeArguments.Count > 0) { + // parameterize the type if necessary + ITypeDefinition returnedTypeDef = returnedType as ITypeDefinition; + if (returnedTypeDef != null) + returnedType = new ParameterizedType(returnedTypeDef, typeArguments); + } + if (isAmbiguous) + return new AmbiguousTypeResolveResult(returnedType); + else + return new TypeResolveResult(returnedType); + } + + /// + /// Performs a member lookup. + /// + public ResolveResult Lookup(IType type, string name, IList typeArguments, bool isInvocation) + { + int typeArgumentCount = typeArguments.Count; + + List types = new List(); + List members = new List(); + if (!isInvocation) { + // Consider nested types only if it's not an invocation. The type parameter count must match in this case. + Predicate typeFilter = delegate (ITypeDefinition d) { + // inner types contain the type parameters of outer types. therefore this count has to been adjusted. + int correctedCount = d.TypeParameterCount - (d.DeclaringType != null ? d.DeclaringType.TypeParameterCount : 0); + return correctedCount == typeArgumentCount && d.Name == name && IsAccessible(d, true); + }; + types.AddRange(type.GetNestedTypes(context, typeFilter)); + } + + bool allowProtectedAccess = IsProtectedAccessAllowed(type); + + if (typeArgumentCount == 0) { + Predicate memberFilter = delegate(IMember member) { + return !member.IsOverride && member.Name == name && IsAccessible(member, allowProtectedAccess); + }; + members.AddRange(type.GetMembers(context, memberFilter)); + if (isInvocation) + members.RemoveAll(m => !IsInvocable(m, context)); + } else { + // No need to check for isInvocation/isInvocable here: + // we filter out all non-methods + Predicate memberFilter = delegate(IMethod method) { + return method.TypeParameters.Count == typeArgumentCount + && !method.IsOverride && method.Name == name && IsAccessible(method, allowProtectedAccess); + }; + members.AddRange(type.GetMethods(context, memberFilter).SafeCast()); + } + + // TODO: can't members also hide types? + + RemoveTypesHiddenByOtherTypes(types); + // remove members hidden by types + for (int i = 0; i < types.Count; i++) { + ITypeDefinition d = GetDeclaringTypeDef(types[i]); + if (d != null) + members.RemoveAll(m => d.IsDerivedFrom(m.DeclaringTypeDefinition, context)); + } + // remove members hidden by other members + for (int i = members.Count - 1; i >= 0; i--) { + ITypeDefinition d = members[i].DeclaringTypeDefinition; + IMethod mi = members[i] as IMethod; + // nested loop depends on the fact that the members of more derived classes appear later in the list + for (int j = i + 1; j < members.Count; j++) { + if (mi != null) { + IMethod mj = members[j] as IMethod; + if (mj != null && !ParameterListComparer.Instance.Equals(mi, mj)) + continue; + } + ITypeDefinition s = members[j].DeclaringTypeDefinition; + if (s != null && s != d && s.IsDerivedFrom(d, context)) { + // members[j] hides members[i] + members.RemoveAt(i); + break; + } + } + } + // remove interface members hidden by class members + if (type is ITypeParameter) { + // this can happen only with type parameters + for (int i = members.Count - 1; i >= 0; i--) { + ITypeDefinition d = members[i].DeclaringTypeDefinition; + if (d.ClassType != ClassType.Interface) + continue; + IMethod mi = members[i] as IMethod; + for (int j = 0; j < members.Count; j++) { + if (mi != null) { + IMethod mj = members[j] as IMethod; + if (mj != null && !ParameterListComparer.Instance.Equals(mi, mj)) + continue; + } + ITypeDefinition s = members[j].DeclaringTypeDefinition; + if (s != null && IsNonInterfaceType(s)) { + // members[j] hides members[i] + members.RemoveAt(i); + break; + } + } + } + } + + if (types.Count > 0) { + bool isAmbiguous = !(types.Count == 1 && members.Count == 0); + return CreateTypeResolveResult(types[0], isAmbiguous, typeArguments); + } + if (members.Count == 0) + return new UnknownMemberResolveResult(type, name, typeArguments); + IMember firstNonMethod = members.FirstOrDefault(m => !(m is IMethod)); + if (members.Count == 1 && firstNonMethod != null) + return new MemberResolveResult(firstNonMethod, context); + if (firstNonMethod == null) + return new MethodGroupResolveResult(type, name, members.ConvertAll(m => (IMethod)m), typeArguments); + return new AmbiguousMemberResultResult(firstNonMethod, firstNonMethod.ReturnType.Resolve(context)); + } + + static bool IsNonInterfaceType(ITypeDefinition def) + { + // return type if def is neither an interface nor System.Object + return def.ClassType != ClassType.Interface && !(def.Name == "Object" && def.Namespace == "System" && def.TypeParameterCount == 0); + } + + static ITypeDefinition GetDeclaringTypeDef(IType type) + { + IType declType = type.DeclaringType; + return declType != null ? declType.GetDefinition() : null; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs new file mode 100644 index 0000000000..f6994ef3a8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs @@ -0,0 +1,62 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents the result of a member invocation. + /// + public class MemberResolveResult : ResolveResult + { + readonly IMember member; + readonly bool isConstant; + readonly object constantValue; + + public MemberResolveResult(IMember member, IType returnType) : base(returnType) + { + if (member == null) + throw new ArgumentNullException("member"); + this.member = member; + } + + public MemberResolveResult(IMember member, IType returnType, object constantValue) : base(returnType) + { + if (member == null) + throw new ArgumentNullException("member"); + this.member = member; + this.isConstant = true; + this.constantValue = constantValue; + } + + public MemberResolveResult(IMember member, ITypeResolveContext context) : base(member.ReturnType.Resolve(context)) + { + this.member = member; + IField field = member as IField; + if (field != null) { + isConstant = field.IsConst; + if (isConstant) + constantValue = field.ConstantValue.GetValue(context); + } + } + + public IMember Member { + get { return member; } + } + + public override bool IsCompileTimeConstant { + get { return isConstant; } + } + + public override object ConstantValue { + get { return constantValue; } + } + + public override string ToString() + { + return string.Format("[{0} {1}]", GetType().Name, member); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs new file mode 100644 index 0000000000..c6c9e00a43 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -0,0 +1,79 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Reference to a qualified type or namespace name. + /// + public sealed class MemberTypeOrNamespaceReference : ITypeOrNamespaceReference + { + readonly ITypeOrNamespaceReference target; + readonly ITypeDefinition parentTypeDefinition; + readonly UsingScope parentUsingScope; + readonly string identifier; + readonly IList typeArguments; + + public MemberTypeOrNamespaceReference(ITypeOrNamespaceReference target, string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope) + { + if (target == null) + throw new ArgumentNullException("target"); + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.target = target; + this.identifier = identifier; + this.typeArguments = typeArguments ?? EmptyList.Instance; + this.parentTypeDefinition = parentTypeDefinition; + this.parentUsingScope = parentUsingScope; + } + + /// + /// Adds a suffix to the identifier. + /// Does not modify the existing type reference, but returns a new one. + /// + public MemberTypeOrNamespaceReference AddSuffix(string suffix) + { + return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope); + } + + public ResolveResult DoResolve(ITypeResolveContext context) + { + ResolveResult targetRR = target.DoResolve(context); + if (targetRR.IsError) + return targetRR; + CSharpResolver r = new CSharpResolver(context); + r.CurrentTypeDefinition = parentTypeDefinition != null ? parentTypeDefinition.GetCompoundClass() : null; + r.UsingScope = parentUsingScope; + IType[] typeArgs = new IType[typeArguments.Count]; + for (int i = 0; i < typeArgs.Length; i++) { + typeArgs[i] = typeArguments[i].Resolve(context); + } + return r.ResolveMemberAccess(targetRR, identifier, typeArgs, false); + } + + public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible + return DoResolve(context) as NamespaceResolveResult; + } + + public IType Resolve(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible; then map the result type into the new context + TypeResolveResult rr = DoResolve(context) as TypeResolveResult; + return rr != null ? rr.Type : SharedTypes.UnknownType; + } + + public override string ToString() + { + if (typeArguments.Count == 0) + return target.ToString() + "." + identifier; + else + return target.ToString() + "." + identifier + "<" + DotNet35Compat.StringJoin(",", typeArguments) + ">"; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs new file mode 100644 index 0000000000..ec456a013e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a group of methods. + /// + public class MethodGroupResolveResult : ResolveResult + { + readonly ReadOnlyCollection methods; + readonly ReadOnlyCollection typeArguments; + readonly IType targetType; + readonly string methodName; + + /// + /// List of extension methods, used to avoid re-calculating it in ResolveInvocation() when it was already + /// calculated by ResolveMemberAccess(). + /// + internal List> ExtensionMethods; + + public MethodGroupResolveResult(IType targetType, string methodName, IList methods, IList typeArguments) : base(SharedTypes.UnknownType) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + if (methods == null) + throw new ArgumentNullException("methods"); + this.targetType = targetType; + this.methodName = methodName; + this.methods = new ReadOnlyCollection(methods); + this.typeArguments = typeArguments != null ? new ReadOnlyCollection(typeArguments) : EmptyList.Instance; + } + + public IType TargetType { + get { return targetType; } + } + + public string MethodName { + get { return methodName; } + } + + public ReadOnlyCollection Methods { + get { return methods; } + } + + public ReadOnlyCollection TypeArguments { + get { return typeArguments; } + } + + public override string ToString() + { + return string.Format("[{0} with {1} method(s)]", GetType().Name, methods.Count); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs new file mode 100644 index 0000000000..8b4ed998b4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs @@ -0,0 +1,30 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents that an expression resolved to a namespace. + /// + public class NamespaceResolveResult : ResolveResult + { + readonly string namespaceName; + + public NamespaceResolveResult(string namespaceName) : base(SharedTypes.UnknownType) + { + this.namespaceName = namespaceName; + } + + public string NamespaceName { + get { return namespaceName; } + } + + public override string ToString() + { + return string.Format("[{0} {1}]", GetType().Name, namespaceName); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs new file mode 100644 index 0000000000..5ed4c619e3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// implementation that resolves a list of nodes. + /// We will skip all nodes which are not the target nodes or ancestors of the target nodes. + /// + public sealed class NodeListResolveVisitorNavigator : IResolveVisitorNavigator + { + readonly Dictionary dict = new Dictionary(); + + /// + /// Creates a new NodeListResolveVisitorNavigator that resolves the specified nodes. + /// + public NodeListResolveVisitorNavigator(IEnumerable nodes) + { + if (nodes == null) + throw new ArgumentNullException("nodes"); + foreach (var node in nodes) { + dict[node] = ResolveVisitorNavigationMode.Resolve; + for (var ancestor = node.Parent; ancestor != null && !dict.ContainsKey(ancestor); ancestor = ancestor.Parent) { + dict.Add(ancestor, ResolveVisitorNavigationMode.Scan); + } + } + } + + /// + public ResolveVisitorNavigationMode Scan(AstNode node) + { + ResolveVisitorNavigationMode mode; + if (dict.TryGetValue(node, out mode)) { + return mode; + } else { + return ResolveVisitorNavigationMode.Skip; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs new file mode 100644 index 0000000000..e3942491af --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs @@ -0,0 +1,550 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// C# overload resolution (C# 4.0 spec: §7.5). + /// + public class OverloadResolution + { + sealed class Candidate + { + public readonly IParameterizedMember Member; + + /// + /// Returns the normal form candidate, if this is an expanded candidate. + /// + public readonly bool IsExpandedForm; + + public readonly IType[] ParameterTypes; + + /// + /// argument index -> parameter index; -1 for arguments that could not be mapped + /// + public int[] ArgumentToParameterMap; + + public OverloadResolutionErrors Errors; + public int ErrorCount; + + public bool HasUnmappedOptionalParameters; + + public IType[] InferredTypes; + + public IList Parameters { get { return Member.Parameters; } } + + public bool IsGenericMethod { + get { + IMethod method = Member as IMethod; + return method != null && method.TypeParameters.Count > 0; + } + } + + public int ArgumentsPassedToParamsArray { + get { + int count = 0; + if (IsExpandedForm) { + int paramsParameterIndex = this.Parameters.Count - 1; + foreach (int parameterIndex in ArgumentToParameterMap) { + if (parameterIndex == paramsParameterIndex) + count++; + } + } + return count; + } + } + + public Candidate(IParameterizedMember member, bool isExpanded) + { + this.Member = member; + this.IsExpandedForm = isExpanded; + this.ParameterTypes = new IType[member.Parameters.Count]; + } + + public void AddError(OverloadResolutionErrors newError) + { + this.Errors |= newError; + this.ErrorCount++; + } + } + + readonly ITypeResolveContext context; + readonly ResolveResult[] arguments; + readonly string[] argumentNames; + readonly Conversions conversions; + //List candidates = new List(); + Candidate bestCandidate; + Candidate bestCandidateAmbiguousWith; + IType[] explicitlyGivenTypeArguments; + + #region Constructor + public OverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null) + { + if (context == null) + throw new ArgumentNullException("context"); + if (arguments == null) + throw new ArgumentNullException("arguments"); + if (argumentNames == null) + argumentNames = new string[arguments.Length]; + else if (argumentNames.Length != arguments.Length) + throw new ArgumentException("argumentsNames.Length must be equal to arguments.Length"); + this.context = context; + this.arguments = arguments; + this.argumentNames = argumentNames; + + // keep explicitlyGivenTypeArguments==null when no type arguments were specified + if (typeArguments != null && typeArguments.Length > 0) + this.explicitlyGivenTypeArguments = typeArguments; + + this.conversions = new Conversions(context); + } + #endregion + + #region AddCandidate + public OverloadResolutionErrors AddCandidate(IParameterizedMember member) + { + if (member == null) + throw new ArgumentNullException("member"); + + Candidate c = new Candidate(member, false); + if (CalculateCandidate(c)) { + //candidates.Add(c); + } + + if (member.Parameters.Count > 0 && member.Parameters[member.Parameters.Count - 1].IsParams) { + Candidate expandedCandidate = new Candidate(member, true); + // consider expanded form only if it isn't obviously wrong + if (CalculateCandidate(expandedCandidate)) { + //candidates.Add(expandedCandidate); + + if (expandedCandidate.ErrorCount < c.ErrorCount) + return expandedCandidate.Errors; + } + } + return c.Errors; + } + + /// + /// Calculates applicability etc. for the candidate. + /// + /// True if the calculation was successful, false if the candidate should be removed without reporting an error + bool CalculateCandidate(Candidate candidate) + { + if (!ResolveParameterTypes(candidate)) + return false; + MapCorrespondingParameters(candidate); + RunTypeInference(candidate); + CheckApplicability(candidate); + ConsiderIfNewCandidateIsBest(candidate); + return true; + } + + bool ResolveParameterTypes(Candidate candidate) + { + for (int i = 0; i < candidate.Parameters.Count; i++) { + IType type = candidate.Parameters[i].Type.Resolve(context); + if (candidate.IsExpandedForm && i == candidate.Parameters.Count - 1) { + ArrayType arrayType = type as ArrayType; + if (arrayType != null && arrayType.Dimensions == 1) + type = arrayType.ElementType; + else + return false; // error: cannot unpack params-array. abort considering the expanded form for this candidate + } + candidate.ParameterTypes[i] = type; + } + return true; + } + #endregion + + #region MapCorrespondingParameters + void MapCorrespondingParameters(Candidate candidate) + { + // C# 4.0 spec: §7.5.1.1 Corresponding parameters + candidate.ArgumentToParameterMap = new int[arguments.Length]; + for (int i = 0; i < arguments.Length; i++) { + candidate.ArgumentToParameterMap[i] = -1; + if (argumentNames[i] == null) { + // positional argument + if (i < candidate.ParameterTypes.Length) { + candidate.ArgumentToParameterMap[i] = i; + } else if (candidate.IsExpandedForm) { + candidate.ArgumentToParameterMap[i] = candidate.ParameterTypes.Length - 1; + } else { + candidate.AddError(OverloadResolutionErrors.TooManyPositionalArguments); + } + } else { + // named argument + for (int j = 0; j < candidate.Member.Parameters.Count; j++) { + if (argumentNames[i] == candidate.Member.Parameters[j].Name) { + candidate.ArgumentToParameterMap[i] = j; + } + } + if (candidate.ArgumentToParameterMap[i] < 0) + candidate.AddError(OverloadResolutionErrors.NoParameterFoundForNamedArgument); + } + } + } + #endregion + + #region RunTypeInference + void RunTypeInference(Candidate candidate) + { + IMethod method = candidate.Member as IMethod; + if (method == null || method.TypeParameters.Count == 0) { + if (explicitlyGivenTypeArguments != null) { + // method does not expect type arguments, but was given some + candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); + } + return; + } + // The method is generic: + if (explicitlyGivenTypeArguments != null) { + if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) { + candidate.InferredTypes = explicitlyGivenTypeArguments; + } else { + candidate.AddError(OverloadResolutionErrors.WrongNumberOfTypeArguments); + // wrong number of type arguments given, so truncate the list or pad with UnknownType + candidate.InferredTypes = new IType[method.TypeParameters.Count]; + for (int i = 0; i < candidate.InferredTypes.Length; i++) { + if (i < explicitlyGivenTypeArguments.Length) + candidate.InferredTypes[i] = explicitlyGivenTypeArguments[i]; + else + candidate.InferredTypes[i] = SharedTypes.UnknownType; + } + } + } else { + TypeInference ti = new TypeInference(context, conversions); + bool success; + candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success); + if (!success) + candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); + } + // Now substitute in the formal parameters: + var substitution = new ConstraintValidatingSubstitution(candidate.InferredTypes, this); + for (int i = 0; i < candidate.ParameterTypes.Length; i++) { + candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); + } + if (!substitution.ConstraintsValid) + candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint); + } + + sealed class ConstraintValidatingSubstitution : MethodTypeParameterSubstitution + { + readonly OverloadResolution overloadResolution; + public bool ConstraintsValid = true; + + public ConstraintValidatingSubstitution(IType[] typeArguments, OverloadResolution overloadResolution) + : base(typeArguments) + { + this.overloadResolution = overloadResolution; + } + + public override IType VisitParameterizedType(ParameterizedType type) + { + IType newType = base.VisitParameterizedType(type); + if (newType != type && ConstraintsValid) { + // something was changed, so we need to validate the constraints + ParameterizedType newParameterizedType = newType as ParameterizedType; + if (newParameterizedType != null) { + // C# 4.0 spec: §4.4.4 Satisfying constraints + var typeParameters = newParameterizedType.GetDefinition().TypeParameters; + for (int i = 0; i < typeParameters.Count; i++) { + ITypeParameter tp = typeParameters[i]; + IType typeArg = newParameterizedType.TypeArguments[i]; + if (tp.HasReferenceTypeConstraint) { + if (typeArg.IsReferenceType(overloadResolution.context) != true) + ConstraintsValid = false; + } + if (tp.HasValueTypeConstraint) { + if (typeArg.IsReferenceType(overloadResolution.context) != false) + ConstraintsValid = false; + if (NullableType.IsNullable(typeArg)) + ConstraintsValid = false; + } + if (tp.HasDefaultConstructorConstraint) { + ITypeDefinition def = typeArg.GetDefinition(); + if (def != null && def.IsAbstract) + ConstraintsValid = false; + ConstraintsValid &= typeArg.GetConstructors( + overloadResolution.context, + m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public + ).Any(); + } + foreach (IType constraintType in tp.Constraints) { + IType c = newParameterizedType.SubstituteInType(constraintType); + ConstraintsValid &= overloadResolution.IsConstraintConvertible(typeArg, c); + } + } + } + } + return newType; + } + } + + bool IsConstraintConvertible(IType typeArg, IType constraintType) + { + // TODO: this isn't exactly correct; not all kinds of implicit conversions are allowed here + return conversions.ImplicitConversion(typeArg, constraintType); + } + #endregion + + #region CheckApplicability + void CheckApplicability(Candidate candidate) + { + // C# 4.0 spec: §7.5.3.1 Applicable function member + + // Test whether parameters were mapped the correct number of arguments: + int[] argumentCountPerParameter = new int[candidate.ParameterTypes.Length]; + foreach (int parameterIndex in candidate.ArgumentToParameterMap) { + if (parameterIndex >= 0) + argumentCountPerParameter[parameterIndex]++; + } + for (int i = 0; i < argumentCountPerParameter.Length; i++) { + if (candidate.IsExpandedForm && i == argumentCountPerParameter.Length - 1) + continue; // any number of arguments is fine for the params-array + if (argumentCountPerParameter[i] == 0) { + if (candidate.Parameters[i].IsOptional) + candidate.HasUnmappedOptionalParameters = true; + else + candidate.AddError(OverloadResolutionErrors.MissingArgumentForRequiredParameter); + } else if (argumentCountPerParameter[i] > 1) { + candidate.AddError(OverloadResolutionErrors.MultipleArgumentsForSingleParameter); + } + } + + // Test whether argument passing mode matches the parameter passing mode + for (int i = 0; i < arguments.Length; i++) { + int parameterIndex = candidate.ArgumentToParameterMap[i]; + if (parameterIndex < 0) continue; + + ByReferenceResolveResult brrr = arguments[i] as ByReferenceResolveResult; + if (brrr != null) { + if ((brrr.IsOut && !candidate.Parameters[parameterIndex].IsOut) || (brrr.IsRef && !candidate.Parameters[parameterIndex].IsRef)) + candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); + } else { + if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef) + candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); + } + if (!conversions.ImplicitConversion(arguments[i], candidate.ParameterTypes[parameterIndex])) + candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); + } + } + #endregion + + #region BetterFunctionMember + /// + /// Returns 1 if c1 is better than c2; 2 if c2 is better than c1; or 0 if neither is better. + /// + int BetterFunctionMember(Candidate c1, Candidate c2) + { + // prefer applicable members (part of heuristic that produces a best candidate even if none is applicable) + if (c1.ErrorCount == 0 && c2.ErrorCount > 0) + return 1; + if (c1.ErrorCount > 0 && c2.ErrorCount == 0) + return 2; + + // C# 4.0 spec: §7.5.3.2 Better function member + bool c1IsBetter = false; + bool c2IsBetter = false; + for (int i = 0; i < arguments.Length; i++) { + int p1 = c1.ArgumentToParameterMap[i]; + int p2 = c2.ArgumentToParameterMap[i]; + if (p1 >= 0 && p2 < 0) { + c1IsBetter = true; + } else if (p1 < 0 && p2 >= 0) { + c2IsBetter = true; + } else if (p1 >= 0 && p2 >= 0) { + switch (conversions.BetterConversion(arguments[i], c1.ParameterTypes[p1], c2.ParameterTypes[p2])) { + case 1: + c1IsBetter = true; + break; + case 2: + c2IsBetter = true; + break; + } + } + } + if (c1IsBetter && !c2IsBetter) + return 1; + if (!c1IsBetter && c2IsBetter) + return 2; + + // prefer members with less errors (part of heuristic that produces a best candidate even if none is applicable) + if (c1.ErrorCount < c2.ErrorCount) return 1; + if (c1.ErrorCount > c2.ErrorCount) return 2; + + if (!c1IsBetter && !c2IsBetter) { + // we need the tie-breaking rules + + // non-generic methods are better + if (!c1.IsGenericMethod && c2.IsGenericMethod) + return 1; + else if (c1.IsGenericMethod && !c2.IsGenericMethod) + return 2; + + // non-expanded members are better + if (!c1.IsExpandedForm && c2.IsExpandedForm) + return 1; + else if (c1.IsExpandedForm && !c2.IsExpandedForm) + return 2; + + // prefer the member with less arguments mapped to the params-array + int r = c1.ArgumentsPassedToParamsArray.CompareTo(c2.ArgumentsPassedToParamsArray); + if (r < 0) return 1; + else if (r > 0) return 2; + + // prefer the member where no default values need to be substituted + if (!c1.HasUnmappedOptionalParameters && c2.HasUnmappedOptionalParameters) + return 1; + else if (c1.HasUnmappedOptionalParameters && !c2.HasUnmappedOptionalParameters) + return 2; + + // compare the formal parameters + r = MoreSpecificFormalParameters(c1, c2); + if (r != 0) + return r; + + // prefer non-lifted operators + ILiftedOperator lift1 = c1.Member as ILiftedOperator; + ILiftedOperator lift2 = c2.Member as ILiftedOperator; + if (lift1 == null && lift2 != null) + return 1; + if (lift1 != null && lift2 == null) + return 2; + } + return 0; + } + + /// + /// Implement this interface to give overload resolution a hint that the member represents a lifted operator, + /// which is used in the tie-breaking rules. + /// + public interface ILiftedOperator : IParameterizedMember + { + IList NonLiftedParameters { get; } + } + + int MoreSpecificFormalParameters(Candidate c1, Candidate c2) + { + // prefer the member with more formal parmeters (in case both have different number of optional parameters) + int r = c1.Parameters.Count.CompareTo(c2.Parameters.Count); + if (r > 0) return 1; + else if (r < 0) return 2; + + return MoreSpecificFormalParameters(c1.Parameters.Select(p => p.Type.Resolve(context)), + c2.Parameters.Select(p => p.Type.Resolve(context))); + } + + static int MoreSpecificFormalParameters(IEnumerable t1, IEnumerable t2) + { + bool c1IsBetter = false; + bool c2IsBetter = false; + foreach (var pair in t1.Zip(t2, (a,b) => new { Item1 = a, Item2 = b })) { + switch (MoreSpecificFormalParameter(pair.Item1, pair.Item2)) { + case 1: + c1IsBetter = true; + break; + case 2: + c2IsBetter = true; + break; + } + } + if (c1IsBetter && !c2IsBetter) + return 1; + if (!c1IsBetter && c2IsBetter) + return 2; + return 0; + } + + static int MoreSpecificFormalParameter(IType t1, IType t2) + { + if ((t1 is ITypeParameter) && !(t2 is ITypeParameter)) + return 2; + if ((t2 is ITypeParameter) && !(t1 is ITypeParameter)) + return 1; + + ParameterizedType p1 = t1 as ParameterizedType; + ParameterizedType p2 = t2 as ParameterizedType; + if (p1 != null && p2 != null && p1.TypeParameterCount == p2.TypeParameterCount) { + int r = MoreSpecificFormalParameters(p1.TypeArguments, p2.TypeArguments); + if (r > 0) + return r; + } + TypeWithElementType tew1 = t1 as TypeWithElementType; + TypeWithElementType tew2 = t2 as TypeWithElementType; + if (tew1 != null && tew2 != null) { + return MoreSpecificFormalParameter(tew1.ElementType, tew2.ElementType); + } + return 0; + } + #endregion + + #region ConsiderIfNewCandidateIsBest + void ConsiderIfNewCandidateIsBest(Candidate candidate) + { + if (bestCandidate == null) { + bestCandidate = candidate; + } else { + switch (BetterFunctionMember(candidate, bestCandidate)) { + case 0: + if (bestCandidateAmbiguousWith == null) + bestCandidateAmbiguousWith = candidate; + break; + case 1: + bestCandidate = candidate; + bestCandidateAmbiguousWith = null; + break; + // case 2: best candidate stays best + } + } + } + #endregion + + public IParameterizedMember BestCandidate { + get { return bestCandidate != null ? bestCandidate.Member : null; } + } + + public OverloadResolutionErrors BestCandidateErrors { + get { + if (bestCandidate == null) + return OverloadResolutionErrors.None; + OverloadResolutionErrors err = bestCandidate.Errors; + if (bestCandidateAmbiguousWith != null) + err |= OverloadResolutionErrors.AmbiguousMatch; + return err; + } + } + + public bool FoundApplicableCandidate { + get { return bestCandidate != null && bestCandidate.Errors == OverloadResolutionErrors.None; } + } + + public IParameterizedMember BestCandidateAmbiguousWith { + get { return bestCandidateAmbiguousWith != null ? bestCandidateAmbiguousWith.Member : null; } + } + + public bool BestCandidateIsExpandedForm { + get { return bestCandidate != null ? bestCandidate.IsExpandedForm : false; } + } + + public bool IsAmbiguous { + get { return bestCandidateAmbiguousWith != null; } + } + + public IList InferredTypeArguments { + get { + if (bestCandidate != null && bestCandidate.InferredTypes != null) + return Array.AsReadOnly(bestCandidate.InferredTypes); + else + return EmptyList.Instance; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolutionErrors.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolutionErrors.cs new file mode 100644 index 0000000000..a9de1e4cdc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolutionErrors.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [Flags] + public enum OverloadResolutionErrors + { + None = 0, + /// + /// Too many positional arguments (some could not be mapped to any parameter). + /// + TooManyPositionalArguments = 0x0001, + /// + /// A named argument could not be mapped to any parameter + /// + NoParameterFoundForNamedArgument = 0x0002, + /// + /// Type inference failed for a generic method. + /// + TypeInferenceFailed = 0x0004, + /// + /// Type arguments were explicitly specified, but did not match the number of type parameters. + /// + WrongNumberOfTypeArguments = 0x0008, + /// + /// After substituting type parameters with the inferred types; a constructed type within the formal parameters + /// does not satisfy its constraint. + /// + ConstructedTypeDoesNotSatisfyConstraint = 0x0010, + /// + /// No argument was mapped to a non-optional parameter + /// + MissingArgumentForRequiredParameter = 0x0020, + /// + /// Several arguments were mapped to a single (non-params-array) parameter + /// + MultipleArgumentsForSingleParameter = 0x0040, + /// + /// 'ref'/'out' passing mode doesn't match for at least 1 parameter + /// + ParameterPassingModeMismatch = 0x0080, + /// + /// Argument type cannot be converted to parameter type + /// + ArgumentTypeMismatch = 0x0100, + /// + /// There is no unique best overload + /// + AmbiguousMatch = 0x0200 + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs new file mode 100644 index 0000000000..0327e13794 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents the result of resolving an expression. + /// + public class ResolveResult + { + IType type; + + public ResolveResult(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + } + + public IType Type { + get { return type; } + } + + public virtual bool IsCompileTimeConstant { + get { return false; } + } + + public virtual object ConstantValue { + get { return null; } + } + + public virtual bool IsError { + get { return false; } + } + + public override string ToString() + { + return "[" + GetType().Name + " " + type + "]"; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs new file mode 100644 index 0000000000..4ef1ec26a5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -0,0 +1,1297 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) + // This code is distributed under MIT X11 license (for details please see \doc\license.txt) + + using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Traverses the DOM and resolves expressions. + /// + /// + /// The ResolveVisitor does two jobs at the same time: it tracks the resolve context (properties on CSharpResolver) + /// and it resolves the expressions visited. + /// To allow using the context tracking without having to resolve every expression in the file (e.g. when you want to resolve + /// only a single node deep within the DOM), you can use the interface. + /// The navigator allows you to switch the between scanning mode and resolving mode. + /// In scanning mode, the context is tracked (local variables registered etc.), but nodes are not resolved. + /// While scanning, the navigator will get asked about every node that the resolve visitor is about to enter. + /// This allows the navigator whether to keep scanning, whether switch to resolving mode, or whether to completely skip the + /// subtree rooted at that node. + /// + /// In resolving mode, the context is tracked and nodes will be resolved. + /// The resolve visitor may decide that it needs to resolve other nodes as well in order to resolve the current node. + /// In this case, those nodes will be resolved automatically, without asking the navigator interface. + /// For child nodes that are not essential to resolving, the resolve visitor will switch back to scanning mode (and thus will + /// ask the navigator for further instructions). + /// + /// Moreover, there is the ResolveAll mode - it works similar to resolving mode, but will not switch back to scanning mode. + /// The whole subtree will be resolved without notifying the navigator. + /// + public sealed class ResolveVisitor : DepthFirstAstVisitor + { + static readonly ResolveResult errorResult = new ErrorResolveResult(SharedTypes.UnknownType); + CSharpResolver resolver; + readonly ParsedFile parsedFile; + readonly Dictionary resolveResultCache = new Dictionary(); + readonly Dictionary resolverBeforeDict = new Dictionary(); + + readonly IResolveVisitorNavigator navigator; + ResolveVisitorNavigationMode mode = ResolveVisitorNavigationMode.Scan; + + #region Constructor + /// + /// Creates a new ResolveVisitor instance. + /// + /// + /// The CSharpResolver, describing the initial resolve context. + /// If you visit a whole CompilationUnit with the resolve visitor, you can simply pass + /// new CSharpResolver(typeResolveContext) without setting up the context. + /// If you only visit a subtree, you need to pass a CSharpResolver initialized to the context for that subtree. + /// + /// + /// Result of the for the file being passed. This is used for setting up the context on the resolver. + /// You may pass null if you are only visiting a part of a method body and have already set up the context in the . + /// + /// + /// The navigator, which controls where the resolve visitor will switch between scanning mode and resolving mode. + /// If you pass null, then ResolveAll mode will be used. + /// + public ResolveVisitor(CSharpResolver resolver, ParsedFile parsedFile, IResolveVisitorNavigator navigator = null) + { + if (resolver == null) + throw new ArgumentNullException("resolver"); + this.resolver = resolver; + this.parsedFile = parsedFile; + this.navigator = navigator; + if (navigator == null) + mode = ResolveVisitorNavigationMode.ResolveAll; + } + #endregion + + /// + /// Gets the TypeResolveContext used by this ResolveVisitor. + /// + public ITypeResolveContext TypeResolveContext { + get { return resolver.Context; } + } + + /// + /// Gets the CancellationToken used by this ResolveVisitor. + /// + public CancellationToken CancellationToken { + get { return resolver.cancellationToken; } + } + + #region Scan / Resolve + bool resolverEnabled { + get { return mode != ResolveVisitorNavigationMode.Scan; } + } + + public void Scan(AstNode node) + { + if (node == null || node.IsNull) + return; + if (mode == ResolveVisitorNavigationMode.ResolveAll) { + Resolve(node); + } else { + ResolveVisitorNavigationMode oldMode = mode; + mode = navigator.Scan(node); + switch (mode) { + case ResolveVisitorNavigationMode.Skip: + if (node is VariableDeclarationStatement) { + // Enforce scanning of variable declarations. + goto case ResolveVisitorNavigationMode.Scan; + } + break; + case ResolveVisitorNavigationMode.Scan: + resolverBeforeDict[node] = resolver.Clone(); + node.AcceptVisitor(this, null); + break; + case ResolveVisitorNavigationMode.Resolve: + case ResolveVisitorNavigationMode.ResolveAll: + Resolve(node); + break; + default: + throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode"); + } + mode = oldMode; + } + } + + public ResolveResult Resolve(AstNode node) + { + if (node == null || node.IsNull) + return errorResult; + bool wasScan = mode == ResolveVisitorNavigationMode.Scan; + if (wasScan) + mode = ResolveVisitorNavigationMode.Resolve; + ResolveResult result; + if (!resolveResultCache.TryGetValue(node, out result)) { + resolver.cancellationToken.ThrowIfCancellationRequested(); + resolverBeforeDict[node] = resolver.Clone(); + result = resolveResultCache[node] = node.AcceptVisitor(this, null) ?? errorResult; + } + if (wasScan) + mode = ResolveVisitorNavigationMode.Scan; + return result; + } + + protected override ResolveResult VisitChildren(AstNode node, object data) + { + ScanChildren(node); + return null; + } + + void ScanChildren(AstNode node) + { + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + Scan(child); + } + } + #endregion + + #region GetResolveResult + /// + /// Gets the cached resolve result for the specified node. + /// Returns null if no cached result was found (e.g. if the node was not visited; or if it was visited in scanning mode). + /// + public ResolveResult GetResolveResult(AstNode node) + { + ResolveResult result; + if (resolveResultCache.TryGetValue(node, out result)) + return result; + else + return null; + } + + /// + /// Gets the resolver state in front of the specified node. + /// Returns null if no cached resolver was found (e.g. if the node was skipped by the navigator) + /// + public CSharpResolver GetResolverStateBefore(AstNode node) + { + CSharpResolver r; + if (resolverBeforeDict.TryGetValue(node, out r)) + return r; + else + return null; + } + #endregion + + #region Track UsingScope + public override ResolveResult VisitCompilationUnit(CompilationUnit unit, object data) + { + UsingScope previousUsingScope = resolver.UsingScope; + try { + if (parsedFile != null) + resolver.UsingScope = parsedFile.RootUsingScope; + ScanChildren(unit); + return null; + } finally { + resolver.UsingScope = previousUsingScope; + } + } + + public override ResolveResult VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + UsingScope previousUsingScope = resolver.UsingScope; + try { + if (parsedFile != null) { + resolver.UsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation); + } + ScanChildren(namespaceDeclaration); + return new NamespaceResolveResult(resolver.UsingScope.NamespaceName); + } finally { + resolver.UsingScope = previousUsingScope; + } + } + #endregion + + #region Track CurrentTypeDefinition + ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration) + { + ITypeDefinition previousTypeDefinition = resolver.CurrentTypeDefinition; + try { + ITypeDefinition newTypeDefinition = null; + if (resolver.CurrentTypeDefinition != null) { + foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) { + if (nestedType.Region.IsInside(typeDeclaration.StartLocation)) { + newTypeDefinition = nestedType; + break; + } + } + } else if (parsedFile != null) { + newTypeDefinition = parsedFile.GetTopLevelTypeDefinition(typeDeclaration.StartLocation); + } + if (newTypeDefinition != null) + resolver.CurrentTypeDefinition = newTypeDefinition; + ScanChildren(typeDeclaration); + return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult; + } finally { + resolver.CurrentTypeDefinition = previousTypeDefinition; + } + } + + public override ResolveResult VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + return VisitTypeOrDelegate(typeDeclaration); + } + + public override ResolveResult VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + { + return VisitTypeOrDelegate(delegateDeclaration); + } + #endregion + + #region Track CurrentMember + public override ResolveResult VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + return VisitFieldOrEventDeclaration(fieldDeclaration); + } + + public override ResolveResult VisitEventDeclaration(EventDeclaration eventDeclaration, object data) + { + return VisitFieldOrEventDeclaration(eventDeclaration); + } + + ResolveResult VisitFieldOrEventDeclaration(AttributedNode fieldOrEventDeclaration) + { + int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count; + ResolveResult result = null; + for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == FieldDeclaration.Roles.Variable) { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(node.StartLocation)); + } + + if (resolverEnabled && initializerCount == 1) { + result = Resolve(node); + } else { + Scan(node); + } + + resolver.CurrentMember = null; + } else { + Scan(node); + } + } + return result; + } + + public override ResolveResult VisitVariableInitializer(VariableInitializer variableInitializer, object data) + { + ScanChildren(variableInitializer); + if (resolverEnabled) { + if (variableInitializer.Parent is FieldDeclaration) { + if (resolver.CurrentMember != null) + return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + } else { + string identifier = variableInitializer.Name; + foreach (IVariable v in resolver.LocalVariables) { + if (v.Name == identifier) { + object constantValue = v.IsConst ? v.ConstantValue.GetValue(resolver.Context) : null; + return new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue); + } + } + } + return errorResult; + } else { + return null; + } + } + + ResolveResult VisitMethodMember(AttributedNode member) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.FirstOrDefault(m => m.Region.IsInside(member.StartLocation)); + } + + ScanChildren(member); + + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + public override ResolveResult VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + return VisitMethodMember(methodDeclaration); + } + + public override ResolveResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + { + return VisitMethodMember(operatorDeclaration); + } + + public override ResolveResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + return VisitMethodMember(constructorDeclaration); + } + + public override ResolveResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) + { + return VisitMethodMember(destructorDeclaration); + } + + // handle properties/indexers + ResolveResult VisitPropertyMember(MemberDeclaration propertyOrIndexerDeclaration) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Properties.FirstOrDefault(p => p.Region.IsInside(propertyOrIndexerDeclaration.StartLocation)); + } + + for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == PropertyDeclaration.SetterRole && resolver.CurrentMember != null) { + resolver.PushBlock(); + resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); + Scan(node); + resolver.PopBlock(); + } else { + Scan(node); + } + } + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + public override ResolveResult VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + { + return VisitPropertyMember(propertyDeclaration); + } + + public override ResolveResult VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) + { + return VisitPropertyMember(indexerDeclaration); + } + + public override ResolveResult VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Events.FirstOrDefault(e => e.Region.IsInside(eventDeclaration.StartLocation)); + } + + if (resolver.CurrentMember != null) { + resolver.PushBlock(); + resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); + ScanChildren(eventDeclaration); + resolver.PopBlock(); + } else { + ScanChildren(eventDeclaration); + } + + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + public override ResolveResult VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) + { + ScanChildren(parameterDeclaration); + if (resolverEnabled) { + IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember; + if (pm != null) { + foreach (IParameter p in pm.Parameters) { + if (p.Name == parameterDeclaration.Name) { + return new LocalResolveResult(p, p.Type.Resolve(resolver.Context)); + } + } + } + return errorResult; + } else { + return null; + } + } + + public override ResolveResult VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) + { + ScanChildren(typeParameterDeclaration); + if (resolverEnabled) { + string name = typeParameterDeclaration.Name; + IMethod m = resolver.CurrentMember as IMethod; + if (m != null) { + foreach (var tp in m.TypeParameters) { + if (tp.Name == name) + return new TypeResolveResult(tp); + } + } + if (resolver.CurrentTypeDefinition != null) { + var typeParameters = resolver.CurrentTypeDefinition.TypeParameters; + // look backwards so that TPs in the current type take precedence over those copied from outer types + for (int i = typeParameters.Count - 1; i >= 0; i--) { + if (typeParameters[i].Name == name) + return new TypeResolveResult(typeParameters[i]); + } + } + return errorResult; + } else { + return null; + } + } + + public override ResolveResult VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(enumMemberDeclaration.StartLocation)); + } + + ScanChildren(enumMemberDeclaration); + + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + public override ResolveResult VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) + { + throw new NotImplementedException(); + } + #endregion + + #region Track CheckForOverflow + public override ResolveResult VisitCheckedExpression(CheckedExpression checkedExpression, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = true; + if (resolverEnabled) { + return Resolve(checkedExpression.Expression); + } else { + ScanChildren(checkedExpression); + return null; + } + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + public override ResolveResult VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = false; + if (resolverEnabled) { + return Resolve(uncheckedExpression.Expression); + } else { + ScanChildren(uncheckedExpression); + return null; + } + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + public override ResolveResult VisitCheckedStatement(CheckedStatement checkedStatement, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = true; + ScanChildren(checkedStatement); + return null; + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + public override ResolveResult VisitUncheckedStatement(UncheckedStatement uncheckedStatement, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = false; + ScanChildren(uncheckedStatement); + return null; + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + #endregion + + #region Visit Expressions + static bool IsTargetOfInvocation(AstNode node) + { + InvocationExpression ie = node.Parent as InvocationExpression; + return ie != null && ie.Target == node; + } + + IType ResolveType(AstType type) + { + return MakeTypeReference(type).Resolve(resolver.Context); + } + + public override ResolveResult VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) + { + throw new NotImplementedException(); + } + + static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr) + { + if (expr is NamedArgumentExpression) { + var namedArgExpr = (NamedArgumentExpression)expr; + resolveExpr = namedArgExpr.Expression; + return namedArgExpr.Identifier; + } + // no name given, so it's a projection initializer + if (expr is MemberReferenceExpression) { + resolveExpr = expr; + return ((MemberReferenceExpression)expr).MemberName; + } + if (expr is IdentifierExpression) { + resolveExpr = expr; + return ((IdentifierExpression)expr).Identifier; + } + resolveExpr = null; + return null; + } + + public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + { + // 7.6.10.6 Anonymous object creation expressions + var anonymousType = new DefaultTypeDefinition(resolver.CurrentTypeDefinition, "$Anonymous$"); + anonymousType.IsSynthetic = true; + foreach (var expr in anonymousTypeCreateExpression.Initializer) { + Expression resolveExpr; + var name = GetAnonymousTypePropertyName(expr, out resolveExpr); + if (string.IsNullOrEmpty(name)) + continue; + + var property = new DefaultProperty(anonymousType, name) { + Accessibility = Accessibility.Public, + ReturnType = new VarTypeReference(this, resolver.Clone(), resolveExpr, false) + }; + anonymousType.Properties.Add(property); + } + return new TypeResolveResult(anonymousType); + } + + public override ResolveResult VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) + { + Scan(arrayCreateExpression.Initializer); + if (resolverEnabled) { + IType arrType; + if (arrayCreateExpression.Type.IsNull) { + var elements = new List(); + foreach (var init in arrayCreateExpression.Initializer.Elements) { + var rr = Resolve(init); + if (!rr.IsError) + elements.Add(rr); + } + TypeInference typeInference = new TypeInference(resolver.Context, new Conversions(resolver.Context)); + bool success; + IType elementType = typeInference.GetBestCommonType(elements, out success); + arrType = new ArrayType(elementType, 1); + } else { + arrType = ResolveType(arrayCreateExpression.Type); + foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) { + arrType = new ArrayType(arrType, spec.Dimensions); + } + // HACK: find a better way to represent this in the AST + if (arrayCreateExpression.Arguments.Count == 0) { + arrType = new ArrayType(arrType, 1); + } else { + arrType = new ArrayType(arrType, arrayCreateExpression.Arguments.Count); + } + } + return new ResolveResult (arrType); + } + return null; + } + + public override ResolveResult VisitAsExpression(AsExpression asExpression, object data) + { + if (resolverEnabled) { + Scan(asExpression.Expression); + return new ResolveResult(ResolveType(asExpression.Type)); + } else { + ScanChildren(asExpression); + return null; + } + } + + public override ResolveResult VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) + { + if (resolverEnabled) { + ResolveResult left = Resolve(assignmentExpression.Left); + Scan(assignmentExpression.Right); + return new ResolveResult(left.Type); + } else { + ScanChildren(assignmentExpression); + return null; + } + } + + public override ResolveResult VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveBaseReference(); + } else { + ScanChildren(baseReferenceExpression); + return null; + } + } + + public override ResolveResult VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + if (resolverEnabled) { + ResolveResult left = Resolve(binaryOperatorExpression.Left); + ResolveResult right = Resolve(binaryOperatorExpression.Right); + return resolver.ResolveBinaryOperator(binaryOperatorExpression.Operator, left, right); + } else { + ScanChildren(binaryOperatorExpression); + return null; + } + } + + public override ResolveResult VisitCastExpression(CastExpression castExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveCast(ResolveType(castExpression.Type), Resolve(castExpression.Expression)); + } else { + ScanChildren(castExpression); + return null; + } + } + + public override ResolveResult VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveConditional( + Resolve(conditionalExpression.Condition), + Resolve(conditionalExpression.TrueExpression), + Resolve(conditionalExpression.FalseExpression)); + } else { + ScanChildren(conditionalExpression); + return null; + } + } + + public override ResolveResult VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type)); + } else { + ScanChildren(defaultValueExpression); + return null; + } + } + + public override ResolveResult VisitDirectionExpression(DirectionExpression directionExpression, object data) + { + if (resolverEnabled) { + ResolveResult rr = Resolve(directionExpression.Expression); + return new ByReferenceResolveResult(rr.Type, directionExpression.FieldDirection == FieldDirection.Out); + } else { + ScanChildren(directionExpression); + return null; + } + } + + public override ResolveResult VisitEmptyExpression(EmptyExpression emptyExpression, object data) + { + return errorResult; + } + + public override ResolveResult VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + if (resolverEnabled) { + List typeArguments = new List(); + foreach (AstType typeArgument in identifierExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } + return resolver.ResolveSimpleName(identifierExpression.Identifier, typeArguments, + IsTargetOfInvocation(identifierExpression)); + } else { + ScanChildren(identifierExpression); + return null; + } + } + + ResolveResult[] GetArguments(IEnumerable argumentExpressions, out string[] argumentNames) + { + argumentNames = null; // TODO: add support for named arguments + ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()]; + int i = 0; + foreach (AstNode argument in argumentExpressions) { + arguments[i++] = Resolve(argument); + } + return arguments; + } + + public override ResolveResult VisitIndexerExpression(IndexerExpression indexerExpression, object data) + { + if (resolverEnabled) { + ResolveResult target = Resolve(indexerExpression.Target); + string[] argumentNames; + ResolveResult[] arguments = GetArguments(indexerExpression.Arguments, out argumentNames); + return resolver.ResolveIndexer(target, arguments, argumentNames); + } else { + ScanChildren(indexerExpression); + return null; + } + } + + public override ResolveResult VisitInvocationExpression(InvocationExpression invocationExpression, object data) + { + if (resolverEnabled) { + ResolveResult target = Resolve(invocationExpression.Target); + string[] argumentNames; + ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames); + return resolver.ResolveInvocation(target, arguments, argumentNames); + } else { + ScanChildren(invocationExpression); + return null; + } + } + + public override ResolveResult VisitIsExpression(IsExpression isExpression, object data) + { + ScanChildren(isExpression); + if (resolverEnabled) + return new ResolveResult(KnownTypeReference.Boolean.Resolve(resolver.Context)); + else + return null; + } + + public override ResolveResult VisitLambdaExpression(LambdaExpression lambdaExpression, object data) + { + throw new NotImplementedException(); + } + + public override ResolveResult VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + { + if (resolverEnabled) { + ResolveResult target = Resolve(memberReferenceExpression.Target); + List typeArguments = new List(); + foreach (AstType typeArgument in memberReferenceExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } + return resolver.ResolveMemberAccess(target, memberReferenceExpression.MemberName, + typeArguments, + IsTargetOfInvocation(memberReferenceExpression)); + } else { + ScanChildren(memberReferenceExpression); + return null; + } + } + + public override ResolveResult VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolvePrimitive(null); + } else { + return null; + } + } + + public override ResolveResult VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) + { + if (resolverEnabled) { + IType type = ResolveType(objectCreateExpression.Type); + string[] argumentNames; + ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); + return resolver.ResolveObjectCreation(type, arguments, argumentNames); + } else { + ScanChildren(objectCreateExpression); + return null; + } + } + + public override ResolveResult VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + { + if (resolverEnabled) { + return Resolve(parenthesizedExpression.Expression); + } else { + Scan(parenthesizedExpression.Expression); + return null; + } + } + + public override ResolveResult VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) + { + if (resolverEnabled) { + ResolveResult target = Resolve(pointerReferenceExpression.Target); + ResolveResult deferencedTarget = resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, target); + List typeArguments = new List(); + foreach (AstType typeArgument in pointerReferenceExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } + return resolver.ResolveMemberAccess(deferencedTarget, pointerReferenceExpression.MemberName, + typeArguments, + IsTargetOfInvocation(pointerReferenceExpression)); + } else { + ScanChildren(pointerReferenceExpression); + return null; + } + } + + public override ResolveResult VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolvePrimitive(primitiveExpression.Value); + } else { + return null; + } + } + + public override ResolveResult VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveSizeOf(ResolveType(sizeOfExpression.Type)); + } else { + ScanChildren(sizeOfExpression); + return null; + } + } + + public override ResolveResult VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) + { + if (resolverEnabled) { + Scan(stackAllocExpression.CountExpression); + return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type))); + } else { + ScanChildren(stackAllocExpression); + return null; + } + } + + public override ResolveResult VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) + { + return resolver.ResolveThisReference(); + } + + static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0); + + public override ResolveResult VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) + { + ScanChildren(typeOfExpression); + if (resolverEnabled) + return new ResolveResult(systemType.Resolve(resolver.Context)); + else + return null; + } + + public override ResolveResult VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + { + if (resolverEnabled) { + return Resolve(typeReferenceExpression.Type); + } else { + Scan(typeReferenceExpression.Type); + return null; + } + } + + public override ResolveResult VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + if (resolverEnabled) { + ResolveResult expr = Resolve(unaryOperatorExpression.Expression); + return resolver.ResolveUnaryOperator(unaryOperatorExpression.Operator, expr); + } else { + ScanChildren(unaryOperatorExpression); + return null; + } + } + + public override ResolveResult VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) + { + ScanChildren(undocumentedExpression); + if (resolverEnabled) { + ITypeReference resultType; + switch (undocumentedExpression.UndocumentedExpressionType) { + case UndocumentedExpressionType.ArgListAccess: + case UndocumentedExpressionType.ArgList: + resultType = typeof(RuntimeArgumentHandle).ToTypeReference(); + break; + case UndocumentedExpressionType.RefValue: + var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression; + if (tre != null) + resultType = ResolveType(tre.Type); + else + resultType = SharedTypes.UnknownType; + break; + case UndocumentedExpressionType.RefType: + resultType = systemType; + break; + case UndocumentedExpressionType.MakeRef: + resultType = typeof(TypedReference).ToTypeReference(); + break; + default: + throw new InvalidOperationException("Invalid value for UndocumentedExpressionType"); + } + return new ResolveResult(resultType.Resolve(resolver.Context)); + } else { + return null; + } + } + #endregion + + #region Local Variable Scopes (Block Statements) + public override ResolveResult VisitBlockStatement(BlockStatement blockStatement, object data) + { + resolver.PushBlock(); + ScanChildren(blockStatement); + resolver.PopBlock(); + return null; + } + + public override ResolveResult VisitUsingStatement(UsingStatement usingStatement, object data) + { + resolver.PushBlock(); + ScanChildren(usingStatement); + resolver.PopBlock(); + return null; + } + + public override ResolveResult VisitFixedStatement(FixedStatement fixedStatement, object data) + { + resolver.PushBlock(); + + VariableInitializer firstInitializer = fixedStatement.Variables.FirstOrDefault(); + ITypeReference type = MakeTypeReference(fixedStatement.Type, + firstInitializer != null ? firstInitializer.Initializer : null, + false); + + for (AstNode node = fixedStatement.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == FixedStatement.Roles.Variable) { + VariableInitializer vi = (VariableInitializer)node; + resolver.AddVariable(type, new DomRegion (parsedFile.FileName, vi.StartLocation, vi.EndLocation) , vi.Name); + } + Scan(node); + } + resolver.PopBlock(); + return null; + } + + public override ResolveResult VisitForStatement(ForStatement forStatement, object data) + { + resolver.PushBlock(); + ScanChildren(forStatement); + resolver.PopBlock(); + return null; + } + + + public override ResolveResult VisitForeachStatement(ForeachStatement foreachStatement, object data) + { + resolver.PushBlock(); + ITypeReference type = MakeTypeReference(foreachStatement.VariableType, foreachStatement.InExpression, true); + resolver.AddVariable(type, new DomRegion (parsedFile.FileName, foreachStatement.VariableNameToken.StartLocation, foreachStatement.VariableNameToken.EndLocation), foreachStatement.VariableName); + ScanChildren(foreachStatement); + resolver.PopBlock(); + return null; + } + + public override ResolveResult VisitCatchClause(CatchClause catchClause, object data) + { + resolver.PushBlock(); + if (catchClause.VariableName != null) { + resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), new DomRegion (parsedFile.FileName, catchClause.VariableNameToken.StartLocation, catchClause.VariableNameToken.EndLocation), catchClause.VariableName); + } + ScanChildren(catchClause); + resolver.PopBlock(); + return null; + } + #endregion + + #region VariableDeclarationStatement + public override ResolveResult VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data) + { + bool isConst = (variableDeclarationStatement.Modifiers & Modifiers.Const) != 0; + VariableInitializer firstInitializer = variableDeclarationStatement.Variables.FirstOrDefault(); + ITypeReference type = MakeTypeReference(variableDeclarationStatement.Type, + firstInitializer != null ? firstInitializer.Initializer : null, + false); + + int initializerCount = variableDeclarationStatement.Variables.Count; + ResolveResult result = null; + for (AstNode node = variableDeclarationStatement.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == VariableDeclarationStatement.Roles.Variable) { + VariableInitializer vi = (VariableInitializer)node; + + IConstantValue cv = null; + if (isConst) + throw new NotImplementedException(); + resolver.AddVariable(type, new DomRegion (parsedFile.FileName, vi.StartLocation, vi.EndLocation), vi.Name, cv); + + if (resolverEnabled && initializerCount == 1) { + result = Resolve(node); + } else { + Scan(node); + } + } else { + Scan(node); + } + } + return result; + } + #endregion + + #region Local Variable Type Inference + /// + /// Creates a type reference for the specified type node. + /// If the type node is 'var', performs type inference on the initializer expression. + /// + ITypeReference MakeTypeReference(AstType type, AstNode initializerExpression, bool isForEach) + { + if (initializerExpression != null && IsVar(type)) { + return new VarTypeReference(this, resolver.Clone(), initializerExpression, isForEach); + } else { + return MakeTypeReference(type); + } + } + + ITypeReference MakeTypeReference(AstType type) + { + return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope, false); + } + + static bool IsVar(AstType returnType) + { + return returnType is SimpleType + && ((SimpleType)returnType).Identifier == "var" + && ((SimpleType)returnType).TypeArguments.Count == 0; + } + + sealed class VarTypeReference : ITypeReference + { + ResolveVisitor visitor; + CSharpResolver storedContext; + AstNode initializerExpression; + bool isForEach; + + IType result; + + public VarTypeReference(ResolveVisitor visitor, CSharpResolver storedContext, AstNode initializerExpression, bool isForEach) + { + this.visitor = visitor; + this.storedContext = storedContext; + this.initializerExpression = initializerExpression; + this.isForEach = isForEach; + } + + public IType Resolve(ITypeResolveContext context) + { + if (visitor == null) + return result ?? SharedTypes.UnknownType; + + var oldMode = visitor.mode; + var oldResolver = visitor.resolver; + try { + visitor.mode = ResolveVisitorNavigationMode.Resolve; + visitor.resolver = storedContext; + + result = visitor.Resolve(initializerExpression).Type; + + if (isForEach) { + result = GetElementType(result); + } + + return result; + } finally { + visitor.mode = oldMode; + visitor.resolver = oldResolver; + + visitor = null; + storedContext = null; + initializerExpression = null; + } + } + + IType GetElementType(IType result) + { + bool foundSimpleIEnumerable = false; + foreach (IType baseType in result.GetAllBaseTypes(storedContext.Context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && baseTypeDef.Name == "IEnumerable") { + if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) { + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + return pt.TypeArguments[0]; + } + } else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) { + foundSimpleIEnumerable = true; + } + } + } + // System.Collections.IEnumerable found in type hierarchy -> Object is element type. + if (foundSimpleIEnumerable) + return KnownTypeReference.Object.Resolve(storedContext.Context); + return SharedTypes.UnknownType; + } + + public override string ToString() + { + if (visitor == null) + return "var=" + result; + else + return "var (not yet resolved)"; + } + } + #endregion + + #region Attributes + ITypeReference GetAttributeType (Attribute attribute) + { + var withoutSuffix = MakeTypeReference(attribute.Type); + ITypeReference withSuffix; + if (attribute.Type is SimpleType) { + var st = (SimpleType)attribute.Type; + withSuffix = MakeTypeReference(new SimpleType (st.Identifier + "Attribute")); + } else if (attribute.Type is MemberType) { + var mt = (MemberType)attribute.Type; + withSuffix = MakeTypeReference(new MemberType (mt.Target.Clone (), mt.MemberName + "Attribute")); + } else { + // unsupported type. + return SharedTypes.UnknownType; + } + return new AttributeTypeReference(withoutSuffix, withSuffix); + } + + public override ResolveResult VisitAttribute(Attribute attribute, object data) + { + ScanChildren(attribute); + if (resolverEnabled) { + var type = GetAttributeType (attribute).Resolve (resolver.Context); + if (!attribute.HasArgumentList) + return new TypeResolveResult (type); + // try if the attribute usage references a constructuor + string[] argumentNames; + ResolveResult[] arguments = GetArguments(attribute.Arguments, out argumentNames); + var result = resolver.ResolveObjectCreation(type, arguments, argumentNames); + Console.WriteLine (result); + // if this is an error give back type resolve result, an attribute arg list isn't a constructor reference + // in all cases. - is it better to always give back the type resolve result ? + if (result.IsError) + return new TypeResolveResult (type); + return result; + } + return null; + } + #endregion + + #region Using Declaration + public override ResolveResult VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + { + // TODO: set isInUsingDeclaration + ScanChildren(usingDeclaration); + return null; + } + + public override ResolveResult VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) + { + // TODO: set isInUsingDeclaration + ScanChildren(usingDeclaration); + return null; + } + #endregion + + #region Type References + public override ResolveResult VisitPrimitiveType(PrimitiveType primitiveType, object data) + { + ScanChildren(primitiveType); + return new TypeResolveResult(ResolveType(primitiveType)); + } + + public override ResolveResult VisitSimpleType(SimpleType simpleType, object data) + { + ScanChildren(simpleType); + return ResolveTypeOrNamespace(simpleType); + } + + ResolveResult ResolveTypeOrNamespace(AstType type) + { + ITypeReference typeRef = MakeTypeReference(type); + ITypeOrNamespaceReference typeOrNsRef = typeRef as ITypeOrNamespaceReference; + if (typeOrNsRef != null) { + return typeOrNsRef.DoResolve(resolver.Context); + } else { + return new TypeResolveResult(typeRef.Resolve(resolver.Context)); + } + } + + public override ResolveResult VisitMemberType(MemberType memberType, object data) + { + ScanChildren(memberType); + return ResolveTypeOrNamespace(memberType); + } + + public override ResolveResult VisitComposedType(ComposedType composedType, object data) + { + ScanChildren(composedType); + return new TypeResolveResult(ResolveType(composedType)); + } + #endregion + + #region Query Expressions + public override ResolveResult VisitQueryExpression(QueryExpression queryExpression, object data) + { + throw new NotImplementedException(); + } + #endregion + + public override ResolveResult VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) + { + ScanChildren(constructorInitializer); + return null; + } + + public override ResolveResult VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) + { + // TODO: array initializers are valid expressions if the parent node is a variable/field declaration + // that explicitly defines an array type + return errorResult; + } + + public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) + { + throw new NotImplementedException(); + } + + public override ResolveResult VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data) + { + throw new NotImplementedException(); + } + + #region Token Nodes + public override ResolveResult VisitIdentifier(Identifier identifier, object data) + { + return null; + } + + public override ResolveResult VisitComment(Comment comment, object data) + { + return null; + } + + public override ResolveResult VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, object data) + { + return null; + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs new file mode 100644 index 0000000000..12699dd1c0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a simple C# name. (a single non-qualified identifier with an optional list of type arguments) + /// + public sealed class SimpleTypeOrNamespaceReference : ITypeOrNamespaceReference + { + readonly ITypeDefinition parentTypeDefinition; + readonly UsingScope parentUsingScope; + readonly string identifier; + readonly IList typeArguments; + readonly bool isInUsingDeclaration; + + public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration = false) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.identifier = identifier; + this.typeArguments = typeArguments ?? EmptyList.Instance; + this.parentTypeDefinition = parentTypeDefinition; + this.parentUsingScope = parentUsingScope; + this.isInUsingDeclaration = isInUsingDeclaration; + } + + /// + /// Adds a suffix to the identifier. + /// Does not modify the existing type reference, but returns a new one. + /// + public SimpleTypeOrNamespaceReference AddSuffix(string suffix) + { + return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); + } + + public ResolveResult DoResolve(ITypeResolveContext context) + { + CSharpResolver r = new CSharpResolver(context); + r.CurrentTypeDefinition = parentTypeDefinition != null ? parentTypeDefinition.GetCompoundClass() : null; + r.UsingScope = parentUsingScope; + IType[] typeArgs = new IType[typeArguments.Count]; + for (int i = 0; i < typeArgs.Length; i++) { + typeArgs[i] = typeArguments[i].Resolve(context); + } + return r.LookupSimpleNamespaceOrTypeName(identifier, typeArgs, isInUsingDeclaration); + } + + public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible + return DoResolve(context) as NamespaceResolveResult; + } + + public IType Resolve(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible; then map the result type into the new context + TypeResolveResult rr = DoResolve(context) as TypeResolveResult; + return rr != null ? rr.Type : SharedTypes.UnknownType; + } + + public override string ToString() + { + if (typeArguments.Count == 0) + return identifier; + else + return identifier + "<" + DotNet35Compat.StringJoin(",", typeArguments) + ">"; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs new file mode 100644 index 0000000000..e3c75632e9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs @@ -0,0 +1,919 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public enum TypeInferenceAlgorithm + { + /// + /// C# 4.0 type inference. + /// + CSharp4, + /// + /// Improved algorithm (not part of any specification) using FindTypeInBounds for fixing. + /// + Improved, + /// + /// Improved algorithm (not part of any specification) using FindTypeInBounds for fixing; + /// uses to report all results (in case of ambiguities). + /// + ImprovedReturnAllResults + } + + /// + /// Implements C# 4.0 Type Inference (§7.5.2). + /// + public sealed class TypeInference + { + readonly ITypeResolveContext context; + readonly Conversions conversions; + TypeInferenceAlgorithm algorithm = TypeInferenceAlgorithm.CSharp4; + + // determines the maximum generic nesting level; necessary to avoid infinite recursion in 'Improved' mode. + const int maxNestingLevel = 5; + int nestingLevel; + + #region Constructor + public TypeInference(ITypeResolveContext context, Conversions conversions = null) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + this.conversions = conversions ?? new Conversions(context); + } + #endregion + + #region Properties + /// + /// Gets/Sets the type inference algorithm used. + /// + public TypeInferenceAlgorithm Algorithm { + get { return algorithm; } + set { algorithm = value; } + } + + TypeInference CreateNestedInstance() + { + TypeInference c = new TypeInference(context, conversions); + c.algorithm = algorithm; + c.nestingLevel = nestingLevel + 1; + return c; + } + #endregion + + TP[] typeParameters; + IType[] parameterTypes; + ResolveResult[] arguments; + bool[,] dependencyMatrix; + + #region InferTypeArguments (main function) + public IType[] InferTypeArguments(IList typeParameters, IList arguments, IList parameterTypes, out bool success) + { + if (typeParameters == null) + throw new ArgumentNullException("typeParameters"); + if (arguments == null) + throw new ArgumentNullException("arguments"); + if (parameterTypes == null) + throw new ArgumentNullException("parameterTypes"); + try { + this.typeParameters = new TP[typeParameters.Count]; + for (int i = 0; i < this.typeParameters.Length; i++) { + if (i != typeParameters[i].Index) + throw new ArgumentException("Type parameter has wrong index"); + this.typeParameters[i] = new TP(typeParameters[i]); + } + this.parameterTypes = new IType[Math.Min(arguments.Count, parameterTypes.Count)]; + this.arguments = new ResolveResult[this.parameterTypes.Length]; + for (int i = 0; i < this.parameterTypes.Length; i++) { + if (arguments[i] == null || parameterTypes[i] == null) + throw new ArgumentNullException(); + this.arguments[i] = arguments[i]; + this.parameterTypes[i] = parameterTypes[i]; + } + PhaseOne(); + success = PhaseTwo(); + return this.typeParameters.Select(tp => tp.FixedTo ?? SharedTypes.UnknownType).ToArray(); + } finally { + Reset(); + } + } + + void Reset() + { + // clean up so that memory used by the operation can be garbage collected as soon as possible + this.typeParameters = null; + this.parameterTypes = null; + this.arguments = null; + this.dependencyMatrix = null; + } + + /// + /// Infers type arguments for the occurring in the + /// so that the resulting type (after substition) satisfies the given bounds. + /// + public IType[] InferTypeArgumentsFromBounds(IList typeParameters, IType targetType, IList lowerBounds, IList upperBounds, out bool success) + { + if (typeParameters == null) + throw new ArgumentNullException("typeParameters"); + if (targetType == null) + throw new ArgumentNullException("targetType"); + if (lowerBounds == null) + throw new ArgumentNullException("lowerBounds"); + if (upperBounds == null) + throw new ArgumentNullException("upperBounds"); + this.typeParameters = new TP[typeParameters.Count]; + for (int i = 0; i < this.typeParameters.Length; i++) { + if (i != typeParameters[i].Index) + throw new ArgumentException("Type parameter has wrong index"); + this.typeParameters[i] = new TP(typeParameters[i]); + } + foreach (IType b in lowerBounds) { + MakeLowerBoundInference(b, targetType); + } + foreach (IType b in upperBounds) { + MakeUpperBoundInference(b, targetType); + } + IType[] result = new IType[this.typeParameters.Length]; + success = true; + for (int i = 0; i < result.Length; i++) { + success &= Fix(this.typeParameters[i]); + result[i] = this.typeParameters[i].FixedTo ?? SharedTypes.UnknownType; + } + Reset(); + return result; + } + #endregion + + sealed class TP + { + public readonly HashSet LowerBounds = new HashSet(); + public readonly HashSet UpperBounds = new HashSet(); + public readonly ITypeParameter TypeParameter; + public IType FixedTo; + + public bool IsFixed { + get { return FixedTo != null; } + } + + public bool HasBounds { + get { return LowerBounds.Count > 0 || UpperBounds.Count > 0; } + } + + public TP(ITypeParameter typeParameter) + { + if (typeParameter == null) + throw new ArgumentNullException("typeParameter"); + this.TypeParameter = typeParameter; + } + + public override string ToString() + { + return TypeParameter.Name; + } + } + + sealed class OccursInVisitor : TypeVisitor + { + readonly TP[] tp; + public readonly bool[] Occurs; + + public OccursInVisitor(TypeInference typeInference) + { + this.tp = typeInference.typeParameters; + this.Occurs = new bool[tp.Length]; + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + int index = type.Index; + if (index < tp.Length && tp[index].TypeParameter == type) + Occurs[index] = true; + return base.VisitTypeParameter(type); + } + } + + #region Inference Phases + void PhaseOne() + { + // C# 4.0 spec: §7.5.2.1 The first phase + Log("Phase One"); + for (int i = 0; i < arguments.Length; i++) { + ResolveResult Ei = arguments[i]; + IType Ti = parameterTypes[i]; + // TODO: what if Ei is an anonymous function? + IType U = Ei.Type; + if (U != SharedTypes.UnknownType) { + if (Ti is ByReferenceType) { + MakeExactInference(Ei.Type, Ti); + } else { + MakeLowerBoundInference(Ei.Type, Ti); + } + } + } + } + + bool PhaseTwo() + { + // C# 4.0 spec: §7.5.2.2 The second phase + Log("Phase Two"); + // All unfixed type variables Xi which do not depend on any Xj are fixed. + List typeParametersToFix = new List(); + foreach (TP Xi in typeParameters) { + if (Xi.IsFixed == false) { + if (!typeParameters.Any((TP Xj) => DependsOn(Xi, Xj))) { + typeParametersToFix.Add(Xi); + } + } + } + // If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold: + if (typeParametersToFix.Count == 0) { + foreach (TP Xi in typeParameters) { + // Xi has a non­empty set of bounds + if (!Xi.IsFixed && Xi.HasBounds) { + // There is at least one type variable Xj that depends on Xi + if (typeParameters.Any((TP Xj) => DependsOn(Xj, Xi))) { + typeParametersToFix.Add(Xi); + } + } + } + } + // now fix 'em + bool errorDuringFix = false; + foreach (TP tp in typeParametersToFix) { + if (!Fix(tp)) + errorDuringFix = true; + } + if (errorDuringFix) + return false; + bool unfixedTypeVariablesExist = typeParameters.Any((TP X) => X.IsFixed == false); + if (typeParametersToFix.Count == 0 && unfixedTypeVariablesExist) { + // If no such type variables exist and there are still unfixed type variables, type inference fails. + return false; + } else if (!unfixedTypeVariablesExist) { + // Otherwise, if no further unfixed type variables exist, type inference succeeds. + return true; + } else { + // Otherwise, for all arguments ei with corresponding parameter type Ti + for (int i = 0; i < arguments.Length; i++) { + ResolveResult Ei = arguments[i]; + IType Ti = parameterTypes[i]; + // where the output types (§7.4.2.4) contain unfixed type variables Xj + // but the input types (§7.4.2.3) do not + if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) { + // an output type inference (§7.4.2.6) is made for ei with type Ti. + Log("MakeOutputTypeInference for #" + i); + MakeOutputTypeInference(Ei, Ti); + } + } + // Then the second phase is repeated. + return PhaseTwo(); + } + } + #endregion + + #region Input Types / Output Types (§7.5.2.3 + §7.5.2.4) + static readonly IType[] emptyTypeArray = new IType[0]; + + IType[] InputTypes(ResolveResult e, IType t) + { + // C# 4.0 spec: §7.5.2.3 Input types + /* TODO + AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; + if (amrt != null && amrt.HasImplicitlyTypedParameters || e is MethodGroupReturnType) { + IMethod m = GetDelegateOrExpressionTreeSignature(t, amrt != null && amrt.CanBeConvertedToExpressionTree); + if (m != null) { + return m.Parameters.Select(p => p.ReturnType); + } + }*/ + return emptyTypeArray; + } + + + IType[] OutputTypes(ResolveResult e, IType t) + { + // C# 4.0 spec: §7.5.2.4 Input types + /* + AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; + if (amrt != null || e is MethodGroupReturnType) { + IMethod m = GetDelegateOrExpressionTreeSignature(T, amrt != null && amrt.CanBeConvertedToExpressionTree); + if (m != null) { + return new[] { m.ReturnType }; + } + } + */ + return emptyTypeArray; + } + + bool InputTypesContainsUnfixed(ResolveResult argument, IType parameterType) + { + return AnyTypeContainsUnfixedParameter(InputTypes(argument, parameterType)); + } + + bool OutputTypeContainsUnfixed(ResolveResult argument, IType parameterType) + { + return AnyTypeContainsUnfixedParameter(OutputTypes(argument, parameterType)); + } + + bool AnyTypeContainsUnfixedParameter(IEnumerable types) + { + OccursInVisitor o = new OccursInVisitor(this); + foreach (var type in types) { + type.AcceptVisitor(o); + } + for (int i = 0; i < typeParameters.Length; i++) { + if (!typeParameters[i].IsFixed && o.Occurs[i]) + return true; + } + return false; + } + #endregion + + #region DependsOn (§7.5.2.5) + // C# 4.0 spec: §7.5.2.5 Dependance + + void CalculateDependencyMatrix() + { + int n = typeParameters.Length; + dependencyMatrix = new bool[n, n]; + for (int k = 0; k < arguments.Length; k++) { + OccursInVisitor input = new OccursInVisitor(this); + OccursInVisitor output = new OccursInVisitor(this); + foreach (var type in InputTypes(arguments[k], parameterTypes[k])) { + type.AcceptVisitor(input); + } + foreach (var type in OutputTypes(arguments[k], parameterTypes[k])) { + type.AcceptVisitor(output); + } + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + dependencyMatrix[i, j] |= input.Occurs[j] && output.Occurs[i]; + } + } + } + // calculate transitive closure using Warshall's algorithm: + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + if (dependencyMatrix[i, j]) { + for (int k = 0; k < n; k++) { + if (dependencyMatrix[j, k]) + dependencyMatrix[i, k] = true; + } + } + } + } + } + + bool DependsOn(TP x, TP y) + { + if (dependencyMatrix == null) + CalculateDependencyMatrix(); + // x depends on y + return dependencyMatrix[x.TypeParameter.Index, y.TypeParameter.Index]; + } + #endregion + + #region MakeOutputTypeInference (§7.5.2.6) + void MakeOutputTypeInference(ResolveResult e, IType t) + { + // If E is an anonymous function with inferred return type U (§7.5.2.12) and T is a delegate type or expression + // tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb. + /* TODO AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; + if (amrt != null) { + IMethod m = GetDelegateOrExpressionTreeSignature(T, amrt.CanBeConvertedToExpressionTree); + if (m != null) { + IReturnType inferredReturnType; + if (amrt.HasParameterList && amrt.MethodParameters.Count == m.Parameters.Count) { + var inferredParameterTypes = m.Parameters.Select(p => SubstituteFixedTypes(p.ReturnType)).ToArray(); + inferredReturnType = amrt.ResolveReturnType(inferredParameterTypes); + } else { + inferredReturnType = amrt.ResolveReturnType(); + } + + MakeLowerBoundInference(inferredReturnType, m.ReturnType); + return; + } + }*/ + // Otherwise, if E is a method group and T is a delegate type or expression tree type + // with parameter types T1…Tk and return type Tb, and overload resolution + // of E with the types T1…Tk yields a single method with return type U, then a lower­-bound + // inference is made from U to Tb. + MethodGroupResolveResult mgrr = e as MethodGroupResolveResult; + if (mgrr != null) { + throw new NotImplementedException(); + } + // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. + if (e.Type != SharedTypes.UnknownType) { + MakeLowerBoundInference(e.Type, t); + } + } + #endregion + + #region MakeExplicitParameterTypeInference (§7.5.2.7) + void MakeExplicitParameterTypeInference(ResolveResult e, IType t) + { + // C# 4.0 spec: §7.5.2.7 Explicit parameter type inferences + throw new NotImplementedException(); + /*AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; + if (amrt != null && amrt.HasParameterList) { + IMethod m = GetDelegateOrExpressionTreeSignature(T, amrt.CanBeConvertedToExpressionTree); + if (m != null && amrt.MethodParameters.Count == m.Parameters.Count) { + for (int i = 0; i < amrt.MethodParameters.Count; i++) { + MakeExactInference(amrt.MethodParameters[i].ReturnType, m.Parameters[i].ReturnType); + } + } + }*/ + } + #endregion + + #region MakeExactInference (§7.5.2.8) + /// + /// Make exact inference from U to V. + /// C# 4.0 spec: §7.5.2.8 Exact inferences + /// + void MakeExactInference(IType U, IType V) + { + Log("MakeExactInference from " + U + " to " + V); + + // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. + TP tp = GetTPForType(V); + if (tp != null && tp.IsFixed == false) { + Log(" Add exact bound '" + U + "' to " + tp); + tp.LowerBounds.Add(U); + tp.UpperBounds.Add(U); + return; + } + // Handle by reference types: + ByReferenceType brU = U as ByReferenceType; + ByReferenceType brV = V as ByReferenceType; + if (brU != null && brV != null) { + MakeExactInference(brU.ElementType, brV.ElementType); + return; + } + // Handle array types: + ArrayType arrU = U as ArrayType; + ArrayType arrV = V as ArrayType; + if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { + MakeExactInference(arrU.ElementType, arrV.ElementType); + return; + } + // Handle parameterized type: + ParameterizedType pU = U as ParameterizedType; + ParameterizedType pV = V as ParameterizedType; + if (pU != null && pV != null + && object.Equals(pU.GetDefinition(), pV.GetDefinition()) + && pU.TypeParameterCount == pV.TypeParameterCount) + { + Debug.Indent(); + for (int i = 0; i < pU.TypeParameterCount; i++) { + MakeExactInference(pU.TypeArguments[i], pV.TypeArguments[i]); + } + Debug.Unindent(); + } + } + + TP GetTPForType(IType v) + { + ITypeParameter p = v as ITypeParameter; + if (p != null) { + int index = p.Index; + if (index < typeParameters.Length && typeParameters[index].TypeParameter == p) + return typeParameters[index]; + } + return null; + } + #endregion + + #region MakeLowerBoundInference (§7.5.2.9) + /// + /// Make lower bound inference from U to V. + /// C# 4.0 spec: §7.5.2.9 Lower-bound inferences + /// + void MakeLowerBoundInference(IType U, IType V) + { + Log(" MakeLowerBoundInference from " + U + " to " + V); + + // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. + TP tp = GetTPForType(V); + if (tp != null && tp.IsFixed == false) { + Log(" Add lower bound '" + U + "' to " + tp); + tp.LowerBounds.Add(U); + return; + } + + // Handle array types: + ArrayType arrU = U as ArrayType; + ArrayType arrV = V as ArrayType; + ParameterizedType pV = V as ParameterizedType; + if (arrU != null && arrV != null && arrU.Dimensions == arrV.Dimensions) { + MakeLowerBoundInference(arrU.ElementType, arrV.ElementType); + return; + } else if (arrU != null && IsIEnumerableCollectionOrList(pV) && arrU.Dimensions == 1) { + MakeLowerBoundInference(arrU.ElementType, pV.TypeArguments[0]); + return; + } + // Handle parameterized types: + if (pV != null) { + ParameterizedType uniqueBaseType = null; + foreach (IType baseU in U.GetAllBaseTypes(context)) { + ParameterizedType pU = baseU as ParameterizedType; + if (pU != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { + if (uniqueBaseType == null) + uniqueBaseType = pU; + else + return; // cannot make an inference because it's not unique + } + } + Debug.Indent(); + if (uniqueBaseType != null) { + for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { + IType Ui = uniqueBaseType.TypeArguments[i]; + IType Vi = pV.TypeArguments[i]; + if (Ui.IsReferenceType(context) == true) { + // look for variance + ITypeParameter Xi = pV.GetDefinition().TypeParameters[i]; + switch (Xi.Variance) { + case VarianceModifier.Covariant: + MakeLowerBoundInference(Ui, Vi); + break; + case VarianceModifier.Contravariant: + MakeUpperBoundInference(Ui, Vi); + break; + default: // invariant + MakeExactInference(Ui, Vi); + break; + } + } else { + // not known to be a reference type + MakeExactInference(Ui, Vi); + } + } + } + Debug.Unindent(); + } + } + + static bool IsIEnumerableCollectionOrList(ParameterizedType rt) + { + if (rt == null || rt.TypeParameterCount != 1) + return false; + switch (rt.GetDefinition().FullName) { + case "System.Collections.Generic.IList": + case "System.Collections.Generic.ICollection": + case "System.Collections.Generic.IEnumerable": + return true; + default: + return false; + } + } + #endregion + + #region MakeUpperBoundInference (§7.5.2.10) + /// + /// Make upper bound inference from U to V. + /// C# 4.0 spec: §7.5.2.10 Upper-bound inferences + /// + void MakeUpperBoundInference(IType U, IType V) + { + Log(" MakeUpperBoundInference from " + U + " to " + V); + + // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. + TP tp = GetTPForType(V); + if (tp != null && tp.IsFixed == false) { + Log(" Add upper bound '" + U + "' to " + tp); + tp.UpperBounds.Add(U); + return; + } + + // Handle array types: + ArrayType arrU = U as ArrayType; + ArrayType arrV = V as ArrayType; + ParameterizedType pU = U as ParameterizedType; + if (arrV != null && arrU != null && arrU.Dimensions == arrV.Dimensions) { + MakeUpperBoundInference(arrU.ElementType, arrV.ElementType); + return; + } else if (arrV != null && IsIEnumerableCollectionOrList(pU) && arrV.Dimensions == 1) { + MakeUpperBoundInference(pU.TypeArguments[0], arrV.ElementType); + return; + } + // Handle parameterized types: + if (pU != null) { + ParameterizedType uniqueBaseType = null; + foreach (IType baseV in V.GetAllBaseTypes(context)) { + ParameterizedType pV = baseV as ParameterizedType; + if (pV != null && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { + if (uniqueBaseType == null) + uniqueBaseType = pV; + else + return; // cannot make an inference because it's not unique + } + } + Debug.Indent(); + if (uniqueBaseType != null) { + for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { + IType Ui = pU.TypeArguments[i]; + IType Vi = uniqueBaseType.TypeArguments[i]; + if (Ui.IsReferenceType(context) == true) { + // look for variance + ITypeParameter Xi = pU.GetDefinition().TypeParameters[i]; + switch (Xi.Variance) { + case VarianceModifier.Covariant: + MakeUpperBoundInference(Ui, Vi); + break; + case VarianceModifier.Contravariant: + MakeLowerBoundInference(Ui, Vi); + break; + default: // invariant + MakeExactInference(Ui, Vi); + break; + } + } else { + // not known to be a reference type + MakeExactInference(Ui, Vi); + } + } + } + Debug.Unindent(); + } + } + #endregion + + #region Fixing (§7.5.2.11) + bool Fix(TP tp) + { + Log(" Trying to fix " + tp); + Debug.Assert(!tp.IsFixed); + Debug.Indent(); + var types = CreateNestedInstance().FindTypesInBounds(tp.LowerBounds.ToArray(), tp.UpperBounds.ToArray()); + Debug.Unindent(); + if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) { + tp.FixedTo = IntersectionType.Create(types); + Log(" T was fixed " + (types.Count >= 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); + return types.Count >= 1; + } else { + tp.FixedTo = GetFirstTypePreferNonInterfaces(types); + Log(" T was fixed " + (types.Count == 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); + return types.Count == 1; + } + } + #endregion + + #region Finding the best common type of a set of expresssions + /// + /// Gets the best common type (C# 4.0 spec: §7.5.2.14) of a set of expressions. + /// + public IType GetBestCommonType(IEnumerable expressions, out bool success) + { + if (expressions == null) + throw new ArgumentNullException("expressions"); + try { + this.typeParameters = new TP[1] { new TP(DummyTypeParameter.Instance) }; + foreach (ResolveResult r in expressions) { + MakeOutputTypeInference(r, DummyTypeParameter.Instance); + } + success = Fix(typeParameters[0]); + return typeParameters[0].FixedTo ?? SharedTypes.UnknownType; + } finally { + Reset(); + } + } + + sealed class DummyTypeParameter : AbstractType, ITypeParameter + { + public static readonly DummyTypeParameter Instance = new DummyTypeParameter(); + + public override string Name { + get { return "X"; } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; + } + + public override int GetHashCode() + { + return 0; + } + + public override bool Equals(IType other) + { + return this == other; + } + + int ITypeParameter.Index { + get { return 0; } + } + + IList ITypeParameter.Attributes { + get { return EmptyList.Instance; } + } + + EntityType ITypeParameter.OwnerType { + get { return EntityType.Method; } + } + + IList ITypeParameter.Constraints { + get { return EmptyList.Instance; } + } + + bool ITypeParameter.HasDefaultConstructorConstraint { + get { return false; } + } + + bool ITypeParameter.HasReferenceTypeConstraint { + get { return false; } + } + + bool ITypeParameter.HasValueTypeConstraint { + get { return false; } + } + + VarianceModifier ITypeParameter.Variance { + get { return VarianceModifier.Invariant; } + } + + IType ITypeParameter.BoundTo { + get { return null; } + } + + ITypeParameter ITypeParameter.UnboundTypeParameter { + get { return null; } + } + + bool IFreezable.IsFrozen { + get { return true; } + } + + void IFreezable.Freeze() + { + } + + DomRegion ITypeParameter.Region { + get { return DomRegion.Empty; } + } + } + #endregion + + #region FindTypeInBounds + /// + /// Finds a type that satisfies the given lower and upper bounds. + /// + public IType FindTypeInBounds(IList lowerBounds, IList upperBounds) + { + if (lowerBounds == null) + throw new ArgumentNullException("lowerBounds"); + if (upperBounds == null) + throw new ArgumentNullException("upperBounds"); + + IList result = FindTypesInBounds(lowerBounds, upperBounds); + + if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) { + return IntersectionType.Create(result); + } else { + // return any of the candidates (prefer non-interfaces) + return GetFirstTypePreferNonInterfaces(result); + } + } + + static IType GetFirstTypePreferNonInterfaces(IList result) + { + return result.FirstOrDefault(c => c.GetDefinition().ClassType != ClassType.Interface) + ?? result.FirstOrDefault() ?? SharedTypes.UnknownType; + } + + IList FindTypesInBounds(IList lowerBounds, IList upperBounds) + { + // If there's only a single type; return that single type. + // If both inputs are empty, return the empty list. + if (lowerBounds.Count == 0 && upperBounds.Count <= 1) + return upperBounds; + if (upperBounds.Count == 0 && lowerBounds.Count <= 1) + return lowerBounds; + if (nestingLevel > maxNestingLevel) + return EmptyList.Instance; + + // Finds a type X so that "LB <: X <: UB" + Log("FindTypesInBound, LowerBounds=", lowerBounds); + Log("FindTypesInBound, UpperBounds=", upperBounds); + Debug.Indent(); + + // First try the Fixing algorithm from the C# spec (§7.5.2.11) + List candidateTypes = lowerBounds.Union(upperBounds) + .Where(c => lowerBounds.All(b => conversions.ImplicitConversion(b, c))) + .Where(c => upperBounds.All(b => conversions.ImplicitConversion(c, b))) + .ToList(); // evaluate the query only once + + candidateTypes = candidateTypes.Where( + c => candidateTypes.All(o => conversions.ImplicitConversion(c, o)) + ).ToList(); + // If the specified algorithm produces a single candidate, we return + // that candidate. + // We also return the whole candidate list if we're not using the improved + // algorithm. + if (candidateTypes.Count == 1 || !(algorithm == TypeInferenceAlgorithm.Improved || algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults)) + { + return candidateTypes; + } + candidateTypes.Clear(); + + // Now try the improved algorithm + List candidateTypeDefinitions; + if (lowerBounds.Count > 0) { + // Find candidates by using the lower bounds: + var hashSet = new HashSet(lowerBounds[0].GetAllBaseTypeDefinitions(context)); + for (int i = 1; i < lowerBounds.Count; i++) { + hashSet.IntersectWith(lowerBounds[i].GetAllBaseTypeDefinitions(context)); + } + candidateTypeDefinitions = hashSet.ToList(); + } else { + // Find candidates by looking at all classes in the project: + candidateTypeDefinitions = context.GetAllTypes().ToList(); + } + + // Now filter out candidates that violate the upper bounds: + foreach (IType ub in upperBounds) { + ITypeDefinition ubDef = ub.GetDefinition(); + if (ubDef != null) { + candidateTypeDefinitions.RemoveAll(c => !c.IsDerivedFrom(ubDef, context)); + } + } + + foreach (ITypeDefinition candidateDef in candidateTypeDefinitions) { + // determine the type parameters for the candidate: + IType candidate; + if (candidateDef.TypeParameterCount == 0) { + candidate = candidateDef; + } else { + Log("Inferring arguments for candidate type definition: " + candidateDef); + bool success; + IType[] result = InferTypeArgumentsFromBounds( + candidateDef.TypeParameters, + new ParameterizedType(candidateDef, candidateDef.TypeParameters.SafeCast()), + lowerBounds, upperBounds, + out success); + if (success) { + candidate = new ParameterizedType(candidateDef, result); + } else { + Log("Inference failed; ignoring candidate"); + continue; + } + } + Log("Candidate type: " + candidate); + + if (lowerBounds.Count > 0) { + // if there were lower bounds, we aim for the most specific candidate: + + // if this candidate isn't made redundant by an existing, more specific candidate: + if (!candidateTypes.Any(c => c.GetDefinition().IsDerivedFrom(candidateDef, context))) { + // remove all existing candidates made redundant by this candidate: + candidateTypes.RemoveAll(c => candidateDef.IsDerivedFrom(c.GetDefinition(), context)); + // add new candidate + candidateTypes.Add(candidate); + } + } else { + // if there only were upper bounds, we aim for the least specific candidate: + + // if this candidate isn't made redundant by an existing, less specific candidate: + if (!candidateTypes.Any(c => candidateDef.IsDerivedFrom(c.GetDefinition(), context))) { + // remove all existing candidates made redundant by this candidate: + candidateTypes.RemoveAll(c => c.GetDefinition().IsDerivedFrom(candidateDef, context)); + // add new candidate + candidateTypes.Add(candidate); + } + } + } + Debug.Unindent(); + return candidateTypes; + } + #endregion + + [Conditional("DEBUG")] + static void Log(string text) + { + Debug.WriteLine(text); + } + + [Conditional("DEBUG")] + static void Log(string text, IEnumerable lines) + { + #if DEBUG + T[] arr = lines.ToArray(); + if (arr.Length == 0) { + Log(text + ""); + } else { + Log(text + (arr[0] != null ? arr[0].ToString() : "")); + for (int i = 1; i < arr.Length; i++) { + Log(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "")); + } + } + #endif + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs new file mode 100644 index 0000000000..093d77c7f0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// The resolved expression refers to a type name. + /// + public class TypeResolveResult : ResolveResult + { + public TypeResolveResult(IType type) + : base(type) + { + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/UnknownMemberResolveResult.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/UnknownMemberResolveResult.cs new file mode 100644 index 0000000000..2f6441fc49 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/UnknownMemberResolveResult.cs @@ -0,0 +1,99 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents an unknown member. + /// + public class UnknownMemberResolveResult : ResolveResult + { + readonly IType targetType; + readonly string memberName; + readonly ReadOnlyCollection typeArguments; + + public UnknownMemberResolveResult(IType targetType, string memberName, IEnumerable typeArguments) : base(SharedTypes.UnknownType) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + this.targetType = targetType; + this.memberName = memberName; + this.typeArguments = new ReadOnlyCollection(typeArguments.ToArray()); + } + + /// + /// The type on which the method is being called. + /// + public IType TargetType { + get { return targetType; } + } + + public string MemberName { + get { return memberName; } + } + + public ReadOnlyCollection TypeArguments { + get { return typeArguments; } + } + + public override bool IsError { + get { return true; } + } + + public override string ToString() + { + return string.Format("[{0} {1}.{2}]", GetType().Name, targetType, memberName); + } + } + + /// + /// Represents an unknown method. + /// + public class UnknownMethodResolveResult : UnknownMemberResolveResult + { + readonly ReadOnlyCollection parameters; + + public UnknownMethodResolveResult(IType targetType, string methodName, IEnumerable typeArguments, IEnumerable parameters) + : base(targetType, methodName, typeArguments) + { + this.parameters = new ReadOnlyCollection(parameters.ToArray()); + } + + public ReadOnlyCollection Parameters { + get { return parameters; } + } + } + + /// + /// Represents an unknown identifier. + /// + public class UnknownIdentifierResolveResult : ResolveResult + { + readonly string identifier; + + public UnknownIdentifierResolveResult(string identifier) + : base(SharedTypes.UnknownType) + { + this.identifier = identifier; + } + + public string Identifier { + get { return identifier; } + } + + public override bool IsError { + get { return true; } + } + + public override string ToString() + { + return string.Format("[{0} {1}]", GetType().Name, identifier); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs new file mode 100644 index 0000000000..6b55f34746 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs @@ -0,0 +1,150 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a scope that contains "using" statements. + /// This is either the file itself, or a namespace declaration. + /// + public class UsingScope : AbstractFreezable + { + readonly IProjectContent projectContent; + readonly UsingScope parent; + DomRegion region; + string namespaceName = ""; + IList usings; + IList> usingAliases; + IList externAliases; + //IList childScopes; + + protected override void FreezeInternal() + { + if (usings == null || usings.Count == 0) + usings = EmptyList.Instance; + else + usings = Array.AsReadOnly(usings.ToArray()); + + if (usingAliases == null || usingAliases.Count == 0) + usingAliases = EmptyList>.Instance; + else + usingAliases = Array.AsReadOnly(usingAliases.ToArray()); + + externAliases = FreezeList(externAliases); + //childScopes = FreezeList(childScopes); + + // In current model (no child scopes), it makes sense to freeze the parent as well + // to ensure the whole lookup chain is immutable. + // But we probably shouldn't do this if we add back childScopes. + if (parent != null) + parent.Freeze(); + + base.FreezeInternal(); + } + + /// + /// Creates a new root using scope. + /// + public UsingScope(IProjectContent projectContent) + { + if (projectContent == null) + throw new ArgumentNullException("projectContent"); + this.projectContent = projectContent; + } + + /// + /// Creates a new nested using scope. + /// + /// The parent using scope. + /// The full namespace name. + public UsingScope(UsingScope parent, string namespaceName) + { + if (parent == null) + throw new ArgumentNullException("parent"); + if (namespaceName == null) + throw new ArgumentNullException("namespaceName"); + this.parent = parent; + this.projectContent = parent.projectContent; + this.namespaceName = namespaceName; + } + + public UsingScope Parent { + get { return parent; } + } + + public IProjectContent ProjectContent { + get { return projectContent; } + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + public string NamespaceName { + get { return namespaceName; } + set { + if (value == null) + throw new ArgumentNullException("NamespaceName"); + CheckBeforeMutation(); + namespaceName = value; + } + } + + public IList Usings { + get { + if (usings == null) + usings = new List(); + return usings; + } + } + + public IList> UsingAliases { + get { + if (usingAliases == null) + usingAliases = new List>(); + return usingAliases; + } + } + + public IList ExternAliases { + get { + if (externAliases == null) + externAliases = new List(); + return externAliases; + } + } + +// public IList ChildScopes { +// get { +// if (childScopes == null) +// childScopes = new List(); +// return childScopes; +// } +// } + + /// + /// Gets whether this using scope has an alias (either using or extern) + /// with the specified name. + /// + public bool HasAlias(string identifier) + { + if (usingAliases != null) { + foreach (var pair in usingAliases) { + if (pair.Key == identifier) + return true; + } + } + return externAliases != null && externAliases.Contains(identifier); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs new file mode 100644 index 0000000000..70d88aa164 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs @@ -0,0 +1,378 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Xml; + +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Documentation +{ + /// + /// Provides documentation from an .xml file (as generated by the Microsoft C# compiler). + /// + /// + /// This class first creates an in-memory index of the .xml file, and then uses that to read only the requested members. + /// This way, we avoid keeping all the documentation in memory. + /// + public class XmlDocumentationProvider : IDocumentationProvider + { + #region Cache + sealed class XmlDocumentationCache + { + readonly KeyValuePair[] entries; + int pos; + + public XmlDocumentationCache(int size = 50) + { + if (size <= 0) + throw new ArgumentOutOfRangeException("size", size, "Value must be positive"); + this.entries = new KeyValuePair[size]; + } + + internal string Get(string key) + { + foreach (var pair in entries) { + if (pair.Key == key) + return pair.Value; + } + return null; + } + + internal void Add(string key, string value) + { + entries[pos++] = new KeyValuePair(key, value); + if (pos == entries.Length) + pos = 0; + } + } + #endregion + + struct IndexEntry : IComparable + { + /// + /// Hash code of the documentation tag + /// + internal readonly int HashCode; + + /// + /// Position in the .xml file where the documentation starts + /// + internal readonly int PositionInFile; + + internal IndexEntry(int hashCode, int positionInFile) + { + this.HashCode = hashCode; + this.PositionInFile = positionInFile; + } + + public int CompareTo(IndexEntry other) + { + return this.HashCode.CompareTo(other.HashCode); + } + } + + readonly XmlDocumentationCache cache = new XmlDocumentationCache(); + readonly string fileName; + DateTime lastWriteDate; + IndexEntry[] index; // SORTED array of index entries + + #region Constructor / Redirection support + /// + /// Creates a new XmlDocumentationProvider. + /// + /// Name of the .xml file. + public XmlDocumentationProvider(string fileName) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + + using (XmlTextReader xmlReader = new XmlTextReader(fileName)) { + xmlReader.XmlResolver = null; // no DTD resolving + xmlReader.MoveToContent(); + if (string.IsNullOrEmpty(xmlReader.GetAttribute("redirect"))) { + this.fileName = fileName; + ReadXmlDoc(xmlReader); + } else { + string redirectionTarget = GetRedirectionTarget(xmlReader.GetAttribute("redirect")); + if (redirectionTarget != null) { + Debug.WriteLine("XmlDoc " + fileName + " is redirecting to " + redirectionTarget); + using (XmlTextReader redirectedXmlReader = new XmlTextReader(redirectionTarget)) { + this.fileName = redirectionTarget; + ReadXmlDoc(redirectedXmlReader); + } + } else { + throw new XmlException("XmlDoc " + fileName + " is redirecting to " + xmlReader.GetAttribute("redirect") + ", but that file was not found."); + } + } + } + } + + private XmlDocumentationProvider(string fileName, DateTime lastWriteDate, IndexEntry[] index) + { + this.fileName = fileName; + this.lastWriteDate = lastWriteDate; + this.index = index; + } + + static string GetRedirectionTarget(string target) + { + string programFilesDir = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + programFilesDir = AppendDirectorySeparator(programFilesDir); + + string corSysDir = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(); + corSysDir = AppendDirectorySeparator(corSysDir); + + return LookupLocalizedXmlDoc(target.Replace("%PROGRAMFILESDIR%", programFilesDir) + .Replace("%CORSYSDIR%", corSysDir)); + } + + static string AppendDirectorySeparator(string dir) + { + if (dir.EndsWith("\\", StringComparison.Ordinal) || dir.EndsWith("/", StringComparison.Ordinal)) + return dir; + else + return dir + Path.DirectorySeparatorChar; + } + + internal static string LookupLocalizedXmlDoc(string fileName) + { + string xmlFileName = Path.ChangeExtension(fileName, ".xml"); + string currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; + string localizedXmlDocFile = GetLocalizedName(xmlFileName, currentCulture); + + Debug.WriteLine("Try find XMLDoc @" + localizedXmlDocFile); + if (File.Exists(localizedXmlDocFile)) { + return localizedXmlDocFile; + } + Debug.WriteLine("Try find XMLDoc @" + xmlFileName); + if (File.Exists(xmlFileName)) { + return xmlFileName; + } + if (currentCulture != "en") { + string englishXmlDocFile = GetLocalizedName(xmlFileName, "en"); + Debug.WriteLine("Try find XMLDoc @" + englishXmlDocFile); + if (File.Exists(englishXmlDocFile)) { + return englishXmlDocFile; + } + } + return null; + } + + static string GetLocalizedName(string fileName, string language) + { + string localizedXmlDocFile = Path.GetDirectoryName(fileName); + localizedXmlDocFile = Path.Combine(localizedXmlDocFile, language); + localizedXmlDocFile = Path.Combine(localizedXmlDocFile, Path.GetFileName(fileName)); + return localizedXmlDocFile; + } + #endregion + + #region Load / Create Index + void ReadXmlDoc(XmlTextReader reader) + { + lastWriteDate = File.GetLastWriteTimeUtc(fileName); + // Open up a second file stream for the line<->position mapping + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { + LinePositionMapper linePosMapper = new LinePositionMapper(fs); + List indexList = new List(); + while (reader.Read()) { + if (reader.IsStartElement()) { + switch (reader.LocalName) { + case "members": + ReadMembersSection(reader, linePosMapper, indexList); + break; + } + } + } + indexList.Sort(); + this.index = indexList.ToArray(); + } + } + + sealed class LinePositionMapper + { + readonly FileStream fs; + int currentLine = 1; + + public LinePositionMapper(FileStream fs) + { + this.fs = fs; + } + + public int GetPositionForLine(int line) + { + Debug.Assert(line >= currentLine); + while (line > currentLine) { + int b = fs.ReadByte(); + if (b < 0) + throw new EndOfStreamException(); + if (b == '\n') { + currentLine++; + } + } + return checked((int)fs.Position); + } + } + + void ReadMembersSection(XmlTextReader reader, LinePositionMapper linePosMapper, List indexList) + { + while (reader.Read()) { + switch (reader.NodeType) { + case XmlNodeType.EndElement: + if (reader.LocalName == "members") { + return; + } + break; + case XmlNodeType.Element: + if (reader.LocalName == "member") { + int pos = linePosMapper.GetPositionForLine(reader.LineNumber) + Math.Max(reader.LinePosition - 2, 0); + string memberAttr = reader.GetAttribute("name"); + if (memberAttr != null) + indexList.Add(new IndexEntry(memberAttr.GetHashCode(), pos)); + reader.Skip(); + } + break; + } + } + } + #endregion + + #region Save index / Restore from index + // FILE FORMAT FOR BINARY DOCUMENTATION + // long magic = 0x4244636f446c6d58 (identifies file type = 'XmlDocDB') + const long magic = 0x4244636f446c6d58; + // short version = 5 (file format version) + const short version = 5; + // string fileName (full name of .xml file) + // long fileDate (last change date of xml file in DateTime ticks) + // int testHashCode = magicTestString.GetHashCode() // (check if hash-code implementation is compatible) + // int entryCount (count of entries) + // int indexPointer (points to location where index starts in the file) + // { + // int hashcode + // int positionInFile (byte number where the docu string starts in the .xml file) + // } + + const string magicTestString = "XmlDoc-Test-String"; + + /// + /// Saves the index into a binary file. + /// Use to load the saved file. + /// + public void SaveIndex(BinaryWriter w) + { + if (w == null) + throw new ArgumentNullException("w"); + w.Write(magic); + w.Write(version); + w.Write(fileName); + w.Write(lastWriteDate.Ticks); + w.Write(magicTestString.GetHashCode()); + w.Write(index.Length); + foreach (var entry in index) { + w.Write(entry.HashCode); + w.Write(entry.PositionInFile); + } + } + + /// + /// Restores XmlDocumentationProvider from the index file (created by ). + /// + public static XmlDocumentationProvider LoadFromIndex(BinaryReader r) + { + if (r.ReadInt64() != magic) + throw new InvalidDataException("File is not a stored XmlDoc index"); + if (r.ReadInt16() != version) + throw new InvalidDataException("Index file was created by incompatible version"); + string fileName = r.ReadString(); + DateTime lastWriteDate = new DateTime(r.ReadInt64(), DateTimeKind.Utc); + if (r.ReadInt32() != magicTestString.GetHashCode()) + throw new InvalidDataException("Index file was created by another hash code algorithm"); + int indexLength = r.ReadInt32(); + IndexEntry[] index = new IndexEntry[indexLength]; + for (int i = 0; i < index.Length; i++) { + index[i] = new IndexEntry(r.ReadInt32(), r.ReadInt32()); + } + return new XmlDocumentationProvider(fileName, lastWriteDate, index); + } + #endregion + + #region GetDocumentation + /// + public string GetDocumentation(IEntity entity) + { + return GetDocumentation(GetDocumentationKey(entity)); + } + + /// + /// Get the documentation for the member with the specified documentation key. + /// + public string GetDocumentation(string key) + { + if (key == null) + throw new ArgumentNullException("key"); + + int hashcode = key.GetHashCode(); + // index is sorted, so we can use binary search + int m = Array.BinarySearch(index, new IndexEntry(hashcode, 0)); + if (m < 0) + return null; + // correct hash code found. + // possibly there are multiple items with the same hash, so go to the first. + while (--m >= 0 && index[m].HashCode == hashcode); + // m is now 1 before the first item with the correct hash + + lock (cache) { + string val = cache.Get(key); + if (val == null) { + // go through all items that have the correct hash + while (++m < index.Length && index[m].HashCode == hashcode) { + val = LoadDocumentation(key, index[m].PositionInFile); + if (val != null) + break; + } + // cache the result (even if it is null) + cache.Add(key, val); + } + return val; + } + } + #endregion + + #region Load / Read XML + string LoadDocumentation(string key, int positionInFile) + { + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { + fs.Position = positionInFile; + using (XmlTextReader r = new XmlTextReader(fs, XmlNodeType.Element, null)) { + r.XmlResolver = null; // no DTD resolving + while (r.Read()) { + if (r.NodeType == XmlNodeType.Element) { + string memberAttr = r.GetAttribute("name"); + if (memberAttr == key) { + return r.ReadInnerXml(); + } else { + return null; + } + } + } + return null; + } + } + } + #endregion + + #region GetDocumentationKey + public static string GetDocumentationKey(IEntity entity) + { + if (entity == null) + throw new ArgumentNullException("entity"); + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj new file mode 100644 index 0000000000..1fad1819d5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -0,0 +1,416 @@ + + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + Debug + AnyCPU + Library + ICSharpCode.NRefactory + ICSharpCode.NRefactory + v4.0 + Properties + 10.0.0 + 2.0 + False + False + false + 1591,0618 + False + -Microsoft.Design#CA1026;-Microsoft.Security#CA2104 + + + AnyCPU + False + Auto + 4194304 + 4096 + + + bin\Debug\ + Full + False + DEBUG;TRACE;FULL_AST + False + true + + + bin\Release\ + None + True + TRACE;FULL_AST + False + + + 4 + + + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + + + {F054A788-B591-4561-A8BA-AE745BBEB817} + ICSharpCode.Editor + + + + \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs new file mode 100644 index 0000000000..0f36736800 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Matches any node. + /// + /// Does not match null nodes. + public class AnyNode : Pattern + { + readonly string groupName; + + public string GroupName { + get { return groupName; } + } + + public AnyNode(string groupName = null) + { + this.groupName = groupName; + } + + public override bool DoMatch(INode other, Match match) + { + match.Add(this.groupName, other); + return other != null && !other.IsNull; + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitAnyNode(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Backreference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Backreference.cs new file mode 100644 index 0000000000..61338dde62 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Backreference.cs @@ -0,0 +1,72 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Linq; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Matches the last entry in the specified named group. + /// + public class Backreference : Pattern + { + readonly string referencedGroupName; + + public string ReferencedGroupName { + get { return referencedGroupName; } + } + + public Backreference(string referencedGroupName) + { + if (referencedGroupName == null) + throw new ArgumentNullException("referencedGroupName"); + this.referencedGroupName = referencedGroupName; + } + + public override bool DoMatch(INode other, Match match) + { + return match.Get(referencedGroupName).Last().IsMatch(other); + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitBackreference(this, data); + } + } + + /// + /// Matches identifier expressions that have the same identifier as the referenced variable/type definition/method definition. + /// + public class IdentifierExpressionBackreference : Pattern + { + readonly string referencedGroupName; + + public string ReferencedGroupName { + get { return referencedGroupName; } + } + + public IdentifierExpressionBackreference(string referencedGroupName) + { + if (referencedGroupName == null) + throw new ArgumentNullException("referencedGroupName"); + this.referencedGroupName = referencedGroupName; + } + + public override bool DoMatch(INode other, Match match) + { + CSharp.IdentifierExpression ident = other as CSharp.IdentifierExpression; + if (ident == null || ident.TypeArguments.Any()) + return false; + CSharp.AstNode referenced = (CSharp.AstNode)match.Get(referencedGroupName).Last(); + if (referenced == null) + return false; + return ident.Identifier == referenced.GetChildByRole(CSharp.AstNode.Roles.Identifier).Name; + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitIdentifierExpressionBackreference(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs new file mode 100644 index 0000000000..35721c496e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs @@ -0,0 +1,16 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Container for the backtracking info. + /// + public class BacktrackingInfo + { + internal Stack backtrackingStack = new Stack(); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Choice.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Choice.cs new file mode 100644 index 0000000000..8c19cc645f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Choice.cs @@ -0,0 +1,58 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Matches one of several alternatives. + /// + public class Choice : Pattern, IEnumerable + { + readonly List alternatives = new List(); + + public void Add(string name, INode alternative) + { + if (alternative == null) + throw new ArgumentNullException("alternative"); + alternatives.Add(new NamedNode(name, alternative)); + } + + public void Add(INode alternative) + { + if (alternative == null) + throw new ArgumentNullException("alternative"); + alternatives.Add(alternative); + } + + public override bool DoMatch(INode other, Match match) + { + var checkPoint = match.CheckPoint(); + foreach (INode alt in alternatives) { + if (alt.DoMatch(other, match)) + return true; + else + match.RestoreCheckPoint(checkPoint); + } + return false; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return alternatives.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return alternatives.GetEnumerator(); + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitChoice(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs new file mode 100644 index 0000000000..4e54cff3e2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/INode.cs @@ -0,0 +1,54 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// AST node that supports pattern matching. + /// + public interface INode + { + Role Role { get; } + INode FirstChild { get; } + INode NextSibling { get; } + bool IsNull { get; } + + bool DoMatch(INode other, Match match); + bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo); + } + + public static class PatternExtensions + { + /// + /// Performs a pattern matching operation. + /// this is the pattern, is the AST that is being matched. + /// + /// + /// A match object. Check to see whether the match was successful. + /// + /// + /// Patterns are ASTs that contain special pattern nodes (from the PatternMatching namespace). + /// However, it is also possible to match two ASTs without any pattern nodes - + /// doing so will produce a successful match if the two ASTs are structurally identical. + /// + public static Match Match(this INode pattern, INode other) + { + if (pattern == null) + throw new ArgumentNullException("pattern"); + Match match = PatternMatching.Match.CreateNew(); + if (pattern.DoMatch(other, match)) + return match; + else + return default(PatternMatching.Match); + } + + public static bool IsMatch(this INode pattern, INode other) + { + if (pattern == null) + throw new ArgumentNullException("pattern"); + return pattern.DoMatch(other, PatternMatching.Match.CreateNew()); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs new file mode 100644 index 0000000000..e5246cce3d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs @@ -0,0 +1,21 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// AST visitor that works for patterns. + /// + public interface IPatternAstVisitor + { + S VisitAnyNode(AnyNode anyNode, T data); + S VisitBackreference(Backreference backreference, T data); + S VisitChoice(Choice choice, T data); + S VisitNamedNode(NamedNode namedNode, T data); + S VisitRepeat(Repeat repeat, T data); + S VisitOptionalNode(OptionalNode optionalNode, T data); + S VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference, T data); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Match.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Match.cs new file mode 100644 index 0000000000..7fd6830394 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Match.cs @@ -0,0 +1,78 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Represents the result of a pattern matching operation. + /// + public struct Match + { + // TODO: maybe we should add an implicit Match->bool conversion? (implicit operator bool(Match m) { return m != null; }) + + List> results; + + public bool Success { + get { return results != null; } + } + + internal static Match CreateNew() + { + Match m; + m.results = new List>(); + return m; + } + + internal int CheckPoint() + { + return results.Count; + } + + internal void RestoreCheckPoint(int checkPoint) + { + results.RemoveRange(checkPoint, results.Count - checkPoint); + } + + public IEnumerable Get(string groupName) + { + if (results == null) + yield break; + foreach (var pair in results) { + if (pair.Key == groupName) + yield return pair.Value; + } + } + + public IEnumerable Get(string groupName) where T : INode + { + if (results == null) + yield break; + foreach (var pair in results) { + if (pair.Key == groupName) + yield return (T)pair.Value; + } + } + + public bool Has(string groupName) + { + if (results == null) + return false; + foreach (var pair in results) { + if (pair.Key == groupName) + return true; + } + return false; + } + + internal void Add(string groupName, INode node) + { + if (groupName != null && node != null) { + results.Add(new KeyValuePair(groupName, node)); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs new file mode 100644 index 0000000000..64802ce576 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Represents a named node within a pattern. + /// + public class NamedNode : Pattern + { + readonly string groupName; + readonly INode childNode; + + public string GroupName { + get { return groupName; } + } + + public INode ChildNode { + get { return childNode; } + } + + public NamedNode(string groupName, INode childNode) + { + if (childNode == null) + throw new ArgumentNullException("childNode"); + this.groupName = groupName; + this.childNode = childNode; + } + + public override bool DoMatch(INode other, Match match) + { + match.Add(this.groupName, other); + return childNode.DoMatch(other, match); + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitNamedNode(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs new file mode 100644 index 0000000000..b42db0209b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs @@ -0,0 +1,48 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + public class OptionalNode : Pattern + { + readonly INode childNode; + + public INode ChildNode { + get { return childNode; } + } + + public OptionalNode(INode childNode) + { + if (childNode == null) + throw new ArgumentNullException("childNode"); + this.childNode = childNode; + } + + public OptionalNode(string groupName, INode childNode) : this(new NamedNode(groupName, childNode)) + { + } + + public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) + { + backtrackingInfo.backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint())); + return childNode.DoMatch(pos, match); + } + + public override bool DoMatch(INode other, Match match) + { + if (other == null || other.IsNull) + return true; + else + return childNode.DoMatch(other, match); + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitOptionalNode(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs new file mode 100644 index 0000000000..5553840afb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Pattern.cs @@ -0,0 +1,101 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Base class for all patterns. + /// + public abstract class Pattern : INode + { + internal struct PossibleMatch + { + public readonly INode NextOther; // next node after the last matched node + public readonly int Checkpoint; // checkpoint + + public PossibleMatch(INode nextOther, int checkpoint) + { + this.NextOther = nextOther; + this.Checkpoint = checkpoint; + } + } + + bool INode.IsNull { + get { return false; } + } + + Role INode.Role { + get { return null; } + } + + INode INode.NextSibling { + get { return null; } + } + + INode INode.FirstChild { + get { return null; } + } + + public abstract bool DoMatch(INode other, Match match); + + public virtual bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) + { + return DoMatch (pos, match); + } + + public abstract S AcceptVisitor (IPatternAstVisitor visitor, T data); + + // Make debugging easier by giving Patterns a ToString() implementation + public override string ToString() + { + // TODO: what if this pattern contains a VB-AST? + // either remove ToString() here, or add some magic to figure out the correct output visitor + StringWriter w = new StringWriter(); + AcceptVisitor(new CSharp.OutputVisitor(w, new CSharp.CSharpFormattingOptions()), null); + return w.ToString(); + } + + public static bool DoMatchCollection(Role role, INode firstPatternChild, INode firstOtherChild, Match match) + { + BacktrackingInfo backtrackingInfo = new BacktrackingInfo(); + Stack patternStack = new Stack(); + Stack stack = backtrackingInfo.backtrackingStack; + patternStack.Push(firstPatternChild); + stack.Push(new PossibleMatch(firstOtherChild, match.CheckPoint())); + while (stack.Count > 0) { + INode cur1 = patternStack.Pop(); + INode cur2 = stack.Peek().NextOther; + match.RestoreCheckPoint(stack.Pop().Checkpoint); + bool success = true; + while (cur1 != null && success) { + while (cur1 != null && cur1.Role != role) + cur1 = cur1.NextSibling; + while (cur2 != null && cur2.Role != role) + cur2 = cur2.NextSibling; + if (cur1 == null) + break; + + Debug.Assert(stack.Count == patternStack.Count); + success = cur1.DoMatchCollection(role, cur2, match, backtrackingInfo); + Debug.Assert(stack.Count >= patternStack.Count); + while (stack.Count > patternStack.Count) + patternStack.Push(cur1.NextSibling); + + cur1 = cur1.NextSibling; + if (cur2 != null) + cur2 = cur2.NextSibling; + } + while (cur2 != null && cur2.Role != role) + cur2 = cur2.NextSibling; + if (success && cur2 == null) + return true; + } + return false; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs new file mode 100644 index 0000000000..249075fe36 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/PatternMatching/Repeat.cs @@ -0,0 +1,64 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace ICSharpCode.NRefactory.PatternMatching +{ + /// + /// Represents an optional node. + /// + public class Repeat : Pattern + { + readonly INode childNode; + + public int MinCount { get; set; } + public int MaxCount { get; set; } + + public INode ChildNode { + get { return childNode; } + } + + public Repeat(INode childNode) + { + if (childNode == null) + throw new ArgumentNullException("childNode"); + this.childNode = childNode; + this.MinCount = 0; + this.MaxCount = int.MaxValue; + } + + public override bool DoMatchCollection(Role role, INode pos, Match match, BacktrackingInfo backtrackingInfo) + { + var backtrackingStack = backtrackingInfo.backtrackingStack; + Debug.Assert(pos == null || pos.Role == role); + int matchCount = 0; + if (this.MinCount <= 0) + backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint())); + while (matchCount < this.MaxCount && pos != null && childNode.DoMatch(pos, match)) { + matchCount++; + do { + pos = pos.NextSibling; + } while (pos != null && pos.Role != role); + if (matchCount >= this.MinCount) + backtrackingStack.Push(new PossibleMatch(pos, match.CheckPoint())); + } + return false; // never do a normal (single-element) match; always make the caller look at the results on the back-tracking stack. + } + + public override bool DoMatch(INode other, Match match) + { + if (other == null || other.IsNull) + return this.MinCount <= 0; + else + return this.MaxCount >= 1 && childNode.DoMatch(other, match); + } + + public override S AcceptVisitor(IPatternAstVisitor visitor, T data) + { + return visitor.VisitRepeat(this, data); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..28987ead7d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +#region Using directives + +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ICSharpCode.NRefactory")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ICSharpCode")] +[assembly: AssemblyProduct("SharpDevelop/MonoDevelop")] +[assembly: AssemblyCopyright("Copyright 2010 AlphaSierraPapa")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// 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.*")] diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs new file mode 100644 index 0000000000..7717e61124 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs @@ -0,0 +1,46 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Enum that describes the accessibility of an entity. + /// + public enum Accessibility : byte + { + // note: some code depends on the fact that these values are within the range 0-7 + + /// + /// The entity is completely inaccessible. This is used for C# explicit interface implementations. + /// + None, + /// + /// The entity is only accessible within the same class. + /// + Private, + /// + /// The entity is accessible everywhere. + /// + Public, + /// + /// The entity is only accessible within the same class and in derived classes. + /// + Protected, + /// + /// The entity is accessible within the same project content. + /// + Internal, + /// + /// The entity is accessible both everywhere in the project content, and in all derived classes. + /// + /// This corresponds to C# 'protected internal'. + ProtectedOrInternal, + /// + /// The entity is accessible in derived classes within the same project content. + /// + /// C# does not support this accessibility. + ProtectedAndInternal, + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs new file mode 100644 index 0000000000..9f42a2ec85 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -0,0 +1,174 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents an array type. + /// + public class ArrayType : TypeWithElementType + { + readonly int dimensions; + + public ArrayType(IType elementType, int dimensions = 1) : base(elementType) + { + if (dimensions <= 0) + throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive"); + this.dimensions = dimensions; + } + + public int Dimensions { + get { return dimensions; } + } + + public override string NameSuffix { + get { + return "[" + new string(',', dimensions-1) + "]"; + } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return true; + } + + public override int GetHashCode() + { + return unchecked(elementType.GetHashCode() * 71681 + dimensions); + } + + public override bool Equals(IType other) + { + ArrayType a = other as ArrayType; + return a != null && elementType.Equals(a.elementType) && a.dimensions == dimensions; + } + + static readonly GetClassTypeReference systemArray = new GetClassTypeReference("System", "Array", 0); + static readonly GetClassTypeReference listInterface = new GetClassTypeReference("System.Collections.Generic", "IList", 1); + + public override IEnumerable GetBaseTypes(ITypeResolveContext context) + { + List baseTypes = new List(); + IType t = systemArray.Resolve(context); + if (t != SharedTypes.UnknownType) + baseTypes.Add(t); + if (dimensions == 1) { // single-dimensional arrays implement IList + ITypeDefinition def = listInterface.Resolve(context) as ITypeDefinition; + if (def != null) + baseTypes.Add(new ParameterizedType(def, new[] { elementType })); + } + return baseTypes; + } + + public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + { + return systemArray.Resolve(context).GetMethods(context, filter); + } + + static readonly DefaultParameter indexerParam = new DefaultParameter(KnownTypeReference.Int32, string.Empty); + + public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition arrayDef = systemArray.Resolve(context) as ITypeDefinition; + if (arrayDef != null) { + foreach (IProperty p in arrayDef.GetProperties(context, filter)) { + yield return p; + } + DefaultProperty indexer = new DefaultProperty(arrayDef, "Items") { + EntityType = EntityType.Indexer, + ReturnType = elementType, + Accessibility = Accessibility.Public, + Getter = DefaultAccessor.GetFromAccessibility(Accessibility.Public), + Setter = DefaultAccessor.GetFromAccessibility(Accessibility.Public), + IsSynthetic = true + }; + for (int i = 0; i < dimensions; i++) { + indexer.Parameters.Add(indexerParam); + } + indexer.Freeze(); + if (filter == null || filter(indexer)) { + yield return indexer; + } + } + } + + // Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation + // that simply returns an empty list + + public override IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitArrayType(this); + } + + public override IType VisitChildren(TypeVisitor visitor) + { + IType e = elementType.AcceptVisitor(visitor); + if (e == elementType) + return this; + else + return new ArrayType(e, dimensions); + } + } + + public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning + { + ITypeReference elementType; + int dimensions; + + public ArrayTypeReference(ITypeReference elementType, int dimensions = 1) + { + if (elementType == null) + throw new ArgumentNullException("elementType"); + if (dimensions <= 0) + throw new ArgumentOutOfRangeException("dimensions", dimensions, "dimensions must be positive"); + this.elementType = elementType; + this.dimensions = dimensions; + } + + public ITypeReference ElementType { + get { return elementType; } + } + + public int Dimensions { + get { return dimensions; } + } + + public IType Resolve(ITypeResolveContext context) + { + return new ArrayType(elementType.Resolve(context), dimensions); + } + + public override string ToString() + { + return elementType.ToString() + "[" + new string(',', dimensions - 1) + "]"; + } + + public static ITypeReference Create(ITypeReference elementType, int dimensions) + { + if (elementType is IType) + return new ArrayType((IType)elementType, dimensions); + else + return new ArrayTypeReference(elementType, dimensions); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + elementType = provider.Intern(elementType); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return elementType.GetHashCode() ^ dimensions; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ArrayTypeReference o = other as ArrayTypeReference; + return o != null && elementType == o.elementType && dimensions == o.dimensions; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs new file mode 100644 index 0000000000..39288f25fd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs @@ -0,0 +1,83 @@ + +using System; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + public class ByReferenceType : TypeWithElementType + { + public ByReferenceType(IType elementType) : base(elementType) + { + } + + public override string NameSuffix { + get { + return "&"; + } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; + } + + public override int GetHashCode() + { + return elementType.GetHashCode() ^ 91725813; + } + + public override bool Equals(IType other) + { + ByReferenceType a = other as ByReferenceType; + return a != null && elementType.Equals(a.elementType); + } + + public override IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitByReferenceType(this); + } + + public override IType VisitChildren(TypeVisitor visitor) + { + IType e = elementType.AcceptVisitor(visitor); + if (e == elementType) + return this; + else + return new ByReferenceType(e); + } + } + + public class ByReferenceTypeReference : ITypeReference + { + readonly ITypeReference elementType; + + public ByReferenceTypeReference(ITypeReference elementType) + { + if (elementType == null) + throw new ArgumentNullException("elementType"); + this.elementType = elementType; + } + + public ITypeReference ElementType { + get { return elementType; } + } + + public IType Resolve(ITypeResolveContext context) + { + return new ByReferenceType(elementType.Resolve(context)); + } + + public override string ToString() + { + return elementType.ToString() + "&"; + } + + public static ITypeReference Create(ITypeReference elementType) + { + if (elementType is IType) + return new ByReferenceType((IType)elementType); + else + return new ByReferenceTypeReference(elementType); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs new file mode 100644 index 0000000000..d7765d938d --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -0,0 +1,1255 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using Mono.Cecil; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Allows loading an IProjectContent from an already compiled assembly. + /// + /// Instance methods are not thread-safe; you need to create multiple instances of CecilLoader + /// if you want to load multiple project contents in parallel. + public class CecilLoader + { + #region Options + /// + /// Gets/Sets the early bind context. + /// This context is used to pre-resolve type references - setting this property will cause the CecilLoader + /// to directly reference the resolved types, and create links () to types + /// that could not be resolved. + /// + public ITypeResolveContext EarlyBindContext { get; set; } + + /// + /// Specifies whether to include internal members. The default is false. + /// + public bool IncludeInternalMembers { get; set; } + + /// + /// Gets/Sets the documentation provider that is used to retrieve the XML documentation for all members. + /// + public IDocumentationProvider DocumentationProvider { get; set; } + + /// + /// Gets/Sets the interning provider. + /// + public IInterningProvider InterningProvider { get; set; } + + /// + /// Gets a value indicating whether this instance stores references to the cecil objects. + /// + /// + /// true if this instance has references to the cecil objects; otherwise, false. + /// + public bool HasCecilReferences { get { return typeSystemTranslationTable != null; } } + #endregion + + /// + /// Initializes a new instance of the class. + /// + /// + /// If true references to the cecil objects are hold. In this case the cecil loader can do a type system -> cecil mapping. + /// + public CecilLoader (bool createCecilReferences = false) + { + if (createCecilReferences) + typeSystemTranslationTable = new Dictionary (); + } + + #region Load From AssemblyDefinition + /// + /// Loads the assembly definition into a project content. + /// + /// IProjectContent that represents the assembly + public IProjectContent LoadAssembly(AssemblyDefinition assemblyDefinition) + { + if (assemblyDefinition == null) + throw new ArgumentNullException("assemblyDefinition"); + ITypeResolveContext oldEarlyBindContext = this.EarlyBindContext; + try { + IList assemblyAttributes = new List(); + foreach (var attr in assemblyDefinition.CustomAttributes) { + assemblyAttributes.Add(ReadAttribute(attr)); + } + if (this.InterningProvider != null) + assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes); + else + assemblyAttributes = new ReadOnlyCollection(assemblyAttributes); + TypeStorage typeStorage = new TypeStorage(); + CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes, this.DocumentationProvider); + + this.EarlyBindContext = CompositeTypeResolveContext.Combine(pc, this.EarlyBindContext); + List types = new List(); + foreach (ModuleDefinition module in assemblyDefinition.Modules) { + foreach (TypeDefinition td in module.Types) { + if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { + string name = td.FullName; + if (name.Length == 0 || name[0] == '<') + continue; + if (name == "System.Void") { + var c = new VoidTypeDefinition(pc); + AddAttributes(td, c); + typeStorage.UpdateType(c); + } else { + CecilTypeDefinition c = new CecilTypeDefinition(pc, td); + types.Add(c); + typeStorage.UpdateType(c); + } + } + } + } + foreach (CecilTypeDefinition c in types) { + c.Init(this); + } + if (HasCecilReferences) + typeSystemTranslationTable[pc] = assemblyDefinition; + return pc; + } finally { + this.EarlyBindContext = oldEarlyBindContext; + } + } + + /// + /// Loads a type from Cecil. + /// + /// The Cecil TypeDefinition. + /// The project content used as parent for the new type. + /// ITypeDefinition representing the Cecil type. + public ITypeDefinition LoadType(TypeDefinition typeDefinition, IProjectContent projectContent) + { + if (typeDefinition == null) + throw new ArgumentNullException("typeDefinition"); + if (projectContent == null) + throw new ArgumentNullException("projectContent"); + var c = new CecilTypeDefinition(projectContent, typeDefinition); + c.Init(this); + return c; + } + #endregion + + #region IProjectContent implementation + sealed class CecilProjectContent : ProxyTypeResolveContext, IProjectContent, ISynchronizedTypeResolveContext, IDocumentationProvider + { + readonly string assemblyName; + readonly IList assemblyAttributes; + readonly IDocumentationProvider documentationProvider; + + public CecilProjectContent(TypeStorage types, string assemblyName, IList assemblyAttributes, IDocumentationProvider documentationProvider) + : base(types) + { + Debug.Assert(assemblyName != null); + Debug.Assert(assemblyAttributes != null); + this.assemblyName = assemblyName; + this.assemblyAttributes = assemblyAttributes; + this.documentationProvider = documentationProvider; + } + + public IList AssemblyAttributes { + get { return assemblyAttributes; } + } + + public override string ToString() + { + return "[CecilProjectContent " + assemblyName + "]"; + } + + public override ISynchronizedTypeResolveContext Synchronize() + { + // CecilProjectContent is immutable, so we don't need to synchronize + return this; + } + + public void Dispose() + { + // Disposing the synchronization context has no effect + } + + public IParsedFile GetFile(string fileName) + { + return null; + } + + public IEnumerable Files { + get { + return EmptyList.Instance; + } + } + + string IDocumentationProvider.GetDocumentation(IEntity entity) + { + if (documentationProvider != null) + return documentationProvider.GetDocumentation(entity); + else + return null; + } + } + #endregion + + #region Load Assembly From Disk + public IProjectContent LoadAssemblyFile(string fileName) + { + if (fileName == null) + throw new ArgumentNullException("fileName"); + var param = new ReaderParameters { AssemblyResolver = new DummyAssemblyResolver() }; + AssemblyDefinition asm = AssemblyDefinition.ReadAssembly(fileName, param); + var result = LoadAssembly(asm); + if (HasCecilReferences) + typeSystemTranslationTable[result] = asm; + return result; + } + + // used to prevent Cecil from loading referenced assemblies + sealed class DummyAssemblyResolver : IAssemblyResolver + { + public AssemblyDefinition Resolve(AssemblyNameReference name) + { + return null; + } + + public AssemblyDefinition Resolve(string fullName) + { + return null; + } + + public AssemblyDefinition Resolve(AssemblyNameReference name, ReaderParameters parameters) + { + return null; + } + + public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters) + { + return null; + } + } + #endregion + + #region Read Type Reference + /// + /// Reads a type reference. + /// + /// The Cecil type reference that should be converted into + /// a type system type reference. + /// Attributes associated with the Cecil type reference. + /// This is used to support the 'dynamic' type. + /// The entity that owns this type reference. + /// Used for generic type references. + public ITypeReference ReadTypeReference( + TypeReference type, + ICustomAttributeProvider typeAttributes = null, + IEntity entity = null) + { + int typeIndex = 0; + return CreateType(type, entity, typeAttributes, ref typeIndex); + } + + ITypeReference CreateType( + TypeReference type, + IEntity entity, + ICustomAttributeProvider typeAttributes, ref int typeIndex) + { + while (type is OptionalModifierType || type is RequiredModifierType) { + type = ((TypeSpecification)type).ElementType; + } + if (type == null) { + return SharedTypes.UnknownType; + } + + if (type is Mono.Cecil.ByReferenceType) { + typeIndex++; + return ByReferenceTypeReference.Create( + CreateType( + (type as Mono.Cecil.ByReferenceType).ElementType, + entity, typeAttributes, ref typeIndex)); + } else if (type is Mono.Cecil.PointerType) { + typeIndex++; + return PointerTypeReference.Create( + CreateType( + (type as Mono.Cecil.PointerType).ElementType, + entity, typeAttributes, ref typeIndex)); + } else if (type is Mono.Cecil.ArrayType) { + typeIndex++; + return ArrayTypeReference.Create( + CreateType( + (type as Mono.Cecil.ArrayType).ElementType, + entity, typeAttributes, ref typeIndex), + (type as Mono.Cecil.ArrayType).Rank); + } else if (type is GenericInstanceType) { + GenericInstanceType gType = (GenericInstanceType)type; + ITypeReference baseType = CreateType(gType.ElementType, entity, typeAttributes, ref typeIndex); + ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count]; + for (int i = 0; i < para.Length; ++i) { + typeIndex++; + para[i] = CreateType(gType.GenericArguments[i], entity, typeAttributes, ref typeIndex); + } + return ParameterizedTypeReference.Create(baseType, para); + } else if (type is GenericParameter) { + GenericParameter typeGP = type as GenericParameter; + if (typeGP.Owner is MethodDefinition) { + IMethod method = entity as IMethod; + if (method != null) { + if (typeGP.Position < method.TypeParameters.Count) { + return method.TypeParameters[typeGP.Position]; + } + } + return SharedTypes.UnknownType; + } else { + ITypeDefinition c = (entity as ITypeDefinition) ?? (entity is IMember ? ((IMember)entity).DeclaringTypeDefinition : null); + if (c != null && typeGP.Position < c.TypeParameters.Count) { + if (c.TypeParameters[typeGP.Position].Name == type.Name) { + return c.TypeParameters[typeGP.Position]; + } + } + return SharedTypes.UnknownType; + } + } else if (type.IsNested) { + ITypeReference typeRef = CreateType(type.DeclaringType, entity, typeAttributes, ref typeIndex); + int partTypeParameterCount; + string namepart = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out partTypeParameterCount); + return new NestedTypeReference(typeRef, namepart, partTypeParameterCount); + } else { + string ns = type.Namespace ?? string.Empty; + string name = type.Name; + if (name == null) + throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString()); + + if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) { + return SharedTypes.Dynamic; + } else { + int typeParameterCount; + name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out typeParameterCount); + var earlyBindContext = this.EarlyBindContext; + if (earlyBindContext != null) { + IType c = earlyBindContext.GetTypeDefinition(ns, name, typeParameterCount, StringComparer.Ordinal); + if (c != null) + return c; + } + return new GetClassTypeReference(ns, name, typeParameterCount); + } + } + } + + static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) + { + if (attributeProvider == null || !attributeProvider.HasCustomAttributes) + return false; + foreach (CustomAttribute a in attributeProvider.CustomAttributes) { + TypeReference type = a.AttributeType; + if (type.Name == "DynamicAttribute" && type.Namespace == "System.Runtime.CompilerServices") { + if (a.ConstructorArguments.Count == 1) { + CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[]; + if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool) + return (bool)values[typeIndex].Value; + } + return true; + } + } + return false; + } + #endregion + + #region Read Attributes + void AddAttributes(ICustomAttributeProvider customAttributeProvider, IEntity targetEntity) + { + if (customAttributeProvider.HasCustomAttributes) { + AddCustomAttributes(customAttributeProvider.CustomAttributes, targetEntity.Attributes); + } + } + + static readonly IAttribute inAttribute = new DefaultAttribute(typeof(InAttribute).ToTypeReference(), null); + static readonly IAttribute outAttribute = new DefaultAttribute(typeof(OutAttribute).ToTypeReference(), null); + + void AddAttributes(ParameterDefinition parameter, DefaultParameter targetParameter) + { + if (!targetParameter.IsOut) { + if (parameter.IsIn) + targetParameter.Attributes.Add(inAttribute); + if (parameter.IsOut) + targetParameter.Attributes.Add(outAttribute); + } + if (parameter.HasCustomAttributes) { + AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes); + } + } + + static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference(); + static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); + static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); + static readonly ITypeReference callingConventionTypeRef = typeof(CallingConvention).ToTypeReference(); + static readonly IAttribute preserveSigAttribute = new DefaultAttribute(typeof(PreserveSigAttribute).ToTypeReference(), null); + static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference(); + static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference(); + + bool HasAnyAttributes(MethodDefinition methodDefinition) + { + if (methodDefinition.HasPInvokeInfo) + return true; + if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0) + return true; + if (methodDefinition.MethodReturnType.HasFieldMarshal) + return true; + return methodDefinition.HasCustomAttributes || methodDefinition.MethodReturnType.HasCustomAttributes; + } + + void AddAttributes(MethodDefinition methodDefinition, IList attributes, IList returnTypeAttributes) + { + MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; + + #region DllImportAttribute + if (methodDefinition.HasPInvokeInfo) { + PInvokeInfo info = methodDefinition.PInvokeInfo; + DefaultAttribute dllImport = new DefaultAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String }); + dllImport.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, info.Module.Name)); + + if (info.IsBestFitDisabled) + AddNamedArgument(dllImport, "BestFitMapping", falseValue); + if (info.IsBestFitEnabled) + AddNamedArgument(dllImport, "BestFitMapping", trueValue); + + CallingConvention callingConvention; + switch (info.Attributes & PInvokeAttributes.CallConvMask) { + case PInvokeAttributes.CallConvCdecl: + callingConvention = CallingConvention.Cdecl; + break; + case PInvokeAttributes.CallConvFastcall: + callingConvention = CallingConvention.FastCall; + break; + case PInvokeAttributes.CallConvStdCall: + callingConvention = CallingConvention.StdCall; + break; + case PInvokeAttributes.CallConvThiscall: + callingConvention = CallingConvention.ThisCall; + break; + case PInvokeAttributes.CallConvWinapi: + callingConvention = CallingConvention.Winapi; + break; + default: + throw new NotSupportedException("unknown calling convention"); + } + if (callingConvention != CallingConvention.Winapi) + AddNamedArgument(dllImport, "CallingConvention", new SimpleConstantValue(callingConventionTypeRef, (int)callingConvention)); + + CharSet charSet = CharSet.None; + switch (info.Attributes & PInvokeAttributes.CharSetMask) { + case PInvokeAttributes.CharSetAnsi: + charSet = CharSet.Ansi; + break; + case PInvokeAttributes.CharSetAuto: + charSet = CharSet.Auto; + break; + case PInvokeAttributes.CharSetUnicode: + charSet = CharSet.Unicode; + break; + } + if (charSet != CharSet.None) + dllImport.NamedArguments.Add(new KeyValuePair( + "CharSet", new SimpleConstantValue(charSetTypeRef, (int)charSet))); + + if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name) + AddNamedArgument(dllImport, "EntryPoint", new SimpleConstantValue(KnownTypeReference.String, info.EntryPoint)); + + if (info.IsNoMangle) + AddNamedArgument(dllImport, "ExactSpelling", trueValue); + + if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) + implAttributes &= ~MethodImplAttributes.PreserveSig; + else + AddNamedArgument(dllImport, "PreserveSig", falseValue); + + if (info.SupportsLastError) + AddNamedArgument(dllImport, "SetLastError", trueValue); + + if (info.IsThrowOnUnmappableCharDisabled) + AddNamedArgument(dllImport, "ThrowOnUnmappableChar", falseValue); + if (info.IsThrowOnUnmappableCharEnabled) + AddNamedArgument(dllImport, "ThrowOnUnmappableChar", trueValue); + + attributes.Add(dllImport); + } + #endregion + + #region PreserveSigAttribute + if (implAttributes == MethodImplAttributes.PreserveSig) { + attributes.Add(preserveSigAttribute); + implAttributes = 0; + } + #endregion + + #region MethodImplAttribute + if (implAttributes != 0) { + DefaultAttribute methodImpl = new DefaultAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef }); + methodImpl.PositionalArguments.Add(new SimpleConstantValue(methodImplOptionsTypeRef, (int)implAttributes)); + attributes.Add(methodImpl); + } + #endregion + + if (methodDefinition.HasCustomAttributes) { + AddCustomAttributes(methodDefinition.CustomAttributes, attributes); + } + if (methodDefinition.MethodReturnType.HasMarshalInfo) { + returnTypeAttributes.Add(ConvertMarshalInfo(methodDefinition.MethodReturnType.MarshalInfo)); + } + if (methodDefinition.MethodReturnType.HasCustomAttributes) { + AddCustomAttributes(methodDefinition.MethodReturnType.CustomAttributes, returnTypeAttributes); + } + } + + static void AddNamedArgument(DefaultAttribute attribute, string name, IConstantValue value) + { + attribute.NamedArguments.Add(new KeyValuePair(name, value)); + } + + static readonly DefaultAttribute serializableAttribute = new DefaultAttribute(typeof(SerializableAttribute).ToTypeReference(), null); + static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference(); + static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference(); + static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference(); + + void AddAttributes(TypeDefinition typeDefinition, ITypeDefinition targetEntity) + { + #region SerializableAttribute + if (typeDefinition.IsSerializable) + targetEntity.Attributes.Add(serializableAttribute); + #endregion + + #region StructLayoutAttribute + LayoutKind layoutKind = LayoutKind.Auto; + switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) { + case TypeAttributes.SequentialLayout: + layoutKind = LayoutKind.Sequential; + break; + case TypeAttributes.ExplicitLayout: + layoutKind = LayoutKind.Explicit; + break; + } + CharSet charSet = CharSet.None; + switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) { + case TypeAttributes.AnsiClass: + charSet = CharSet.Ansi; + break; + case TypeAttributes.AutoClass: + charSet = CharSet.Auto; + break; + case TypeAttributes.UnicodeClass: + charSet = CharSet.Unicode; + break; + } + LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto; + if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) { + DefaultAttribute structLayout = new DefaultAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); + structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); + if (charSet != CharSet.Ansi) { + structLayout.NamedArguments.Add(new KeyValuePair( + "CharSet", + new SimpleConstantValue(charSetTypeRef, (int)charSet))); + } + if (typeDefinition.PackingSize > 0) { + structLayout.NamedArguments.Add(new KeyValuePair( + "Pack", + new SimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.PackingSize))); + } + if (typeDefinition.ClassSize > 0) { + structLayout.NamedArguments.Add(new KeyValuePair( + "Size", + new SimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.ClassSize))); + } + targetEntity.Attributes.Add(structLayout); + } + #endregion + + if (typeDefinition.HasCustomAttributes) { + AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes); + } + } + + static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference(); + static readonly DefaultAttribute nonSerializedAttribute = new DefaultAttribute(typeof(NonSerializedAttribute).ToTypeReference(), null); + + void AddAttributes(FieldDefinition fieldDefinition, IEntity targetEntity) + { + #region FieldOffsetAttribute + if (fieldDefinition.HasLayoutInfo) { + DefaultAttribute fieldOffset = new DefaultAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 }); + fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset)); + targetEntity.Attributes.Add(fieldOffset); + } + #endregion + + #region NonSerializedAttribute + if (fieldDefinition.IsNotSerialized) { + targetEntity.Attributes.Add(nonSerializedAttribute); + } + #endregion + + if (fieldDefinition.HasMarshalInfo) { + targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo)); + } + + if (fieldDefinition.HasCustomAttributes) { + AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes); + } + } + + #region MarshalAsAttribute (ConvertMarshalInfo) + static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference(); + static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference(); + + static IAttribute ConvertMarshalInfo(MarshalInfo marshalInfo) + { + DefaultAttribute attr = new DefaultAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef }); + attr.PositionalArguments.Add(new SimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType)); + // TODO: handle classes derived from MarshalInfo + return attr; + } + #endregion + + void AddCustomAttributes(Mono.Collections.Generic.Collection attributes, IList targetCollection) + { + foreach (var cecilAttribute in attributes) { + TypeReference type = cecilAttribute.AttributeType; + if (type.Namespace == "System.Runtime.CompilerServices") { + if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute") + continue; + } else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") { + continue; + } + targetCollection.Add(ReadAttribute(cecilAttribute)); + } + } + + public IAttribute ReadAttribute(CustomAttribute attribute) + { + if (attribute == null) + throw new ArgumentNullException("attribute"); + MethodReference ctor = attribute.Constructor; + ITypeReference[] ctorParameters = null; + if (ctor.HasParameters) { + ctorParameters = new ITypeReference[ctor.Parameters.Count]; + for (int i = 0; i < ctorParameters.Length; i++) { + ctorParameters[i] = ReadTypeReference(ctor.Parameters[i].ParameterType); + } + } + DefaultAttribute a = new DefaultAttribute(ReadTypeReference(attribute.AttributeType), ctorParameters); + try { + if (attribute.HasConstructorArguments) { + foreach (var arg in attribute.ConstructorArguments) { + a.PositionalArguments.Add(ReadConstantValue(arg)); + } + } + } catch (InvalidOperationException) { + // occurs when Cecil can't decode an argument + } + try { + if (attribute.HasFields || attribute.HasProperties) { + foreach (var arg in attribute.Fields) { + a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + } + foreach (var arg in attribute.Properties) { + a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + } + } + } catch (InvalidOperationException) { + // occurs when Cecil can't decode an argument + } + return a; + } + #endregion + + #region Read Constant Value + public IConstantValue ReadConstantValue(CustomAttributeArgument arg) + { + object value = arg.Value; + if (value is CustomAttributeArgument) { + // Cecil uses this representation for boxed values + arg = (CustomAttributeArgument)value; + value = arg.Value; + } + ITypeReference type = ReadTypeReference(arg.Type); + CustomAttributeArgument[] array = value as CustomAttributeArgument[]; + if (array != null) { + // TODO: write unit test for this + // TODO: are multi-dimensional arrays possible as well? + throw new NotImplementedException(); + } + + TypeReference valueType = value as TypeReference; + if (valueType != null) + value = ReadTypeReference(valueType); + return new SimpleConstantValue(type, value); + } + #endregion + + #region Read Type Definition + sealed class CecilTypeDefinition : DefaultTypeDefinition + { + internal TypeDefinition typeDefinition; + + public CecilTypeDefinition(IProjectContent pc, TypeDefinition typeDefinition) + : base(pc, typeDefinition.Namespace, ReflectionHelper.SplitTypeParameterCountFromReflectionName(typeDefinition.Name)) + { + this.typeDefinition = typeDefinition; + InitTypeParameters(); + } + + public CecilTypeDefinition(CecilTypeDefinition parentType, string name, TypeDefinition typeDefinition) + : base(parentType, name) + { + this.typeDefinition = typeDefinition; + InitTypeParameters(); + } + + void InitTypeParameters() + { + // Type parameters are initialized within the constructor so that the class can be put into the type storage + // before the rest of the initialization runs - this allows it to be available for early binding as soon as possible. + for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) { + if (typeDefinition.GenericParameters[i].Position != i) + throw new InvalidOperationException("g.Position != i"); + this.TypeParameters.Add(new DefaultTypeParameter( + EntityType.TypeDefinition, i, typeDefinition.GenericParameters[i].Name)); + } + } + + public void Init(CecilLoader loader) + { + InitModifiers(); + + if (typeDefinition.HasGenericParameters) { + for (int i = 0; i < typeDefinition.GenericParameters.Count; i++) { + loader.AddConstraints(this, (DefaultTypeParameter)this.TypeParameters[i], typeDefinition.GenericParameters[i]); + } + } + + InitNestedTypes(loader); // nested types can be initialized only after generic parameters were created + + loader.AddAttributes(typeDefinition, this); + + this.HasExtensionMethods = HasExtensionAttribute(typeDefinition); + + // set base classes + if (typeDefinition.IsEnum) { + foreach (FieldDefinition enumField in typeDefinition.Fields) { + if (!enumField.IsStatic) { + BaseTypes.Add(loader.ReadTypeReference(enumField.FieldType, entity: this)); + break; + } + } + } else { + if (typeDefinition.BaseType != null) { + BaseTypes.Add(loader.ReadTypeReference(typeDefinition.BaseType, entity: this)); + } + if (typeDefinition.HasInterfaces) { + foreach (TypeReference iface in typeDefinition.Interfaces) { + BaseTypes.Add(loader.ReadTypeReference(iface, entity: this)); + } + } + } + + InitMembers(loader); + if (!loader.HasCecilReferences) + this.typeDefinition = null; + Freeze(); // freeze after initialization + ApplyInterningProvider(loader.InterningProvider); + } + + void InitNestedTypes(CecilLoader loader) + { + if (!typeDefinition.HasNestedTypes) + return; + foreach (TypeDefinition nestedType in typeDefinition.NestedTypes) { + TypeAttributes visibility = nestedType.Attributes & TypeAttributes.VisibilityMask; + if (loader.IncludeInternalMembers + || visibility == TypeAttributes.NestedPublic + || visibility == TypeAttributes.NestedFamily + || visibility == TypeAttributes.NestedFamORAssem) + { + string name = nestedType.Name; + int pos = name.LastIndexOf('/'); + if (pos > 0) + name = name.Substring(pos + 1); + if (name.Length == 0 || name[0] == '<') + continue; + name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name); + NestedTypes.Add(new CecilTypeDefinition(this, name, nestedType)); + } + } + foreach (CecilTypeDefinition nestedType in this.NestedTypes) { + nestedType.Init(loader); + } + } + + void InitModifiers() + { + TypeDefinition td = this.typeDefinition; + // set classtype + if (td.IsInterface) { + this.ClassType = ClassType.Interface; + } else if (td.IsEnum) { + this.ClassType = ClassType.Enum; + } else if (td.IsValueType) { + this.ClassType = ClassType.Struct; + } else if (IsDelegate(td)) { + this.ClassType = ClassType.Delegate; + } else if (IsModule(td)) { + this.ClassType = ClassType.Module; + } else { + this.ClassType = ClassType.Class; + } + this.IsSealed = td.IsSealed; + this.IsAbstract = td.IsAbstract; + switch (td.Attributes & TypeAttributes.VisibilityMask) { + case TypeAttributes.NotPublic: + case TypeAttributes.NestedAssembly: + this.Accessibility = Accessibility.Internal; + break; + case TypeAttributes.Public: + case TypeAttributes.NestedPublic: + this.Accessibility = Accessibility.Public; + break; + case TypeAttributes.NestedPrivate: + this.Accessibility = Accessibility.Private; + break; + case TypeAttributes.NestedFamily: + this.Accessibility = Accessibility.Protected; + break; + case TypeAttributes.NestedFamANDAssem: + this.Accessibility = Accessibility.ProtectedAndInternal; + break; + case TypeAttributes.NestedFamORAssem: + this.Accessibility = Accessibility.ProtectedOrInternal; + break; + case TypeAttributes.LayoutMask: + this.Accessibility = Accessibility; + break; + } + } + + static bool IsDelegate(TypeDefinition type) + { + if (type.BaseType == null) + return false; + else + return type.BaseType.FullName == "System.Delegate" + || type.BaseType.FullName == "System.MulticastDelegate"; + } + + static bool IsModule(TypeDefinition type) + { + if (!type.HasCustomAttributes) + return false; + foreach (var att in type.CustomAttributes) { + if (att.AttributeType.FullName == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute" + || att.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute") + { + return true; + } + } + return false; + } + + void InitMembers(CecilLoader loader) + { + this.AddDefaultConstructorIfRequired = (this.ClassType == ClassType.Struct || this.ClassType == ClassType.Enum); + if (typeDefinition.HasMethods) { + foreach (MethodDefinition method in typeDefinition.Methods) { + if (loader.IsVisible(method.Attributes)) { + EntityType type = EntityType.Method; + if (method.IsSpecialName) { + if (method.IsConstructor) + type = EntityType.Constructor; + else if (method.Name.StartsWith("op_", StringComparison.Ordinal)) + type = EntityType.Operator; + else + continue; + } + this.Methods.Add(loader.ReadMethod(method, this, type)); + } + } + } + if (typeDefinition.HasFields) { + foreach (FieldDefinition field in typeDefinition.Fields) { + if (loader.IsVisible(field.Attributes) && !field.IsSpecialName) { + this.Fields.Add(loader.ReadField(field, this)); + } + } + } + if (typeDefinition.HasProperties) { + string defaultMemberName = null; + var defaultMemberAttribute = typeDefinition.CustomAttributes.FirstOrDefault( + a => a.AttributeType.FullName == typeof(System.Reflection.DefaultMemberAttribute).FullName); + if (defaultMemberAttribute != null && defaultMemberAttribute.ConstructorArguments.Count == 1) { + defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string; + } + foreach (PropertyDefinition property in typeDefinition.Properties) { + bool getterVisible = property.GetMethod != null && loader.IsVisible(property.GetMethod.Attributes); + bool setterVisible = property.SetMethod != null && loader.IsVisible(property.SetMethod.Attributes); + if (getterVisible || setterVisible) { + EntityType type = property.Name == defaultMemberName ? EntityType.Indexer : EntityType.Property; + this.Properties.Add(loader.ReadProperty(property, this, type)); + } + } + } + if (typeDefinition.HasEvents) { + foreach (EventDefinition ev in typeDefinition.Events) { + if (ev.AddMethod != null && loader.IsVisible(ev.AddMethod.Attributes)) { + this.Events.Add(loader.ReadEvent(ev, this)); + } + } + } + } + } + #endregion + + #region Read Method + public IMethod ReadMethod(MethodDefinition method, ITypeDefinition parentType, EntityType methodType = EntityType.Method) + { + DefaultMethod m = new DefaultMethod(parentType, method.Name); + m.EntityType = methodType; + if (method.HasGenericParameters) { + for (int i = 0; i < method.GenericParameters.Count; i++) { + if (method.GenericParameters[i].Position != i) + throw new InvalidOperationException("g.Position != i"); + m.TypeParameters.Add(new DefaultTypeParameter( + EntityType.Method, i, method.GenericParameters[i].Name)); + } + for (int i = 0; i < method.GenericParameters.Count; i++) { + AddConstraints(m, (DefaultTypeParameter)m.TypeParameters[i], method.GenericParameters[i]); + } + } + + if (method.IsConstructor) + m.ReturnType = parentType; + else + m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method.MethodReturnType, entity: m); + + if (HasAnyAttributes(method)) + AddAttributes(method, m.Attributes, m.ReturnTypeAttributes); + TranslateModifiers(method, m); + + if (method.HasParameters) { + foreach (ParameterDefinition p in method.Parameters) { + m.Parameters.Add(ReadParameter(p, parentMember: m)); + } + } + + // mark as extension method if the attribute is set + if (method.IsStatic && HasExtensionAttribute(method)) { + m.IsExtensionMethod = true; + } + + FinishReadMember(m, method); + return m; + } + + static bool HasExtensionAttribute(ICustomAttributeProvider provider) + { + if (provider.HasCustomAttributes) { + foreach (var attr in provider.CustomAttributes) { + if (attr.AttributeType.Name == "ExtensionAttribute" && attr.AttributeType.Namespace == "System.Runtime.CompilerServices") + return true; + } + } + return false; + } + + bool IsVisible(MethodAttributes att) + { + att &= MethodAttributes.MemberAccessMask; + return IncludeInternalMembers + || att == MethodAttributes.Public + || att == MethodAttributes.Family + || att == MethodAttributes.FamORAssem; + } + + static Accessibility GetAccessibility(MethodAttributes attr) + { + switch (attr & MethodAttributes.MemberAccessMask) { + case MethodAttributes.Public: + return Accessibility.Public; + case MethodAttributes.FamANDAssem: + return Accessibility.ProtectedAndInternal; + case MethodAttributes.Assembly: + return Accessibility.Internal; + case MethodAttributes.Family: + return Accessibility.Protected; + case MethodAttributes.FamORAssem: + return Accessibility.ProtectedOrInternal; + default: + return Accessibility.Private; + } + } + + void TranslateModifiers(MethodDefinition method, AbstractMember m) + { + if (m.DeclaringTypeDefinition.ClassType == ClassType.Interface) { + // interface members don't have modifiers, but we want to handle them as "public abstract" + m.Accessibility = Accessibility.Public; + m.IsAbstract = true; + } else { + m.Accessibility = GetAccessibility(method.Attributes); + if (method.IsAbstract) { + m.IsAbstract = true; + m.IsOverride = !method.IsNewSlot; + } else if (method.IsFinal) { + if (!method.IsNewSlot) { + m.IsSealed = true; + m.IsOverride = true; + } + } else if (method.IsVirtual) { + if (method.IsNewSlot) + m.IsVirtual = true; + else + m.IsOverride = true; + } + m.IsStatic = method.IsStatic; + } + } + #endregion + + #region Read Parameter + public IParameter ReadParameter(ParameterDefinition parameter, IParameterizedMember parentMember = null) + { + if (parameter == null) + throw new ArgumentNullException("parameter"); + var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter, entity: parentMember); + DefaultParameter p = new DefaultParameter(type, parameter.Name); + + if (parameter.ParameterType is Mono.Cecil.ByReferenceType) { + if (!parameter.IsIn && parameter.IsOut) + p.IsOut = true; + else + p.IsRef = true; + } + AddAttributes(parameter, p); + + if (parameter.IsOptional) { + p.DefaultValue = ReadConstantValue(new CustomAttributeArgument(parameter.ParameterType, parameter.Constant)); + } + + if (parameter.ParameterType is Mono.Cecil.ArrayType) { + foreach (CustomAttribute att in parameter.CustomAttributes) { + if (att.AttributeType.FullName == typeof(ParamArrayAttribute).FullName) { + p.IsParams = true; + break; + } + } + } + + return p; + } + #endregion + + #region Read Field + bool IsVisible(FieldAttributes att) + { + att &= FieldAttributes.FieldAccessMask; + return IncludeInternalMembers + || att == FieldAttributes.Public + || att == FieldAttributes.Family + || att == FieldAttributes.FamORAssem; + } + + public IField ReadField(FieldDefinition field, ITypeDefinition parentType) + { + if (field == null) + throw new ArgumentNullException("field"); + if (parentType == null) + throw new ArgumentNullException("parentType"); + + DefaultField f = new DefaultField(parentType, field.Name); + f.Accessibility = GetAccessibility(field.Attributes); + f.IsReadOnly = field.IsInitOnly; + f.IsStatic = field.IsStatic; + if (field.HasConstant) { + f.ConstantValue = ReadConstantValue(new CustomAttributeArgument(field.FieldType, field.Constant)); + } + AddAttributes(field, f); + + f.ReturnType = ReadTypeReference(field.FieldType, typeAttributes: field, entity: f); + RequiredModifierType modreq = field.FieldType as RequiredModifierType; + if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName) { + f.IsVolatile = true; + } + + FinishReadMember(f, field); + return f; + } + + static Accessibility GetAccessibility(FieldAttributes attr) + { + switch (attr & FieldAttributes.FieldAccessMask) { + case FieldAttributes.Public: + return Accessibility.Public; + case FieldAttributes.FamANDAssem: + return Accessibility.ProtectedAndInternal; + case FieldAttributes.Assembly: + return Accessibility.Internal; + case FieldAttributes.Family: + return Accessibility.Protected; + case FieldAttributes.FamORAssem: + return Accessibility.ProtectedOrInternal; + default: + return Accessibility.Private; + } + } + #endregion + + #region Type Parameter Constraints + void AddConstraints(IEntity parentEntity, DefaultTypeParameter tp, GenericParameter g) + { + switch (g.Attributes & GenericParameterAttributes.VarianceMask) { + case GenericParameterAttributes.Contravariant: + tp.Variance = VarianceModifier.Contravariant; + break; + case GenericParameterAttributes.Covariant: + tp.Variance = VarianceModifier.Covariant; + break; + } + + tp.HasReferenceTypeConstraint = g.HasReferenceTypeConstraint; + tp.HasValueTypeConstraint = g.HasNotNullableValueTypeConstraint; + tp.HasDefaultConstructorConstraint = g.HasDefaultConstructorConstraint; + + if (g.HasConstraints) { + foreach (TypeReference constraint in g.Constraints) { + tp.Constraints.Add(ReadTypeReference(constraint, entity: parentEntity)); + } + } + } + #endregion + + #region Read Property + public IProperty ReadProperty(PropertyDefinition property, ITypeDefinition parentType, EntityType propertyType = EntityType.Property) + { + if (property == null) + throw new ArgumentNullException("property"); + if (parentType == null) + throw new ArgumentNullException("parentType"); + DefaultProperty p = new DefaultProperty(parentType, property.Name); + p.EntityType = propertyType; + TranslateModifiers(property.GetMethod ?? property.SetMethod, p); + p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property, entity: p); + + p.Getter = ReadAccessor(property.GetMethod); + p.Setter = ReadAccessor(property.SetMethod); + + if (property.HasParameters) { + foreach (ParameterDefinition par in property.Parameters) { + p.Parameters.Add(ReadParameter(par, parentMember: p)); + } + } + AddAttributes(property, p); + + FinishReadMember(p, property); + return p; + } + + IAccessor ReadAccessor(MethodDefinition accessorMethod) + { + if (accessorMethod != null && IsVisible(accessorMethod.Attributes)) { + Accessibility accessibility = GetAccessibility(accessorMethod.Attributes); + if (HasAnyAttributes(accessorMethod)) { + DefaultAccessor a = new DefaultAccessor(); + a.Accessibility = accessibility; + AddAttributes(accessorMethod, a.Attributes, a.ReturnTypeAttributes); + return a; + } else { + return DefaultAccessor.GetFromAccessibility(accessibility); + } + } else { + return null; + } + } + #endregion + + #region Read Event + public IEvent ReadEvent(EventDefinition ev, ITypeDefinition parentType) + { + if (ev == null) + throw new ArgumentNullException("ev"); + if (parentType == null) + throw new ArgumentNullException("parentType"); + + DefaultEvent e = new DefaultEvent(parentType, ev.Name); + TranslateModifiers(ev.AddMethod, e); + e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev, entity: e); + + e.AddAccessor = ReadAccessor(ev.AddMethod); + e.RemoveAccessor = ReadAccessor(ev.RemoveMethod); + e.InvokeAccessor = ReadAccessor(ev.InvokeMethod); + + AddAttributes(ev, e); + + FinishReadMember(e, ev); + + return e; + } + #endregion + + void FinishReadMember(AbstractMember member, object cecilDefinition) + { + member.Freeze(); + member.ApplyInterningProvider(this.InterningProvider); + if (HasCecilReferences) + typeSystemTranslationTable[member] = cecilDefinition; + } + + #region Type system translation table + Dictionary typeSystemTranslationTable; + + T InternalGetCecilObject (object typeSystemObject) where T : class + { + if (typeSystemObject == null) + throw new ArgumentNullException ("typeSystemObject"); + if (!HasCecilReferences) + throw new NotSupportedException ("This instance contains no cecil references."); + object result; + if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result)) + throw new InvalidOperationException ("No cecil reference stored for " + typeSystemObject); + return result as T; + } + + public AssemblyDefinition GetCecilObject (IProjectContent content) + { + return InternalGetCecilObject (content); + } + + public TypeDefinition GetCecilObject (ITypeDefinition type) + { + if (type == null) + throw new ArgumentNullException ("type"); + var cecilType = type as CecilTypeDefinition; + if (cecilType == null) + throw new ArgumentException ("type is no cecil type definition."); + return cecilType.typeDefinition; + } + + public MethodDefinition GetCecilObject (IMethod method) + { + return InternalGetCecilObject (method); + } + + public FieldDefinition GetCecilObject (IField field) + { + return InternalGetCecilObject (field); + } + + public EventDefinition GetCecilObject (IEvent evt) + { + return InternalGetCecilObject (evt); + } + + public PropertyDefinition GetCecilObject (IProperty property) + { + return InternalGetCecilObject (property); + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ClassType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ClassType.cs new file mode 100644 index 0000000000..4440264ed8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ClassType.cs @@ -0,0 +1,17 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + public enum ClassType : byte + { + Class, + Enum, + Interface, + Struct, + Delegate, + Module, + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs new file mode 100644 index 0000000000..851b97e90a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs @@ -0,0 +1,185 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Globalization; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [Serializable] + public struct DomRegion : IEquatable + { + readonly string fileName; + readonly int beginLine; + readonly int endLine; + readonly int beginColumn; + readonly int endColumn; + + public readonly static DomRegion Empty = new DomRegion(null, -1, -1); + + public bool IsEmpty { + get { + return BeginLine <= 0; + } + } + + public string FileName { + get { return fileName; } + } + + public int BeginLine { + get { + return beginLine; + } + } + + /// + /// if the end line is == -1 the end column is -1 too + /// this stands for an unknwon end + /// + public int EndLine { + get { + return endLine; + } + } + + public int BeginColumn { + get { + return beginColumn; + } + } + + /// + /// if the end column is == -1 the end line is -1 too + /// this stands for an unknown end + /// + public int EndColumn { + get { + return endColumn; + } + } + + public AstLocation Begin { + get { + return new AstLocation (beginLine, beginColumn); + } + } + + public AstLocation End { + get { + return new AstLocation (endLine, endColumn); + } + } + + public DomRegion (int beginLine, int beginColumn, int endLine, int endColumn) : this (null, beginLine, beginColumn, endLine, endColumn) + { + } + + public DomRegion(string fileName, int beginLine, int beginColumn, int endLine, int endColumn) + { + this.fileName = fileName; + this.beginLine = beginLine; + this.beginColumn = beginColumn; + this.endLine = endLine; + this.endColumn = endColumn; + } + + public DomRegion (int beginLine, int beginColumn) : this (null, beginLine, beginColumn) + { + } + + public DomRegion (string fileName, int beginLine, int beginColumn) + { + this.fileName = fileName; + this.beginLine = beginLine; + this.beginColumn = beginColumn; + this.endLine = -1; + this.endColumn = -1; + } + + public DomRegion (AstLocation begin, AstLocation end) : this (null, begin, end) + { + } + + public DomRegion (string fileName, AstLocation begin, AstLocation end) + { + this.fileName = fileName; + this.beginLine = begin.Line; + this.beginColumn = begin.Column; + this.endLine = end.Line; + this.endColumn = end.Column; + } + + public DomRegion (AstLocation begin) : this (null, begin) + { + } + + public DomRegion (string fileName, AstLocation begin) + { + this.fileName = fileName; + this.beginLine = begin.Line; + this.beginColumn = begin.Column; + this.endLine = -1; + this.endColumn = -1; + } + + /// + /// Returns true, if the given coordinates (line, column) are in the region. + /// This method assumes that for an unknown end the end line is == -1 + /// + public bool IsInside(int line, int column) + { + if (IsEmpty) + return false; + return line >= BeginLine && + (line <= EndLine || EndLine == -1) && + (line != BeginLine || column >= BeginColumn) && + (line != EndLine || column <= EndColumn); + } + + public bool IsInside(AstLocation location) + { + return IsInside(location.Line, location.Column); + } + + public override string ToString() + { + return string.Format( + CultureInfo.InvariantCulture, + "[DomRegion FileName={0}, BeginLine={1}, EndLine={2}, BeginColumn={3}, EndColumn={4}]", + fileName, beginLine, endLine, beginColumn, endColumn); + } + + public override bool Equals(object obj) + { + return obj is DomRegion && Equals((DomRegion)obj); + } + + public override int GetHashCode() + { + unchecked { + int hashCode = fileName != null ? fileName.GetHashCode() : 0; + hashCode ^= BeginColumn + 1100009 * BeginLine + 1200007 * BeginColumn + 1300021 * EndColumn; + return hashCode; + } + } + + public bool Equals(DomRegion other) + { + return BeginLine == other.BeginLine && BeginColumn == other.BeginColumn + && EndLine == other.EndLine && EndColumn == other.EndColumn + && fileName == other.fileName; + } + + public static bool operator ==(DomRegion left, DomRegion right) + { + return left.Equals(right); + } + + public static bool operator !=(DomRegion left, DomRegion right) + { + return !left.Equals(right); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/EntityType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/EntityType.cs new file mode 100644 index 0000000000..86cb046167 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/EntityType.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + public enum EntityType : byte + { + None, + TypeDefinition, + Field, + Property, + Indexer, + Event, + Method, + Operator, + Constructor, + Destructor + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs new file mode 100644 index 0000000000..1684e8d81c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Error.cs @@ -0,0 +1,135 @@ +// +// Error.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Mike Krüger +// +// 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.CSharp; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Enum that describes the type of an error. + /// + public enum ErrorType + { + Unknown, + Error, + Warning + } + + /// + /// Descibes an error during parsing. + /// + public class Error + { + /// + /// The type of the error. + /// + public ErrorType ErrorType { get; private set; } + + /// + /// The error description. + /// + public string Message { get; private set; } + + /// + /// The region of the error. + /// + public DomRegion Region { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + /// + /// The region of the error. + /// + public Error (ErrorType errorType, string message, DomRegion region) + { + this.ErrorType = errorType; + this.Message = message; + this.Region = region; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + /// + /// The location of the error. + /// + public Error (ErrorType errorType, string message, AstLocation location) + { + this.ErrorType = errorType; + this.Message = message; + this.Region = new DomRegion (location, location); + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + /// + /// The line of the error. + /// + /// + /// The column of the error. + /// + public Error (ErrorType errorType, string message, int line, int col) : this (errorType, message, new AstLocation (line, col)) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The error type. + /// + /// + /// The description of the error. + /// + public Error (ErrorType errorType, string message) + { + this.ErrorType = errorType; + this.Message = message; + this.Region = DomRegion.Empty; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs new file mode 100644 index 0000000000..e2608b812f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -0,0 +1,266 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; +using ICSharpCode.NRefactory.CSharp.Refactoring; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Contains extension methods for the type system. + /// + public static class ExtensionMethods + { + #region GetAllBaseTypes + /// + /// Gets all base types. + /// + /// This is the reflexive and transitive closure of . + /// Note that this method does not return all supertypes - doing so is impossible due to contravariance + /// (and undesirable for covariance as the list could become very large). + /// + public static IEnumerable GetAllBaseTypes(this IType type, ITypeResolveContext context) + { + List output = new List(); + Stack activeTypeDefinitions = new Stack(); + CollectAllBaseTypes(type, context, activeTypeDefinitions, output); + return output; + } + + static void CollectAllBaseTypes(IType type, ITypeResolveContext context, Stack activeTypeDefinitions, List output) + { + ITypeDefinition def = type.GetDefinition(); + if (def != null) { + // Maintain a stack of currently active type definitions, and avoid having one definition + // multiple times on that stack. + // This is necessary to ensure the output is finite in the presence of cyclic inheritance: + // class C : C> {} would not be caught by the 'no duplicate output' check, yet would + // produce infinite output. + if (activeTypeDefinitions.Contains(def)) + return; + activeTypeDefinitions.Push(def); + } + // Avoid outputting a type more than once - necessary for "diamond" multiple inheritance + // (e.g. C implements I1 and I2, and both interfaces derive from Object) + if (!output.Contains(type)) { + output.Add(type); + foreach (IType baseType in type.GetBaseTypes(context)) { + CollectAllBaseTypes(baseType, context, activeTypeDefinitions, output); + } + } + if (def != null) + activeTypeDefinitions.Pop(); + } + #endregion + + #region GetAllBaseTypeDefinitions + /// + /// Gets all base type definitions. + /// + /// + /// This is equivalent to type.GetAllBaseTypes().Select(t => t.GetDefinition()).Where(d => d != null).Distinct(). + /// + public static IEnumerable GetAllBaseTypeDefinitions(this IType type, ITypeResolveContext context) + { + if (type == null) + throw new ArgumentNullException("type"); + if (context == null) + throw new ArgumentNullException("context"); + + HashSet typeDefinitions = new HashSet(); + Func> recursion = + t => t.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)); + + ITypeDefinition typeDef = type.GetDefinition(); + if (typeDef != null) { + typeDefinitions.Add(typeDef); + return TreeTraversal.PreOrder(typeDef, recursion); + } else { + return TreeTraversal.PreOrder( + type.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)), + recursion); + } + } + + /// + /// Gets whether this type definition is derived from the base type defintiion. + /// + public static bool IsDerivedFrom(this ITypeDefinition type, ITypeDefinition baseType, ITypeResolveContext context) + { + return GetAllBaseTypeDefinitions(type, context).Contains(baseType); + } + #endregion + + #region IsOpen / IsUnbound + sealed class TypeClassificationVisitor : TypeVisitor + { + internal bool isOpen; + + public override IType VisitTypeParameter(ITypeParameter type) + { + isOpen = true; + return base.VisitTypeParameter(type); + } + } + + /// + /// Gets whether the type is an open type (contains type parameters). + /// + public static bool IsOpen(this IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + TypeClassificationVisitor v = new TypeClassificationVisitor(); + type.AcceptVisitor(v); + return v.isOpen; + } + + /// + /// Gets whether the type is unbound. + /// + public static bool IsUnbound(this IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + return type is ITypeDefinition && type.TypeParameterCount > 0; + } + #endregion + + #region IsEnum / IsDelegate + /// + /// Gets whether the type is an enumeration type. + /// + public static bool IsEnum(this IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + ITypeDefinition def = type.GetDefinition(); + return def != null && def.ClassType == ClassType.Enum; + } + + /// + /// Gets the underlying type for this enum type. + /// + public static IType GetEnumUnderlyingType(this IType enumType, ITypeResolveContext context) + { + if (enumType == null) + throw new ArgumentNullException("enumType"); + if (context == null) + throw new ArgumentNullException("context"); + ITypeDefinition def = enumType.GetDefinition(); + if (def != null && def.ClassType == ClassType.Enum) { + if (def.BaseTypes.Count == 1) + return def.BaseTypes[0].Resolve(context); + else + return KnownTypeReference.Int32.Resolve(context); + } else { + throw new ArgumentException("enumType must be an enum"); + } + } + + /// + /// Gets whether the type is an delegate type. + /// + /// This method returns false for System.Delegate itself + public static bool IsDelegate(this IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + ITypeDefinition def = type.GetDefinition(); + return def != null && def.ClassType == ClassType.Delegate; + } + + /// + /// Gets the invoke method for a delegate type. + /// + /// + /// Returns null if the type is not a delegate type; or if the invoke method could not be found. + /// + public static IMethod GetDelegateInvokeMethod(this IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + ITypeDefinition def = type.GetDefinition(); + if (def != null && def.ClassType == ClassType.Delegate) { + foreach (IMethod method in def.Methods) { + if (method.Name == "Invoke") { + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + SpecializedMethod m = new SpecializedMethod(method); + m.SetDeclaringType(pt); + var substitution = pt.GetSubstitution(); + m.SubstituteTypes(t => new SubstitutionTypeReference(t, substitution)); + return m; + } + return method; + } + } + } + return null; + } + #endregion + + #region InternalsVisibleTo + /// + /// Gets whether the internals of this project are visible to the other project + /// + public static bool InternalsVisibleTo(this IProjectContent projectContent, IProjectContent other, ITypeResolveContext context) + { + if (projectContent == other) + return true; + // TODO: implement support for [InternalsVisibleToAttribute] + // Make sure implementation doesn't hurt performance, e.g. don't resolve all assembly attributes whenever + // this method is called - it'll be called once per internal member during lookup operations + return false; + } + #endregion + + #region GetAllTypes + /// + /// Gets all type definitions, including nested types. + /// + public static IEnumerable GetAllTypes(this ITypeResolveContext context) + { + return TreeTraversal.PreOrder(context.GetTypes(), t => t.NestedTypes); + } + #endregion + + #region GetType/Member + /// + /// Gets the type (potentially a nested type) defined at the specified location. + /// Returns null if no type is defined at that location. + /// + public static ITypeDefinition GetTypeDefinition (this IParsedFile file, int line, int column) + { + return file.GetTypeDefinition (new AstLocation (line, column)); + } + + /// + /// Gets the member defined at the specified location. + /// Returns null if no member is defined at that location. + /// + public static IMember GetMember (this IParsedFile file, int line, int column) + { + return file.GetMember (new AstLocation (line, column)); + } + #endregion + + #region GetSubTypeDefinitions + /// + /// Gets all sub type definitions defined in a context. + /// + public static IEnumerable GetSubTypeDefinitions (this ITypeDefinition baseType, ITypeResolveContext context) + { + foreach (var contextType in context.GetAllTypes ()) { + if (contextType.IsDerivedFrom (baseType, context)) + yield return contextType; + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs new file mode 100644 index 0000000000..9c33b586ec --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents an accessor (property getter/setter; or event add/remove/invoke). + /// + public interface IAccessor : IFreezable + { + /// + /// Gets the accessor region. + /// + DomRegion Region { get; } + + /// + /// Gets the attributes defined on this accessor. + /// + IList Attributes { get; } + + /// + /// Gets the attributes defined on the return type of the accessor. (e.g. [return: MarshalAs(...)]) + /// + IList ReturnTypeAttributes { get; } + + /// + /// Gets the accessibility of this accessor. + /// + Accessibility Accessibility { get; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs new file mode 100644 index 0000000000..c7f8e7c238 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs @@ -0,0 +1,216 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace ICSharpCode.NRefactory +{ + /// + /// Provides an interface to handle annotations in an object. + /// + public interface IAnnotatable + { + /// + /// Gets all annotations stored on this IAnnotatable. + /// + IEnumerable Annotations { + get; + } + + /// + /// Gets the first annotation of the specified type. + /// Returns null if no matching annotation exists. + /// + /// + /// The type of the annotation. + /// + T Annotation () where T: class; + + /// + /// Gets the first annotation of the specified type. + /// Returns null if no matching annotation exists. + /// + /// + /// The type of the annotation. + /// + object Annotation (Type type); + + /// + /// Adds an annotation to this instance. + /// + /// + /// The annotation to add. + /// + void AddAnnotation (object annotation); + + /// + /// Removes all annotations of the specified type. + /// + /// + /// The type of the annotations to remove. + /// + void RemoveAnnotations () where T : class; + + /// + /// Removes all annotations of the specified type. + /// + /// + /// The type of the annotations to remove. + /// + void RemoveAnnotations(Type type); + } + + public abstract class AbstractAnnotatable : IAnnotatable + { + // Annotations: points either null (no annotations), to the single annotation, + // or to an AnnotationList. + // Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list) + protected object annotations; + + sealed class AnnotationList : List, ICloneable + { + // There are two uses for this custom list type: + // 1) it's private, and thus (unlike List) cannot be confused with real annotations + // 2) It allows us to simplify the cloning logic by making the list behave the same as a clonable annotation. + public AnnotationList (int initialCapacity) : base(initialCapacity) + { + } + + public object Clone () + { + lock (this) { + AnnotationList copy = new AnnotationList (this.Count); + for (int i = 0; i < this.Count; i++) { + object obj = this [i]; + ICloneable c = obj as ICloneable; + copy.Add (c != null ? c.Clone () : obj); + } + return copy; + } + } + } + + public virtual void AddAnnotation (object annotation) + { + if (annotation == null) + throw new ArgumentNullException ("annotation"); + retry: // Retry until successful + object oldAnnotation = Interlocked.CompareExchange (ref this.annotations, annotation, null); + if (oldAnnotation == null) { + return; // we successfully added a single annotation + } + AnnotationList list = oldAnnotation as AnnotationList; + if (list == null) { + // we need to transform the old annotation into a list + list = new AnnotationList (4); + list.Add (oldAnnotation); + list.Add (annotation); + if (Interlocked.CompareExchange (ref this.annotations, list, oldAnnotation) != oldAnnotation) { + // the transformation failed (some other thread wrote to this.annotations first) + goto retry; + } + } else { + // once there's a list, use simple locking + lock (list) { + list.Add (annotation); + } + } + } + + public virtual void RemoveAnnotations () where T : class + { + retry: // Retry until successful + object oldAnnotations = this.annotations; + AnnotationList list = oldAnnotations as AnnotationList; + if (list != null) { + lock (list) + list.RemoveAll (obj => obj is T); + } else if (oldAnnotations is T) { + if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) { + // Operation failed (some other thread wrote to this.annotations first) + goto retry; + } + } + } + + public virtual void RemoveAnnotations (Type type) + { + if (type == null) + throw new ArgumentNullException ("type"); + retry: // Retry until successful + object oldAnnotations = this.annotations; + AnnotationList list = oldAnnotations as AnnotationList; + if (list != null) { + lock (list) + list.RemoveAll (obj => type.IsInstanceOfType (obj)); + } else if (type.IsInstanceOfType (oldAnnotations)) { + if (Interlocked.CompareExchange (ref this.annotations, null, oldAnnotations) != oldAnnotations) { + // Operation failed (some other thread wrote to this.annotations first) + goto retry; + } + } + } + + public T Annotation () where T: class + { + object annotations = this.annotations; + AnnotationList list = annotations as AnnotationList; + if (list != null) { + lock (list) { + foreach (object obj in list) { + T t = obj as T; + if (t != null) + return t; + } + return null; + } + } else { + return annotations as T; + } + } + + public object Annotation (Type type) + { + if (type == null) + throw new ArgumentNullException ("type"); + object annotations = this.annotations; + AnnotationList list = annotations as AnnotationList; + if (list != null) { + lock (list) { + foreach (object obj in list) { + if (type.IsInstanceOfType (obj)) + return obj; + } + } + } else { + if (type.IsInstanceOfType (annotations)) + return annotations; + } + return null; + } + + /// + /// Gets all annotations stored on this AstNode. + /// + public IEnumerable Annotations { + get { + object annotations = this.annotations; + AnnotationList list = annotations as AnnotationList; + if (list != null) { + lock (list) { + return list.ToArray (); + } + } else { + if (annotations != null) + return new object[] { annotations }; + else + return Enumerable.Empty (); + } + } + } + } +} + diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs new file mode 100644 index 0000000000..ff6abe9eb6 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents an attribute. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IAttributeContract))] + #endif + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] + public interface IAttribute : IFreezable + { + /// + /// Gets the code region of this attribute. + /// + DomRegion Region { get; } + + /// + /// Gets the type of the attribute. + /// + ITypeReference AttributeType { get; } + + /// + /// Gets the positional arguments passed to the attribute. + /// + IList GetPositionalArguments(ITypeResolveContext context); + + /// + /// Gets the named arguments passed to the attribute. + /// + IList> GetNamedArguments(ITypeResolveContext context); + + /// + /// Resolves the constructor method used for this attribute invocation. + /// Returns null if the constructor cannot be found. + /// + IMethod ResolveConstructor(ITypeResolveContext context); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IAttribute))] + abstract class IAttributeContract : IFreezableContract, IAttribute + { + DomRegion IAttribute.Region { + get { return DomRegion.Empty; } + } + + ITypeReference IAttribute.AttributeType { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + IList IAttribute.GetPositionalArguments(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IList> IAttribute.GetNamedArguments(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>>() != null); + return null; + } + + IMethod IAttribute.ResolveConstructor(ITypeResolveContext context) + { + Contract.Requires(context != null); + return null; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs new file mode 100644 index 0000000000..8ea9a8f3df --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + #if WITH_CONTRACTS + [ContractClass(typeof(IConstantValueContract))] + #endif + public interface IConstantValue : IFreezable + { + /// + /// Gets the type of the constant value. + /// + IType GetValueType(ITypeResolveContext context); + + /// + /// Gets the .NET value of the constant value. + /// Possible return values are: + /// - null + /// - primitive integers + /// - float/double + /// - bool + /// - string + /// - IType (for typeof-expressions) + /// and arrays of these values. Enum values are returned using the underlying primitive integer. + /// + /// TODO: how do we represent errors (value not available?) + /// + object GetValue(ITypeResolveContext context); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IConstantValue))] + abstract class IConstantValueContract : IFreezableContract, IConstantValue + { + IType IConstantValue.GetValueType(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result() != null); + return null; + } + + object IConstantValue.GetValue(ITypeResolveContext context) + { + Contract.Requires(context != null); + return null; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IConversions.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IConversions.cs new file mode 100644 index 0000000000..5495a78b76 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IConversions.cs @@ -0,0 +1,16 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Interface used to check whether types are convertible. + /// + public interface IConversions + { + bool ImplicitConversion(IType fromType, IType toType); + bool ImplicitReferenceConversion(IType fromType, IType toType); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs new file mode 100644 index 0000000000..fbd74b75c3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs @@ -0,0 +1,19 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Provides XML documentation for members. + /// + public interface IDocumentationProvider + { + /// + /// Gets the XML documentation for the specified entity. + /// + string GetDocumentation(IEntity entity); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs new file mode 100644 index 0000000000..74bdec3802 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEntity.cs @@ -0,0 +1,199 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + #if WITH_CONTRACTS + [ContractClass(typeof(IEntityContract))] + #endif + public interface IEntity : INamedElement, IFreezable + { + EntityType EntityType { get; } + + /// + /// Gets the complete entity region (including header+body) + /// + DomRegion Region { get; } + + /// + /// Gets the entity body region. + /// + DomRegion BodyRegion { get; } + + /// + /// Gets the declaring class. + /// For members, this is the class that contains the member. + /// For nested classes, this is the outer class. For top-level entities, this property returns null. + /// + ITypeDefinition DeclaringTypeDefinition { get; } + + IList Attributes { get; } + + string Documentation { get; } + + /// + /// Gets the accessibility of this entity. + /// + Accessibility Accessibility { get; } + + /// + /// Gets whether this entity is static. + /// Returns true if either the 'static' or the 'const' modifier is set. + /// + bool IsStatic { get; } + + /// + /// Returns whether this entity is abstract. + /// + /// Static classes also count as abstract classes. + bool IsAbstract { get; } + + /// + /// Returns whether this entity is sealed. + /// + /// Static classes also count as sealed classes. + bool IsSealed { get; } + + /// + /// Gets whether this member is declared to be shadowing another member with the same name. + /// + bool IsShadowing { get; } + + /// + /// Gets whether this member is generated by a macro/compiler feature. + /// + bool IsSynthetic { get; } + + /// + /// Gets a value indicating whether this instance is private. + /// + /// + /// true if this instance is private; otherwise, false. + /// + bool IsPrivate { get; } + + /// + /// Gets a value indicating whether this instance is public. + /// + /// + /// true if this instance is public; otherwise, false. + /// + bool IsPublic { get; } + + /// + /// Gets a value indicating whether this instance is protected. + /// + /// + /// true if this instance is protected; otherwise, false. + /// + bool IsProtected { get; } + + /// + /// Gets a value indicating whether this instance is internal. + /// + /// + /// true if this instance is internal; otherwise, false. + /// + bool IsInternal { get; } + + /// + /// Gets a value indicating whether this instance is protected or internal. + /// + /// + /// true if this instance is protected or internal; otherwise, false. + /// + bool IsProtectedOrInternal { get; } + + /// + /// Gets a value indicating whether this instance is protected and internal. + /// + /// + /// true if this instance is protected and internal; otherwise, false. + /// + bool IsProtectedAndInternal { get; } + + /// + /// The assembly in which this entity is defined. + /// This property never returns null. + /// + IProjectContent ProjectContent { get; } + + //bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IEntity))] + abstract class IEntityContract : INamedElementContract, IEntity + { + EntityType IEntity.EntityType { + get { return default(EntityType); } + } + + DomRegion IEntity.Region { + get { return DomRegion.Empty; } + } + + DomRegion IEntity.BodyRegion { + get { return DomRegion.Empty; } + } + + ITypeDefinition IEntity.DeclaringTypeDefinition { + get { return null; } + } + + IList IEntity.Attributes { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + string IEntity.Documentation { + get { return null; } + } + + bool IEntity.IsStatic { + get { return false; } + } + + Accessibility IEntity.Accessibility { + get { return default(Accessibility); } + } + + bool IEntity.IsAbstract { + get { return false; } + } + + bool IEntity.IsSealed { + get { return false; } + } + + bool IEntity.IsShadowing { + get { return false; } + } + + bool IEntity.IsSynthetic { + get { return false; } + } + + IProjectContent IEntity.ProjectContent { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + bool IFreezable.IsFrozen { + get { return false; } + } + + void IFreezable.Freeze() + { + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEvent.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEvent.cs new file mode 100644 index 0000000000..8a3d6cbfdc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IEvent.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + public interface IEvent : IMember + { + bool CanAdd { get; } + bool CanRemove { get; } + bool CanInvoke { get; } + + IAccessor AddAccessor { get; } + IAccessor RemoveAccessor { get; } + IAccessor InvokeAccessor { get; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs new file mode 100644 index 0000000000..60452a6702 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents an explicit interface implementation. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IExplicitInterfaceImplementationContract))] + #endif + public interface IExplicitInterfaceImplementation : IFreezable + { + /// + /// Gets the type of the interface. + /// + ITypeReference InterfaceType { get; } + + /// + /// Gets the member name. + /// + string MemberName { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IExplicitInterfaceImplementation))] + abstract class IExplicitInterfaceImplementationContract : IFreezableContract, IExplicitInterfaceImplementation + { + ITypeReference IExplicitInterfaceImplementation.InterfaceType { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + string IExplicitInterfaceImplementation.MemberName { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IField.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IField.cs new file mode 100644 index 0000000000..c5c0152998 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IField.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a field or constant. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IFieldContract))] + #endif + public interface IField : IMember, IVariable + { + /// + /// Gets the name of the field. + /// + new string Name { get; } // solve ambiguity between INamedElement.Name and IVariable.Name + + /// + /// Gets whether this field is readonly. + /// + bool IsReadOnly { get; } + + /// + /// Gets whether this field is volatile. + /// + bool IsVolatile { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IField))] + abstract class IFieldContract : IMemberContract, IField + { + string IField.Name { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + bool IField.IsReadOnly { + get { return false; } + } + + bool IField.IsVolatile { + get { return false; } + } + + + string IVariable.Name { + get { return null; } + } + + ITypeReference IVariable.Type { + get { return null; } + } + + bool IVariable.IsConst { + get { return false; } + } + + IConstantValue IVariable.ConstantValue { + get { return null; } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs new file mode 100644 index 0000000000..baa35f42db --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs @@ -0,0 +1,40 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + #if WITH_CONTRACTS + [ContractClass(typeof(IFreezableContract))] + #endif + public interface IFreezable + { + /// + /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. + /// + bool IsFrozen { get; } + + /// + /// Freezes this instance. + /// + void Freeze(); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IFreezable))] + abstract class IFreezableContract : IFreezable + { + bool IFreezable.IsFrozen { + get { return default(bool); } + } + + void IFreezable.Freeze() + { + IFreezable self = this; + Contract.Ensures(self.IsFrozen); + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs new file mode 100644 index 0000000000..16b23d0634 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Provider used for interning. + /// + /// + /// A simple IInterningProvider implementation could use 3 dictionaries: + /// 1. using value equality comparer (for certain types known to implement value equality, e.g. string and IType) + /// 2. using comparer that calls into ISupportsInterning (for types implementing ISupportsInterning) + /// 3. list comparer (for InternList method) + /// + /// On the first Intern()-call, the provider tells the object to prepare for interning (ISupportsInterning.PrepareForInterning) + /// and stores it into a dictionary. On further Intern() calls, the original object is returned for all equal objects. + /// This allows reducing the memory usage by using a single object instance where possible. + /// + /// Interning provider implementations could also use the interning logic for different purposes: + /// for example, it could be used to determine which objects are used jointly between multiple type definitions + /// and which are used only within a single type definition. Then a persistent file format could be organized so + /// that shared objects are loaded only once, yet non-shared objects get loaded lazily together with the class. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IInterningProviderContract))] + #endif + public interface IInterningProvider + { + /// + /// Interns the specified object. + /// The object must implement , or must be of one of the types + /// known to the interning provider to use value equality, + /// otherwise it will be returned without being interned. + /// + T Intern(T obj) where T : class; + + IList InternList(IList list) where T : class; + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IInterningProvider))] + abstract class IInterningProviderContract : IInterningProvider + { + T IInterningProvider.Intern(T obj) + { + Contract.Ensures((Contract.Result() == null) == (obj == null)); + return obj; + } + + IList IInterningProvider.InternList(IList list) + { + Contract.Ensures((Contract.Result>() == null) == (list == null)); + return list; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IMember.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IMember.cs new file mode 100644 index 0000000000..4a51074bf5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IMember.cs @@ -0,0 +1,108 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Method/field/entity. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IMemberContract))] + #endif + public interface IMember : IEntity + { + /// + /// Gets/Sets the declaring type (incl. type arguments, if any). + /// This property never returns null -- for top-level members, it returns SharedTypes.UnknownType. + /// If this is not a specialized member, the value returned is equal to . + /// + IType DeclaringType { get; } + + /// + /// Gets the original member definition for this member. + /// Returns this if this is not a specialized member. + /// Specialized members are the result of overload resolution with type substitution. + /// + IMember MemberDefinition { get; } + + /// + /// Gets the return type of this member. + /// This property never returns null. + /// + ITypeReference ReturnType { get; } + + /// + /// Gets the list of interfaces this member is implementing explicitly. + /// + IList InterfaceImplementations { get; } + + /// + /// Gets if the member is virtual. Is true only if the "virtual" modifier was used, but non-virtual + /// members can be overridden, too; if they are already overriding a method. + /// + bool IsVirtual { + get; + } + + bool IsOverride { + get; + } + + /// + /// Gets if the member can be overridden. Returns true when the member is "virtual" or "override" but not "sealed". + /// + bool IsOverridable { + get; + } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IMember))] + abstract class IMemberContract : IEntityContract, IMember + { + IType IMember.DeclaringType { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + IMember IMember.MemberDefinition { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + ITypeReference IMember.ReturnType { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + IList IMember.InterfaceImplementations { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + bool IMember.IsVirtual { + get { return false; } + } + + bool IMember.IsOverride { + get { return false; } + } + + bool IMember.IsOverridable { + get { return false; } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IMethod.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IMethod.cs new file mode 100644 index 0000000000..7f6241b3dd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IMethod.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a method, constructor, destructor or operator. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IMethodContract))] + #endif + public interface IMethod : IParameterizedMember + { + /// + /// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)]) + /// + IList ReturnTypeAttributes { get; } + + IList TypeParameters { get; } + + // handles is VB-specific and not part of the public API, so + // we don't really need it + //IList HandlesClauses { get; } + + bool IsExtensionMethod { get; } + bool IsConstructor { get; } + bool IsDestructor { get; } + bool IsOperator { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IMethod))] + abstract class IMethodContract : IParameterizedMemberContract, IMethod + { + IList IMethod.ReturnTypeAttributes { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList IMethod.TypeParameters { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + bool IMethod.IsExtensionMethod { + get { return false; } + } + + bool IMethod.IsConstructor { + get { return false; } + } + + bool IMethod.IsDestructor { + get { return false; } + } + + bool IMethod.IsOperator { + get { return false; } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs new file mode 100644 index 0000000000..789108543b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + #if WITH_CONTRACTS + [ContractClass(typeof(INamedElementContract))] + #endif + public interface INamedElement + { + /// + /// Gets the fully qualified name of the class the return type is pointing to. + /// + /// + /// "System.Int32[]" for int[]
+ /// "System.Collections.Generic.List" for List<string> + /// "System.Environment.SpecialFolder" for Environment.SpecialFolder + ///
+ string FullName { + get; + } + + /// + /// Gets the short name of the class the return type is pointing to. + /// + /// + /// "Int32[]" for int[]
+ /// "List" for List<string> + /// "SpecialFolder" for Environment.SpecialFolder + ///
+ string Name { + get; + } + + /// + /// Gets the namespace of the class the return type is pointing to. + /// + /// + /// "System" for int[]
+ /// "System.Collections.Generic" for List<string> + /// "System" for Environment.SpecialFolder + ///
+ string Namespace { + get; + } + + /// + /// Gets the full reflection name of the element. + /// + /// + /// For types, the reflection name can be parsed back into a ITypeReference by using + /// . + /// + /// + /// "System.Int32[]" for int[]
+ /// "System.Int32[][,]" for C# int[,][]
+ /// "System.Collections.Generic.List`1[[System.String]]" for List<string> + /// "System.Environment+SpecialFolder" for Environment.SpecialFolder + ///
+ string ReflectionName { + get; + } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(INamedElement))] + abstract class INamedElementContract : INamedElement + { + string INamedElement.FullName { + get { + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result())); + return null; + } + } + + string INamedElement.Name { + get { + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result())); + return null; + } + } + + string INamedElement.Namespace { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + string INamedElement.ReflectionName { + get { + Contract.Ensures(!string.IsNullOrEmpty(Contract.Result())); + return null; + } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParameter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParameter.cs new file mode 100644 index 0000000000..3f7d9b0825 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParameter.cs @@ -0,0 +1,99 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + #if WITH_CONTRACTS + [ContractClass(typeof(IParameterContract))] + #endif + public interface IParameter : IVariable, IFreezable + { + /// + /// Gets the list of attributes. + /// + IList Attributes { get; } + + /// + /// Gets the default value of optional parameters. + /// + IConstantValue DefaultValue { get; } + + /// + /// Gets the code region where the parameter is defined. + /// + DomRegion Region { get; } + + /// + /// Gets whether this parameter is a C# 'ref' parameter. + /// + bool IsRef { get; } + + /// + /// Gets whether this parameter is a C# 'out' parameter. + /// + bool IsOut { get; } + + /// + /// Gets whether this parameter is a C# 'params' parameter. + /// + bool IsParams { get; } + + /// + /// Gets whether this parameter is optional. + /// + bool IsOptional { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IParameter))] + abstract class IParameterContract : IVariableContract, IParameter + { + IList IParameter.Attributes { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IConstantValue IParameter.DefaultValue { + get { return null; } + } + + DomRegion IParameter.Region { + get { return DomRegion.Empty; } + } + + bool IParameter.IsRef { + get { return false; } + } + + bool IParameter.IsOut { + get { return false; } + } + + bool IParameter.IsParams { + get { return false; } + } + + bool IParameter.IsOptional { + get { + IParameter @this = this; + Contract.Ensures(Contract.Result() == (@this.DefaultValue != null)); + return false; + } + } + + bool IFreezable.IsFrozen { + get { return false; } + } + + void IFreezable.Freeze() + { + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs new file mode 100644 index 0000000000..a60c75133b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a method or property. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IParameterizedMemberContract))] + #endif + public interface IParameterizedMember : IMember + { + IList Parameters { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IParameterizedMember))] + abstract class IParameterizedMemberContract : IMemberContract, IParameterizedMember + { + IList IParameterizedMember.Parameters { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs new file mode 100644 index 0000000000..0852028f20 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.CSharp; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a single file that was parsed. + /// + public interface IParsedFile : IFreezable + { + /// + /// Gets the parent project content. + /// + IProjectContent ProjectContent { get; } + + /// + /// Returns the full path of the file. + /// + string FileName { get; } + + /// + /// Gets the time of object creation. + /// + DateTime ParseTime { get; } + + /// + /// Gets all top-level type definitions. + /// + IList TopLevelTypeDefinitions { get; } + + /// + /// Gets all assembly attributes that are defined in this file. + /// + IList AssemblyAttributes { get; } + + /// + /// Gets the top-level type defined at the specified location. + /// Returns null if no type is defined at that location. + /// + ITypeDefinition GetTopLevelTypeDefinition(AstLocation location); + + /// + /// Gets the type (potentially a nested type) defined at the specified location. + /// Returns null if no type is defined at that location. + /// + ITypeDefinition GetTypeDefinition(AstLocation location); + + /// + /// Gets the member defined at the specified location. + /// Returns null if no member is defined at that location. + /// + IMember GetMember(AstLocation location); + + /// + /// Gets the parser errors. + /// + IList Errors { get; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs new file mode 100644 index 0000000000..8485531140 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Mutable container of all classes in an assembly. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IProjectContentContract))] + #endif + public interface IProjectContent : ITypeResolveContext, IAnnotatable + { + /// + /// Gets the list of all assembly attributes in the project. + /// + IList AssemblyAttributes { get; } + + /// + /// Gets a parsed file by its file name. + /// + IParsedFile GetFile(string fileName); + + /// + /// Gets the list of all parsed files in the project content. + /// + IEnumerable Files { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IProjectContent))] + abstract class IProjectContentContract : ITypeResolveContextContract, IProjectContent + { + IList IProjectContent.AssemblyAttributes { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IParsedFile IProjectContent.GetFile(string fileName) + { + Contract.Requires(fileName != null); + return; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IProperty.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IProperty.cs new file mode 100644 index 0000000000..23cbd573cf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IProperty.cs @@ -0,0 +1,21 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a property or indexer. + /// + public interface IProperty : IParameterizedMember + { + bool CanGet { get; } + bool CanSet { get; } + + IAccessor Getter { get; } + IAccessor Setter { get; } + + bool IsIndexer { get; } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs new file mode 100644 index 0000000000..86de1c3790 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs @@ -0,0 +1,55 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Interface for TypeSystem objects that support interning. + /// See for more information. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(ISupportsInterningContract))] + #endif + public interface ISupportsInterning + { + /// + /// Interns child objects and strings. + /// + void PrepareForInterning(IInterningProvider provider); + + /// + /// Gets a hash code for interning. + /// + int GetHashCodeForInterning(); + + /// + /// Equality test for interning. + /// + bool EqualsForInterning(ISupportsInterning other); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(ISupportsInterning))] + abstract class ISupportsInterningContract : ISupportsInterning + { + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + Contract.Requires(provider != null); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return 0; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + return false; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs new file mode 100644 index 0000000000..085cb25cb8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs @@ -0,0 +1,27 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Context representing the set of assemblies in which a type is being searched. + /// Guarantees that the list of types available in the context is not changed until Dispose() is called. + /// The Dispose() method must be called from the same thread that create the + /// ISynchronizedTypeResolveContext. + /// + /// + /// A simple implementation might enter a ReaderWriterLock when the synchronized context + /// is created, and releases the lock when Dispose() is called. + /// However, implementations based on immutable data structures are also possible. + /// + /// Calling Synchronize() on an already synchronized context is possible, but has no effect. + /// Only disposing the outermost ISynchronizedTypeResolveContext releases the lock. + /// + public interface ISynchronizedTypeResolveContext : ITypeResolveContext, IDisposable + { + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs new file mode 100644 index 0000000000..6e64bf1204 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -0,0 +1,235 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + #if WITH_CONTRACTS + [ContractClass(typeof(ITypeContract))] + #endif + public interface IType : ITypeReference, INamedElement, IEquatable + { + /// + /// Gets whether the type is a reference type or value type. + /// + /// + /// true, if the type is a reference type. + /// false, if the type is a value type. + /// null, if the type is not known (e.g. unconstrained generic type parameter or type not found) + /// + /// + /// The resolve context is required for type parameters with a constraint "T : SomeType": + /// the type parameter is a reference type iff SomeType is a class type. + /// + bool? IsReferenceType(ITypeResolveContext context); + + /// + /// Gets the underlying type definition. + /// Can return null for types which do not have a type definition (for example arrays, pointers, type parameters) + /// + ITypeDefinition GetDefinition(); + + /// + /// Gets the parent type, if this is a nested type. + /// Returns null for top-level types. + /// + IType DeclaringType { get; } + + /// + /// Gets the number of type parameters. + /// + int TypeParameterCount { get; } + + /// + /// Calls ITypeVisitor.Visit for this type. + /// + /// The return value of the ITypeVisitor.Visit call + IType AcceptVisitor(TypeVisitor visitor); + + /// + /// Calls ITypeVisitor.Visit for all children of this type, and reconstructs this type with the children based + /// on the return values of the visit calls. + /// + /// A copy of this type, with all children replaced by the return value of the corresponding visitor call. + /// If the visitor returned the original types for all children (or if there are no children), returns this. + /// + IType VisitChildren(TypeVisitor visitor); + + /// + /// Gets the direct base types. + /// + IEnumerable GetBaseTypes(ITypeResolveContext context); + + /// + /// Gets inner classes (including inherited inner classes). + /// + IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all methods that can be called on this return type. + /// + /// The list does not include constructors. + IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all instance constructors for this type. + /// + /// This list does not include constructors in base classes or static constructors. + IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all properties that can be called on this return type. + /// + IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all fields that can be called on this return type. + /// + IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all events that can be called on this return type. + /// + IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null); + + /// + /// Gets all members that can be called on this return type. + /// This is the union of GetFields(),GetProperties(),GetMethods() and GetEvents(). This does not include constructors. + /// + IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IType))] + abstract class ITypeContract : ITypeReferenceContract, IType + { + bool? IType.IsReferenceType(ITypeResolveContext context) + { + Contract.Requires(context != null); + return null; + } + + int IType.TypeParameterCount { + get { + Contract.Ensures(Contract.Result() >= 0); + return 0; + } + } + + IType IType.DeclaringType { + get { return null; } + } + + IEnumerable IType.GetBaseTypes(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetMethods(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetConstructors(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetProperties(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetFields(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + string INamedElement.FullName { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + string INamedElement.Name { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + string INamedElement.Namespace { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + string INamedElement.ReflectionName { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + ITypeDefinition IType.GetDefinition() + { + return null; + } + + bool IEquatable.Equals(IType other) + { + return false; + } + + IType IType.AcceptVisitor(TypeVisitor visitor) + { + Contract.Requires(visitor != null); + Contract.Ensures(Contract.Result() != null); + return this; + } + + IType IType.VisitChildren(TypeVisitor visitor) + { + Contract.Requires(visitor != null); + Contract.Ensures(Contract.Result() != null); + return this; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs new file mode 100644 index 0000000000..507d5420d3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs @@ -0,0 +1,198 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a class, enum, interface, struct, delegate or VB module. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(ITypeDefinitionContract))] + #endif + public interface ITypeDefinition : IType, IEntity + { + ClassType ClassType { get; } + + IList BaseTypes { get; } + IList TypeParameters { get; } + + /// + /// If this is a partial class, gets the compound class containing information from all parts. + /// If this is not a partial class, a reference to this class is returned. + /// + /// This method will always retrieve the latest version of the class, which might not contain this class as a part. + /// + ITypeDefinition GetCompoundClass(); + + /// + /// If this is a compound class (combination of class parts), this method retrieves all individual class parts. + /// Otherwise, a list containing this is returned. + /// + IList GetParts(); + + IList NestedTypes { get; } + IList Fields { get; } + IList Properties { get; } + IList Methods { get; } + IList Events { get; } + + /// + /// Gets all members declared in this class. This is the union of Fields,Properties,Methods and Events. + /// + IEnumerable Members { get; } + + /// + /// Gets whether this type contains extension methods. + /// + /// This property is used to speed up the search for extension methods. + bool HasExtensionMethods { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(ITypeDefinition))] + abstract class ITypeDefinitionContract : ITypeContract, ITypeDefinition + { + ClassType ITypeDefinition.ClassType { + get { return default(ClassType); } + } + + IList ITypeDefinition.BaseTypes { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeDefinition.TypeParameters { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeDefinition.InnerClasses { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeDefinition.Fields { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeDefinition.Properties { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeDefinition.Methods { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeDefinition.Events { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IEnumerable ITypeDefinition.Members { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + ITypeDefinition ITypeDefinition.GetCompoundClass() + { + Contract.Ensures(Contract.Result() != null); + return null; + } + + IList ITypeDefinition.GetParts() + { + Contract.Ensures(Contract.Result>() != null); + return null; + } + + bool ITypeDefinition.HasExtensionMethods { + get { return default(bool); } + } + + #region IEntity + EntityType IEntity.EntityType { + get { return EntityType.None; } + } + + DomRegion IEntity.Region { + get { return DomRegion.Empty; } + } + + DomRegion IEntity.BodyRegion { + get { return DomRegion.Empty; } + } + + ITypeDefinition IEntity.DeclaringTypeDefinition { + get { return null; } + } + + IList IEntity.Attributes { + get { return null; } + } + + string IEntity.Documentation { + get { return null; } + } + + bool IEntity.IsStatic { + get { return false; } + } + + Accessibility IEntity.Accessibility { + get { return Accessibility.None; } + } + + bool IEntity.IsAbstract { + get { return false; } + } + + bool IEntity.IsSealed { + get { return false; } + } + + bool IEntity.IsShadowing { + get { return false; } + } + + bool IEntity.IsSynthetic { + get { return false; } + } + + IProjectContent IEntity.ProjectContent { + get { return null; } + } + + bool IFreezable.IsFrozen { + get { return false; } + } + + void IFreezable.Freeze() + { + } + #endregion + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs new file mode 100644 index 0000000000..f9a0cc3cd5 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -0,0 +1,167 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Type parameter of a generic class/method. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(ITypeParameterContract))] + #endif + public interface ITypeParameter : IType, IFreezable + { + /// + /// Get the type of this type parameter's owner. + /// + /// EntityType.TypeDefinition or EntityType.Method + EntityType OwnerType { get; } + + /// + /// Gets the index of the type parameter in the type parameter list of the owning method/class. + /// + int Index { get; } + + /// + /// Gets the list of attributes declared on this type parameter. + /// + IList Attributes { get; } + + /// + /// Gets the constraints of this type parameter. + /// + IList Constraints { get; } + + /// + /// Gets if the type parameter has the 'new()' constraint. + /// + bool HasDefaultConstructorConstraint { get; } + + /// + /// Gets if the type parameter has the 'class' constraint. + /// + bool HasReferenceTypeConstraint { get; } + + /// + /// Gets if the type parameter has the 'struct' constraint. + /// + bool HasValueTypeConstraint { get; } + + /// + /// Gets the variance of this type parameter. + /// + VarianceModifier Variance { get; } + + /// + /// Gets the type that was used to bind this type parameter. + /// This property returns null for generic methods/classes, it + /// is non-null only for constructed versions of generic methods. + /// + IType BoundTo { get; } + + /// + /// If this type parameter was bound, returns the unbound version of it. + /// + ITypeParameter UnboundTypeParameter { get; } + + /// + /// Gets the region where the type parameter is defined. + /// + DomRegion Region { get; } + } + + /// + /// Represents the variance of a type parameter. + /// + public enum VarianceModifier : byte + { + /// + /// The type parameter is not variant. + /// + Invariant, + /// + /// The type parameter is covariant (used in output position). + /// + Covariant, + /// + /// The type parameter is contravariant (used in input position). + /// + Contravariant + }; + + #if WITH_CONTRACTS + [ContractClassFor(typeof(ITypeParameter))] + abstract class ITypeParameterContract : ITypeContract, ITypeParameter + { + int ITypeParameter.Index { + get { + Contract.Ensures(Contract.Result() >= 0); + return 0; + } + } + + IList ITypeParameter.Attributes { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + IList ITypeParameter.Constraints { + get { + Contract.Ensures(Contract.Result>() != null); + return null; + } + } + + bool ITypeParameter.HasDefaultConstructorConstraint { + get { return false; } + } + + bool ITypeParameter.HasReferenceTypeConstraint { + get { return false; } + } + + bool ITypeParameter.HasValueTypeConstraint { + get { return false; } + } + + IType ITypeParameter.BoundTo { + get { return null; } + } + + ITypeParameter ITypeParameter.UnboundTypeParameter { + get { + ITypeParameter @this = this; + Contract.Ensures((Contract.Result() != null) == (@this.BoundTo != null)); + return null; + } + } + + VarianceModifier ITypeParameter.Variance { + get { return VarianceModifier.Invariant; } + } + + bool IFreezable.IsFrozen { + get { return false; } + } + + void IFreezable.Freeze() + { + } + + EntityType ITypeParameter.OwnerType { + get { return EntityType.None; } + } + + DomRegion ITypeParameter.Region { + get { return DomRegion.Empty; } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs new file mode 100644 index 0000000000..50795311b2 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a reference to a type. + /// Must be resolved before it can be used as type. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(ITypeReferenceContract))] + #endif + public interface ITypeReference + { + // Keep this interface simple: I decided against having GetMethods/GetEvents etc. here, + // so that the Resolve step is never hidden from the consumer. + + // I decided against implementing IFreezable here: ITypeDefinition can be used as ITypeReference, + // but when freezing the reference, one wouldn't expect the definition to freeze. + + /// + /// Resolves this type reference. + /// + IType Resolve(ITypeResolveContext context); + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(ITypeReference))] + abstract class ITypeReferenceContract : ITypeReference + { + IType ITypeReference.Resolve(ITypeResolveContext context) + { + Contract.Requires(context != null); + Contract.Ensures(Contract.Result() != null); + return null; + } + } + #endif +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs new file mode 100644 index 0000000000..b1490a653b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs @@ -0,0 +1,147 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Context representing the set of assemblies in which a type is being searched. + /// + #if WITH_CONTRACTS + [ContractClass(typeof(ITypeResolveContextContract))] + #endif + public interface ITypeResolveContext + { + /// + /// Retrieves a type. + /// + /// Namespace that contains the type + /// Name of the type + /// Number of type parameters + /// Language-specific rules for how class names are compared + /// The type definition for the class; or null if no such type exists. + /// This method never returns inner types; it can be used only with top-level types. + ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer); + + /// + /// Retrieves all top-level types. + /// + /// + /// If this method is called within using (pc.Synchronize()), then the returned enumerable is valid + /// only until the end of the synchronize block. + /// + IEnumerable GetTypes(); + + /// + /// Retrieves all types in the specified namespace. + /// + /// Namespace in which types are being retrieved. Use string.Empty for the root namespace. + /// Language-specific rules for how namespace names are compared + /// List of types within that namespace. + /// + /// If this method is called within using (var spc = pc.Synchronize()), then the returned enumerable is valid + /// only until the end of the synchronize block. + /// + IEnumerable GetTypes(string nameSpace, StringComparer nameComparer); + + /// + /// Retrieves all namespaces. + /// + /// + /// If this method is called within using (var spc = pc.Synchronize()), then the returned enumerable is valid + /// only until the end of the synchronize block. + /// + IEnumerable GetNamespaces(); + + /// + /// Gets a namespace. + /// + /// The full name of the namespace. + /// The comparer to use. + /// The full name of the namespace, if it exists; or null if the namespace does not exist. + /// + /// For StringComparer.Ordinal, the return value is either null or the input namespace. + /// For other name comparers, this method returns the declared name of the namespace. + /// + string GetNamespace(string nameSpace, StringComparer nameComparer); + + /// + /// Returns a that + /// represents the same context as this instance, but cannot be modified + /// by other threads. + /// The ISynchronizedTypeResolveContext must be disposed from the same thread + /// that called this method when it is no longer used. + /// + /// + /// A simple implementation might enter a ReaderWriterLock when the synchronized context + /// is created, and releases the lock when Dispose() is called. + /// However, implementations based on immutable data structures are also possible. + /// + ISynchronizedTypeResolveContext Synchronize(); + + /// + /// Returns the cache manager associated with this resolve context, + /// or null if caching is not allowed. + /// Whenever the resolve context changes in some way, this property must return a new object to + /// ensure that old caches are cleared. + /// + CacheManager CacheManager { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(ITypeResolveContext))] + abstract class ITypeResolveContextContract : ITypeResolveContext + { + ITypeDefinition ITypeResolveContext.GetClass(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + { + Contract.Requires(nameSpace != null); + Contract.Requires(name != null); + Contract.Requires(typeParameterCount >= 0); + Contract.Requires(nameComparer != null); + return null; + } + + ISynchronizedTypeResolveContext ITypeResolveContext.Synchronize() + { + Contract.Ensures(Contract.Result() != null); + return null; + } + + IEnumerable ITypeResolveContext.GetTypes() + { + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable ITypeResolveContext.GetTypes(string nameSpace, StringComparer nameComparer) + { + Contract.Requires(nameSpace != null); + Contract.Requires(nameComparer != null); + Contract.Ensures(Contract.Result>() != null); + return null; + } + + IEnumerable ITypeResolveContext.GetNamespaces() + { + Contract.Ensures(Contract.Result>() != null); + return null; + } + + Utils.CacheManager ITypeResolveContext.CacheManager { + get { return null; } + } + + string ITypeResolveContext.GetNamespace(string nameSpace, StringComparer nameComparer) + { + Contract.Requires(nameSpace != null); + Contract.Requires(nameComparer != null); + return null; + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs new file mode 100644 index 0000000000..b5a0bad882 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IVariable.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Diagnostics.Contracts; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents a variable (name/return type pair). + /// + #if WITH_CONTRACTS + [ContractClass(typeof(IVariableContract))] + #endif + public interface IVariable + { + /// + /// Gets the name of the variable. + /// + string Name { get; } + + /// + /// Gets the declaration region of the variable. + /// + DomRegion DeclarationRegion { get; } + + /// + /// Gets the type of the variable. + /// + ITypeReference Type { get; } + + /// + /// Gets whether this field is a constant (C#-like const). + /// + bool IsConst { get; } + + /// + /// If this field is a constant, retrieves the value. + /// + IConstantValue ConstantValue { get; } + } + + #if WITH_CONTRACTS + [ContractClassFor(typeof(IVariable))] + abstract class IVariableContract : IVariable + { + string IVariable.Name { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + ITypeReference IVariable.Type { + get { + Contract.Ensures(Contract.Result() != null); + return null; + } + } + + bool IVariable.IsConst { + get { + IVariable @this = this; + Contract.Ensures(Contract.Result() == (@this.ConstantValue != null)); + return false; + } + } + + IConstantValue IVariable.ConstantValue { + get { return null; } + } + } + #endif +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs new file mode 100644 index 0000000000..10ca6ee6e3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs @@ -0,0 +1,93 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Base class for immutable objects. Provides implementation for IFreezable that reports the + /// object as always-frozen. + /// + public abstract class Immutable : IFreezable + { + bool IFreezable.IsFrozen { + get { return true; } + } + + void IFreezable.Freeze() + { + } + } + + public abstract class AbstractFreezable : IFreezable + { + bool isFrozen; + + /// + /// Gets if this instance is frozen. Frozen instances are immutable and thus thread-safe. + /// + public bool IsFrozen { + get { return isFrozen; } + } + + /// + /// Freezes this instance. + /// + public void Freeze() + { + if (!isFrozen) { + FreezeInternal(); + isFrozen = true; + } + } + + protected virtual void FreezeInternal() + { + } + + protected void CheckBeforeMutation() + { + if (isFrozen) + throw new InvalidOperationException("Cannot mutate frozen " + GetType().Name); + } + + protected static IList CopyList(IList inputList) + { + if (inputList == null || inputList.Count == 0) + return null; + else + return new List(inputList); + } + + protected static ReadOnlyCollection FreezeList(IList list) where T : IFreezable + { + if (list == null || list.Count == 0) + return EmptyList.Instance; + var result = new ReadOnlyCollection(list.ToArray()); + foreach (T item in result) { + item.Freeze(); + } + return result; + } + + protected static ReadOnlyCollection FreezeList(IList list) + { + if (list == null || list.Count == 0) + return EmptyList.Instance; + else + return new ReadOnlyCollection(list.ToArray()); + } + + protected static ReadOnlyCollection FreezeList(IList list) + { + if (list == null || list.Count == 0) + return EmptyList.Instance; + else + return new ReadOnlyCollection(list.ToArray()); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs new file mode 100644 index 0000000000..7d5961b9c7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs @@ -0,0 +1,297 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Base class for implementations. + /// + public abstract class AbstractMember : AbstractFreezable, IMember + { + // possible optimizations to reduce the memory usage of AbstractMember: + // - put 'bool isFrozen' into flags + // - store regions in more compact form (e.g. assume both file names are identical; use ushort for columns) + + ITypeDefinition declaringTypeDefinition; + ITypeReference returnType = SharedTypes.UnknownType; + IList attributes; + IList interfaceImplementations; + DomRegion region; + DomRegion bodyRegion; + string name; + + // 1 byte per enum + 2 bytes for flags + Accessibility accessibility; + EntityType entityType; + + protected BitVector16 flags; + const ushort FlagSealed = 0x0001; + const ushort FlagAbstract = 0x0002; + const ushort FlagShadowing = 0x0004; + const ushort FlagSynthetic = 0x0008; + const ushort FlagVirtual = 0x0010; + const ushort FlagOverride = 0x0020; + const ushort FlagStatic = 0x0040; + // Flags of form 0xY000 are reserved for use in derived classes (DefaultMethod etc.) + + protected override void FreezeInternal() + { + attributes = FreezeList(attributes); + interfaceImplementations = FreezeList(interfaceImplementations); + base.FreezeInternal(); + } + + protected AbstractMember(ITypeDefinition declaringTypeDefinition, string name, EntityType entityType) + { + if (declaringTypeDefinition == null) + throw new ArgumentNullException("declaringTypeDefinition"); + if (name == null) + throw new ArgumentNullException("name"); + this.declaringTypeDefinition = declaringTypeDefinition; + this.entityType = entityType; + this.name = name; + } + + /// + /// Copy constructor + /// + protected AbstractMember(IMember member) + { + if (member == null) + throw new ArgumentNullException("member"); + this.declaringTypeDefinition = member.DeclaringTypeDefinition; + this.returnType = member.ReturnType; + this.attributes = CopyList(member.Attributes); + this.interfaceImplementations = CopyList(member.InterfaceImplementations); + this.region = member.Region; + this.bodyRegion = member.BodyRegion; + this.name = member.Name; + this.accessibility = member.Accessibility; + this.entityType = member.EntityType; + this.IsSealed = member.IsSealed; + this.IsAbstract = member.IsAbstract; + this.IsShadowing = member.IsShadowing; + this.IsSynthetic = member.IsSynthetic; + this.IsVirtual = member.IsVirtual; + this.IsOverride = member.IsOverride; + this.IsStatic = member.IsStatic; + } + + public ITypeDefinition DeclaringTypeDefinition { + get { return declaringTypeDefinition; } + } + + public virtual IType DeclaringType { + get { return declaringTypeDefinition; } + } + + public virtual IMember MemberDefinition { + get { return this; } + } + + public ITypeReference ReturnType { + get { return returnType; } + set { + CheckBeforeMutation(); + if (value == null) + throw new ArgumentNullException(); + returnType = value; + } + } + + public IList InterfaceImplementations { + get { + if (interfaceImplementations == null) + interfaceImplementations = new List(); + return interfaceImplementations; + } + } + + public bool IsVirtual { + get { return flags[FlagVirtual]; } + set { + CheckBeforeMutation(); + flags[FlagVirtual] = value; + } + } + + public bool IsOverride { + get { return flags[FlagOverride]; } + set { + CheckBeforeMutation(); + flags[FlagOverride] = value; + } + } + + public bool IsOverridable { + get { + return (IsVirtual || IsOverride) && !IsSealed; + } + } + + public EntityType EntityType { + get { return entityType; } + set { + CheckBeforeMutation(); + entityType = value; + } + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + public DomRegion BodyRegion { + get { return bodyRegion; } + set { + CheckBeforeMutation(); + bodyRegion = value; + } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public virtual string Documentation { + get { + // To save memory, we don't store the documentation provider within the member, + // but simply use our declaring type definition as documentation provider. + // If that fails, we try if the project content is a documentation provider: + IDocumentationProvider provider = declaringTypeDefinition as IDocumentationProvider + ?? declaringTypeDefinition.ProjectContent as IDocumentationProvider; + if (provider != null) + return provider.GetDocumentation(this); + else + return null; + } + } + + public Accessibility Accessibility { + get { return accessibility; } + set { + CheckBeforeMutation(); + accessibility = value; + } + } + + public bool IsStatic { + get { return flags[FlagStatic]; } + set { + CheckBeforeMutation(); + flags[FlagStatic] = value; + } + } + + public bool IsAbstract { + get { return flags[FlagAbstract]; } + set { + CheckBeforeMutation(); + flags[FlagAbstract] = value; + } + } + + public bool IsSealed { + get { return flags[FlagSealed]; } + set { + CheckBeforeMutation(); + flags[FlagSealed] = value; + } + } + + public bool IsShadowing { + get { return flags[FlagShadowing]; } + set { + CheckBeforeMutation(); + flags[FlagShadowing] = value; + } + } + + public bool IsSynthetic { + get { return flags[FlagSynthetic]; } + set { + CheckBeforeMutation(); + flags[FlagSynthetic] = value; + } + } + + public bool IsPrivate { + get { return Accessibility == Accessibility.Private; } + } + + public bool IsPublic { + get { return Accessibility == Accessibility.Public; } + } + + public bool IsProtected { + get { return Accessibility == Accessibility.Protected; } + } + + public bool IsInternal { + get { return Accessibility == Accessibility.Internal; } + } + + public bool IsProtectedOrInternal { + get { return Accessibility == Accessibility.ProtectedOrInternal; } + } + + public bool IsProtectedAndInternal { + get { return Accessibility == Accessibility.ProtectedAndInternal; } + } + + public IProjectContent ProjectContent { + get { return declaringTypeDefinition.ProjectContent; } + } + + public string Name { + get { return name; } + set { + CheckBeforeMutation(); + if (value == null) + throw new ArgumentNullException(); + name = value; + } + } + + public virtual string FullName { + get { + return this.DeclaringType.FullName + "." + this.Name; + } + } + + public string Namespace { + get { return declaringTypeDefinition.Namespace; } + } + + public virtual string ReflectionName { + get { return this.DeclaringType.ReflectionName + "." + this.Name; } + } + + public override string ToString() + { + return "[" + EntityType + " " + ReflectionName + ":" + ReturnType + "]"; + } + + public virtual void ApplyInterningProvider(IInterningProvider provider) + { + if (provider != null) { + returnType = provider.Intern(returnType); + attributes = provider.InternList(attributes); + interfaceImplementations = provider.InternList(interfaceImplementations); + name = provider.Intern(name); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs new file mode 100644 index 0000000000..76cc4db1da --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -0,0 +1,124 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation for IType interface. + /// + public abstract class AbstractType : IType + { + public virtual string FullName { + get { + string ns = this.Namespace; + string name = this.Name; + if (string.IsNullOrEmpty(ns)) { + return name; + } else { + return ns + "." + name; + } + } + } + + public abstract string Name { get; } + + public virtual string Namespace { + get { return string.Empty; } + } + + public virtual string ReflectionName { + get { return this.FullName; } + } + + public abstract bool? IsReferenceType(ITypeResolveContext context); + + public virtual int TypeParameterCount { + get { return 0; } + } + + public virtual IType DeclaringType { + get { return null; } + } + + public virtual ITypeDefinition GetDefinition() + { + return null; + } + + IType ITypeReference.Resolve(ITypeResolveContext context) + { + return this; + } + + public virtual IEnumerable GetBaseTypes(ITypeResolveContext context) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + return GetMethods(context, filter).SafeCast() + .Concat(GetProperties(context, filter).SafeCast()) + .Concat(GetFields(context, filter).SafeCast()) + .Concat(GetEvents(context, filter).SafeCast()); + } + + public override bool Equals(object obj) + { + return Equals(obj as IType); + } + + public abstract override int GetHashCode(); + public abstract bool Equals(IType other); + + public override string ToString() + { + return this.ReflectionName; + } + + public virtual IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitOtherType(this); + } + + public virtual IType VisitChildren(TypeVisitor visitor) + { + return this; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs new file mode 100644 index 0000000000..3e12c921bf --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs @@ -0,0 +1,165 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents multiple type resolve contexts. + /// + public class CompositeTypeResolveContext : ITypeResolveContext + { + /// + /// Creates a that combines the given resolve contexts. + /// If one of the input parameters is null, the other input parameter is returned directly. + /// If both input parameters are null, the function returns null. + /// + public static ITypeResolveContext Combine(ITypeResolveContext a, ITypeResolveContext b) + { + if (a == null) + return b; + if (b == null) + return a; + return new CompositeTypeResolveContext(new [] { a, b }); + } + + readonly ITypeResolveContext[] children; + + /// + /// Creates a new + /// + public CompositeTypeResolveContext(IEnumerable children) + { + if (children == null) + throw new ArgumentNullException("children"); + this.children = children.ToArray(); + foreach (ITypeResolveContext c in this.children) { + if (c == null) + throw new ArgumentException("children enumeration contains nulls"); + } + } + + private CompositeTypeResolveContext(ITypeResolveContext[] children) + { + Debug.Assert(children != null); + this.children = children; + } + + /// + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + { + foreach (ITypeResolveContext context in children) { + ITypeDefinition d = context.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); + if (d != null) + return d; + } + return null; + } + + /// + public IEnumerable GetTypes() + { + return children.SelectMany(c => c.GetTypes()); + } + + /// + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) + { + return children.SelectMany(c => c.GetTypes(nameSpace, nameComparer)); + } + + /// + public IEnumerable GetNamespaces() + { + return children.SelectMany(c => c.GetNamespaces()).Distinct(); + } + + /// + public string GetNamespace(string nameSpace, StringComparer nameComparer) + { + foreach (ITypeResolveContext context in children) { + string r = context.GetNamespace(nameSpace, nameComparer); + if (r != null) + return r; + } + return null; + } + + /// + public virtual ISynchronizedTypeResolveContext Synchronize() + { + ISynchronizedTypeResolveContext[] sync = new ISynchronizedTypeResolveContext[children.Length]; + bool success = false; + try { + for (int i = 0; i < sync.Length; i++) { + sync[i] = children[i].Synchronize(); + if (sync[i] == null) + throw new InvalidOperationException(children[i] + ".Synchronize() returned null"); + } + ISynchronizedTypeResolveContext r = new CompositeSynchronizedTypeResolveContext(sync, new CacheManager(), true); + success = true; + return r; + } finally { + if (!success) { + // something went wrong, so immediately dispose the contexts we acquired + for (int i = 0; i < sync.Length; i++) { + if (sync[i] != null) + sync[i].Dispose(); + } + } + } + } + + public virtual CacheManager CacheManager { + // We don't know if our input contexts are mutable, so, to be on the safe side, + // we don't implement caching here. + get { return null; } + } + + sealed class CompositeSynchronizedTypeResolveContext : CompositeTypeResolveContext, ISynchronizedTypeResolveContext + { + readonly CacheManager cacheManager; + readonly bool isTopLevel; + + public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, CacheManager cacheManager, bool isTopLevel) + : base(children) + { + Debug.Assert(cacheManager != null); + this.cacheManager = cacheManager; + this.isTopLevel = isTopLevel; + } + + public void Dispose() + { + if (isTopLevel) { + foreach (ISynchronizedTypeResolveContext element in children) { + element.Dispose(); + } + // When the top-level synchronized block is closed, clear any cached data + cacheManager.Dispose(); + } + } + + public override CacheManager CacheManager { + // I expect CompositeTypeResolveContext to be used for almost all resolver operations, + // so this is the only place where implementing CacheManager is really important. + get { return cacheManager; } + } + + public override ISynchronizedTypeResolveContext Synchronize() + { + // re-use the same cache manager for nested synchronized contexts + if (isTopLevel) + return new CompositeSynchronizedTypeResolveContext(children, cacheManager, false); + else + return this; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs new file mode 100644 index 0000000000..917b1f4732 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs @@ -0,0 +1,107 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public sealed class DefaultAccessor : AbstractFreezable, IAccessor, ISupportsInterning + { + static readonly DefaultAccessor[] defaultAccessors = CreateDefaultAccessors(); + + static DefaultAccessor[] CreateDefaultAccessors() + { + DefaultAccessor[] accessors = new DefaultAccessor[(int)Accessibility.ProtectedAndInternal + 1]; + for (int i = 0; i < accessors.Length; i++) { + accessors[i] = new DefaultAccessor(); + accessors[i].accessibility = (Accessibility)i; + accessors[i].Freeze(); + } + return accessors; + } + + /// + /// Gets the default accessor with the specified accessibility (and without attributes or region). + /// + public static IAccessor GetFromAccessibility(Accessibility accessibility) + { + int index = (int)accessibility; + if (index >= 0 && index < defaultAccessors.Length) { + return defaultAccessors[index]; + } else { + DefaultAccessor a = new DefaultAccessor(); + a.accessibility = accessibility; + a.Freeze(); + return a; + } + } + + Accessibility accessibility; + DomRegion region; + IList attributes; + IList returnTypeAttributes; + + protected override void FreezeInternal() + { + base.FreezeInternal(); + this.attributes = FreezeList(this.attributes); + } + + public Accessibility Accessibility { + get { return accessibility; } + set { + CheckBeforeMutation(); + accessibility = value; + } + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public IList ReturnTypeAttributes { + get { + if (returnTypeAttributes == null) + returnTypeAttributes = new List(); + return returnTypeAttributes; + } + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + attributes = provider.InternList(attributes); + returnTypeAttributes = provider.InternList(returnTypeAttributes); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return (attributes != null ? attributes.GetHashCode() : 0) + ^ (returnTypeAttributes != null ? returnTypeAttributes.GetHashCode() : 0) + ^ region.GetHashCode() ^ (int)accessibility; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + DefaultAccessor a = other as DefaultAccessor; + return a != null && (attributes == a.attributes && returnTypeAttributes == a.returnTypeAttributes + && accessibility == a.accessibility && region == a.region); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs new file mode 100644 index 0000000000..15f8a18158 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs @@ -0,0 +1,167 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public sealed class DefaultAttribute : AbstractFreezable, IAttribute, ISupportsInterning + { + ITypeReference attributeType; + readonly ITypeReference[] constructorParameterTypes; + DomRegion region; + IList positionalArguments; + IList> namedArguments; + + protected override void FreezeInternal() + { + positionalArguments = FreezeList(positionalArguments); + + if (namedArguments == null || namedArguments.Count == 0) { + namedArguments = EmptyList>.Instance; + } else { + namedArguments = Array.AsReadOnly(namedArguments.ToArray()); + foreach (var pair in namedArguments) { + pair.Value.Freeze(); + } + } + + base.FreezeInternal(); + } + + public DefaultAttribute(ITypeReference attributeType, IEnumerable constructorParameterTypes) + { + if (attributeType == null) + throw new ArgumentNullException("attributeType"); + this.attributeType = attributeType; + this.constructorParameterTypes = constructorParameterTypes != null ? constructorParameterTypes.ToArray() : null; + } + + public ITypeReference AttributeType { + get { return attributeType; } + } + + public ReadOnlyCollection ConstructorParameterTypes { + get { return Array.AsReadOnly(constructorParameterTypes); } + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + public IList PositionalArguments { + get { + if (positionalArguments == null) + positionalArguments = new List(); + return positionalArguments; + } + } + + IList IAttribute.GetPositionalArguments(ITypeResolveContext context) + { + return this.PositionalArguments; + } + + public IList> NamedArguments { + get { + if (namedArguments == null) + namedArguments = new List>(); + return namedArguments; + } + } + + IList> IAttribute.GetNamedArguments(ITypeResolveContext context) + { + return this.NamedArguments; + } + + public IMethod ResolveConstructor(ITypeResolveContext context) + { + IType[] parameterTypes = null; + if (constructorParameterTypes != null && constructorParameterTypes.Length > 0) { + parameterTypes = new IType[constructorParameterTypes.Length]; + for (int i = 0; i < parameterTypes.Length; i++) { + parameterTypes[i] = constructorParameterTypes[i].Resolve(context); + } + } + IMethod bestMatch = null; + foreach (IMethod ctor in attributeType.Resolve(context).GetConstructors(context)) { + if (ctor.IsStatic) + continue; + if (parameterTypes == null) { + if (ctor.Parameters.Count == 0) + return ctor; + } else if (ctor.Parameters.Count == parameterTypes.Length) { + bestMatch = ctor; + bool ok = true; + for (int i = 0; i < parameterTypes.Length; i++) { + if (ctor.Parameters[i].Type != parameterTypes[i]) { + ok = false; + break; + } + } + if (ok) + return ctor; + } + } + return bestMatch; + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append('['); + b.Append(attributeType.ToString()); + if (this.PositionalArguments.Count + this.NamedArguments.Count > 0) { + b.Append('('); + bool first = true; + foreach (var element in this.PositionalArguments) { + if (first) first = false; else b.Append(", "); + b.Append(element.ToString()); + } + foreach (var pair in this.NamedArguments) { + if (first) first = false; else b.Append(", "); + b.Append(pair.Key); + b.Append('='); + b.Append(pair.Value.ToString()); + } + b.Append(')'); + } + b.Append(']'); + return b.ToString(); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + attributeType = provider.Intern(attributeType); + if (constructorParameterTypes != null) { + for (int i = 0; i < constructorParameterTypes.Length; i++) { + constructorParameterTypes[i] = provider.Intern(constructorParameterTypes[i]); + } + } + positionalArguments = provider.InternList(positionalArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return attributeType.GetHashCode() ^ (positionalArguments != null ? positionalArguments.GetHashCode() : 0) ^ (namedArguments != null ? namedArguments.GetHashCode() : 0) ^ region.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + DefaultAttribute a = other as DefaultAttribute; + return a != null && attributeType == a.attributeType && positionalArguments == a.positionalArguments && namedArguments == a.namedArguments && region == a.region; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs new file mode 100644 index 0000000000..c5c35ea1f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs @@ -0,0 +1,75 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public class DefaultEvent : AbstractMember, IEvent + { + IAccessor addAccessor, removeAccessor, invokeAccessor; + + protected override void FreezeInternal() + { + base.FreezeInternal(); + if (addAccessor != null) addAccessor.Freeze(); + if (removeAccessor != null) removeAccessor.Freeze(); + if (invokeAccessor != null) invokeAccessor.Freeze(); + } + + public DefaultEvent(ITypeDefinition declaringTypeDefinition, string name) + : base(declaringTypeDefinition, name, EntityType.Event) + { + } + + /// + /// Copy constructor + /// + protected DefaultEvent(IEvent ev) + : base(ev) + { + this.addAccessor = ev.AddAccessor; + this.removeAccessor = ev.RemoveAccessor; + this.invokeAccessor = ev.InvokeAccessor; + } + + public bool CanAdd { + get { return addAccessor != null; } + } + + public bool CanRemove { + get { return removeAccessor != null; } + } + + public bool CanInvoke { + get { return invokeAccessor != null; } + } + + public IAccessor AddAccessor{ + get { return addAccessor; } + set { + CheckBeforeMutation(); + addAccessor = value; + } + } + + public IAccessor RemoveAccessor { + get { return removeAccessor; } + set { + CheckBeforeMutation(); + removeAccessor = value; + } + } + + public IAccessor InvokeAccessor { + get { return invokeAccessor; } + set { + CheckBeforeMutation(); + invokeAccessor = value; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs new file mode 100644 index 0000000000..1cf12df69b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation for IExplicitInterfaceImplementation. + /// + public sealed class DefaultExplicitInterfaceImplementation : Immutable, IExplicitInterfaceImplementation, ISupportsInterning + { + public ITypeReference InterfaceType { get; private set; } + public string MemberName { get; private set; } + + public DefaultExplicitInterfaceImplementation(ITypeReference interfaceType, string memberName) + { + if (interfaceType == null) + throw new ArgumentNullException("interfaceType"); + if (memberName == null) + throw new ArgumentNullException("memberName"); + this.InterfaceType = interfaceType; + this.MemberName = memberName; + } + + public override string ToString() + { + return InterfaceType + "." + MemberName; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + InterfaceType = provider.Intern(InterfaceType); + MemberName = provider.Intern(MemberName); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return InterfaceType.GetHashCode() ^ MemberName.GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + DefaultExplicitInterfaceImplementation o = other as DefaultExplicitInterfaceImplementation; + return InterfaceType == o.InterfaceType && MemberName == o.MemberName; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs new file mode 100644 index 0000000000..c4fd96b3e4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs @@ -0,0 +1,82 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public class DefaultField : AbstractMember, IField + { + IConstantValue constantValue; + + const ushort FlagIsReadOnly = 0x1000; + const ushort FlagIsVolatile = 0x2000; + + protected override void FreezeInternal() + { + if (constantValue != null) + constantValue.Freeze(); + base.FreezeInternal(); + } + + public DefaultField(ITypeDefinition declaringTypeDefinition, string name) + : base(declaringTypeDefinition, name, EntityType.Field) + { + } + + protected DefaultField(IField f) : base(f) + { + this.constantValue = f.ConstantValue; + this.IsReadOnly = f.IsReadOnly; + this.IsVolatile = f.IsVolatile; + } + + public override void ApplyInterningProvider(IInterningProvider provider) + { + base.ApplyInterningProvider(provider); + if (provider != null) + constantValue = provider.Intern(constantValue); + } + + DomRegion IVariable.DeclarationRegion { + get { + return Region; + } + } + + public bool IsConst { + get { return constantValue != null; } + } + + public bool IsReadOnly { + get { return flags[FlagIsReadOnly]; } + set { + CheckBeforeMutation(); + flags[FlagIsReadOnly] = value; + } + } + + public bool IsVolatile { + get { return flags[FlagIsVolatile]; } + set { + CheckBeforeMutation(); + flags[FlagIsVolatile] = value; + } + } + + public IConstantValue ConstantValue { + get { return constantValue; } + set { + CheckBeforeMutation(); + constantValue = value; + } + } + + ITypeReference IVariable.Type { + get { return this.ReturnType; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs new file mode 100644 index 0000000000..a0c57feda8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs @@ -0,0 +1,131 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Text; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of interface. + /// + public class DefaultMethod : AbstractMember, IMethod + { + IList returnTypeAttributes; + IList typeParameters; + IList parameters; + + const ushort FlagExtensionMethod = 0x1000; + + protected override void FreezeInternal() + { + returnTypeAttributes = FreezeList(returnTypeAttributes); + typeParameters = FreezeList(typeParameters); + parameters = FreezeList(parameters); + base.FreezeInternal(); + } + + public DefaultMethod(ITypeDefinition declaringTypeDefinition, string name) + : base(declaringTypeDefinition, name, EntityType.Method) + { + } + + /// + /// Copy constructor + /// + protected DefaultMethod(IMethod method) : base(method) + { + returnTypeAttributes = CopyList(method.ReturnTypeAttributes); + typeParameters = CopyList(method.TypeParameters); + parameters = CopyList(method.Parameters); + this.IsExtensionMethod = method.IsExtensionMethod; + } + + public override void ApplyInterningProvider(IInterningProvider provider) + { + base.ApplyInterningProvider(provider); + if (provider != null) { + returnTypeAttributes = provider.InternList(returnTypeAttributes); + typeParameters = provider.InternList(typeParameters); + parameters = provider.InternList(parameters); + } + } + + public IList ReturnTypeAttributes { + get { + if (returnTypeAttributes == null) + returnTypeAttributes = new List(); + return returnTypeAttributes; + } + } + + public IList TypeParameters { + get { + if (typeParameters == null) + typeParameters = new List(); + return typeParameters; + } + } + + public bool IsExtensionMethod { + get { return flags[FlagExtensionMethod]; } + set { + CheckBeforeMutation(); + flags[FlagExtensionMethod] = value; + } + } + + public bool IsConstructor { + get { return this.EntityType == EntityType.Constructor; } + } + + public bool IsDestructor { + get { return this.EntityType == EntityType.Destructor; } + } + + public bool IsOperator { + get { return this.EntityType == EntityType.Operator; } + } + + public IList Parameters { + get { + if (parameters == null) + parameters = new List(); + return parameters; + } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder("["); + b.Append(EntityType.ToString()); + b.Append(' '); + b.Append(DeclaringType.Name); + b.Append('.'); + b.Append(Name); + b.Append('('); + var p = this.Parameters; + for (int i = 0; i < p.Count; i++) { + if (i > 0) b.Append(", "); + b.Append(p[i].ToString()); + } + b.Append("):"); + b.Append(ReturnType.ToString()); + b.Append(']'); + return b.ToString(); + } + + public static DefaultMethod CreateDefaultConstructor(ITypeDefinition typeDefinition) + { + DomRegion region = new DomRegion(typeDefinition.Region.FileName, typeDefinition.Region.BeginLine, typeDefinition.Region.BeginColumn); + return new DefaultMethod(typeDefinition, ".ctor") { + EntityType = EntityType.Constructor, + Accessibility = typeDefinition.IsAbstract ? Accessibility.Protected : Accessibility.Public, + IsSynthetic = true, + Region = region, + ReturnType = typeDefinition + }; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs new file mode 100644 index 0000000000..08455723e3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -0,0 +1,193 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Text; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation for IParameter. + /// + public sealed class DefaultParameter : AbstractFreezable, IParameter, ISupportsInterning + { + string name = string.Empty; + ITypeReference type = SharedTypes.UnknownType; + IList attributes; + IConstantValue defaultValue; + DomRegion region; + byte flags; + + public DefaultParameter(ITypeReference type, string name) + { + if (type == null) + throw new ArgumentNullException("type"); + if (name == null) + throw new ArgumentNullException("name"); + this.type = type; + this.name = name; + } + + /// + /// Copy constructor + /// + public DefaultParameter(IParameter p) + { + this.name = p.Name; + this.type = p.Type; + this.attributes = CopyList(p.Attributes); + this.defaultValue = p.DefaultValue; + this.region = p.Region; + this.IsRef = p.IsRef; + this.IsOut = p.IsOut; + this.IsParams = p.IsParams; + } + + protected override void FreezeInternal() + { + attributes = FreezeList(attributes); + if (defaultValue != null) + defaultValue.Freeze(); + base.FreezeInternal(); + } + + public string Name { + get { return name; } + set { + if (value == null) + throw new ArgumentNullException(); + CheckBeforeMutation(); + name = value; + } + } + + public ITypeReference Type { + get { return type; } + set { + if (value == null) + throw new ArgumentNullException(); + CheckBeforeMutation(); + type = value; + } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public IConstantValue DefaultValue { + get { return defaultValue; } + set { + CheckBeforeMutation(); + defaultValue = value; + } + } + + public object GetDefaultValue(ITypeResolveContext context) + { + if (defaultValue == null) + throw new InvalidOperationException(); + else + return defaultValue.GetValue(context); + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + DomRegion IVariable.DeclarationRegion { + get { + return Region; + } + } + + bool HasFlag(byte flag) + { + return (this.flags & flag) != 0; + } + void SetFlag(byte flag, bool value) + { + CheckBeforeMutation(); + if (value) + this.flags |= flag; + else + this.flags &= unchecked((byte)~flag); + } + + public bool IsRef { + get { return HasFlag(1); } + set { SetFlag(1, value); } + } + + public bool IsOut { + get { return HasFlag(2); } + set { SetFlag(2, value); } + } + + public bool IsParams { + get { return HasFlag(4); } + set { SetFlag(4, value); } + } + + public bool IsOptional { + get { return this.DefaultValue != null; } + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + name = provider.Intern(name); + type = provider.Intern(type); + attributes = provider.InternList(attributes); + defaultValue = provider.Intern(defaultValue); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode() ^ (attributes != null ? attributes.GetHashCode() : 0) ^ (defaultValue != null ? defaultValue.GetHashCode() : 0); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + DefaultParameter p = other as DefaultParameter; + return p != null && type == p.type && attributes == p.attributes + && defaultValue == p.defaultValue && region == p.region && flags == p.flags; + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + if (IsRef) + b.Append("ref "); + if (IsOut) + b.Append("out "); + if (IsParams) + b.Append("params "); + b.Append(name); + b.Append(':'); + b.Append(type.ToString()); + if (defaultValue != null) { + b.Append(" = "); + b.Append(defaultValue.ToString()); + } + return b.ToString(); + } + + bool IVariable.IsConst { + get { return false; } + } + + IConstantValue IVariable.ConstantValue { + get { return null; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs new file mode 100644 index 0000000000..558dc6eb35 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs @@ -0,0 +1,83 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public class DefaultProperty : AbstractMember, IProperty + { + IAccessor getter, setter; + IList parameters; + + protected override void FreezeInternal() + { + parameters = FreezeList(parameters); + if (getter != null) getter.Freeze(); + if (setter != null) setter.Freeze(); + base.FreezeInternal(); + } + + public DefaultProperty(ITypeDefinition declaringTypeDefinition, string name) + : base(declaringTypeDefinition, name, EntityType.Property) + { + } + + protected DefaultProperty(IProperty p) : base(p) + { + this.getter = p.Getter; + this.setter = p.Setter; + this.parameters = CopyList(p.Parameters); + } + + public override void ApplyInterningProvider(IInterningProvider provider) + { + base.ApplyInterningProvider(provider); + if (provider != null) { + getter = provider.Intern(getter); + setter = provider.Intern(setter); + parameters = provider.InternList(parameters); + } + } + + public bool IsIndexer { + get { return this.EntityType == EntityType.Indexer; } + } + + public IList Parameters { + get { + if (parameters == null) + parameters = new List(); + return parameters; + } + } + + public bool CanGet { + get { return getter != null; } + } + + public bool CanSet { + get { return setter != null; } + } + + public IAccessor Getter{ + get { return getter; } + set { + CheckBeforeMutation(); + getter = value; + } + } + + public IAccessor Setter { + get { return setter; } + set { + CheckBeforeMutation(); + setter = value; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs new file mode 100644 index 0000000000..f9ee9a45ea --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -0,0 +1,644 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Globalization; +using System.Linq; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition + { + readonly IProjectContent projectContent; + readonly ITypeDefinition declaringTypeDefinition; + + string ns; + string name; + + IList baseTypes; + IList typeParameters; + IList nestedTypes; + IList fields; + IList methods; + IList properties; + IList events; + IList attributes; + + DomRegion region; + DomRegion bodyRegion; + + // 1 byte per enum + 2 bytes for flags + ClassType classType; + Accessibility accessibility; + BitVector16 flags; + const ushort FlagSealed = 0x0001; + const ushort FlagAbstract = 0x0002; + const ushort FlagShadowing = 0x0004; + const ushort FlagSynthetic = 0x0008; + const ushort FlagAddDefaultConstructorIfRequired = 0x0010; + const ushort FlagHasExtensionMethods = 0x0020; + + protected override void FreezeInternal() + { + baseTypes = FreezeList(baseTypes); + typeParameters = FreezeList(typeParameters); + nestedTypes = FreezeList(nestedTypes); + fields = FreezeList(fields); + methods = FreezeList(methods); + properties = FreezeList(properties); + events = FreezeList(events); + attributes = FreezeList(attributes); + base.FreezeInternal(); + } + + public DefaultTypeDefinition(ITypeDefinition declaringTypeDefinition, string name) + { + if (declaringTypeDefinition == null) + throw new ArgumentNullException("declaringTypeDefinition"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("name"); + this.projectContent = declaringTypeDefinition.ProjectContent; + this.declaringTypeDefinition = declaringTypeDefinition; + this.name = name; + this.ns = declaringTypeDefinition.Namespace; + } + + public DefaultTypeDefinition(IProjectContent projectContent, string ns, string name) + { + if (projectContent == null) + throw new ArgumentNullException("projectContent"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("name"); + this.projectContent = projectContent; + this.ns = ns ?? string.Empty; + this.name = name; + } + + public ClassType ClassType { + get { return classType; } + set { + CheckBeforeMutation(); + classType = value; + } + } + + public IList BaseTypes { + get { + if (baseTypes == null) + baseTypes = new List(); + return baseTypes; + } + } + + public void ApplyInterningProvider(IInterningProvider provider) + { + if (provider != null) { + ns = provider.Intern(ns); + name = provider.Intern(name); + baseTypes = provider.InternList(baseTypes); + typeParameters = provider.InternList(typeParameters); + attributes = provider.InternList(attributes); + } + } + + public IList TypeParameters { + get { + if (typeParameters == null) + typeParameters = new List(); + return typeParameters; + } + } + + public IList NestedTypes { + get { + if (nestedTypes == null) + nestedTypes = new List(); + return nestedTypes; + } + } + + public IList Fields { + get { + if (fields == null) + fields = new List(); + return fields; + } + } + + public IList Properties { + get { + if (properties == null) + properties = new List(); + return properties; + } + } + + public IList Methods { + get { + if (methods == null) + methods = new List(); + return methods; + } + } + + public IList Events { + get { + if (events == null) + events = new List(); + return events; + } + } + + public IEnumerable Members { + get { + return this.Fields.SafeCast() + .Concat(this.Properties.SafeCast()) + .Concat(this.Methods.SafeCast()) + .Concat(this.Events.SafeCast()); + } + } + + public bool? IsReferenceType(ITypeResolveContext context) + { + switch (this.ClassType) { + case ClassType.Class: + case ClassType.Interface: + case ClassType.Delegate: + return true; + case ClassType.Enum: + case ClassType.Struct: + return false; + default: + return null; + } + } + + public string FullName { + get { + if (declaringTypeDefinition != null) { + return declaringTypeDefinition.FullName + "." + this.name; + } else if (string.IsNullOrEmpty(ns)) { + return this.name; + } else { + return this.ns + "." + this.name; + } + } + } + + public string Name { + get { return this.name; } + } + + public string Namespace { + get { return this.ns; } + } + + public string ReflectionName { + get { + if (declaringTypeDefinition != null) { + int tpCount = this.TypeParameterCount - declaringTypeDefinition.TypeParameterCount; + string combinedName; + if (tpCount > 0) + combinedName = declaringTypeDefinition.ReflectionName + "+" + this.Name + "`" + tpCount.ToString(CultureInfo.InvariantCulture); + else + combinedName = declaringTypeDefinition.ReflectionName + "+" + this.Name; + return combinedName; + } else { + int tpCount = this.TypeParameterCount; + if (string.IsNullOrEmpty(ns)) { + if (tpCount > 0) + return this.Name + "`" + tpCount.ToString(CultureInfo.InvariantCulture); + else + return this.Name; + } else { + if (tpCount > 0) + return this.Namespace + "." + this.Name + "`" + tpCount.ToString(CultureInfo.InvariantCulture); + else + return this.Namespace + "." + this.Name; + } + } + } + } + + public int TypeParameterCount { + get { return typeParameters != null ? typeParameters.Count : 0; } + } + + public EntityType EntityType { + get { return EntityType.TypeDefinition; } + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + public DomRegion BodyRegion { + get { return bodyRegion; } + set { + CheckBeforeMutation(); + bodyRegion = value; + } + } + + public ITypeDefinition DeclaringTypeDefinition { + get { return declaringTypeDefinition; } + } + + public IType DeclaringType { + get { return declaringTypeDefinition; } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public virtual string Documentation { + get { return null; } + } + + public Accessibility Accessibility { + get { return accessibility; } + set { + CheckBeforeMutation(); + accessibility = value; + } + } + + public bool IsStatic { + get { return IsAbstract && IsSealed; } + } + + public bool IsAbstract { + get { return flags[FlagAbstract]; } + set { + CheckBeforeMutation(); + flags[FlagAbstract] = value; + } + } + + public bool IsSealed { + get { return flags[FlagSealed]; } + set { + CheckBeforeMutation(); + flags[FlagSealed] = value; + } + } + + public bool IsShadowing { + get { return flags[FlagShadowing]; } + set { + CheckBeforeMutation(); + flags[FlagShadowing] = value; + } + } + + public bool IsSynthetic { + get { return flags[FlagSynthetic]; } + set { + CheckBeforeMutation(); + flags[FlagSynthetic] = value; + } + } + + public bool IsPrivate { + get { return Accessibility == Accessibility.Private; } + } + + public bool IsPublic { + get { return Accessibility == Accessibility.Public; } + } + + public bool IsProtected { + get { return Accessibility == Accessibility.Protected; } + } + + public bool IsInternal { + get { return Accessibility == Accessibility.Internal; } + } + + public bool IsProtectedOrInternal { + get { return Accessibility == Accessibility.ProtectedOrInternal; } + } + + public bool IsProtectedAndInternal { + get { return Accessibility == Accessibility.ProtectedAndInternal; } + } + + public bool HasExtensionMethods { + get { return flags[FlagHasExtensionMethods]; } + set { + CheckBeforeMutation(); + flags[FlagHasExtensionMethods] = value; + } + } + + public IProjectContent ProjectContent { + get { return projectContent; } + } + + public IEnumerable GetBaseTypes(ITypeResolveContext context) + { + bool hasNonInterface = false; + if (baseTypes != null && this.ClassType != ClassType.Enum) { + foreach (ITypeReference baseTypeRef in baseTypes) { + IType baseType = baseTypeRef.Resolve(context); + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef == null || baseTypeDef.ClassType != ClassType.Interface) + hasNonInterface = true; + yield return baseType; + } + } + if (!hasNonInterface && !(this.Name == "Object" && this.Namespace == "System" && this.TypeParameterCount == 0)) { + Type primitiveBaseType; + switch (classType) { + case ClassType.Enum: + primitiveBaseType = typeof(Enum); + break; + case ClassType.Struct: + primitiveBaseType = typeof(ValueType); + break; + case ClassType.Delegate: + primitiveBaseType = typeof(Delegate); + break; + default: + primitiveBaseType = typeof(object); + break; + } + IType t = context.GetTypeDefinition(primitiveBaseType); + if (t != null) + yield return t; + } + } + + public virtual ITypeDefinition GetCompoundClass() + { + return this; + } + + public virtual IList GetParts() + { + return new ITypeDefinition[] { this }; + } + + public ITypeDefinition GetDefinition() + { + return this; + } + + public IType Resolve(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + return this; + } + + public virtual IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetNestedTypes(context, filter); + + List nestedTypes = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + foreach (var baseTypeRef in this.BaseTypes) { + IType baseType = baseTypeRef.Resolve(context); + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && baseTypeDef.ClassType != ClassType.Interface) { + // get nested types from baseType (not baseTypeDef) so that generics work correctly + nestedTypes.AddRange(baseType.GetNestedTypes(context, filter)); + break; // there is at most 1 non-interface base + } + } + foreach (ITypeDefinition nestedType in this.NestedTypes) { + if (filter == null || filter(nestedType)) { + nestedTypes.Add(nestedType); + } + } + } + } + return nestedTypes; + } + + public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetMethods(context, filter); + + List methods = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + int baseCount = 0; + foreach (var baseType in GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { + methods.AddRange(baseType.GetMethods(context, filter)); + baseCount++; + } + } + if (baseCount > 1) + RemoveDuplicates(methods); + AddFilteredRange(methods, this.Methods.Where(m => !m.IsConstructor), filter); + } + } + return methods; + } + + public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetConstructors(context, filter); + + List methods = new List(); + AddFilteredRange(methods, this.Methods.Where(m => m.IsConstructor && !m.IsStatic), filter); + + if (this.AddDefaultConstructorIfRequired) { + if (this.ClassType == ClassType.Class && methods.Count == 0 + || this.ClassType == ClassType.Enum || this.ClassType == ClassType.Struct) + { + var m = DefaultMethod.CreateDefaultConstructor(this); + if (filter == null || filter(m)) + methods.Add(m); + } + } + return methods; + } + + public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetProperties(context, filter); + + List properties = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + int baseCount = 0; + foreach (var baseType in GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { + properties.AddRange(baseType.GetProperties(context, filter)); + baseCount++; + } + } + if (baseCount > 1) + RemoveDuplicates(properties); + AddFilteredRange(properties, this.Properties, filter); + } + } + return properties; + } + + public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetFields(context, filter); + + List fields = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + int baseCount = 0; + foreach (var baseType in GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { + fields.AddRange(baseType.GetFields(context, filter)); + baseCount++; + } + } + if (baseCount > 1) + RemoveDuplicates(fields); + AddFilteredRange(fields, this.Fields, filter); + } + } + return fields; + } + + public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetEvents(context, filter); + + List events = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + int baseCount = 0; + foreach (var baseType in GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { + events.AddRange(baseType.GetEvents(context, filter)); + baseCount++; + } + } + if (baseCount > 1) + RemoveDuplicates(events); + AddFilteredRange(events, this.Events, filter); + } + } + return events; + } + + public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + ITypeDefinition compound = GetCompoundClass(); + if (compound != this) + return compound.GetMembers(context, filter); + + List members = new List(); + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + int baseCount = 0; + foreach (var baseType in GetBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { + members.AddRange(baseType.GetMembers(context, filter)); + baseCount++; + } + } + if (baseCount > 1) + RemoveDuplicates(members); + AddFilteredRange(members, this.Methods.Where(m => !m.IsConstructor), filter); + AddFilteredRange(members, this.Properties, filter); + AddFilteredRange(members, this.Fields, filter); + AddFilteredRange(members, this.Events, filter); + } + } + return members; + } + + static void AddFilteredRange(List targetList, IEnumerable sourceList, Predicate filter) where T : class + { + if (filter == null) { + targetList.AddRange(sourceList); + } else { + foreach (T element in sourceList) { + if (filter(element)) + targetList.Add(element); + } + } + } + + /// + /// Removes duplicate members from the list. + /// This is necessary when the same member can be inherited twice due to multiple inheritance. + /// + static void RemoveDuplicates(List list) where T : class + { + if (list.Count > 1) { + HashSet hash = new HashSet(); + list.RemoveAll(m => !hash.Add(m)); + } + } + + // we use reference equality + bool IEquatable.Equals(IType other) + { + return this == other; + } + + public override string ToString() + { + return ReflectionName; + } + + /// + /// Gets whether a default constructor should be added to this class if it is required. + /// Such automatic default constructors will not appear in ITypeDefinition.Methods, but will be present + /// in IType.GetMethods(). + /// + /// This way of creating the default constructor is necessary because + /// we cannot create it directly in the IClass - we need to consider partial classes. + public bool AddDefaultConstructorIfRequired { + get { return flags[FlagAddDefaultConstructorIfRequired]; } + set { + CheckBeforeMutation(); + flags[FlagAddDefaultConstructorIfRequired] = value; + } + } + + public IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitTypeDefinition(this); + } + + public IType VisitChildren(TypeVisitor visitor) + { + return this; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs new file mode 100644 index 0000000000..ec8ce70079 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs @@ -0,0 +1,396 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Default implementation of . + /// + public sealed class DefaultTypeParameter : AbstractFreezable, ITypeParameter, ISupportsInterning + { + string name; + int index; + IList constraints; + IList attributes; + + DomRegion region; + + // Small fields: byte+byte+short + VarianceModifier variance; + EntityType ownerType; + BitVector16 flags; + + const ushort FlagReferenceTypeConstraint = 0x0001; + const ushort FlagValueTypeConstraint = 0x0002; + const ushort FlagDefaultConstructorConstraint = 0x0004; + + protected override void FreezeInternal() + { + constraints = FreezeList(constraints); + attributes = FreezeList(attributes); + base.FreezeInternal(); + } + + public DefaultTypeParameter(EntityType ownerType, int index, string name) + { + if (!(ownerType == EntityType.TypeDefinition || ownerType == EntityType.Method)) + throw new ArgumentException("owner must be a type or a method", "ownerType"); + if (index < 0) + throw new ArgumentOutOfRangeException("index", index, "Value must not be negative"); + if (name == null) + throw new ArgumentNullException("name"); + this.ownerType = ownerType; + this.index = index; + this.name = name; + } + + public string Name { + get { return name; } + } + + string INamedElement.FullName { + get { return name; } + } + + string INamedElement.Namespace { + get { return string.Empty; } + } + + public string ReflectionName { + get { + if (ownerType == EntityType.Method) + return "``" + index.ToString(); + else + return "`" + index.ToString(); + } + } + + public bool? IsReferenceType(ITypeResolveContext context) + { + switch (flags.Data & (FlagReferenceTypeConstraint | FlagValueTypeConstraint)) { + case FlagReferenceTypeConstraint: + return true; + case FlagValueTypeConstraint: + return false; + } + // protect against cyclic dependencies between type parameters + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + foreach (ITypeReference constraintRef in this.Constraints) { + IType constraint = constraintRef.Resolve(context); + ITypeDefinition constraintDef = constraint.GetDefinition(); + // While interfaces are reference types, an interface constraint does not + // force the type parameter to be a reference type; so we need to explicitly look for classes here. + if (constraintDef != null && constraintDef.ClassType == ClassType.Class) + return true; + if (constraint is ITypeParameter) { + bool? isReferenceType = constraint.IsReferenceType(context); + if (isReferenceType.HasValue) + return isReferenceType.Value; + } + } + } + } + return null; + } + + int IType.TypeParameterCount { + get { return 0; } + } + + IType IType.DeclaringType { + get { return null; } + } + + ITypeDefinition IType.GetDefinition() + { + return null; + } + + IType ITypeReference.Resolve(ITypeResolveContext context) + { + return this; + } + + public override int GetHashCode() + { + unchecked { + return (int)ownerType * 178256151 + index; + } + } + + public override bool Equals(object obj) + { + return Equals(obj as IType); + } + + public bool Equals(IType other) + { + DefaultTypeParameter p = other as DefaultTypeParameter; + if (p == null) + return false; + return ownerType == p.ownerType && index == p.index; + } + + public EntityType OwnerType { + get { + return ownerType; + } + } + + public int Index { + get { return index; } + } + + public IList Attributes { + get { + if (attributes == null) + attributes = new List(); + return attributes; + } + } + + public IList Constraints { + get { + if (constraints == null) + constraints = new List(); + return constraints; + } + } + + public bool HasDefaultConstructorConstraint { + get { return flags[FlagDefaultConstructorConstraint]; } + set { + CheckBeforeMutation(); + flags[FlagDefaultConstructorConstraint] = value; + } + } + + public bool HasReferenceTypeConstraint { + get { return flags[FlagReferenceTypeConstraint]; } + set { + CheckBeforeMutation(); + flags[FlagReferenceTypeConstraint] = value; + } + } + + public bool HasValueTypeConstraint { + get { return flags[FlagValueTypeConstraint]; } + set { + CheckBeforeMutation(); + flags[FlagValueTypeConstraint] = value; + } + } + + public VarianceModifier Variance { + get { return variance; } + set { + CheckBeforeMutation(); + variance = value; + } + } + + public DomRegion Region { + get { return region; } + set { + CheckBeforeMutation(); + region = value; + } + } + + IType ITypeParameter.BoundTo { + get { return null; } + } + + ITypeParameter ITypeParameter.UnboundTypeParameter { + get { return null; } + } + + public IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitTypeParameter(this); + } + + public IType VisitChildren(TypeVisitor visitor) + { + return this; + } + + static readonly SimpleProjectContent dummyProjectContent = new SimpleProjectContent(); + + DefaultTypeDefinition GetDummyClassForTypeParameter() + { + DefaultTypeDefinition c = new DefaultTypeDefinition(dummyProjectContent, string.Empty, this.Name); + c.Region = this.Region; + if (HasValueTypeConstraint) { + c.ClassType = ClassType.Struct; + } else if (HasDefaultConstructorConstraint) { + c.ClassType = ClassType.Class; + } else { + c.ClassType = ClassType.Interface; + } + return c; + } + + public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + { + if (HasDefaultConstructorConstraint || HasValueTypeConstraint) { + DefaultMethod m = DefaultMethod.CreateDefaultConstructor(GetDummyClassForTypeParameter()); + if (filter(m)) + return new [] { m }; + } + return EmptyList.Instance; + } + + public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + { + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetMethods(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + { + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetProperties(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + { + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetFields(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + { + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetEvents(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + foreach (var baseType in GetNonCircularBaseTypes(context)) { + foreach (var m in baseType.GetMembers(context, filter)) { + if (!m.IsStatic) + yield return m; + } + } + } + + // Problem with type parameter resolving - circular declarations + // void Example (S s, T t) where S : T where T : S + IEnumerable GetNonCircularBaseTypes(ITypeResolveContext context) + { + var result = this.GetBaseTypes(context).Where(bt => !IsCircular (context, bt)); + if (result.Any ()) + return result; + + // result may be empty, GetBaseTypes doesn't return object/struct when there are only constraints (even circular) as base types are available, + // but even when there are only circular references the default base type should be included. + IType defaultBaseType = context.GetTypeDefinition("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal); + if (defaultBaseType != null) + return new [] { defaultBaseType }; + return Enumerable.Empty (); + } + + bool IsCircular(ITypeResolveContext context, IType baseType) + { + var parameter = baseType as DefaultTypeParameter; + if (parameter == null) + return false; + var stack = new Stack(); + while (true) { + if (parameter == this) + return true; + foreach (DefaultTypeParameter parameterBaseType in parameter.GetNonCircularBaseTypes(context).Where(t => t is DefaultTypeParameter)) { + stack.Push(parameterBaseType); + } + if (stack.Count == 0) + return false; + parameter = stack.Pop(); + } + } + + IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter) + { + return EmptyList.Instance; + } + + public IEnumerable GetBaseTypes(ITypeResolveContext context) + { + bool hasNonInterfaceConstraint = false; + foreach (ITypeReference constraint in this.Constraints) { + IType c = constraint.Resolve(context); + yield return c; + ITypeDefinition cdef = c.GetDefinition(); + if (!(cdef != null && cdef.ClassType == ClassType.Interface)) + hasNonInterfaceConstraint = true; + } + // Do not add the 'System.Object' constraint if there is another constraint with a base class. + if (HasValueTypeConstraint || !hasNonInterfaceConstraint) { + IType defaultBaseType = context.GetTypeDefinition("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal); + if (defaultBaseType != null) + yield return defaultBaseType; + } + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + constraints = provider.InternList(constraints); + attributes = provider.InternList(attributes); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + unchecked { + int hashCode = GetHashCode(); + if (name != null) + hashCode += name.GetHashCode(); + if (attributes != null) + hashCode += attributes.GetHashCode(); + if (constraints != null) + hashCode += constraints.GetHashCode(); + hashCode += 771 * flags.Data + 900103 * (int)variance; + return hashCode; + } + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + DefaultTypeParameter o = other as DefaultTypeParameter; + return o != null + && this.attributes == o.attributes + && this.constraints == o.constraints + && this.flags == o.flags + && this.ownerType == o.ownerType + && this.index == o.index + && this.variance == o.variance; + } + + public override string ToString() + { + return this.ReflectionName; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs new file mode 100644 index 0000000000..976b90ca5c --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs @@ -0,0 +1,114 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Type Reference used when the fully qualified type name is known. + /// + public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning + { + string nameSpace, name; + int typeParameterCount; + //volatile CachedResult v_cachedResult; + + public GetClassTypeReference(string nameSpace, string name, int typeParameterCount) + { + if (nameSpace == null) + throw new ArgumentNullException("nameSpace"); + if (name == null) + throw new ArgumentNullException("name"); + this.nameSpace = nameSpace; + this.name = name; + this.typeParameterCount = typeParameterCount; + } + + public GetClassTypeReference(string fullTypeName, int typeParameterCount) + { + if (fullTypeName == null) + throw new ArgumentNullException("fullTypeName"); + int pos = fullTypeName.LastIndexOf('.'); + if (pos < 0) { + nameSpace = string.Empty; + name = fullTypeName; + } else { + nameSpace = fullTypeName.Substring(0, pos); + name = fullTypeName.Substring(pos + 1); + } + this.typeParameterCount = typeParameterCount; + } + + /* + sealed class CachedResult + { + public readonly CacheManager CacheManager; + public readonly IType Result; + + public CachedResult(CacheManager cacheManager, IType result) + { + this.CacheManager = cacheManager; + this.Result = result; + } + } + */ + + public IType Resolve(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + + /* TODO PERF: caching disabled until we measure how much of an advantage it is + * (and whether other approaches like caching only the last N resolve calls in a thread-static cache would work better) + * Maybe even make a distinction between the really common type references (e.g. primitiveTypeReferences) and + * normal GetClassTypeReferences? + CacheManager cacheManager = context.CacheManager; + if (cacheManager != null) { + CachedResult result = this.v_cachedResult; + if (result != null && result.CacheManager == cacheManager) + return result.Result; + IType newResult = DoResolve(context); + this.v_cachedResult = new CachedResult(cacheManager, newResult); + cacheManager.Disposed += delegate { v_cachedResult = null; }; // maybe optimize this to use interface call instead of delegate? + return newResult; + } else { + return DoResolve(context); + } + + } + + IType DoResolve(ITypeResolveContext context) + { + */ + return context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType; + } + + public override string ToString() + { + if (typeParameterCount == 0) + return NamespaceDeclaration.BuildQualifiedName(nameSpace, name); + else + return NamespaceDeclaration.BuildQualifiedName(nameSpace, name) + "`" + typeParameterCount; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + nameSpace = provider.Intern(nameSpace); + name = provider.Intern(name); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return nameSpace.GetHashCode() ^ name.GetHashCode() ^ typeParameterCount; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + GetClassTypeReference o = other as GetClassTypeReference; + return o != null && name == o.name && nameSpace == o.nameSpace && typeParameterCount == o.typeParameterCount; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs new file mode 100644 index 0000000000..1a5d048f03 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Substitutes method type parameters with type arguments. Does not modify class type parameters. + /// + public class MethodTypeParameterSubstitution : TypeVisitor + { + readonly IList typeArguments; + + public MethodTypeParameterSubstitution(IList typeArguments) + { + this.typeArguments = typeArguments; + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + int index = type.Index; + if (type.OwnerType == EntityType.Method) { + if (index >= 0 && index < typeArguments.Count) + return typeArguments[index]; + else + return SharedTypes.UnknownType; + } else { + return base.VisitTypeParameter(type); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs new file mode 100644 index 0000000000..856b7aa63a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs @@ -0,0 +1,76 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Type reference used to reference nested types. + /// + public sealed class NestedTypeReference : ITypeReference, ISupportsInterning + { + ITypeReference declaringTypeRef; + string name; + int additionalTypeParameterCount; + + /// + /// Creates a new NestedTypeReference. + /// + /// Reference to the declaring type. + /// Name of the nested class + /// Number of type parameters on the inner class (without type parameters on baseTypeRef) + /// + /// must be exactly the (unbound) declaring type, not a derived type, not a parameterized type. + /// NestedTypeReference thus always resolves to a type definition, never to (partially) parameterized types. + /// + public NestedTypeReference(ITypeReference declaringTypeRef, string name, int additionalTypeParameterCount) + { + if (declaringTypeRef == null) + throw new ArgumentNullException("declaringTypeRef"); + if (name == null) + throw new ArgumentNullException("name"); + this.declaringTypeRef = declaringTypeRef; + this.name = name; + this.additionalTypeParameterCount = additionalTypeParameterCount; + } + + public IType Resolve(ITypeResolveContext context) + { + ITypeDefinition declaringType = declaringTypeRef.Resolve(context) as ITypeDefinition; + if (declaringType != null) { + int tpc = declaringType.TypeParameterCount; + foreach (IType type in declaringType.NestedTypes) { + if (type.Name == name && type.TypeParameterCount == tpc + additionalTypeParameterCount) + return type; + } + } + return SharedTypes.UnknownType; + } + + public override string ToString() + { + if (additionalTypeParameterCount == 0) + return declaringTypeRef + "+" + name; + else + return declaringTypeRef + "+" + name + "`" + additionalTypeParameterCount; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + declaringTypeRef = provider.Intern(declaringTypeRef); + name = provider.Intern(name); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return declaringTypeRef.GetHashCode() ^ name.GetHashCode() ^ additionalTypeParameterCount; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + NestedTypeReference o = other as NestedTypeReference; + return o != null && declaringTypeRef == o.declaringTypeRef && name == o.name && additionalTypeParameterCount == o.additionalTypeParameterCount; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs new file mode 100644 index 0000000000..4876c1e5cd --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs @@ -0,0 +1,70 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Proxy that forwards calls to another TypeResolveContext. + /// Useful as base class for decorators. + /// + public class ProxyTypeResolveContext : AbstractAnnotatable, ITypeResolveContext + { + protected readonly ITypeResolveContext target; + + /// + /// Creates a new ProxyTypeResolveContext. + /// + public ProxyTypeResolveContext(ITypeResolveContext target) + { + if (target == null) + throw new ArgumentNullException("target"); + this.target = target; + } + + /// + public virtual ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + { + return target.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); + } + + /// + public virtual IEnumerable GetTypes() + { + return target.GetTypes(); + } + + /// + public virtual IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) + { + return target.GetTypes(nameSpace, nameComparer); + } + + /// + public virtual IEnumerable GetNamespaces() + { + return target.GetNamespaces(); + } + + /// + public virtual string GetNamespace(string nameSpace, StringComparer nameComparer) + { + return target.GetNamespace(nameSpace, nameComparer); + } + + /// + public virtual ISynchronizedTypeResolveContext Synchronize() + { + return target.Synchronize(); + } + + /// + public virtual Utils.CacheManager CacheManager { + // Don't forward this by default; we don't know what derived classes are doing; + // it might not be cache-safe. + get { return null; } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs new file mode 100644 index 0000000000..d61fd4d522 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// A simple constant value that is independent of the resolve context. + /// + public sealed class SimpleConstantValue : Immutable, IConstantValue, ISupportsInterning + { + ITypeReference type; + object value; + + public SimpleConstantValue(ITypeReference type, object value) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + this.value = value; + } + + public IType GetValueType(ITypeResolveContext context) + { + return type.Resolve(context); + } + + public object GetValue(ITypeResolveContext context) + { + if (value is ITypeReference) + return ((ITypeReference)value).Resolve(context); + else + return value; + } + + public override string ToString() + { + if (value == null) + return "null"; + else if (value is bool) + return value.ToString().ToLowerInvariant(); + else + return value.ToString(); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + type = provider.Intern(type); + value = provider.Intern(value); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + SimpleConstantValue scv = other as SimpleConstantValue; + return scv != null && type == scv.type && value == scv.value; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs new file mode 100644 index 0000000000..7ed18be858 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs @@ -0,0 +1,141 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.CompilerServices; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Simple interning provider. + /// + public sealed class SimpleInterningProvider : IInterningProvider + { + public SimpleInterningProvider() + { + // Intern the well-known types first; so that they are used when possible. + foreach (ITypeReference r in KnownTypeReference.AllKnownTypeReferences) + Intern(r); + } + + sealed class ReferenceComparer : IEqualityComparer + { + public readonly static ReferenceComparer Instance = new ReferenceComparer(); + + public new bool Equals(object a, object b) + { + return ReferenceEquals(a, b); + } + + public int GetHashCode(object obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } + + sealed class InterningComparer : IEqualityComparer + { + public bool Equals(ISupportsInterning x, ISupportsInterning y) + { + return x.EqualsForInterning(y); + } + + public int GetHashCode(ISupportsInterning obj) + { + return obj.GetHashCodeForInterning(); + } + } + + sealed class ListComparer : IEqualityComparer + { + public bool Equals(IEnumerable a, IEnumerable b) + { + if (a.GetType() != b.GetType()) + return false; + IEnumerator e1 = a.GetEnumerator(); + IEnumerator e2 = b.GetEnumerator(); + while (e1.MoveNext()) { + // e1 has more elements than e2; or elements are different + if (!e2.MoveNext() || e1.Current != e2.Current) + return false; + } + if (e2.MoveNext()) // e2 has more elements than e1 + return false; + // No need to dispose e1/e2: non-generic IEnumerator doesn't implement IDisposable, + // and the underlying enumerator will likely be a List.Enumerator which has an empty Dispose() method. + return true; + } + + public int GetHashCode(IEnumerable obj) + { + int hashCode = obj.GetType().GetHashCode(); + unchecked { + foreach (object o in obj) { + hashCode *= 27; + hashCode += RuntimeHelpers.GetHashCode(o); + } + } + return hashCode; + } + } + + Dictionary byValueDict = new Dictionary(); + Dictionary supportsInternDict = new Dictionary(new InterningComparer()); + Dictionary listDict = new Dictionary(new ListComparer()); + + public T Intern(T obj) where T : class + { + if (obj == null) + return null; + ISupportsInterning s = obj as ISupportsInterning; + if (s != null) { + ISupportsInterning output; + if (supportsInternDict.TryGetValue(s, out output)) { + obj = (T)output; + } else { + s.PrepareForInterning(this); + if (supportsInternDict.TryGetValue(s, out output)) + obj = (T)output; + else + supportsInternDict.Add(s, s); + } + } else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { + object output; + if (byValueDict.TryGetValue(obj, out output)) + obj = (T)output; + else + byValueDict.Add(obj, obj); + } + return obj; + } + + public IList InternList(IList list) where T : class + { + if (list == null) + return null; + for (int i = 0; i < list.Count; i++) { + T oldItem = list[i]; + T newItem = Intern(oldItem); + if (oldItem != newItem) { + if (list.IsReadOnly) + list = new T[list.Count]; + list[i] = newItem; + } + } + if (!list.IsReadOnly) + list = new ReadOnlyCollection(list); + IEnumerable output; + if (listDict.TryGetValue(list, out output)) + list = (IList)output; + else + listDict.Add(list, list); + return list; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs new file mode 100644 index 0000000000..6cb78cbfaa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs @@ -0,0 +1,239 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Simple implementation that stores the list of classes/namespaces. + /// Synchronization is implemented using a . + /// + /// + /// Compared with , this class adds support for the IProjectContent interface, + /// for partial classes, and for multi-threading. + /// + public sealed class SimpleProjectContent : AbstractAnnotatable, IProjectContent + { + // This class is sealed by design: + // the synchronization story doesn't mix well with someone trying to extend this class. + // If you wanted to derive from this: use delegation, not inheritance. + + readonly TypeStorage types = new TypeStorage(); + readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); + readonly Dictionary fileDict = new Dictionary(Platform.FileNameComparer); + + #region AssemblyAttributes + readonly List assemblyAttributes = new List(); // mutable assembly attribute storage + + volatile IAttribute[] readOnlyAssemblyAttributes = {}; // volatile field with copy for reading threads + + /// + public IList AssemblyAttributes { + get { return readOnlyAssemblyAttributes; } + } + + void AddRemoveAssemblyAttributes(ICollection removedAttributes, ICollection addedAttributes) + { + // API uses ICollection instead of IEnumerable to discourage users from evaluating + // the list inside the lock (this method is called inside the write lock) + // [[not an issue anymore; the user now passes IParsedFile]] + bool hasChanges = false; + if (removedAttributes != null && removedAttributes.Count > 0) { + if (assemblyAttributes.RemoveAll(removedAttributes.Contains) > 0) + hasChanges = true; + } + if (addedAttributes != null) { + assemblyAttributes.AddRange(addedAttributes); + hasChanges = true; + } + + if (hasChanges) + readOnlyAssemblyAttributes = assemblyAttributes.ToArray(); + } + #endregion + + #region AddType + void AddType(ITypeDefinition typeDefinition) + { + if (typeDefinition == null) + throw new ArgumentNullException("typeDefinition"); + typeDefinition.Freeze(); // Type definition must be frozen before it can be added to a project content + if (typeDefinition.ProjectContent != this) + throw new ArgumentException("Cannot add a type definition that belongs to another project content"); + + // TODO: handle partial classes + types.UpdateType(typeDefinition); + } + #endregion + + #region RemoveType + void RemoveType(ITypeDefinition typeDefinition) + { + types.RemoveType (typeDefinition); // <- Daniel: Correct ? + } + #endregion + + #region UpdateProjectContent + /// + /// Removes types and attributes from oldFile from the project, and adds those from newFile. + /// + /// + /// The update is done inside a write lock; when other threads access this project content + /// from within a using (Synchronize()) block, they will not see intermediate (inconsistent) state. + /// + public void UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) + { + 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."); + } + readerWriterLock.EnterWriteLock(); + try { + if (oldFile != null) { + foreach (var element in oldFile.TopLevelTypeDefinitions) { + RemoveType(element); + } + if (newFile == null) { + fileDict.Remove(oldFile.FileName); + } + } + if (newFile != null) { + foreach (var element in newFile.TopLevelTypeDefinitions) { + AddType(element); + } + fileDict[newFile.FileName] = newFile; + } + AddRemoveAssemblyAttributes(oldFile != null ? oldFile.AssemblyAttributes : null, newFile != null ? newFile.AssemblyAttributes : null); + } finally { + readerWriterLock.ExitWriteLock(); + } + } + #endregion + + #region IProjectContent implementation + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + { + readerWriterLock.EnterReadLock(); + try { + return types.GetTypeDefinition(nameSpace, name, typeParameterCount, nameComparer); + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public IEnumerable GetTypes() + { + readerWriterLock.EnterReadLock(); + try { + // make a copy with ToArray() for thread-safe access + return types.GetTypes().ToArray(); + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) + { + readerWriterLock.EnterReadLock(); + try { + // make a copy with ToArray() for thread-safe access + return types.GetTypes(nameSpace, nameComparer).ToArray(); + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public IEnumerable GetNamespaces() + { + readerWriterLock.EnterReadLock(); + try { + // make a copy with ToArray() for thread-safe access + return types.GetNamespaces().ToArray(); + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public string GetNamespace(string nameSpace, StringComparer nameComparer) + { + readerWriterLock.EnterReadLock(); + try { + return types.GetNamespace(nameSpace, nameComparer); + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public IParsedFile GetFile(string fileName) + { + readerWriterLock.EnterReadLock(); + try { + IParsedFile file; + if (fileDict.TryGetValue(fileName, out file)) + return file; + else + return null; + } finally { + readerWriterLock.ExitReadLock(); + } + } + + public IEnumerable Files { + get { + readerWriterLock.EnterReadLock(); + try { + return fileDict.Values.ToArray(); + } finally { + readerWriterLock.ExitReadLock(); + } + } + } + #endregion + + #region Synchronization + public CacheManager CacheManager { + get { return null; } + } + + public ISynchronizedTypeResolveContext Synchronize() + { + // don't acquire the lock on OutOfMemoryException etc. + ISynchronizedTypeResolveContext sync = new ReadWriteSynchronizedTypeResolveContext(types, readerWriterLock); + readerWriterLock.EnterReadLock(); + return sync; + } + + sealed class ReadWriteSynchronizedTypeResolveContext : ProxyTypeResolveContext, ISynchronizedTypeResolveContext + { + ReaderWriterLockSlim readerWriterLock; + + public ReadWriteSynchronizedTypeResolveContext(ITypeResolveContext target, ReaderWriterLockSlim readerWriterLock) + : base(target) + { + this.readerWriterLock = readerWriterLock; + } + + public void Dispose() + { + if (readerWriterLock != null) { + readerWriterLock.ExitReadLock(); + readerWriterLock = null; + } + } + + public override ISynchronizedTypeResolveContext Synchronize() + { + // nested Synchronize() calls don't need any locking + return new ReadWriteSynchronizedTypeResolveContext(target, null); + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs new file mode 100644 index 0000000000..b344d94914 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IEvent (e.g. after type substitution). + /// + public class SpecializedEvent : DefaultEvent + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedEvent(IEvent e) : base(e) + { + this.memberDefinition = e.MemberDefinition; + this.declaringType = e.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + + public override int GetHashCode() + { + int hashCode = 0; + unchecked { + if (memberDefinition != null) + hashCode += 1000000007 * memberDefinition.GetHashCode(); + if (declaringType != null) + hashCode += 1000000009 * declaringType.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(object obj) + { + SpecializedEvent other = obj as SpecializedEvent; + if (other == null) + return false; + return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs new file mode 100644 index 0000000000..d8fc104b1e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IField (e.g. after type substitution). + /// + public class SpecializedField : DefaultField + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedField(IField f) : base(f) + { + this.memberDefinition = f.MemberDefinition; + this.declaringType = f.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + + public override int GetHashCode() + { + int hashCode = 0; + unchecked { + if (memberDefinition != null) + hashCode += 1000000007 * memberDefinition.GetHashCode(); + if (declaringType != null) + hashCode += 1000000009 * declaringType.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(object obj) + { + SpecializedField other = obj as SpecializedField; + if (other == null) + return false; + return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs new file mode 100644 index 0000000000..9d76f93e26 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs @@ -0,0 +1,72 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IMethod (e.g. after type substitution). + /// + public class SpecializedMethod : DefaultMethod + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedMethod(IMethod m) : base(m) + { + this.memberDefinition = m.MemberDefinition; + this.declaringType = m.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + + public override int GetHashCode() + { + int hashCode = 0; + unchecked { + if (memberDefinition != null) + hashCode += 1000000007 * memberDefinition.GetHashCode(); + if (declaringType != null) + hashCode += 1000000009 * declaringType.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(object obj) + { + SpecializedMethod other = obj as SpecializedMethod; + if (other == null) + return false; + return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + } + + /// + /// Performs type substitution in parameter types and in the return type. + /// + public void SubstituteTypes(Func substitution) + { + this.ReturnType = substitution(this.ReturnType); + var p = this.Parameters; + for (int i = 0; i < p.Count; i++) { + ITypeReference newType = substitution(p[i].Type); + if (newType != p[i].Type) { + p[i] = new DefaultParameter(p[i]) { Type = newType }; + } + } + // TODO: we might also have to perform substitution within the method's constraints + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs new file mode 100644 index 0000000000..921ffc0299 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs @@ -0,0 +1,71 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IProperty (e.g. after type substitution). + /// + public class SpecializedProperty : DefaultProperty + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedProperty(IProperty p) : base(p) + { + this.memberDefinition = p.MemberDefinition; + this.declaringType = p.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + + public override int GetHashCode() + { + int hashCode = 0; + unchecked { + if (memberDefinition != null) + hashCode += 1000000007 * memberDefinition.GetHashCode(); + if (declaringType != null) + hashCode += 1000000009 * declaringType.GetHashCode(); + } + return hashCode; + } + + public override bool Equals(object obj) + { + SpecializedProperty other = obj as SpecializedProperty; + if (other == null) + return false; + return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + } + + /// + /// Performs type substitution in parameter types and in the return type. + /// + public void SubstituteTypes(Func substitution) + { + this.ReturnType = substitution(this.ReturnType); + var p = this.Parameters; + for (int i = 0; i < p.Count; i++) { + ITypeReference newType = substitution(p[i].Type); + if (newType != p[i].Type) { + p[i] = new DefaultParameter(p[i]) { Type = newType }; + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs new file mode 100644 index 0000000000..aaf38718c9 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs @@ -0,0 +1,31 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// A type reference that wraps another type reference; but performs a substitution in the resolved type. + /// + public class SubstitutionTypeReference : ITypeReference + { + readonly ITypeReference baseTypeReference; + readonly TypeVisitor substitution; + + public SubstitutionTypeReference(ITypeReference baseTypeReference, TypeVisitor substitution) + { + if (baseTypeReference == null) + throw new ArgumentNullException("baseTypeReference"); + if (substitution == null) + throw new ArgumentNullException("substitution"); + this.baseTypeReference = baseTypeReference; + this.substitution = substitution; + } + + public IType Resolve(ITypeResolveContext context) + { + return baseTypeReference.Resolve(context).AcceptVisitor(substitution); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs new file mode 100644 index 0000000000..d5f2842952 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs @@ -0,0 +1,350 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Stores a set of types and allows resolving them. + /// + /// + /// Concurrent read accesses are thread-safe, but a write access concurrent to any other access is not safe. + /// + public sealed class TypeStorage : ITypeResolveContext + { + #region FullNameAndTypeParameterCount + struct FullNameAndTypeParameterCount + { + public readonly string Namespace; + public readonly string Name; + public readonly int TypeParameterCount; + + public FullNameAndTypeParameterCount(string nameSpace, string name, int typeParameterCount) + { + this.Namespace = nameSpace; + this.Name = name; + this.TypeParameterCount = typeParameterCount; + } + } + + sealed class FullNameAndTypeParameterCountComparer : IEqualityComparer + { + public static readonly FullNameAndTypeParameterCountComparer Ordinal = new FullNameAndTypeParameterCountComparer(StringComparer.Ordinal); + + public readonly StringComparer NameComparer; + + public FullNameAndTypeParameterCountComparer(StringComparer nameComparer) + { + this.NameComparer = nameComparer; + } + + public bool Equals(FullNameAndTypeParameterCount x, FullNameAndTypeParameterCount y) + { + return x.TypeParameterCount == y.TypeParameterCount + && NameComparer.Equals(x.Name, y.Name) + && NameComparer.Equals(x.Namespace, y.Namespace); + } + + public int GetHashCode(FullNameAndTypeParameterCount obj) + { + return NameComparer.GetHashCode(obj.Name) ^ NameComparer.GetHashCode(obj.Namespace) ^ obj.TypeParameterCount; + } + } + #endregion + + #region Type Dictionary Storage + volatile Dictionary[] _typeDicts = { + new Dictionary(FullNameAndTypeParameterCountComparer.Ordinal) + }; + readonly object dictsLock = new object(); + + Dictionary GetTypeDictionary(StringComparer nameComparer) + { + // Gets the dictionary for the specified comparer, creating it if necessary. + // New dictionaries might be added during read accesses, so this method needs to be thread-safe, + // as we allow concurrent read-accesses. + var typeDicts = this._typeDicts; + foreach (var dict in typeDicts) { + FullNameAndTypeParameterCountComparer comparer = (FullNameAndTypeParameterCountComparer)dict.Comparer; + if (comparer.NameComparer == nameComparer) + return dict; + } + + // ensure that no other thread can try to lazy-create this (or another) dict + lock (dictsLock) { + typeDicts = this._typeDicts; // fetch fresh value after locking + // try looking for it again, maybe it was added while we were waiting for a lock + // (double-checked locking pattern) + foreach (var dict in typeDicts) { + FullNameAndTypeParameterCountComparer comparer = (FullNameAndTypeParameterCountComparer)dict.Comparer; + if (comparer.NameComparer == nameComparer) + return dict; + } + + // now create new dict + var oldDict = typeDicts[0]; // Ordinal dict + var newDict = new Dictionary( + oldDict.Count, + new FullNameAndTypeParameterCountComparer(nameComparer)); + foreach (var pair in oldDict) { + // don't use Add() as there might be conflicts in the target language + newDict[pair.Key] = pair.Value; + } + + // add the new dict to the array of dicts + var newTypeDicts = new Dictionary[typeDicts.Length + 1]; + Array.Copy(typeDicts, 0, newTypeDicts, 0, typeDicts.Length); + newTypeDicts[typeDicts.Length] = newDict; + this._typeDicts = newTypeDicts; + return newDict; + } + } + #endregion + + #region Namespace Storage + class NamespaceEntry + { + /// + /// Full namespace name + /// + public readonly string Name; + + /// + /// Parent namespace + /// + public readonly NamespaceEntry Parent; + + /// + /// Number of classes in this namespace (not in sub-namespaces). + /// Note: this always refers to the number of classes from the ordinal typeDict that map + /// to this namespace when compared with the appropriate StringComparer. + /// The actual number of classes in the typeDict matching this StringComparer might be lower. + /// + public int ClassCount; + + /// + /// Number of sub-namespaces. + /// + public int SubNamespaceCount; + + public NamespaceEntry(NamespaceEntry parent, string name) + { + this.Parent = parent; + this.Name = name; + } + } + + volatile Dictionary[] _namespaceDicts = { + new Dictionary(StringComparer.Ordinal) + }; + + Dictionary GetNamespaceDictionary(StringComparer nameComparer) + { + // Gets the dictionary for the specified comparer, creating it if necessary. + // New dictionaries might be added during read accesses, so this method needs to be thread-safe, + // as we allow concurrent read-accesses. + var namespaceDicts = this._namespaceDicts; + foreach (var dict in namespaceDicts) { + if (dict.Comparer == nameComparer) + return dict; + } + + // ensure that no other thread can try to lazy-create this (or another) dict + lock (dictsLock) { + namespaceDicts = this._namespaceDicts; // fetch fresh value after locking + // try looking for it again, maybe it was added while we were waiting for a lock + // (double-checked locking pattern) + foreach (var dict in namespaceDicts) { + if (dict.Comparer == nameComparer) + return dict; + } + + // now create new dict + var newDict = new Dictionary(nameComparer); + foreach (ITypeDefinition type in _typeDicts[0].Values) { + NamespaceEntry ne = GetOrCreateNamespaceEntry(newDict, type.Namespace); + ne.ClassCount++; + } + + // add the new dict to the array of dicts + var newNamespaceDicts = new Dictionary[namespaceDicts.Length + 1]; + Array.Copy(namespaceDicts, 0, newNamespaceDicts, 0, namespaceDicts.Length); + newNamespaceDicts[namespaceDicts.Length] = newDict; + this._namespaceDicts = newNamespaceDicts; + return newDict; + } + } + + NamespaceEntry GetOrCreateNamespaceEntry(Dictionary dict, string ns) + { + NamespaceEntry ne; + if (!dict.TryGetValue(ns, out ne)) { + NamespaceEntry parentEntry; + if (string.IsNullOrEmpty(ns)) { + parentEntry = null; + } else { + int pos = ns.LastIndexOf('.'); + string parentNS = pos < 0 ? string.Empty : ns.Substring(0, pos); + parentEntry = GetOrCreateNamespaceEntry(dict, parentNS); + parentEntry.SubNamespaceCount++; + } + ne = new NamespaceEntry(parentEntry, ns); + dict.Add(ns, ne); + } + return ne; + } + #endregion + + #region ITypeResolveContext implementation + /// + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) + { + if (nameSpace == null) + throw new ArgumentNullException("nameSpace"); + if (name == null) + throw new ArgumentNullException("name"); + if (nameComparer == null) + throw new ArgumentNullException("nameComparer"); + + var key = new FullNameAndTypeParameterCount(nameSpace, name, typeParameterCount); + ITypeDefinition result; + if (GetTypeDictionary(nameComparer).TryGetValue(key, out result)) + return result; + else + return null; + } + + /// + public IEnumerable GetTypes() + { + return _typeDicts[0].Values; + } + + /// + public IEnumerable GetTypes(string nameSpace, StringComparer nameComparer) + { + if (nameSpace == null) + throw new ArgumentNullException("nameSpace"); + if (nameComparer == null) + throw new ArgumentNullException("nameComparer"); + return GetTypes().Where(c => nameComparer.Equals(nameSpace, c.Namespace)); + } + + /// + public IEnumerable GetNamespaces() + { + return _namespaceDicts[0].Keys; + } + + /// + public string GetNamespace(string nameSpace, StringComparer nameComparer) + { + if (nameSpace == null) + throw new ArgumentNullException("nameSpace"); + if (nameComparer == null) + throw new ArgumentNullException("nameComparer"); + NamespaceEntry result; + if (GetNamespaceDictionary(nameComparer).TryGetValue(nameSpace, out result)) + return result.Name; + else + return null; + } + #endregion + + #region Synchronize + /// + /// TypeStorage is mutable and does not provide any means for synchronization, so this method + /// always throws a . + /// + public ISynchronizedTypeResolveContext Synchronize() + { + throw new NotSupportedException(); + } + + /// + public CacheManager CacheManager { + // TypeStorage is mutable, so caching is a bad idea. + // We could provide a CacheToken if we update it on every modication, but + // that's not worth the effort as TypeStorage is rarely directly used in resolve operations. + get { return null; } + } + #endregion + + #region RemoveType + /// + /// Removes a type definition from this project content. + /// + public void RemoveType(ITypeDefinition typeDefinition) + { + if (typeDefinition == null) + throw new ArgumentNullException("typeDefinition"); + var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount); + bool wasRemoved = false; + foreach (var dict in _typeDicts) { + ITypeDefinition defInDict; + if (dict.TryGetValue(key, out defInDict)) { + if (defInDict == typeDefinition) { + if (dict.Comparer == FullNameAndTypeParameterCountComparer.Ordinal) { + // Set wasRemoved flag only on removal in the ordinal comparison. + // This keeps the ClassCount consistent when there are name clashes. + wasRemoved = true; + } + dict.Remove(key); + } + } + } + if (wasRemoved) { + foreach (var dict in _namespaceDicts) { + NamespaceEntry ns; + if (dict.TryGetValue(typeDefinition.Namespace, out ns)) { + ns.ClassCount--; + RemoveNamespaceIfPossible(dict, ns); + } + } + } + } + + void RemoveNamespaceIfPossible(Dictionary dict, NamespaceEntry ns) + { + while (ns.ClassCount == 0 && ns.SubNamespaceCount == 0) { + dict.Remove(ns.Name); + ns = ns.Parent; + if (ns == null) + break; + ns.SubNamespaceCount--; + } + } + #endregion + + #region UpdateType + /// + /// Adds the type definition to this project content. + /// Replaces existing type definitions with the same name. + /// + public void UpdateType(ITypeDefinition typeDefinition) + { + if (typeDefinition == null) + throw new ArgumentNullException("typeDefinition"); + var key = new FullNameAndTypeParameterCount(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount); + // Set isNew on addition in the ordinal comparison. + // This keeps the ClassCount consistent when there are name clashes. + bool isNew = !_typeDicts[0].ContainsKey(key); + foreach (var dict in _typeDicts) { + dict[key] = typeDefinition; + } + if (isNew) { + foreach (var dict in _namespaceDicts) { + NamespaceEntry ns = GetOrCreateNamespaceEntry(dict, typeDefinition.Namespace); + ++ns.ClassCount; + } + } + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs new file mode 100644 index 0000000000..7f4830555a --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs @@ -0,0 +1,45 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + public abstract class TypeWithElementType : AbstractType + { + protected readonly IType elementType; + + protected TypeWithElementType(IType elementType) + { + if (elementType == null) + throw new ArgumentNullException("elementType"); + this.elementType = elementType; + } + + public override string Name { + get { return elementType.Name + NameSuffix; } + } + + public override string Namespace { + get { return elementType.Namespace; } + } + + public override string FullName { + get { return elementType.FullName + NameSuffix; } + } + + public override string ReflectionName { + get { return elementType.ReflectionName + NameSuffix; } + } + + public abstract string NameSuffix { get; } + + public IType ElementType { + get { return elementType; } + } + + // Force concrete implementations to override VisitChildren - the base implementation + // in AbstractType assumes there are no children, but we know there is (at least) 1. + public abstract override IType VisitChildren(TypeVisitor visitor); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs new file mode 100644 index 0000000000..e966d66c7b --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs @@ -0,0 +1,47 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Special type definition for 'void'. + /// + public class VoidTypeDefinition : DefaultTypeDefinition + { + public VoidTypeDefinition(IProjectContent projectContent) + : base(projectContent, "System", "Void") + { + this.ClassType = ClassType.Struct; + this.Accessibility = Accessibility.Public; + this.IsSealed = true; + } + + public override IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter) + { + return EmptyList.Instance; + } + + public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter) + { + return EmptyList.Instance; + } + + public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter) + { + return EmptyList.Instance; + } + + public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter) + { + return EmptyList.Instance; + } + + public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter) + { + return EmptyList.Instance; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs new file mode 100644 index 0000000000..688dc38932 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -0,0 +1,135 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents the intersection of several types. + /// + public class IntersectionType : AbstractType + { + readonly ReadOnlyCollection types; + + public ReadOnlyCollection Types { + get { return types; } + } + + private IntersectionType(IType[] types) + { + Debug.Assert(types.Length >= 2); + this.types = Array.AsReadOnly(types); + } + + public static IType Create(IEnumerable types) + { + IType[] arr = types.Where(t => t != null).Distinct().ToArray(); + if (arr.Length == 0) + return SharedTypes.UnknownType; + else if (arr.Length == 1) + return arr[0]; + else + return new IntersectionType(arr); + } + + public override string Name { + get { + StringBuilder b = new StringBuilder(); + foreach (var t in types) { + if (b.Length > 0) + b.Append(" & "); + b.Append(t.Name); + } + return b.ToString(); + } + } + + public override string ReflectionName { + get { + StringBuilder b = new StringBuilder(); + foreach (var t in types) { + if (b.Length > 0) + b.Append(" & "); + b.Append(t.ReflectionName); + } + return b.ToString(); + } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + foreach (var t in types) { + bool? isReferenceType = t.IsReferenceType(context); + if (isReferenceType.HasValue) + return isReferenceType.Value; + } + return null; + } + + public override int GetHashCode() + { + int hashCode = 0; + unchecked { + foreach (var t in types) { + hashCode *= 7137517; + hashCode += t.GetHashCode(); + } + } + return hashCode; + } + + public override bool Equals(IType other) + { + IntersectionType o = other as IntersectionType; + if (o != null && types.Count == o.types.Count) { + for (int i = 0; i < types.Count; i++) { + if (!types[i].Equals(o.types[i])) + return false; + } + return true; + } + return false; + } + + public override IEnumerable GetBaseTypes(ITypeResolveContext context) + { + return types; + } + + public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter) + { + filter = FilterNonStatic(filter); + return types.SelectMany(t => t.GetEvents(context, filter)); + } + + public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter) + { + filter = FilterNonStatic(filter); + return types.SelectMany(t => t.GetMethods(context, filter)); + } + + public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter) + { + filter = FilterNonStatic(filter); + return types.SelectMany(t => t.GetProperties(context, filter)); + } + + public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter) + { + filter = FilterNonStatic(filter); + return types.SelectMany(t => t.GetFields(context, filter)); + } + + static Predicate FilterNonStatic(Predicate filter) where T : class, IMember + { + return member => !member.IsStatic && (filter == null || filter(member)); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs new file mode 100644 index 0000000000..19daedef16 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs @@ -0,0 +1,103 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Contains well-known type references. + /// + public static class KnownTypeReference + { + /// + /// Gets a type reference pointing to the void type. + /// + public static readonly ITypeReference Void = new GetClassTypeReference("System", "Void", 0); + + /// + /// Gets a type reference pointing to the object type. + /// + public static readonly ITypeReference Object = new GetClassTypeReference("System", "Object", 0); + + /// + /// Gets a type reference pointing to the bool type. + /// + public static readonly ITypeReference Boolean = new GetClassTypeReference("System", "Boolean", 0); + + /// + /// Gets a type reference pointing to the sbyte type. + /// + public static readonly ITypeReference SByte = new GetClassTypeReference("System", "SByte", 0); + + /// + /// Gets a type reference pointing to the byte type. + /// + public static readonly ITypeReference Byte = new GetClassTypeReference("System", "Byte", 0); + + /// + /// Gets a type reference pointing to the short type. + /// + public static readonly ITypeReference Int16 = new GetClassTypeReference("System", "Int16", 0); + + /// + /// Gets a type reference pointing to the ushort type. + /// + public static readonly ITypeReference UInt16 = new GetClassTypeReference("System", "UInt16", 0); + + /// + /// Gets a type reference pointing to the int type. + /// + public static readonly ITypeReference Int32 = new GetClassTypeReference("System", "Int32", 0); + + /// + /// Gets a type reference pointing to the uint type. + /// + public static readonly ITypeReference UInt32 = new GetClassTypeReference("System", "UInt32", 0); + + /// + /// Gets a type reference pointing to the long type. + /// + public static readonly ITypeReference Int64 = new GetClassTypeReference("System", "Int64", 0); + + /// + /// Gets a type reference pointing to the ulong type. + /// + public static readonly ITypeReference UInt64 = new GetClassTypeReference("System", "UInt64", 0); + + /// + /// Gets a type reference pointing to the string type. + /// + public static readonly ITypeReference String = new GetClassTypeReference("System", "String", 0); + + /// + /// Gets a type reference pointing to the char type. + /// + public static readonly ITypeReference Char = new GetClassTypeReference("System", "Char", 0); + + /// + /// Gets a type reference pointing to the float type. + /// + public static readonly ITypeReference Single = new GetClassTypeReference("System", "Single", 0); + + /// + /// Gets a type reference pointing to the double type. + /// + public static readonly ITypeReference Double = new GetClassTypeReference("System", "Double", 0); + + /// + /// Gets all known type references. + /// + public static IEnumerable AllKnownTypeReferences { + get { + return new[] { + Void, Object, Boolean, + SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, + String, Char, Single, Double + }; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs new file mode 100644 index 0000000000..11809396eb --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/NullableType.cs @@ -0,0 +1,69 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Static helper methods for working with nullable types. + /// + public static class NullableType + { + /// + /// Gets whether the specified type is a nullable type. + /// + public static bool IsNullable(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + ParameterizedType pt = type as ParameterizedType; + return pt != null && pt.TypeArguments.Count == 1 && pt.FullName == "System.Nullable"; + } + + /// + /// Returns the element type, if is a nullable type. + /// Otherwise, returns the type itself. + /// + public static IType GetUnderlyingType(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + ParameterizedType pt = type as ParameterizedType; + if (pt != null && pt.TypeArguments.Count == 1 && pt.FullName == "System.Nullable") + return pt.TypeArguments[0]; + else + return type; + } + + /// + /// Creates a nullable type. + /// + public static IType Create(IType elementType, ITypeResolveContext context) + { + if (elementType == null) + throw new ArgumentNullException("elementType"); + if (context == null) + throw new ArgumentNullException("context"); + + ITypeDefinition nullable = context.GetTypeDefinition("System", "Nullable", 1, StringComparer.Ordinal); + if (nullable != null) + return new ParameterizedType(nullable, new [] { elementType }); + else + return SharedTypes.UnknownType; + } + + static readonly ITypeReference NullableReference = new GetClassTypeReference("System", "Nullable", 1); + + /// + /// Creates a nullable type reference. + /// + public static ITypeReference Create(ITypeReference elementType) + { + if (elementType == null) + throw new ArgumentNullException("elementType"); + return new ParameterizedTypeReference(NullableReference, new [] { elementType }); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs new file mode 100644 index 0000000000..e488f6def8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + public sealed class ParameterListComparer : IEqualityComparer + { + public static readonly ParameterListComparer Instance = new ParameterListComparer(); + + public bool Equals(IParameterizedMember x, IParameterizedMember y) + { + var px = x.Parameters; + var py = y.Parameters; + if (px.Count != py.Count) + return false; + for (int i = 0; i < px.Count; i++) { + if (!px[i].Type.Equals(py[i].Type)) + return false; + } + return true; + } + + public int GetHashCode(IParameterizedMember obj) + { + int hashCode = obj.Parameters.Count; + unchecked { + foreach (IParameter p in obj.Parameters) { + hashCode *= 27; + hashCode += p.Type.GetHashCode(); + } + } + return hashCode; + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs new file mode 100644 index 0000000000..a75fb7c217 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -0,0 +1,505 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Text; + +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// ParameterizedType represents an instance of a generic type. + /// Example: List<string> + /// + /// + /// When getting the members, this type modifies the lists so that + /// type parameters in the signatures of the members are replaced with + /// the type arguments. + /// + public sealed class ParameterizedType : Immutable, IType + { + sealed class Substitution : TypeVisitor + { + readonly IType[] typeArguments; + + public Substitution(IType[] typeArguments) + { + this.typeArguments = typeArguments; + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + int index = type.Index; + if (type.OwnerType == EntityType.TypeDefinition) { + if (index >= 0 && index < typeArguments.Length) + return typeArguments[index]; + else + return SharedTypes.UnknownType; + } else { + return base.VisitTypeParameter(type); + } + } + } + + readonly ITypeDefinition genericType; + readonly IType[] typeArguments; + + public ParameterizedType(ITypeDefinition genericType, IEnumerable typeArguments) + { + if (genericType == null) + throw new ArgumentNullException("genericType"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + this.genericType = genericType; + this.typeArguments = typeArguments.ToArray(); // copy input array to ensure it isn't modified + if (this.typeArguments.Length == 0) + throw new ArgumentException("Cannot use ParameterizedType with 0 type arguments."); + if (genericType.TypeParameterCount != this.typeArguments.Length) + throw new ArgumentException("Number of type arguments must match the type definition's number of type parameters"); + for (int i = 0; i < this.typeArguments.Length; i++) { + if (this.typeArguments[i] == null) + throw new ArgumentNullException("typeArguments[" + i + "]"); + } + } + + /// + /// Fast internal version of the constructor. (no safety checks) + /// Keeps the array that was passed and assumes it won't be modified. + /// + internal ParameterizedType(ITypeDefinition genericType, IType[] typeArguments) + { + Debug.Assert(genericType.TypeParameterCount == typeArguments.Length); + this.genericType = genericType; + this.typeArguments = typeArguments; + } + + public bool? IsReferenceType(ITypeResolveContext context) + { + return genericType.IsReferenceType(context); + } + + public IType DeclaringType { + get { + ITypeDefinition declaringTypeDef = genericType.DeclaringTypeDefinition; + if (declaringTypeDef != null && declaringTypeDef.TypeParameterCount > 0) { + IType[] newTypeArgs = new IType[declaringTypeDef.TypeParameterCount]; + Array.Copy(this.typeArguments, 0, newTypeArgs, 0, newTypeArgs.Length); + return new ParameterizedType(declaringTypeDef, newTypeArgs); + } + return declaringTypeDef; + } + } + + public int TypeParameterCount { + get { return genericType.TypeParameterCount; } + } + + public string FullName { + get { return genericType.FullName; } + } + + public string Name { + get { return genericType.Name; } + } + + public string Namespace { + get { return genericType.Namespace;} + } + + public string ReflectionName { + get { + StringBuilder b = new StringBuilder(genericType.ReflectionName); + b.Append('['); + for (int i = 0; i < typeArguments.Length; i++) { + if (i > 0) + b.Append(','); + b.Append('['); + b.Append(typeArguments[i].ReflectionName); + b.Append(']'); + } + b.Append(']'); + return b.ToString(); + } + } + + public override string ToString() + { + return ReflectionName; + } + + public ReadOnlyCollection TypeArguments { + get { + return Array.AsReadOnly(typeArguments); + } + } + + public ITypeDefinition GetDefinition() + { + return genericType; + } + + public IType Resolve(ITypeResolveContext context) + { + return this; + } + + /// + /// Substitutes the class type parameters in the with the + /// type arguments of this parameterized type. + /// + public IType SubstituteInType(IType type) + { + return type.AcceptVisitor(new Substitution(typeArguments)); + } + + /// + /// Gets a type visitor that performs the substitution of class type parameters with the type arguments + /// of this parameterized type. + /// + public TypeVisitor GetSubstitution() + { + return new Substitution(typeArguments); + } + + public IEnumerable GetBaseTypes(ITypeResolveContext context) + { + Substitution substitution = new Substitution(typeArguments); + return genericType.GetBaseTypes(context).Select(t => t.AcceptVisitor(substitution)); + } + + public IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null) + { + /* + class Base { + class Nested {} + } + class Derived : Base {} + + Derived.GetNestedTypes() = { Base`1+Nested } + Derived.GetNestedTypes() = { Base`1+Nested } + Base.GetNestedTypes() = { Base`1+Nested } + Base.GetNestedTypes() = { Base`1+Nested } where T2 = copy of T in Base`1+Nested + */ + Substitution substitution = new Substitution(typeArguments); + List types = genericType.GetNestedTypes(context, filter).ToList(); + for (int i = 0; i < types.Count; i++) { + ITypeDefinition def = types[i] as ITypeDefinition; + if (def != null && def.TypeParameterCount > 0) { + // (partially) parameterize the nested type definition + IType[] newTypeArgs = new IType[def.TypeParameterCount]; + for (int j = 0; j < newTypeArgs.Length; j++) { + if (i < typeArguments.Length) + newTypeArgs[j] = typeArguments[i]; + else + newTypeArgs[j] = def.TypeParameters[j]; + } + types[i] = new ParameterizedType(def, newTypeArgs); + } else { + types[i] = types[i].AcceptVisitor(substitution); + } + } + return types; + } + + public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + List methods = genericType.GetMethods(context, filter).ToList(); + for (int i = 0; i < methods.Count; i++) { + SpecializedMethod m = new SpecializedMethod(methods[i]); + m.SetDeclaringType(this); + m.SubstituteTypes(substitutionFunc); + methods[i] = m; + } + return methods; + } + + public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + List methods = genericType.GetConstructors(context, filter).ToList(); + for (int i = 0; i < methods.Count; i++) { + SpecializedMethod m = new SpecializedMethod(methods[i]); + m.SetDeclaringType(this); + m.SubstituteTypes(substitutionFunc); + methods[i] = m; + } + return methods; + } + + public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + List properties = genericType.GetProperties(context, filter).ToList(); + for (int i = 0; i < properties.Count; i++) { + SpecializedProperty p = new SpecializedProperty(properties[i]); + p.SetDeclaringType(this); + p.SubstituteTypes(substitutionFunc); + properties[i] = p; + } + return properties; + } + + public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + List fields = genericType.GetFields(context, filter).ToList(); + for (int i = 0; i < fields.Count; i++) { + SpecializedField f = new SpecializedField(fields[i]); + f.SetDeclaringType(this); + f.ReturnType = f.ReturnType.Resolve(context).AcceptVisitor(substitution); + fields[i] = f; + } + return fields; + } + + public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + List events = genericType.GetEvents(context, filter).ToList(); + for (int i = 0; i < events.Count; i++) { + SpecializedEvent e = new SpecializedEvent(events[i]); + e.SetDeclaringType(this); + e.ReturnType = e.ReturnType.Resolve(context).AcceptVisitor(substitution); + events[i] = e; + } + return events; + } + + public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + { + Substitution substitution = new Substitution(typeArguments); + Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); + List members = genericType.GetMembers(context, filter).ToList(); + for (int i = 0; i < members.Count; i++) { + members[i] = Specialize(members[i], substitutionFunc); + } + return members; + } + + IMember Specialize(IMember member, Func substitution) + { + IMethod method = member as IMethod; + if (method != null) { + SpecializedMethod m = new SpecializedMethod(method); + m.SetDeclaringType(this); + m.SubstituteTypes(substitution); + return m; + } + IProperty property = member as IProperty; + if (property != null) { + SpecializedProperty p = new SpecializedProperty(property); + p.SetDeclaringType(this); + p.SubstituteTypes(substitution); + return p; + } + IField field = member as IField; + if (field != null) { + SpecializedField f = new SpecializedField(field); + f.SetDeclaringType(this); + f.ReturnType = substitution(f.ReturnType); + return f; + } + IEvent ev = member as IEvent; + if (ev != null) { + SpecializedEvent e = new SpecializedEvent(ev); + e.SetDeclaringType(this); + e.ReturnType = substitution(e.ReturnType); + return e; + } + throw new ArgumentException("Unknown member"); + } + + public override bool Equals(object obj) + { + return Equals(obj as IType); + } + + public bool Equals(IType other) + { + ParameterizedType c = other as ParameterizedType; + if (c == null || !genericType.Equals(c.genericType) || typeArguments.Length != c.typeArguments.Length) + return false; + for (int i = 0; i < typeArguments.Length; i++) { + if (!typeArguments[i].Equals(c.typeArguments[i])) + return false; + } + return true; + } + + public override int GetHashCode() + { + int hashCode = genericType.GetHashCode(); + unchecked { + foreach (var ta in typeArguments) { + hashCode *= 1000000007; + hashCode += 1000000009 * ta.GetHashCode(); + } + } + return hashCode; + } + + public IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitParameterizedType(this); + } + + public IType VisitChildren(TypeVisitor visitor) + { + IType g = genericType.AcceptVisitor(visitor); + ITypeDefinition def = g as ITypeDefinition; + if (def == null) + return g; + // Keep ta == null as long as no elements changed, allocate the array only if necessary. + IType[] ta = (g != genericType) ? new IType[typeArguments.Length] : null; + for (int i = 0; i < typeArguments.Length; i++) { + IType r = typeArguments[i].AcceptVisitor(visitor); + if (r == null) + throw new NullReferenceException("TypeVisitor.Visit-method returned null"); + if (ta == null && r != typeArguments[i]) { + // we found a difference, so we need to allocate the array + ta = new IType[typeArguments.Length]; + for (int j = 0; j < i; j++) { + ta[j] = typeArguments[j]; + } + } + if (ta != null) + ta[i] = r; + } + if (ta == null) + return this; + else + return new ParameterizedType(def, ta); + } + } + + /// + /// ParameterizedTypeReference is a reference to generic class that specifies the type parameters. + /// Example: List<string> + /// + public sealed class ParameterizedTypeReference : ITypeReference, ISupportsInterning + { + public static ITypeReference Create(ITypeReference genericType, IEnumerable typeArguments) + { + if (genericType == null) + throw new ArgumentNullException("genericType"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + + ITypeReference[] typeArgs = typeArguments.ToArray(); + if (typeArgs.Length == 0) { + return genericType; + } else if (genericType is ITypeDefinition && Array.TrueForAll(typeArgs, t => t is IType)) { + IType[] ta = new IType[typeArgs.Length]; + for (int i = 0; i < ta.Length; i++) { + ta[i] = (IType)typeArgs[i]; + } + return new ParameterizedType((ITypeDefinition)genericType, ta); + } else { + return new ParameterizedTypeReference(genericType, typeArgs); + } + } + + ITypeReference genericType; + ITypeReference[] typeArguments; + + public ParameterizedTypeReference(ITypeReference genericType, IEnumerable typeArguments) + { + if (genericType == null) + throw new ArgumentNullException("genericType"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + this.genericType = genericType; + this.typeArguments = typeArguments.ToArray(); + for (int i = 0; i < this.typeArguments.Length; i++) { + if (this.typeArguments[i] == null) + throw new ArgumentNullException("typeArguments[" + i + "]"); + } + } + + public ITypeReference GenericType { + get { return genericType; } + } + + public ReadOnlyCollection TypeArguments { + get { + return Array.AsReadOnly(typeArguments); + } + } + + public IType Resolve(ITypeResolveContext context) + { + ITypeDefinition baseTypeDef = genericType.Resolve(context).GetDefinition(); + if (baseTypeDef == null) + return SharedTypes.UnknownType; + int tpc = baseTypeDef.TypeParameterCount; + if (tpc == 0) + return baseTypeDef; + IType[] resolvedTypes = new IType[tpc]; + for (int i = 0; i < resolvedTypes.Length; i++) { + if (i < typeArguments.Length) + resolvedTypes[i] = typeArguments[i].Resolve(context); + else + resolvedTypes[i] = SharedTypes.UnknownType; + } + return new ParameterizedType(baseTypeDef, resolvedTypes); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(genericType.ToString()); + b.Append('['); + for (int i = 0; i < typeArguments.Length; i++) { + if (i > 0) + b.Append(','); + b.Append('['); + b.Append(typeArguments[i].ToString()); + b.Append(']'); + } + b.Append(']'); + return b.ToString(); + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + genericType = provider.Intern(genericType); + for (int i = 0; i < typeArguments.Length; i++) { + typeArguments[i] = provider.Intern(typeArguments[i]); + } + } + + int ISupportsInterning.GetHashCodeForInterning() + { + int hashCode = genericType.GetHashCode(); + unchecked { + foreach (ITypeReference t in typeArguments) { + hashCode *= 27; + hashCode += t.GetHashCode(); + } + } + return hashCode; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ParameterizedTypeReference o = other as ParameterizedTypeReference; + if (o != null && genericType == o.genericType && typeArguments.Length == o.typeArguments.Length) { + for (int i = 0; i < typeArguments.Length; i++) { + if (typeArguments[i] != o.typeArguments[i]) + return false; + } + return true; + } + return false; + + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs new file mode 100644 index 0000000000..692e814793 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/PointerType.cs @@ -0,0 +1,85 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + public class PointerType : TypeWithElementType + { + public PointerType(IType elementType) : base(elementType) + { + } + + public override string NameSuffix { + get { + return "*"; + } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; + } + + public override int GetHashCode() + { + return elementType.GetHashCode() ^ 91725811; + } + + public override bool Equals(IType other) + { + PointerType a = other as PointerType; + return a != null && elementType.Equals(a.elementType); + } + + public override IType AcceptVisitor(TypeVisitor visitor) + { + return visitor.VisitPointerType(this); + } + + public override IType VisitChildren(TypeVisitor visitor) + { + IType e = elementType.AcceptVisitor(visitor); + if (e == elementType) + return this; + else + return new PointerType(e); + } + } + + public class PointerTypeReference : ITypeReference + { + readonly ITypeReference elementType; + + public PointerTypeReference(ITypeReference elementType) + { + if (elementType == null) + throw new ArgumentNullException("elementType"); + this.elementType = elementType; + } + + public ITypeReference ElementType { + get { return elementType; } + } + + public IType Resolve(ITypeResolveContext context) + { + return new PointerType(elementType.Resolve(context)); + } + + public override string ToString() + { + return elementType.ToString() + "*"; + } + + public static ITypeReference Create(ITypeReference elementType) + { + if (elementType is IType) + return new PointerType((IType)elementType); + else + return new PointerTypeReference(elementType); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs new file mode 100644 index 0000000000..7decbb8004 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs @@ -0,0 +1,411 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Text; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Static helper methods for reflection names. + /// + public static class ReflectionHelper + { + /// + /// A reflection class used to represent null. + /// + public sealed class Null {} + + /// + /// A reflection class used to represent dynamic. + /// + public sealed class Dynamic {} + + #region ITypeResolveContext.GetTypeDefinition(Type) + /// + /// Retrieves a type definition. + /// + /// Returns the type definition; or null if it is not found. + /// + /// This method retrieves the type definition; consider using type.ToTypeReference().Resolve(context) instead + /// if you need an . + /// + public static ITypeDefinition GetTypeDefinition(this ITypeResolveContext context, Type type) + { + if (type == null) + return null; + while (type.IsArray || type.IsPointer || type.IsByRef) + type = type.GetElementType(); + if (type.IsGenericType && !type.IsGenericTypeDefinition) + type = type.GetGenericTypeDefinition(); + if (type.IsGenericParameter) + return null; + if (type.DeclaringType != null) { + ITypeDefinition declaringType = GetTypeDefinition(context, type.DeclaringType); + if (declaringType != null) { + int typeParameterCount; + string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); + typeParameterCount += declaringType.TypeParameterCount; + foreach (ITypeDefinition nestedType in declaringType.NestedTypes) { + if (nestedType.Name == name && nestedType.TypeParameterCount == typeParameterCount) { + return nestedType; + } + } + } + return null; + } else { + int typeParameterCount; + string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); + return context.GetTypeDefinition(type.Namespace, name, typeParameterCount, StringComparer.Ordinal); + } + } + #endregion + + #region Type.ToTypeReference() + /// + /// Creates a reference to the specified type. + /// + /// The type to be converted. + /// The parent entity, used to fetch the ITypeParameter for generic types. + /// Returns the type reference. + public static ITypeReference ToTypeReference(this Type type, IEntity entity = null) + { + if (type == null) + return SharedTypes.UnknownType; + if (type.IsGenericType && !type.IsGenericTypeDefinition) { + ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition(), entity); + Type[] arguments = type.GetGenericArguments(); + ITypeReference[] args = new ITypeReference[arguments.Length]; + for (int i = 0; i < arguments.Length; i++) { + args[i] = ToTypeReference(arguments[i], entity); + } + return new ParameterizedTypeReference(def, args); + } else if (type.IsArray) { + return new ArrayTypeReference(ToTypeReference(type.GetElementType(), entity), type.GetArrayRank()); + } else if (type.IsPointer) { + return new PointerTypeReference(ToTypeReference(type.GetElementType(), entity)); + } else if (type.IsByRef) { + return new ByReferenceTypeReference(ToTypeReference(type.GetElementType(), entity)); + } else if (type.IsGenericParameter) { + if (type.DeclaringMethod != null) { + IMethod method = entity as IMethod; + if (method != null) { + if (type.GenericParameterPosition < method.TypeParameters.Count) { + return method.TypeParameters[type.GenericParameterPosition]; + } + } + return SharedTypes.UnknownType; + } else { + ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); + if (c != null && type.GenericParameterPosition < c.TypeParameters.Count) { + if (c.TypeParameters[type.GenericParameterPosition].Name == type.Name) { + return c.TypeParameters[type.GenericParameterPosition]; + } + } + return SharedTypes.UnknownType; + } + } else if (type.DeclaringType != null) { + if (type == typeof(Dynamic)) + return SharedTypes.Dynamic; + else if (type == typeof(Null)) + return SharedTypes.Null; + ITypeReference baseTypeRef = ToTypeReference(type.DeclaringType, entity); + int typeParameterCount; + string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); + return new NestedTypeReference(baseTypeRef, name, typeParameterCount); + } else { + int typeParameterCount; + string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); + return new GetClassTypeReference(type.Namespace, name, typeParameterCount); + } + } + #endregion + + #region SplitTypeParameterCountFromReflectionName + /// + /// Removes the ` with type parameter count from the reflection name. + /// + /// Do not use this method with the full name of inner classes. + public static string SplitTypeParameterCountFromReflectionName(string reflectionName) + { + int pos = reflectionName.LastIndexOf('`'); + if (pos < 0) { + return reflectionName; + } else { + return reflectionName.Substring(0, pos); + } + } + + /// + /// Removes the ` with type parameter count from the reflection name. + /// + /// Do not use this method with the full name of inner classes. + public static string SplitTypeParameterCountFromReflectionName(string reflectionName, out int typeParameterCount) + { + int pos = reflectionName.LastIndexOf('`'); + if (pos < 0) { + typeParameterCount = 0; + return reflectionName; + } else { + string typeCount = reflectionName.Substring(pos + 1); + if (int.TryParse(typeCount, out typeParameterCount)) + return reflectionName.Substring(0, pos); + else + return reflectionName; + } + } + #endregion + + #region TypeCode.ToTypeReference() + static readonly ITypeReference[] primitiveTypeReferences = { + SharedTypes.UnknownType, // TypeCode.Empty + KnownTypeReference.Object, + new GetClassTypeReference("System", "DBNull", 0), + KnownTypeReference.Boolean, + KnownTypeReference.Char, + KnownTypeReference.SByte, + KnownTypeReference.Byte, + KnownTypeReference.Int16, + KnownTypeReference.UInt16, + KnownTypeReference.Int32, + KnownTypeReference.UInt32, + KnownTypeReference.Int64, + KnownTypeReference.UInt64, + KnownTypeReference.Single, + KnownTypeReference.Double, + new GetClassTypeReference("System", "Decimal", 0), + new GetClassTypeReference("System", "DateTime", 0), + SharedTypes.UnknownType, // (TypeCode)17 has no enum value? + KnownTypeReference.String + }; + + /// + /// Creates a reference to the specified type. + /// + /// The type to be converted. + /// Returns the type reference. + public static ITypeReference ToTypeReference(this TypeCode typeCode) + { + return primitiveTypeReferences[(int)typeCode]; + } + #endregion + + #region GetTypeCode + static readonly Dictionary typeNameToCodeDict = new Dictionary { + { "Object", TypeCode.Object }, + { "DBNull", TypeCode.DBNull }, + { "Boolean", TypeCode.Boolean }, + { "Char", TypeCode.Char }, + { "SByte", TypeCode.SByte }, + { "Byte", TypeCode.Byte }, + { "Int16", TypeCode.Int16 }, + { "UInt16", TypeCode.UInt16 }, + { "Int32", TypeCode.Int32 }, + { "UInt32", TypeCode.UInt32 }, + { "Int64", TypeCode.Int64 }, + { "UInt64", TypeCode.UInt64 }, + { "Single", TypeCode.Single }, + { "Double", TypeCode.Double }, + { "Decimal", TypeCode.Decimal }, + { "DateTime", TypeCode.DateTime }, + { "String", TypeCode.String } + }; + + /// + /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches. + /// + public static TypeCode GetTypeCode(IType type) + { + ITypeDefinition def = type as ITypeDefinition; + TypeCode typeCode; + if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System" && typeNameToCodeDict.TryGetValue(def.Name, out typeCode)) + return typeCode; + else + return TypeCode.Empty; + } + #endregion + + #region ParseReflectionName + /// + /// Parses a reflection name into a type reference. + /// + /// The reflection name of the type. + /// Parent entity, used to find the type parameters for open types. + /// If no entity is provided, type parameters are converted to . + /// The syntax of the reflection type name is invalid + /// A type reference that represents the reflection name. + public static ITypeReference ParseReflectionName(string reflectionTypeName, IEntity parentEntity = null) + { + if (reflectionTypeName == null) + throw new ArgumentNullException("reflectionTypeName"); + int pos = 0; + ITypeReference r = ParseReflectionName(reflectionTypeName, ref pos, parentEntity); + if (pos < reflectionTypeName.Length) + throw new ReflectionNameParseException(pos, "Expected end of type name"); + return r; + } + + static bool IsReflectionNameSpecialCharacter(char c) + { + switch (c) { + case '+': + case '`': + case '[': + case ']': + case ',': + case '*': + case '&': + return true; + default: + return false; + } + } + + static ITypeReference ParseReflectionName(string reflectionTypeName, ref int pos, IEntity entity) + { + if (pos == reflectionTypeName.Length) + throw new ReflectionNameParseException(pos, "Unexpected end"); + if (reflectionTypeName[pos] == '`') { + // type parameter reference + pos++; + if (pos == reflectionTypeName.Length) + throw new ReflectionNameParseException(pos, "Unexpected end"); + if (reflectionTypeName[pos] == '`') { + // method type parameter reference + pos++; + int index = ReadTypeParameterCount(reflectionTypeName, ref pos); + IMethod method = entity as IMethod; + if (method != null && index >= 0 && index < method.TypeParameters.Count) + return method.TypeParameters[index]; + else + return SharedTypes.UnknownType; + } else { + // class type parameter reference + int index = ReadTypeParameterCount(reflectionTypeName, ref pos); + ITypeDefinition c = (entity as ITypeDefinition) ?? (entity != null ? entity.DeclaringTypeDefinition : null); + if (c != null && index >= 0 && index < c.TypeParameters.Count) + return c.TypeParameters[index]; + else + return SharedTypes.UnknownType; + } + } + // not a type parameter reference: read the actual type name + int tpc; + string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); + ITypeReference reference = new GetClassTypeReference(typeName, tpc); + // read type suffixes + while (pos < reflectionTypeName.Length) { + switch (reflectionTypeName[pos++]) { + case '+': + typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); + reference = new NestedTypeReference(reference, typeName, tpc); + break; + case '*': + reference = new PointerTypeReference(reference); + break; + case '&': + reference = new ByReferenceTypeReference(reference); + break; + case '[': + // this might be an array or a generic type + if (pos == reflectionTypeName.Length) + throw new ReflectionNameParseException(pos, "Unexpected end"); + if (reflectionTypeName[pos] == '[') { + // it's a generic type + List typeArguments = new List(tpc); + pos++; + typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') + pos++; + else + throw new ReflectionNameParseException(pos, "Expected end of type argument"); + + while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { + pos++; + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '[') + pos++; + else + throw new ReflectionNameParseException(pos, "Expected another type argument"); + + typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos, entity)); + + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') + pos++; + else + throw new ReflectionNameParseException(pos, "Expected end of type argument"); + } + + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { + pos++; + reference = new ParameterizedTypeReference(reference, typeArguments); + } else { + throw new ReflectionNameParseException(pos, "Expected end of generic type"); + } + } else { + // it's an array + int dimensions = 1; + while (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ',') { + dimensions++; + pos++; + } + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']') { + pos++; // end of array + reference = new ArrayTypeReference(reference, dimensions); + } else { + throw new ReflectionNameParseException(pos, "Invalid array modifier"); + } + } + break; + case ',': + // assembly qualified name, ignore everything up to the end/next ']' + while (pos < reflectionTypeName.Length && reflectionTypeName[pos] != ']') + pos++; + break; + default: + pos--; // reset pos to the character we couldn't read + if (reflectionTypeName[pos] == ']') + return reference; // return from a nested generic + else + throw new ReflectionNameParseException(pos, "Unexpected character: '" + reflectionTypeName[pos] + "'"); + } + } + return reference; + } + + static string ReadTypeName(string reflectionTypeName, ref int pos, out int tpc) + { + int startPos = pos; + // skip the simple name portion: + while (pos < reflectionTypeName.Length && !IsReflectionNameSpecialCharacter(reflectionTypeName[pos])) + pos++; + if (pos == startPos) + throw new ReflectionNameParseException(pos, "Expected type name"); + string typeName = reflectionTypeName.Substring(startPos, pos - startPos); + if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == '`') { + pos++; + tpc = ReadTypeParameterCount(reflectionTypeName, ref pos); + } else { + tpc = 0; + } + return typeName; + } + + static int ReadTypeParameterCount(string reflectionTypeName, ref int pos) + { + int startPos = pos; + while (pos < reflectionTypeName.Length) { + char c = reflectionTypeName[pos]; + if (c < '0' || c > '9') + break; + pos++; + } + int tpc; + if (!int.TryParse(reflectionTypeName.Substring(startPos, pos - startPos), out tpc)) + throw new ReflectionNameParseException(pos, "Expected type parameter count"); + return tpc; + } + #endregion + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs new file mode 100644 index 0000000000..0ef6054272 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs @@ -0,0 +1,45 @@ + +using System; +using System.Runtime.Serialization; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Represents an error while parsing a reflection name. + /// + public class ReflectionNameParseException : Exception + { + int position; + + public int Position { + get { return position; } + } + + public ReflectionNameParseException(int position) + { + this.position = position; + } + + public ReflectionNameParseException(int position, string message) : base(message) + { + this.position = position; + } + + public ReflectionNameParseException(int position, string message, Exception innerException) : base(message, innerException) + { + this.position = position; + } + + // This constructor is needed for serialization. + protected ReflectionNameParseException(SerializationInfo info, StreamingContext context) : base(info, context) + { + position = info.GetInt32("position"); + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + info.AddValue("position", position); + } + } +} \ No newline at end of file diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs new file mode 100644 index 0000000000..f72e5fc15e --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs @@ -0,0 +1,126 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Contains static implementations of well-known types. + /// + public static class SharedTypes + { + /// + /// Gets the type representing resolve errors. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] + public readonly static IType UnknownType = new UnknownTypeImpl(); + + /// + /// The null type is used as type of the null literal. It is a reference type without any members; and it is a subtype of all reference types. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] + public readonly static IType Null = new NullType(); + + /// + /// Type representing the C# 'dynamic' type. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] + public readonly static IType Dynamic = new DynamicType(); + + /* + * I'd like to define static instances for common types like + * void, int, etc.; but there are two problems with this: + * + * SharedTypes.Void.GetDefinition().ProjectContent should return mscorlib, but + * we can't do that without providing a context. + * + * Assuming we add a context parameter to GetDefinition(): + * + * SharedType.Void.Equals(SharedType.Void.GetDefinition(x)) + * SharedType.Void.GetDefinition(y).Equals(SharedType.Void) + * should both return true. + * But if the type can have multiple definitions (multiple mscorlib versions loaded), + * then this is not possible without violating transitivity of Equals(): + * + * SharedType.Void.GetDefinition(x).Equals(SharedType.Void.GetDefinition(y)) + * would have to return true even though these are two distinct definitions. + */ + + /// + /// Type representing resolve errors. + /// + sealed class UnknownTypeImpl : AbstractType + { + public override string Name { + get { return "?"; } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return null; + } + + public override bool Equals(IType other) + { + return other is UnknownTypeImpl; + } + + public override int GetHashCode() + { + return 950772036; + } + } + + /// + /// Type of the 'null' literal. + /// + sealed class NullType : AbstractType + { + public override string Name { + get { return "null"; } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return true; + } + + public override bool Equals(IType other) + { + return other is NullType; + } + + public override int GetHashCode() + { + return 362709548; + } + } + + /// + /// Type representing the C# 'dynamic' type. + /// + sealed class DynamicType : AbstractType + { + public override string Name { + get { return "dynamic"; } + } + + public override bool? IsReferenceType(ITypeResolveContext context) + { + return true; + } + + public override bool Equals(IType other) + { + return other is DynamicType; + } + + public override int GetHashCode() + { + return 31986112; + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs new file mode 100644 index 0000000000..37042842fa --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// Base class for the visitor pattern on . + /// + public abstract class TypeVisitor + { + public virtual IType VisitTypeDefinition(ITypeDefinition type) + { + return type.VisitChildren(this); + } + + public virtual IType VisitTypeParameter(ITypeParameter type) + { + return type.VisitChildren(this); + } + + public virtual IType VisitParameterizedType(ParameterizedType type) + { + return type.VisitChildren(this); + } + + public virtual IType VisitArrayType(ArrayType type) + { + return type.VisitChildren(this); + } + + public virtual IType VisitPointerType(PointerType type) + { + return type.VisitChildren(this); + } + + public virtual IType VisitByReferenceType(ByReferenceType type) + { + return type.VisitChildren(this); + } + + public virtual IType VisitOtherType(IType type) + { + return type.VisitChildren(this); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/BitVector16.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/BitVector16.cs new file mode 100644 index 0000000000..82f4124070 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/BitVector16.cs @@ -0,0 +1,65 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Holds 16 boolean values. + /// + public struct BitVector16 : IEquatable + { + ushort data; + + public bool this[ushort mask] { + get { return (data & mask) != 0; } + set { + if (value) + data |= mask; + else + data &= unchecked((ushort)~mask); + } + } + + public ushort Data { + get { return data; } + set { data = value; } + } + + #region Equals and GetHashCode implementation + public override bool Equals(object obj) + { + if (obj is BitVector16) + return Equals((BitVector16)obj); // use Equals method below + else + return false; + } + + public bool Equals(BitVector16 other) + { + return this.data == other.data; + } + + public override int GetHashCode() + { + return data; + } + + public static bool operator ==(BitVector16 left, BitVector16 right) + { + return left.data == right.data; + } + + public static bool operator !=(BitVector16 left, BitVector16 right) + { + return left.data != right.data; + } + #endregion + + public override string ToString() + { + return data.ToString("x4"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/BusyManager.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/BusyManager.cs new file mode 100644 index 0000000000..c743b7bfd7 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/BusyManager.cs @@ -0,0 +1,55 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// This class is used to prevent stack overflows by representing a 'busy' flag + /// that prevents reentrance when another call is running. + /// However, using a simple 'bool busy' is not thread-safe, so we use a + /// thread-static BusyManager. + /// + static class BusyManager + { + public struct BusyLock : IDisposable + { + public static readonly BusyLock Failed = new BusyLock(null); + + readonly List objectList; + + public BusyLock(List objectList) + { + this.objectList = objectList; + } + + public bool Success { + get { return objectList != null; } + } + + public void Dispose() + { + if (objectList != null) { + objectList.RemoveAt(objectList.Count - 1); + } + } + } + + [ThreadStatic] static List _activeObjects; + + public static BusyLock Enter(object obj) + { + List activeObjects = _activeObjects; + if (activeObjects == null) + activeObjects = _activeObjects = new List(); + for (int i = 0; i < activeObjects.Count; i++) { + if (activeObjects[i] == obj) + return BusyLock.Failed; + } + activeObjects.Add(obj); + return new BusyLock(activeObjects); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs new file mode 100644 index 0000000000..41d9f5bffe --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs @@ -0,0 +1,414 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Static helper method for converting between primitive types. + /// + public static class CSharpPrimitiveCast + { + /// + /// Performs a conversion between primitive types. + /// Unfortunately we cannot use Convert.ChangeType because it has different semantics + /// (e.g. rounding behavior for floats, overflow, etc.), so we write down every possible primitive C# cast + /// and let the compiler figure out the exact semantics. + /// And we have to do everything twice, once in a checked-block, once in an unchecked-block. + /// + public static object Cast(TypeCode targetType, object input, bool checkForOverflow) + { + if (input == null) + return null; + if (checkForOverflow) + return CSharpPrimitiveCastChecked(targetType, input); + else + return CSharpPrimitiveCastUnchecked(targetType, input); + } + + static object CSharpPrimitiveCastChecked(TypeCode targetType, object input) + { + checked { + TypeCode sourceType = Type.GetTypeCode(input.GetType()); + if (sourceType == targetType) + return input; + switch (targetType) { + case TypeCode.Char: + switch (sourceType) { + case TypeCode.SByte: return (char)(sbyte)input; + case TypeCode.Byte: return (char)(byte)input; + case TypeCode.Int16: return (char)(short)input; + case TypeCode.UInt16: return (char)(ushort)input; + case TypeCode.Int32: return (char)(int)input; + case TypeCode.UInt32: return (char)(uint)input; + case TypeCode.Int64: return (char)(long)input; + case TypeCode.UInt64: return (char)(ulong)input; + case TypeCode.Single: return (char)(float)input; + case TypeCode.Double: return (char)(double)input; + case TypeCode.Decimal: return (char)(decimal)input; + } + break; + case TypeCode.SByte: + switch (sourceType) { + case TypeCode.Char: return (sbyte)(char)input; + case TypeCode.Byte: return (sbyte)(byte)input; + case TypeCode.Int16: return (sbyte)(short)input; + case TypeCode.UInt16: return (sbyte)(ushort)input; + case TypeCode.Int32: return (sbyte)(int)input; + case TypeCode.UInt32: return (sbyte)(uint)input; + case TypeCode.Int64: return (sbyte)(long)input; + case TypeCode.UInt64: return (sbyte)(ulong)input; + case TypeCode.Single: return (sbyte)(float)input; + case TypeCode.Double: return (sbyte)(double)input; + case TypeCode.Decimal: return (sbyte)(decimal)input; + } + break; + case TypeCode.Byte: + switch (sourceType) { + case TypeCode.Char: return (byte)(char)input; + case TypeCode.SByte: return (byte)(sbyte)input; + case TypeCode.Int16: return (byte)(short)input; + case TypeCode.UInt16: return (byte)(ushort)input; + case TypeCode.Int32: return (byte)(int)input; + case TypeCode.UInt32: return (byte)(uint)input; + case TypeCode.Int64: return (byte)(long)input; + case TypeCode.UInt64: return (byte)(ulong)input; + case TypeCode.Single: return (byte)(float)input; + case TypeCode.Double: return (byte)(double)input; + case TypeCode.Decimal: return (byte)(decimal)input; + } + break; + case TypeCode.Int16: + switch (sourceType) { + case TypeCode.Char: return (short)(char)input; + case TypeCode.SByte: return (short)(sbyte)input; + case TypeCode.Byte: return (short)(byte)input; + case TypeCode.UInt16: return (short)(ushort)input; + case TypeCode.Int32: return (short)(int)input; + case TypeCode.UInt32: return (short)(uint)input; + case TypeCode.Int64: return (short)(long)input; + case TypeCode.UInt64: return (short)(ulong)input; + case TypeCode.Single: return (short)(float)input; + case TypeCode.Double: return (short)(double)input; + case TypeCode.Decimal: return (short)(decimal)input; + } + break; + case TypeCode.UInt16: + switch (sourceType) { + case TypeCode.Char: return (ushort)(char)input; + case TypeCode.SByte: return (ushort)(sbyte)input; + case TypeCode.Byte: return (ushort)(byte)input; + case TypeCode.Int16: return (ushort)(short)input; + case TypeCode.Int32: return (ushort)(int)input; + case TypeCode.UInt32: return (ushort)(uint)input; + case TypeCode.Int64: return (ushort)(long)input; + case TypeCode.UInt64: return (ushort)(ulong)input; + case TypeCode.Single: return (ushort)(float)input; + case TypeCode.Double: return (ushort)(double)input; + case TypeCode.Decimal: return (ushort)(decimal)input; + } + break; + case TypeCode.Int32: + switch (sourceType) { + case TypeCode.Char: return (int)(char)input; + case TypeCode.SByte: return (int)(sbyte)input; + case TypeCode.Byte: return (int)(byte)input; + case TypeCode.Int16: return (int)(short)input; + case TypeCode.UInt16: return (int)(ushort)input; + case TypeCode.UInt32: return (int)(uint)input; + case TypeCode.Int64: return (int)(long)input; + case TypeCode.UInt64: return (int)(ulong)input; + case TypeCode.Single: return (int)(float)input; + case TypeCode.Double: return (int)(double)input; + case TypeCode.Decimal: return (int)(decimal)input; + } + break; + case TypeCode.UInt32: + switch (sourceType) { + case TypeCode.Char: return (uint)(char)input; + case TypeCode.SByte: return (uint)(sbyte)input; + case TypeCode.Byte: return (uint)(byte)input; + case TypeCode.Int16: return (uint)(short)input; + case TypeCode.UInt16: return (uint)(ushort)input; + case TypeCode.Int32: return (uint)(int)input; + case TypeCode.Int64: return (uint)(long)input; + case TypeCode.UInt64: return (uint)(ulong)input; + case TypeCode.Single: return (uint)(float)input; + case TypeCode.Double: return (uint)(double)input; + case TypeCode.Decimal: return (uint)(decimal)input; + } + break; + case TypeCode.Int64: + switch (sourceType) { + case TypeCode.Char: return (long)(char)input; + case TypeCode.SByte: return (long)(sbyte)input; + case TypeCode.Byte: return (long)(byte)input; + case TypeCode.Int16: return (long)(short)input; + case TypeCode.UInt16: return (long)(ushort)input; + case TypeCode.Int32: return (long)(int)input; + case TypeCode.UInt32: return (long)(uint)input; + case TypeCode.UInt64: return (long)(ulong)input; + case TypeCode.Single: return (long)(float)input; + case TypeCode.Double: return (long)(double)input; + case TypeCode.Decimal: return (long)(decimal)input; + } + break; + case TypeCode.UInt64: + switch (sourceType) { + case TypeCode.Char: return (ulong)(char)input; + case TypeCode.SByte: return (ulong)(sbyte)input; + case TypeCode.Byte: return (ulong)(byte)input; + case TypeCode.Int16: return (ulong)(short)input; + case TypeCode.UInt16: return (ulong)(ushort)input; + case TypeCode.Int32: return (ulong)(int)input; + case TypeCode.UInt32: return (ulong)(uint)input; + case TypeCode.Int64: return (ulong)(long)input; + case TypeCode.Single: return (ulong)(float)input; + case TypeCode.Double: return (ulong)(double)input; + case TypeCode.Decimal: return (ulong)(decimal)input; + } + break; + case TypeCode.Single: + switch (sourceType) { + case TypeCode.Char: return (float)(char)input; + case TypeCode.SByte: return (float)(sbyte)input; + case TypeCode.Byte: return (float)(byte)input; + case TypeCode.Int16: return (float)(short)input; + case TypeCode.UInt16: return (float)(ushort)input; + case TypeCode.Int32: return (float)(int)input; + case TypeCode.UInt32: return (float)(uint)input; + case TypeCode.Int64: return (float)(long)input; + case TypeCode.UInt64: return (float)(ulong)input; + case TypeCode.Double: return (float)(double)input; + case TypeCode.Decimal: return (float)(decimal)input; + } + break; + case TypeCode.Double: + switch (sourceType) { + case TypeCode.Char: return (double)(char)input; + case TypeCode.SByte: return (double)(sbyte)input; + case TypeCode.Byte: return (double)(byte)input; + case TypeCode.Int16: return (double)(short)input; + case TypeCode.UInt16: return (double)(ushort)input; + case TypeCode.Int32: return (double)(int)input; + case TypeCode.UInt32: return (double)(uint)input; + case TypeCode.Int64: return (double)(long)input; + case TypeCode.UInt64: return (double)(ulong)input; + case TypeCode.Single: return (double)(float)input; + case TypeCode.Decimal: return (double)(decimal)input; + } + break; + case TypeCode.Decimal: + switch (sourceType) { + case TypeCode.Char: return (decimal)(char)input; + case TypeCode.SByte: return (decimal)(sbyte)input; + case TypeCode.Byte: return (decimal)(byte)input; + case TypeCode.Int16: return (decimal)(short)input; + case TypeCode.UInt16: return (decimal)(ushort)input; + case TypeCode.Int32: return (decimal)(int)input; + case TypeCode.UInt32: return (decimal)(uint)input; + case TypeCode.Int64: return (decimal)(long)input; + case TypeCode.UInt64: return (decimal)(ulong)input; + case TypeCode.Single: return (decimal)(float)input; + case TypeCode.Double: return (decimal)(double)input; + } + break; + } + throw new InvalidCastException("Cast from " + sourceType + " to " + targetType + "not supported."); + } + } + + static object CSharpPrimitiveCastUnchecked(TypeCode targetType, object input) + { + unchecked { + TypeCode sourceType = Type.GetTypeCode(input.GetType()); + if (sourceType == targetType) + return input; + switch (targetType) { + case TypeCode.Char: + switch (sourceType) { + case TypeCode.SByte: return (char)(sbyte)input; + case TypeCode.Byte: return (char)(byte)input; + case TypeCode.Int16: return (char)(short)input; + case TypeCode.UInt16: return (char)(ushort)input; + case TypeCode.Int32: return (char)(int)input; + case TypeCode.UInt32: return (char)(uint)input; + case TypeCode.Int64: return (char)(long)input; + case TypeCode.UInt64: return (char)(ulong)input; + case TypeCode.Single: return (char)(float)input; + case TypeCode.Double: return (char)(double)input; + case TypeCode.Decimal: return (char)(decimal)input; + } + break; + case TypeCode.SByte: + switch (sourceType) { + case TypeCode.Char: return (sbyte)(char)input; + case TypeCode.Byte: return (sbyte)(byte)input; + case TypeCode.Int16: return (sbyte)(short)input; + case TypeCode.UInt16: return (sbyte)(ushort)input; + case TypeCode.Int32: return (sbyte)(int)input; + case TypeCode.UInt32: return (sbyte)(uint)input; + case TypeCode.Int64: return (sbyte)(long)input; + case TypeCode.UInt64: return (sbyte)(ulong)input; + case TypeCode.Single: return (sbyte)(float)input; + case TypeCode.Double: return (sbyte)(double)input; + case TypeCode.Decimal: return (sbyte)(decimal)input; + } + break; + case TypeCode.Byte: + switch (sourceType) { + case TypeCode.Char: return (byte)(char)input; + case TypeCode.SByte: return (byte)(sbyte)input; + case TypeCode.Int16: return (byte)(short)input; + case TypeCode.UInt16: return (byte)(ushort)input; + case TypeCode.Int32: return (byte)(int)input; + case TypeCode.UInt32: return (byte)(uint)input; + case TypeCode.Int64: return (byte)(long)input; + case TypeCode.UInt64: return (byte)(ulong)input; + case TypeCode.Single: return (byte)(float)input; + case TypeCode.Double: return (byte)(double)input; + case TypeCode.Decimal: return (byte)(decimal)input; + } + break; + case TypeCode.Int16: + switch (sourceType) { + case TypeCode.Char: return (short)(char)input; + case TypeCode.SByte: return (short)(sbyte)input; + case TypeCode.Byte: return (short)(byte)input; + case TypeCode.UInt16: return (short)(ushort)input; + case TypeCode.Int32: return (short)(int)input; + case TypeCode.UInt32: return (short)(uint)input; + case TypeCode.Int64: return (short)(long)input; + case TypeCode.UInt64: return (short)(ulong)input; + case TypeCode.Single: return (short)(float)input; + case TypeCode.Double: return (short)(double)input; + case TypeCode.Decimal: return (short)(decimal)input; + } + break; + case TypeCode.UInt16: + switch (sourceType) { + case TypeCode.Char: return (ushort)(char)input; + case TypeCode.SByte: return (ushort)(sbyte)input; + case TypeCode.Byte: return (ushort)(byte)input; + case TypeCode.Int16: return (ushort)(short)input; + case TypeCode.Int32: return (ushort)(int)input; + case TypeCode.UInt32: return (ushort)(uint)input; + case TypeCode.Int64: return (ushort)(long)input; + case TypeCode.UInt64: return (ushort)(ulong)input; + case TypeCode.Single: return (ushort)(float)input; + case TypeCode.Double: return (ushort)(double)input; + case TypeCode.Decimal: return (ushort)(decimal)input; + } + break; + case TypeCode.Int32: + switch (sourceType) { + case TypeCode.Char: return (int)(char)input; + case TypeCode.SByte: return (int)(sbyte)input; + case TypeCode.Byte: return (int)(byte)input; + case TypeCode.Int16: return (int)(short)input; + case TypeCode.UInt16: return (int)(ushort)input; + case TypeCode.UInt32: return (int)(uint)input; + case TypeCode.Int64: return (int)(long)input; + case TypeCode.UInt64: return (int)(ulong)input; + case TypeCode.Single: return (int)(float)input; + case TypeCode.Double: return (int)(double)input; + case TypeCode.Decimal: return (int)(decimal)input; + } + break; + case TypeCode.UInt32: + switch (sourceType) { + case TypeCode.Char: return (uint)(char)input; + case TypeCode.SByte: return (uint)(sbyte)input; + case TypeCode.Byte: return (uint)(byte)input; + case TypeCode.Int16: return (uint)(short)input; + case TypeCode.UInt16: return (uint)(ushort)input; + case TypeCode.Int32: return (uint)(int)input; + case TypeCode.Int64: return (uint)(long)input; + case TypeCode.UInt64: return (uint)(ulong)input; + case TypeCode.Single: return (uint)(float)input; + case TypeCode.Double: return (uint)(double)input; + case TypeCode.Decimal: return (uint)(decimal)input; + } + break; + case TypeCode.Int64: + switch (sourceType) { + case TypeCode.Char: return (long)(char)input; + case TypeCode.SByte: return (long)(sbyte)input; + case TypeCode.Byte: return (long)(byte)input; + case TypeCode.Int16: return (long)(short)input; + case TypeCode.UInt16: return (long)(ushort)input; + case TypeCode.Int32: return (long)(int)input; + case TypeCode.UInt32: return (long)(uint)input; + case TypeCode.UInt64: return (long)(ulong)input; + case TypeCode.Single: return (long)(float)input; + case TypeCode.Double: return (long)(double)input; + case TypeCode.Decimal: return (long)(decimal)input; + } + break; + case TypeCode.UInt64: + switch (sourceType) { + case TypeCode.Char: return (ulong)(char)input; + case TypeCode.SByte: return (ulong)(sbyte)input; + case TypeCode.Byte: return (ulong)(byte)input; + case TypeCode.Int16: return (ulong)(short)input; + case TypeCode.UInt16: return (ulong)(ushort)input; + case TypeCode.Int32: return (ulong)(int)input; + case TypeCode.UInt32: return (ulong)(uint)input; + case TypeCode.Int64: return (ulong)(long)input; + case TypeCode.Single: return (ulong)(float)input; + case TypeCode.Double: return (ulong)(double)input; + case TypeCode.Decimal: return (ulong)(decimal)input; + } + break; + case TypeCode.Single: + switch (sourceType) { + case TypeCode.Char: return (float)(char)input; + case TypeCode.SByte: return (float)(sbyte)input; + case TypeCode.Byte: return (float)(byte)input; + case TypeCode.Int16: return (float)(short)input; + case TypeCode.UInt16: return (float)(ushort)input; + case TypeCode.Int32: return (float)(int)input; + case TypeCode.UInt32: return (float)(uint)input; + case TypeCode.Int64: return (float)(long)input; + case TypeCode.UInt64: return (float)(ulong)input; + case TypeCode.Double: return (float)(double)input; + case TypeCode.Decimal: return (float)(decimal)input; + } + break; + case TypeCode.Double: + switch (sourceType) { + case TypeCode.Char: return (double)(char)input; + case TypeCode.SByte: return (double)(sbyte)input; + case TypeCode.Byte: return (double)(byte)input; + case TypeCode.Int16: return (double)(short)input; + case TypeCode.UInt16: return (double)(ushort)input; + case TypeCode.Int32: return (double)(int)input; + case TypeCode.UInt32: return (double)(uint)input; + case TypeCode.Int64: return (double)(long)input; + case TypeCode.UInt64: return (double)(ulong)input; + case TypeCode.Single: return (double)(float)input; + case TypeCode.Decimal: return (double)(decimal)input; + } + break; + case TypeCode.Decimal: + switch (sourceType) { + case TypeCode.Char: return (decimal)(char)input; + case TypeCode.SByte: return (decimal)(sbyte)input; + case TypeCode.Byte: return (decimal)(byte)input; + case TypeCode.Int16: return (decimal)(short)input; + case TypeCode.UInt16: return (decimal)(ushort)input; + case TypeCode.Int32: return (decimal)(int)input; + case TypeCode.UInt32: return (decimal)(uint)input; + case TypeCode.Int64: return (decimal)(long)input; + case TypeCode.UInt64: return (decimal)(ulong)input; + case TypeCode.Single: return (decimal)(float)input; + case TypeCode.Double: return (decimal)(double)input; + } + break; + } + throw new InvalidCastException("Cast from " + sourceType + " to " + targetType + " not supported."); + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/CacheManager.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/CacheManager.cs new file mode 100644 index 0000000000..bfb05248e8 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/CacheManager.cs @@ -0,0 +1,137 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Threading; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Allows the registration of static "caching types" which can then be used to efficiently retrieve an + /// instance per CacheManager (or even per CacheManager and thread). + /// + /// This class is thread-safe + public sealed class CacheManager : IDisposable + { + /* Lots of code commented out because I don't know if it's useful, clients can usually replicate + * the functionality much more easily and only need the Disposed event to ensure cleanup. + * + * Actually, what I've implemented here looks very much like .NET's internal System.LocalDataStore + * (used for Thread.GetData/SetData) + * + static int nextSharedIndex, nextThreadLocalIndex; + + /// + /// Registers a new cache type. This causes each CacheManager to allocate space for the new cache type. + /// + /// Specifies whether this cache is shared (multi-threaded) or whether + /// there is one instance per thread. + /// Returns a token that can be used to access the cache. + public static CacheToken RegisterType(CacheMode mode) where T : class, new() + { + int index; + switch (mode) { + case CacheMode.Shared: + index = Interlocked.Increment(ref nextSharedIndex); + break; + case CacheMode.ThreadLocal: + index = Interlocked.Increment(ref nextThreadLocalIndex); + break; + default: + throw new ArgumentException("Invalid value for CacheMode", "mode"); + } + return new CacheToken(mode, index); + } + + readonly object lockObj = new object(); + volatile object[] _sharedCaches = new object[nextSharedIndex]; + ThreadLocal threadLocalCaches = new ThreadLocal(() => new object[nextThreadLocalIndex]); + + /// + /// Gets the cache using the specified token. + /// + public T Get(CacheToken token) where T : class, new() + { + switch (token.Mode) { + case CacheMode.Shared: + object[] sharedCaches = this._sharedCaches; + if (token.Index < sharedCaches.Length) { + object c = sharedCaches[token.Index]; + if (c != null) + return (T)c; + } + // it seems like the cache doesn't exist yet, so try to create it: + T newCache = new T(); + lock (lockObj) { + sharedCaches = this._sharedCaches; // fetch fresh value after locking + // use double-checked locking + if (token.Index < sharedCaches.Length) { + object c = sharedCaches[token.Index]; + if (c != null) { + // looks like someone else was faster creating it than this thread + return (T)c; + } + } else { + Array.Resize(ref sharedCaches, nextSharedIndex); + this._sharedCaches = sharedCaches; + } + sharedCaches[token.Index] = newCache; + } + return newCache; + case CacheMode.ThreadLocal: + object[] localCaches = threadLocalCaches.Value; + if (token.Index >= localCaches.Length) { + Array.Resize(ref localCaches, nextThreadLocalIndex); + threadLocalCaches.Value = localCaches; + } + object lc = localCaches[token.Index]; + if (lc != null) { + return (T)lc; + } else { + T newLocalCache = new T(); + localCaches[token.Index] = newLocalCache; + return newLocalCache; + } + default: + throw new ArgumentException("Invalid token"); + } + } + */ + + public event EventHandler Disposed; + + /// + /// Invokes the event. + /// + public void Dispose() + { + //threadLocalCaches.Dispose(); // dispose the ThreadLocal + // TODO: test whether this frees the referenced value on all threads + + // fire Disposed() only once by removing the old event handlers + EventHandler disposed = Interlocked.Exchange(ref Disposed, null); + if (disposed != null) + disposed(this, EventArgs.Empty); + } + } + + /* + public enum CacheMode + { + // don't use 0 so that default(CacheToken<...>) is an invalid mode + Shared = 1, + ThreadLocal = 2 + } + + public struct CacheToken where T : class, new() + { + internal readonly CacheMode Mode; + internal readonly int Index; + + internal CacheToken(CacheMode mode, int index) + { + this.Mode = mode; + this.Index = index; + } + }*/ +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs new file mode 100644 index 0000000000..df2a58dea0 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs @@ -0,0 +1,58 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +internal static class DotNet35Compat +{ + public static string StringJoin(string separator, IEnumerable elements) + { + #if DOTNET35 + return string.Join(separator, elements.Select(e => e != null ? e.ToString() : null).ToArray()); + #else + return string.Join(separator, elements); + #endif + } + + public static IEnumerable SafeCast(this IEnumerable elements) where T : class, U where U : class + { + #if DOTNET35 + foreach (T item in elements) + yield return item; + #else + return elements; + #endif + } + + public static Predicate SafeCast(this Predicate predicate) where U : class, T where T : class + { + #if DOTNET35 + return e => predicate(e); + #else + return predicate; + #endif + } + + #if DOTNET35 + public static IEnumerable Zip(this IEnumerable input1, IEnumerable input2, Func f) + { + using (var e1 = input1.GetEnumerator()) + using (var e2 = input2.GetEnumerator()) + while (e1.MoveNext() && e2.MoveNext()) + yield return f(e1.Current, e2.Current); + } + #endif +} + +#if DOTNET35 +namespace System.Diagnostics.Contracts { } +namespace System.Threading +{ + internal struct CancellationToken + { + public void ThrowIfCancellationRequested() {} + } +} +#endif diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/EmptyList.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/EmptyList.cs new file mode 100644 index 0000000000..da4ac74a49 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/EmptyList.cs @@ -0,0 +1,13 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.ObjectModel; + +namespace ICSharpCode.NRefactory +{ + static class EmptyList + { + public static readonly ReadOnlyCollection Instance = new ReadOnlyCollection(new T[0]); + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs new file mode 100644 index 0000000000..d720ba16f3 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs @@ -0,0 +1,20 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Contains extension methods for use within NRefactory. + /// + internal static class ExtensionMethods + { + public static void AddRange(this ICollection target, IEnumerable input) + { + foreach (T item in input) + target.Add(item); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs new file mode 100644 index 0000000000..2bf93c353f --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs @@ -0,0 +1,204 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text.RegularExpressions; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// GraphViz graph. + /// + public sealed class GraphVizGraph + { + List nodes = new List(); + List edges = new List(); + + public string rankdir; + public string Title; + + public void AddEdge(GraphVizEdge edge) + { + edges.Add(edge); + } + + public void AddNode(GraphVizNode node) + { + nodes.Add(node); + } + + public void Save(string fileName) + { + using (StreamWriter writer = new StreamWriter(fileName)) + Save(writer); + } + + public void Show() + { + Show(null); + } + + public void Show(string name) + { + if (name == null) + name = Title; + if (name != null) + foreach (char c in Path.GetInvalidFileNameChars()) + name = name.Replace(c, '-'); + string fileName = name != null ? Path.Combine(Path.GetTempPath(), name) : Path.GetTempFileName(); + Save(fileName + ".gv"); + Process.Start("dot", "\"" + fileName + ".gv\" -Tpng -o \"" + fileName + ".png\"").WaitForExit(); + Process.Start(fileName + ".png"); + } + + static string Escape(string text) + { + if (Regex.IsMatch(text, @"^[\w\d]+$")) { + return text; + } else { + return "\"" + text.Replace("\\", "\\\\").Replace("\r", "").Replace("\n", "\\n").Replace("\"", "\\\"") + "\""; + } + } + + static void WriteGraphAttribute(TextWriter writer, string name, string value) + { + if (value != null) + writer.WriteLine("{0}={1};", name, Escape(value)); + } + + internal static void WriteAttribute(TextWriter writer, string name, double? value, ref bool isFirst) + { + if (value != null) { + WriteAttribute(writer, name, value.Value.ToString(CultureInfo.InvariantCulture), ref isFirst); + } + } + + internal static void WriteAttribute(TextWriter writer, string name, bool? value, ref bool isFirst) + { + if (value != null) { + WriteAttribute(writer, name, value.Value ? "true" : "false", ref isFirst); + } + } + + internal static void WriteAttribute(TextWriter writer, string name, string value, ref bool isFirst) + { + if (value != null) { + if (isFirst) + isFirst = false; + else + writer.Write(','); + writer.Write("{0}={1}", name, Escape(value)); + } + } + + public void Save(TextWriter writer) + { + if (writer == null) + throw new ArgumentNullException("writer"); + writer.WriteLine("digraph G {"); + writer.WriteLine("node [fontsize = 16];"); + WriteGraphAttribute(writer, "rankdir", rankdir); + foreach (GraphVizNode node in nodes) { + node.Save(writer); + } + foreach (GraphVizEdge edge in edges) { + edge.Save(writer); + } + writer.WriteLine("}"); + } + } + + public sealed class GraphVizEdge + { + public readonly string Source, Target; + + /// edge stroke color + public string color; + /// use edge to affect node ranking + public bool? constraint; + + public string label; + + public string style; + + /// point size of label + public int? fontsize; + + public GraphVizEdge(string source, string target) + { + if (source == null) + throw new ArgumentNullException("source"); + if (target == null) + throw new ArgumentNullException("target"); + this.Source = source; + this.Target = target; + } + + public GraphVizEdge(int source, int target) + { + this.Source = source.ToString(CultureInfo.InvariantCulture); + this.Target = target.ToString(CultureInfo.InvariantCulture); + } + + public void Save(TextWriter writer) + { + writer.Write("{0} -> {1} [", Source, Target); + bool isFirst = true; + GraphVizGraph.WriteAttribute(writer, "label", label, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "style", style, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "fontsize", fontsize, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "color", color, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "constraint", constraint, ref isFirst); + writer.WriteLine("];"); + } + } + + public sealed class GraphVizNode + { + public readonly string ID; + public string label; + + public string labelloc; + + /// point size of label + public int? fontsize; + + /// minimum height in inches + public double? height; + + /// space around label + public string margin; + + /// node shape + public string shape; + + public GraphVizNode(string id) + { + if (id == null) + throw new ArgumentNullException("id"); + this.ID = id; + } + + public GraphVizNode(int id) + { + this.ID = id.ToString(CultureInfo.InvariantCulture); + } + + public void Save(TextWriter writer) + { + writer.Write(ID); + writer.Write(" ["); + bool isFirst = true; + GraphVizGraph.WriteAttribute(writer, "label", label, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "labelloc", labelloc, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "fontsize", fontsize, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "margin", margin, ref isFirst); + GraphVizGraph.WriteAttribute(writer, "shape", shape, ref isFirst); + writer.WriteLine("];"); + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/Platform.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/Platform.cs new file mode 100644 index 0000000000..1e512330d4 --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/Platform.cs @@ -0,0 +1,25 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Platform-specific code. + /// + static class Platform + { + public static StringComparer FileNameComparer { + get { + switch (Environment.OSVersion.Platform) { + case PlatformID.Unix: + case PlatformID.MacOSX: + return StringComparer.Ordinal; + default: + return StringComparer.OrdinalIgnoreCase; + } + } + } + } +} diff --git a/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/TreeTraversal.cs b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/TreeTraversal.cs new file mode 100644 index 0000000000..4e1b238acc --- /dev/null +++ b/src/Libraries/NRefactory/ICSharpCode.NRefactory/Utils/TreeTraversal.cs @@ -0,0 +1,97 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// Static helper methods for traversing trees. + /// + public static class TreeTraversal + { + /// + /// Converts a tree data structure into a flat list by traversing it in pre-order. + /// + /// The root element of the tree. + /// The function that gets the children of an element. + /// Iterator that enumerates the tree structure in pre-order. + public static IEnumerable PreOrder(T root, Func> recursion) + { + return PreOrder(new T[] { root }, recursion); + } + + /// + /// Converts a tree data structure into a flat list by traversing it in pre-order. + /// + /// The root elements of the forest. + /// The function that gets the children of an element. + /// Iterator that enumerates the tree structure in pre-order. + public static IEnumerable PreOrder(IEnumerable input, Func> recursion) + { + Stack> stack = new Stack>(); + try { + stack.Push(input.GetEnumerator()); + while (stack.Count > 0) { + while (stack.Peek().MoveNext()) { + T element = stack.Peek().Current; + yield return element; + IEnumerable children = recursion(element); + if (children != null) { + stack.Push(children.GetEnumerator()); + } + } + stack.Pop().Dispose(); + } + } finally { + while (stack.Count > 0) { + stack.Pop().Dispose(); + } + } + } + + /// + /// Converts a tree data structure into a flat list by traversing it in post-order. + /// + /// The root element of the tree. + /// The function that gets the children of an element. + /// Iterator that enumerates the tree structure in post-order. + public static IEnumerable PostOrder(T root, Func> recursion) + { + return PostOrder(new T[] { root }, recursion); + } + + /// + /// Converts a tree data structure into a flat list by traversing it in post-order. + /// + /// The root elements of the forest. + /// The function that gets the children of an element. + /// Iterator that enumerates the tree structure in post-order. + public static IEnumerable PostOrder(IEnumerable input, Func> recursion) + { + Stack> stack = new Stack>(); + try { + stack.Push(input.GetEnumerator()); + while (stack.Count > 0) { + while (stack.Peek().MoveNext()) { + T element = stack.Peek().Current; + IEnumerable children = recursion(element); + if (children != null) { + stack.Push(children.GetEnumerator()); + } else { + yield return element; + } + } + stack.Pop().Dispose(); + if (stack.Count > 0) + yield return stack.Peek().Current; + } + } finally { + while (stack.Count > 0) { + stack.Pop().Dispose(); + } + } + } + } +} diff --git a/src/Libraries/NRefactory/NRefactory.sln b/src/Libraries/NRefactory/NRefactory.sln new file mode 100644 index 0000000000..baf2f03d50 --- /dev/null +++ b/src/Libraries/NRefactory/NRefactory.sln @@ -0,0 +1,85 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +# SharpDevelop 4.1.0.7590-alpha +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC98210E-1646-483B-819A-2BB8272461E4}" + ProjectSection(SolutionItems) = postProject + README = README + doc\TODO = doc\TODO + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory", "ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj", "{3B2A5653-EC97-4001-BB9B-D90F1AF2C371}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Tests", "ICSharpCode.NRefactory.Tests\ICSharpCode.NRefactory.Tests.csproj", "{63D3B27A-D966-4902-90B3-30290E1692F1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.VB", "ICSharpCode.NRefactory.VB\ICSharpCode.NRefactory.VB.csproj", "{7B82B671-419F-45F4-B778-D9286F996EFA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.VB.Tests", "ICSharpCode.NRefactory.VB.Tests\ICSharpCode.NRefactory.VB.Tests.csproj", "{870115DD-960A-4406-A6B9-600BCDC36A03}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "..\Mono.Cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Demo", "ICSharpCode.NRefactory.Demo\ICSharpCode.NRefactory.Demo.csproj", "{9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Editor", "ICSharpCode.Editor\ICSharpCode.Editor.csproj", "{F054A788-B591-4561-A8BA-AE745BBEB817}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.Build.0 = Release|Any CPU + {63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63D3B27A-D966-4902-90B3-30290E1692F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {63D3B27A-D966-4902-90B3-30290E1692F1}.Release|Any CPU.Build.0 = Release|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|Any CPU.Build.0 = Debug|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|Any CPU.ActiveCfg = Debug|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|x86.Build.0 = Debug|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|x86.ActiveCfg = Debug|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|Any CPU.Build.0 = Release|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|Any CPU.ActiveCfg = Release|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|x86.Build.0 = Release|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|x86.ActiveCfg = Release|x86 + {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|Any CPU.Build.0 = Debug|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|x86.Build.0 = Debug|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|x86.ActiveCfg = Debug|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|Any CPU.Build.0 = Release|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|Any CPU.ActiveCfg = Release|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|x86.Build.0 = Release|Any CPU + {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|x86.ActiveCfg = Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_3_5_Release|Any CPU + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|Any CPU.Build.0 = Debug|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|Any CPU.ActiveCfg = Debug|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|x86.Build.0 = Debug|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|x86.ActiveCfg = Debug|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|Any CPU.Build.0 = Release|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|Any CPU.ActiveCfg = Release|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|x86.Build.0 = Release|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|x86.ActiveCfg = Release|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|Any CPU.Build.0 = Debug|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|Any CPU.ActiveCfg = Debug|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|x86.Build.0 = Debug|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|x86.ActiveCfg = Debug|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|Any CPU.Build.0 = Release|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|Any CPU.ActiveCfg = Release|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|x86.Build.0 = Release|x86 + {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|x86.ActiveCfg = Release|x86 + EndGlobalSection + GlobalSection(MonoDevelopProperties) = preSolution + StartupItem = ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj + EndGlobalSection +EndGlobal diff --git a/src/Libraries/NRefactory/README b/src/Libraries/NRefactory/README new file mode 100644 index 0000000000..4c6a493aa3 --- /dev/null +++ b/src/Libraries/NRefactory/README @@ -0,0 +1,229 @@ +Overview of the NRefactory library: + +ICSharpCode.Editor: + Interfaces that abstract from the text editor control used. + Maybe future AvalonEdit versions will directly implement these interfaces, but you could also write adapters for other editors. + +ICSharpCode.NRefactory.TypeSystem: + Contains a language-independent representation of the .NET type system. + +ICSharpCode.NRefactory.TypeSystem.Implementation: + Contains base classes that help implementing the type system interfaces. + +ICSharpCode.NRefactory.CSharp.Ast: + Abstract Syntax Tree for C# + +ICSharpCode.NRefactory.CSharp.Resolver: + Semantic analysis for C# (resolving the meaning of expressions) + +ICSharpCode.NRefactory.CSharp.Analysis: + Semantic analysis for C# (additional analysis functionality) + +ICSharpCode.NRefactory.Documentation: + Classes for working with .xml documentation files. + +ICSharpCode.NRefactory.PatternMatching: + Provides classes for pattern matching over the C# and VB ASTs. + +ICSharpCode.NRefactory.Util: + Various helper classes. + +ICSharpCode.NRefactory.VB.Ast: (in the separate ICSharpCode.NRefactory.VB assembly) + Abstract Syntax Tree for VB + +Dependencies: + .NET 3.5 or .NET 4.0 + Mono.Cecil 0.9.4 + +Null-Object pattern: + The NRefactory library makes extensive use of the null object pattern. + As a result, NullReferenceExceptions should be very rare when working with this library. + In the type system, both ITypeReference and IType use SharedTypes.UnknownType to represent + unknown types. + Unless the method is documented otherwise, no method or property returning a ITypeReference or + IType will return null. + When adding to this library, to try to keep such uses of null rare. + + Note that the null object pattern is not used for ITypeDefinition: + IProjectContent.GetClass() returns null when a type is not found. Take care to abort your + operation or substitute UnknownType instead of passing the null to code expecting an IType. + + The pattern also extends to the C# resolver, which always produces a ResolveResult, even in + error cases. Use ResolveResult.IsError to detect resolver errors. + Also note that many resolver errors still have a meaningful type attached, this allows code + completion to work in the presence of minor semantic errors. + + The C# AST makes use of special null nodes when accessing the getter of an AST property and no + child node with that role exists. Check the IsNull property to test whether a node is a null node. + Null nodes are not considered to be part of the AST (e.g. they don't have a parent). + +FAQ: +Q: What is the difference between types and type definitions? + +A: Basically, a type (IType) is any type in the .NET type system: + - an array (ArrayType) + - a pointer (PointerType) + - a managed reference (ByReferenceType) + - a parameterized type (ParameterizedType, e.g. List) + - a type parameter (ITypeParameter, e.g. T) + - or a type definition (ITypeDefiniton) + + Type definitions are only classes, structs, enums and delegates. + Every type definition is a type, but not every type is a type definition. + NRefactory's ITypeDefinition derives from IType, so you can directly use any type definition + as a type. + In the other direction, you could try to cast a type to ITypeDefinition, or you can call the + GetDefinition() method. The GetDefinition() method will also return the underlying + ITypeDefinition if given a parameterized type, so "List".GetDefinition() is "List". + + +Q: What is the difference between types and type references? + I've seen lots of duplicated classes (ArrayType vs. ArrayTypeReference, etc.) + +A: If you've previously used the .NET Reflection API, the concept of type references will be new + to you. + + NRefactory has the concept of the "project content": every assembly/project is stored + independently from other assemblies/projects. + It is possible to load some source code into a project which contains the type reference + "int[]" without having to load mscorlib into NRefactory. + So inside the entities stored for the project, the array type is only referenced using an + ITypeReference. + This interface has a single method: + interface ITypeReference { + IType Resolve(ITypeResolutionContext context); + } + By calling the Resolve()-method, you will get back the actual ArrayType. + At this point, you have to provide the type resolution context: + + Note that every type can also be used as type reference - the IType interface derives from + ITypeReference. + Every IType simply returns itself when the Resolve()-method is called. + Types are often directly used as references when source and target of the reference are within + the same assembly. + + Because an ArrayType must have an IType as element type, we also need the ArrayTypeReference + to represent an array of a type that's not yet resolved. + When resolved, the ArrayTypeReference produces an array type: + new ArrayTypeReference(r).Resolve(context) = new ArrayType(r.Resolve(context)) + + +Q: What's in an ITypeResolveContext? + +A: An ITypeResolveContext is an environment for looking up namespaces and types. + Usually, a resolve context will represent a set of projects. + Most of the time, that set will be the current project, plus the direct references of the + current project. + + Every project content on its own is a type resolve context (IProjectContent extends + ITypeResolveContext); but (with the exception of mscorlib) isn't useful for resolving types as + you also need the references. + To represent a set of projects, the class CompositeTypeResolveContext can be used. + + +Q: How do I get the IType or ITypeReference for a primitive type such as string or int? + +A: Please use: + TypeCode.Int32.ToTypeReference().Resolve(context) + Skip the Resolve() call if you only need the type reference. + + ReflectionHelper.ToTypeReference is very fast if given a TypeCode (it simply looks up an + existing type reference in an array), and your code will benefit from caching of the resolve + result (once that gets implemented for these primitive type references). + + Avoid using "context.GetClass(typeof(int))" - this call involves Reflection on the System.Type + being passed, cannot benefit from any caching implemented in the future, and most importantly: + it may return null. + And do you always test your code in a scenario where mscorlib isn't contained in the resolve + context? + The approach suggested above will return SharedTypes.UnknownType when the type cannot be + resolved, so you don't run into the risk of getting NullReferenceExceptions. + + +Q: Is it thread-safe? + +A: This question is a bit difficult to answer. + NRefactory was designed to be usable in a multi-threaded IDE. + But of course, this does not mean that everything is thread-safe. + + First off, there's no hidden static state, so any two operations working on independent data + can be executed concurrently. + [Actually, sometimes static state is used for caches, but those uses are thread-safe.] + TODO: what about the C# parser? gmcs is full of static state... + + Some instance methods may use hidden instance state, so it is not safe to e.g use an instance + of the CSharp.Resolver.Conversions class concurrently. + Instead, you need to create an instance on every thread. + + In the case of project contents, it is desirable to be able to use them, and all the classes in + that project content, on multiple threads - for example, to provide code completion in an IDE + while a background thread parses more files and adds them to the project content. + + For this reason, the entity interfaces (ITypeDefinition, IMember, etc.) are designed to be + freezable. Once the Freeze() method is called, an entity instance becomes immutable and + thread-safe. + + Whether an ITypeResolveContext is thread-safe depends on the implementation: + TypeStorage: thread-safe for concurrent reads, but only if it's not written to + (see XML documentation on TypeStorage) + CecilProjectContent: immutable and thread-safe + SimpleProjectContent: fully thread-safe + CompositeTypeResolveContext: depends on the child contexts + + Usually, you'll work with a set of loaded projects (SimpleProjectContents) + and loaded external assemblies (CecilProjectContent). + A CompositeTypeResolveContext representing such a set is thread-safe. + + Hoever, some algorithms can become confused if two GetClass() calls with same arguments + produce different results (e.g. because another thread updated a class definition). + Also, there's a performance problem: if you have a composite of 15 SimpleProjectContents and + the resolve algorithm requests 100 types, that's 1500 times entering and leaving the read-lock. + Moreoever, internal caches in the library are not used when passing a mutable + ITypeResolveContext. + + The solution is to make the read lock more coarse-grained: + using (var syncContext = compositeTypeResolveContext.Synchronize()) { + resolver.ResolveStuff(syncContext); + } + On the call to Synchronize(), all 15 SimpleProjectContents are locked for reading. + The return value "syncContext" can then be used to access the type resolve context without + further synchronization overhead. + It is guaranteed not to change (within the using block), so the library may cache some + information. (TODO: give example of a cache) + Once the return value is disposed, the read-locks are released (and the caches are cleared). + + +Q: What format do the .ToString() methods use? + +A: They don't use any particular format. They're merely intended as a debugging aid. + Currently .ToString() usually matches .ReflectionName, but that may change in the future. + + +Q: Why are there extension methods IType.IsEnum() and IType.IsDelegate(), but no IType.IsStruct() + or IType.IsInterface()? + +A: Because if you're asking whether a type is a struct, it's very likely that you're asking the + wrong question. + The distinction between class/struct/interface/enum/delegate is important in the world of type + definitions, and there's ITypeDefinition.ClassType to address this. But the distinction isn't + so important in the world of types. + + If whatever you are doing works with struct-types, then it likely will also work with + enum-types, and also with type parameters with a value-type constraint. + So instead of asking IsStruct(), you really should be asking: IType.IsReferenceType == false + + Enums and delegates are special because you can do special things with those types + (e.g. subtract them from each other). + If you really need to know, you can do + "type.GetDefinition() != null && type.GetDefinition().ClassType == WhatIWant" + yourself, but for the most part you should be fine with IsReferenceType, IsEnum and IsDelegate. + + +Q: What's the difference between the .NET 3.5 and .NET 4.0 versions? + +A: As for visible API difference, not much. The .NET 4.0 build has some additional overloads for a few methods, + taking a System.Threading.CancellationToken to allow aborting a resolve run. + Internally, the .NET 4.0 version might be tiny bit more performant because it uses covariance for IEnumerable, + where the .NET 3.5 version has to allocate wrapper objects instead. + + Both versions support loading assemblies of all .NET versions (1.0 to 4.0); and both support C# 4.0. diff --git a/src/Libraries/NRefactory/doc/TODO b/src/Libraries/NRefactory/doc/TODO new file mode 100644 index 0000000000..1b43f8b85f --- /dev/null +++ b/src/Libraries/NRefactory/doc/TODO @@ -0,0 +1,24 @@ + +Parser: +- "extern alias" declarations +- "fixed int Field[100];" (fixed-size field declarations) +- support generics +- fix bugs (see currently ignored unit tests) +- put newlines into the AST +- add API to report errors +- allow multithreaded parsing + +Resolver: +- Tons of unit tests for TypeSystemConvertVisitor +- Lambda expressions +- Handle attributes +- Port all #D resolver unit tests to NR +- Port all MD resolver unit tests to NR + +Features: +- Code Completion +- Find References +- Extract Method refactoring + +For integration into SharpDevelop: +- Review NR and DOM changes done in the timeframe \ No newline at end of file diff --git a/src/Libraries/NRefactory/doc/copyright.txt b/src/Libraries/NRefactory/doc/copyright.txt new file mode 100644 index 0000000000..914c9875c5 --- /dev/null +++ b/src/Libraries/NRefactory/doc/copyright.txt @@ -0,0 +1,10 @@ +Copyright 2002-2010 by + + AlphaSierraPapa, Christoph Wille + Vordernberger Strasse 27/8 + A-8700 Leoben + Austria + + email: office@alphasierrapapa.com + court of jurisdiction: Landesgericht Leoben + diff --git a/src/Libraries/NRefactory/doc/license.txt b/src/Libraries/NRefactory/doc/license.txt new file mode 100644 index 0000000000..bcbc668932 --- /dev/null +++ b/src/Libraries/NRefactory/doc/license.txt @@ -0,0 +1,17 @@ +Copyright (c) 2010 AlphaSierraPapa + +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.