/SpecSharp/System.Compiler/Nodes.cs
C# | 12405 lines | 11377 code | 111 blank | 917 comment | 3958 complexity | b111ae665abe1b7131c5e7543d4a30e7 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- //-----------------------------------------------------------------------------
- //
- // Copyright (C) Microsoft Corporation. All Rights Reserved.
- //
- //-----------------------------------------------------------------------------
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Globalization;
- using System.Collections.Specialized;
- #if FxCop
- using AssemblyReferenceList = Microsoft.Cci.AssemblyReferenceCollection;
- using AttributeList = Microsoft.Cci.AttributeNodeCollection;
- using BlockList = Microsoft.Cci.BlockCollection;
- using ExpressionList = Microsoft.Cci.ExpressionCollection;
- using InstructionList = Microsoft.Cci.InstructionCollection;
- using Int32List = System.Collections.Generic.List<int>;
- using InterfaceList = Microsoft.Cci.InterfaceCollection;
- using MemberList = Microsoft.Cci.MemberCollection;
- using MethodList = Microsoft.Cci.MethodCollection;
- using ModuleReferenceList = Microsoft.Cci.ModuleReferenceCollection;
- using NamespaceList = Microsoft.Cci.NamespaceCollection;
- using ParameterList = Microsoft.Cci.ParameterCollection;
- using ResourceList = Microsoft.Cci.ResourceCollection;
- using SecurityAttributeList = Microsoft.Cci.SecurityAttributeCollection;
- using StatementList = Microsoft.Cci.StatementCollection;
- using TypeNodeList = Microsoft.Cci.TypeNodeCollection;
- using Win32ResourceList = Microsoft.Cci.Win32ResourceCollection;
- using Module = Microsoft.Cci.ModuleNode;
- using Class = Microsoft.Cci.ClassNode;
- using Interface = Microsoft.Cci.InterfaceNode;
- using Property = Microsoft.Cci.PropertyNode;
- using Event = Microsoft.Cci.EventNode;
- using Return = Microsoft.Cci.ReturnNode;
- using Throw = Microsoft.Cci.ThrowNode;
- #endif
- #if UseSingularityPDB
- using Microsoft.Singularity.PdbInfo;
- #endif
- #if CCINamespace
- using Cci = Microsoft.Cci;
- using Microsoft.Cci.Metadata;
- using Metadata = Microsoft.Cci.Metadata;
- #else
- using Cci = System.Compiler;
- using System.Compiler.Metadata;
- using Metadata = System.Compiler.Metadata;
- #endif
- using System.Diagnostics;
- using System.IO;
- using System.Text;
- #if !NoXml
- using System.Xml;
- #endif
-
- using BindingFlags = System.Reflection.BindingFlags;
-
- #if CCINamespace
- namespace Microsoft.Cci{
- #else
- namespace System.Compiler{
- #endif
- #if !FxCop
- /// <summary>
- /// This interface can be used to link an arbitrary source text provider into an IR tree via a DocumentText instance.
- /// </summary>
- public interface ISourceText{
- /// <summary>
- /// The number of characters in the source text.
- /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
- /// </summary>
- int Length{get;}
- /// <summary>
- /// Retrieves a substring from this instance. The substring starts with the character at the specified index and has a specified length.
- /// </summary>
- string Substring(int startIndex, int length);
- /// <summary>
- /// Retrieves the character at the given position. The first character is at position zero.
- /// </summary>
- char this[int position]{get;}
- /// <summary>
- /// Indicates that the text has been fully scanned and futher references to the text are expected to be infrequent.
- /// The underlying object can now choose to clear cached information if it comes under resource pressure.
- /// </summary>
- void MakeCollectible();
- }
- public unsafe interface ISourceTextBuffer : ISourceText{
- /// <summary>
- /// Returns null unless the implementer is based on an ASCII buffer that stays alive as long at the implementer itself.
- /// An implementer that returns a non-null value is merely a wrapper to keep the buffer alive. No further methods will
- /// be called on the interface in this case.
- /// </summary>
- byte* Buffer{get;}
- }
- #endif
- #if !MinimalReader
- /// <summary>
- /// Use this after a source text has already been scanned and parsed. This allows the source text to get released
- /// if there is memory pressure, while still allowing portions of it to be retrieved on demand. This is useful when
- /// a large number of source files are read in, but only infrequent references are made to them.
- /// </summary>
- public sealed class CollectibleSourceText : ISourceText{
- private string/*!*/ filePath;
- private WeakReference/*!*/ fileContent;
- private int length;
-
- public CollectibleSourceText(string/*!*/ filePath, int length) {
- this.filePath = filePath;
- this.fileContent = new WeakReference(null);
- this.length = length;
- //^ base();
- }
- public CollectibleSourceText(string/*!*/ filePath, string fileContent) {
- this.filePath = filePath;
- this.fileContent = new WeakReference(fileContent);
- this.length = fileContent == null ? 0 : fileContent.Length;
- //^ base();
- }
- private string/*!*/ ReadFile() {
- string content = string.Empty;
- try {
- StreamReader sr = new StreamReader(filePath);
- content = sr.ReadToEnd();
- this.length = content.Length;
- sr.Close();
- }catch{}
- return content;
- }
- public string/*!*/ GetSourceText() {
- string source = (string)this.fileContent.Target;
- if (source != null) return source;
- source = this.ReadFile();
- this.fileContent.Target = source;
- return source;
- }
-
- int ISourceText.Length{get{return this.length;}}
- string ISourceText.Substring(int startIndex, int length){
- return this.GetSourceText().Substring(startIndex, length);
- }
- char ISourceText.this[int index]{
- get{
- return this.GetSourceText()[index];
- }
- }
- void ISourceText.MakeCollectible(){
- this.fileContent.Target = null;
- }
- }
- /// <summary>
- /// This class is used to wrap the string contents of a source file with an ISourceText interface. It is used while compiling
- /// a project the first time in order to obtain a symbol table. After that the StringSourceText instance is typically replaced with
- /// a CollectibleSourceText instance, so that the actual source text string can be collected. When a file is edited,
- /// and the editor does not provide its own ISourceText wrapper for its edit buffer, this class can be used to wrap a copy of the edit buffer.
- /// </summary>
- public sealed class StringSourceText : ISourceText{
- /// <summary>
- /// The wrapped string used to implement ISourceText. Use this value when unwrapping.
- /// </summary>
- public readonly string/*!*/ SourceText;
- /// <summary>
- /// True when the wrapped string is the contents of a file. Typically used to check if it safe to replace this
- /// StringSourceText instance with a CollectibleSourceText instance.
- /// </summary>
- public bool IsSameAsFileContents;
-
- public StringSourceText(string/*!*/ sourceText, bool isSameAsFileContents) {
- this.SourceText = sourceText;
- this.IsSameAsFileContents = isSameAsFileContents;
- //^ base();
- }
- int ISourceText.Length{get{return this.SourceText.Length;}}
- string ISourceText.Substring(int startIndex, int length){
- return this.SourceText.Substring(startIndex, length);
- }
- char ISourceText.this[int index]{
- get{
- return this.SourceText[index];
- }
- }
- void ISourceText.MakeCollectible(){
- }
- }
- #endif
- #if !FxCop
- /// <summary>
- /// This class provides a uniform interface to program sources provided in the form of Unicode strings,
- /// unsafe pointers to ascii buffers (as obtained from a memory mapped file, for instance) as well as
- /// arbitrary source text providers that implement the ISourceText interface.
- /// </summary>
- public sealed unsafe class DocumentText{
- /// <summary>
- /// If this is not null it is used to obtain 8-bit ASCII characters.
- /// </summary>
- public byte* AsciiStringPtr;
- /// <summary>
- /// If this is not null it represents a Unicode string encoded as UTF16.
- /// </summary>
- public string Source;
- /// <summary>
- /// If this is not null the object implement ISourceText provides some way to get at individual characters and substrings.
- /// </summary>
- public ISourceText TextProvider;
- /// <summary>
- /// The number of characters in the source document.
- /// A "character" corresponds to a System.Char which is actually a Unicode UTF16 code point to be precise.
- /// </summary>
- public int Length;
- public DocumentText(string source){
- if (source == null){Debug.Assert(false); return;}
- this.Source = source;
- this.Length = source.Length;
- }
- public DocumentText(ISourceText textProvider){
- if (textProvider == null){Debug.Assert(false); return;}
- this.TextProvider = textProvider;
- this.Length = textProvider.Length;
- }
- public unsafe DocumentText(ISourceTextBuffer textProvider){
- if (textProvider == null){Debug.Assert(false); return;}
- this.TextProvider = textProvider;
- this.AsciiStringPtr = textProvider.Buffer;
- this.Length = textProvider.Length;
- }
- /// <summary>
- /// Compare this.Substring(offset, length) for equality with str.
- /// Call this only if str.Length is known to be equal to length.
- /// </summary>
- public bool Equals(string str, int position, int length){ //TODO: (int position, int length, string str)
- if (str == null){Debug.Assert(false); return false;}
- if (str.Length != length){Debug.Assert(false); return false;}
- if (position < 0 || position+length > this.Length){Debug.Assert(false); return false;}
- unsafe{
- byte* p = this.AsciiStringPtr;
- if (p != null){
- for (int i = position, j = 0; j < length; i++, j++)
- if (((char)*(p+i)) != str[j]) return false;
- return true;
- }
- }
- string source = this.Source;
- if (source != null){
- for (int i = position, j = 0; j < length; i++, j++)
- if (source[i] != str[j]) return false;
- return true;
- }
- ISourceText myProvider = this.TextProvider;
- if (myProvider == null){Debug.Assert(false); return false;}
- for (int i = position, j = 0; j < length; i++, j++)
- if (myProvider[i] != str[j]) return false;
- return true;
- }
- /// <summary>
- /// Compares the substring of the specificied length starting at offset, with the substring in DocumentText starting at textOffset.
- /// </summary>
- /// <param name="offset">The index of the first character of the substring of this DocumentText.</param>
- /// <param name="text">The Document text with the substring being compared to.</param>
- /// <param name="textOffset">The index of the first character of the substring of the DocumentText being compared to.</param>
- /// <param name="length">The number of characters in the substring being compared.</param>
- /// <returns></returns>
- public bool Equals(int offset, DocumentText text, int textOffset, int length){ //TODO: (int position, int length, DocumentText text, int textPosition)
- if (offset < 0 || length < 0 || offset+length > this.Length){ Debug.Assert(false); return false;}
- if (textOffset < 0 || text == null || textOffset+length > text.Length){Debug.Assert(false); return false;}
- unsafe{
- byte* p = this.AsciiStringPtr;
- if (p != null){
- unsafe{
- byte* q = text.AsciiStringPtr;
- if (q != null){
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (*(p+i) != *(q+j)) return false;
- return true;
- }
- }
- string textSource = text.Source;
- if (textSource != null){
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (((char)*(p+i)) != textSource[j]) return false;
- return true;
- }
- ISourceText textProvider = text.TextProvider;
- if (textProvider == null){Debug.Assert(false); return false;}
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (((char)*(p+i)) != textProvider[j]) return false;
- return true;
- }
- }
- string source = this.Source;
- if (source != null){
- unsafe{
- byte* q = text.AsciiStringPtr;
- if (q != null){
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (source[i] != (char)*(q+j)) return false;
- return true;
- }
- }
- string textSource = text.Source;
- if (textSource != null){
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (source[i] != textSource[j]) return false;
- return true;
- }
- ISourceText textProvider = text.TextProvider;
- if (textProvider == null){Debug.Assert(false); return false;}
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (source[i] != textProvider[j]) return false;
- return true;
- }
- {
- ISourceText myProvider = this.TextProvider;
- if (myProvider == null){Debug.Assert(false); return false;}
- unsafe{
- byte* q = text.AsciiStringPtr;
- if (q != null){
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (myProvider[i] != (char)*(q+j)) return false;
- return true;
- }
- }
- string textSource = text.Source;
- if (textSource != null){
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (myProvider[i] != textSource[j]) return false;
- return true;
- }
- ISourceText textProvider = text.TextProvider;
- if (textProvider == null){Debug.Assert(false); return false;}
- for (int i = offset, j = textOffset, n = offset+length; i < n; i++, j++)
- if (myProvider[i] != textProvider[j]) return false;
- return true;
- }
- }
- /// <summary>
- /// Retrieves a substring from this instance. The substring starts at a specified character position and has a specified length.
- /// </summary>
- public string/*!*/ Substring(int position, int length){
- if (position < 0 || length < 0 || position+length > this.Length+1){Debug.Assert(false); return "";}
- if (position+length > this.Length) length = this.Length-position; //Allow virtual EOF character to be included in length
- if (this.AsciiStringPtr != null){
- unsafe{
- return new String((sbyte*)this.AsciiStringPtr, position, length, System.Text.Encoding.ASCII);
- }
- }else if (this.Source != null)
- return this.Source.Substring(position, length);
- else if (this.TextProvider != null)
- return this.TextProvider.Substring(position, length);
- else{
- Debug.Assert(false);
- return "";
- }
- }
- /// <summary>
- /// Retrieves the character at the given position. The first character is at position zero.
- /// </summary>
- public char this[int position]{
- get{
- if (position < 0 || position >= this.Length){Debug.Assert(false); return (char)0;}
- if (this.AsciiStringPtr != null){
- unsafe{
- unchecked{
- return (char) *(this.AsciiStringPtr+position);
- }
- }
- }else if (this.Source != null)
- return this.Source[position];
- else if (this.TextProvider != null)
- return this.TextProvider[position];
- else{
- Debug.Assert(false);
- return (char)0;
- }
- }
- }
- }
- /// <summary>
- /// A source document from which an Abstract Syntax Tree has been derived.
- /// </summary>
- public class Document{
- /// <summary>
- /// A Guid that identifies the kind of document to applications such as a debugger. Typically System.Diagnostics.SymbolStore.SymDocumentType.Text.
- /// </summary>
- public System.Guid DocumentType;
- /// <summary>
- /// A Guid that identifies the programming language used in the source document. Typically used by a debugger to locate language specific logic.
- /// </summary>
- public System.Guid Language;
- /// <summary>
- /// A Guid that identifies the compiler vendor programming language used in the source document. Typically used by a debugger to locate vendor specific logic.
- /// </summary>
- public System.Guid LanguageVendor;
- /// <summary>
- /// The line number corresponding to the first character in Text. Typically 1 but can be changed by C# preprocessor directives.
- /// </summary>
- public int LineNumber;
- /// <summary>
- /// Indicates that the document contains machine generated source code that should not show up in tools such as debuggers.
- /// Can be set by C# preprocessor directives.
- /// </summary>
- public bool Hidden;
- /// <summary>
- /// The name of the document. Typically a file name. Can be a full or relative file path, or a URI or some other kind of identifier.
- /// </summary>
- public string/*!*/ Name;
- /// <summary>
- /// Contains the source text.
- /// </summary>
- public DocumentText Text;
- public Document(){
- this.Name = "";
- //^ base();
- }
- public Document(string/*!*/ name, int lineNumber, string text, System.Guid documentType, System.Guid language, System.Guid languageVendor)
- :this(name, lineNumber, new DocumentText(text), documentType, language, languageVendor){
- }
- public Document(string/*!*/ name, int lineNumber, DocumentText text, System.Guid documentType, System.Guid language, System.Guid languageVendor) {
- this.DocumentType = documentType;
- this.Language = language;
- this.LanguageVendor = languageVendor;
- this.LineNumber = lineNumber;
- this.Name = name;
- this.Text = text;
- //^ base();
- }
-
- /// <summary>
- /// Maps the given zero based character position to the number of the source line containing the same character.
- /// Line number counting starts from the value of LineNumber.
- /// </summary>
- public virtual int GetLine(int position){
- int line = 0; int column = 0;
- this.GetPosition(position, out line, out column);
- return line+this.LineNumber;
- }
- /// <summary>
- /// Maps the given zero based character position in the entire text to the position of the same character in a source line.
- /// Counting within the source line starts at 1.
- /// </summary>
- public virtual int GetColumn(int position){
- int line = 0; int column = 0;
- this.GetPosition(position, out line, out column);
- return column+1;
- }
-
- /// <summary>
- /// Given a startLine, startColum, endLine and endColumn, this returns the corresponding startPos and endPos. In other words it
- /// converts a range expression in line and columns to a range expressed as a start and end character position.
- /// </summary>
- /// <param name="startLine">The number of the line containing the first character. The number of the first line equals this.LineNumber.</param>
- /// <param name="startColumn">The position of the first character relative to the start of the line. Counting from 1.</param>
- /// <param name="endLine">The number of the line contain the character that immediate follows the last character of the range.</param>
- /// <param name="endColumn">The position, in the last line, of the character that immediately follows the last character of the range.</param>
- /// <param name="startPos">The position in the entire text of the first character of the range, counting from 0.</param>
- /// <param name="endPos">The position in the entire text of the character following the last character of the range.</param>
- public virtual void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startPos, out int endPos){
- lock(this){
- if (this.lineOffsets == null) this.ComputeLineOffsets();
- //^ assert this.lineOffsets != null;
- startPos = this.lineOffsets[startLine-this.LineNumber]+startColumn-1;
- endPos = this.lineOffsets[endLine-this.LineNumber]+endColumn-1;
- }
- }
-
- /// <summary>
- /// Retrieves a substring from the text of this Document. The substring starts at a specified character position and has a specified length.
- /// </summary>
- public virtual string Substring(int position, int length){
- if (this.Text == null) return null;
- return this.Text.Substring(position, length);
- }
-
- /// <summary>
- /// Counts the number of end of line marker sequences in the given text.
- /// </summary>
- protected int GetLineCount(string/*!*/ text) {
- int n = text == null ? 0 : text.Length;
- int count = 0;
- for (int i = 0; i < n; i++){
- switch(text[i]){
- case '\r':
- if (i+1 < n && text[i+1] == '\n')
- i++;
- count++;
- break;
- case '\n':
- case (char)0x2028:
- case (char)0x2029:
- count++;
- break;
- }
- }
- return count;
- }
- /// <summary>An array of offsets, with offset at index i corresponding to the position of the first character of line i, (counting lines from 0).</summary>
- private int[] lineOffsets;
- /// <summary>The number of lines in Text.</summary>
- private int lines;
-
- /// <summary>
- /// Returns the index in this.lineOffsets array such that this.lineOffsets[index] is less than or equal to offset
- /// and offset is less than lineOffsets[index+1]
- /// </summary>
- private int Search(int offset){
- tryAgain:
- int[] lineOffsets = this.lineOffsets;
- int lines = this.lines;
- if (lineOffsets == null){Debug.Assert(false); return -1;}
- if (offset < 0){Debug.Assert(false); return -1;}
- int mid = 0;
- int low = 0;
- int high = lines-1;
- while (low < high){
- mid = (low+high)/2;
- if (lineOffsets[mid] <= offset){
- if (offset < lineOffsets[mid+1])
- return mid;
- else
- low = mid + 1;
- }else
- high = mid;
- }
- Debug.Assert(lines == this.lines);
- Debug.Assert(lineOffsets[low] <= offset);
- Debug.Assert(offset < lineOffsets[low+1]);
- if (lineOffsets != this.lineOffsets) goto tryAgain;
- return low;
- }
-
- /// <summary>
- /// Maps the given zero based character position in the entire text to a (line, column) pair corresponding to the same position.
- /// Counting within the source line starts at 0. Counting source lines start at 0.
- /// </summary>
- private void GetPosition(int offset, out int line, out int column){
- line = 0; column = 0;
- if (offset < 0 || this.Text == null || offset > this.Text.Length){Debug.Assert(false); return;}
- lock(this){
- if (this.lineOffsets == null) this.ComputeLineOffsets();
- if (this.lineOffsets == null){Debug.Assert(false); return;}
- int[] lineOffsets = this.lineOffsets;
- int index = this.Search(offset);
- Debug.Assert(lineOffsets == this.lineOffsets);
- if (index < 0 || index >= this.lineOffsets.Length){Debug.Assert(false); return;}
- Debug.Assert(this.lineOffsets[index] <= offset && offset < this.lineOffsets[index+1]);
- line = index;
- column = offset-this.lineOffsets[index];
- }
- }
- /// <summary>
- /// Adds the given offset to the this.lineOffsets table as the offset corresponding to the start of line this.lines+1.
- /// </summary>
- private void AddOffset(int offset){
- if (this.lineOffsets == null || this.lines < 0){Debug.Assert(false); return;}
- if (this.lines >= this.lineOffsets.Length){
- int n = this.lineOffsets.Length;
- if (n <= 0) n = 16;
- int[] newLineOffsets = new int[n*2];
- Array.Copy(this.lineOffsets, newLineOffsets, this.lineOffsets.Length);
- this.lineOffsets = newLineOffsets;
- }
- this.lineOffsets[this.lines++] = offset;
- }
- public virtual void InsertOrDeleteLines(int offset, int lineCount){
- if (lineCount == 0) return;
- if (offset < 0 || this.Text == null || offset > this.Text.Length){Debug.Assert(false); return;}
- lock(this){
- if (this.lineOffsets == null)
- if (this.lineOffsets == null) this.ComputeLineOffsets();
- if (lineCount < 0)
- this.DeleteLines(offset, -lineCount);
- else
- this.InsertLines(offset, lineCount);
- }
- }
- private void DeleteLines(int offset, int lineCount)
- //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
- {
- Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
- int index = this.Search(offset);
- if (index < 0 || index >= this.lines){Debug.Assert(false); return;}
- for (int i = index+1; i+lineCount < this.lines; i++){
- this.lineOffsets[i] = this.lineOffsets[i+lineCount];
- }
- this.lines -= lineCount;
- if (this.lines <= index){Debug.Assert(false); this.lines = index+1;}
- }
- private void InsertLines(int offset, int lineCount)
- //^ requires offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null;
- {
- Debug.Assert(offset >= 0 && this.Text != null && offset < this.Text.Length && lineCount > 0 && this.lineOffsets != null);
- int index = this.Search(offset);
- if (index < 0 || index >= this.lines){Debug.Assert(false); return;}
- int n = this.lineOffsets[this.lines-1];
- for (int i = 0; i < lineCount; i++) this.AddOffset(++n);
- for (int i = lineCount; i > 0; i--){
- this.lineOffsets[index+i+1] = this.lineOffsets[index+1];
- }
- }
- /// <summary>
- /// Populates this.lineOffsets with an array of offsets, with offset at index i corresponding to the position of the first
- /// character of line i, (counting lines from 0).
- /// </summary>
- private void ComputeLineOffsets()
- //ensures this.lineOffsets != null;
- {
- if (this.Text == null){Debug.Assert(false); return;}
- int n = this.Text.Length;
- this.lineOffsets = new int[n/10+1];
- this.lines = 0;
- this.AddOffset(0);
- for (int i = 0; i < n; i++){
- switch(this.Text[i]){
- case '\r':
- if (i+1 < n && this.Text[i+1] == '\n')
- i++;
- this.AddOffset(i+1);
- break;
- case '\n':
- case (char)0x2028:
- case (char)0x2029:
- this.AddOffset(i+1);
- break;
- }
- }
- this.AddOffset(n+1);
- this.AddOffset(n+2);
- }
-
- /// <summary> Add one to this every time a Document instance gets a unique key.</summary>
- private static int uniqueKeyCounter;
- private int uniqueKey;
- /// <summary>
- /// An integer that uniquely distinguishes this document instance from every other document instance.
- /// This provides an efficient equality test to facilitate hashing.
- /// </summary>
- public int UniqueKey{
- get{
- if (this.uniqueKey == 0){
- TryAgain:
- int c = Document.uniqueKeyCounter;
- int cp1 = c == int.MaxValue ? 1 : c+1;
- if (System.Threading.Interlocked.CompareExchange(ref Document.uniqueKeyCounter, cp1, c) != c) goto TryAgain;
- this.uniqueKey = cp1;
- }
- return this.uniqueKey;
- }
- }
- }
- #endif
- #if !MinimalReader
- /// <summary>
- /// For creating source contexts that have just a filename, start line and column and end line and column.
- /// If a SourceContext has a DocumentWithPrecomputedLineNumbers as its Document, then it should have 0 as its StartPos
- /// and 1 as its EndPos because those are used here to decide what to return.
- /// </summary>
- public class DocumentWithPrecomputedLineNumbers : Document {
- private int startLine, startCol, endLine, endCol;
- public DocumentWithPrecomputedLineNumbers(string/*!*/ filename, int startLine, int startCol, int endLine, int endCol) {
- this.Name = filename;
- this.startLine = startLine;
- this.startCol = startCol;
- this.endLine = endLine;
- this.endCol = endCol;
- }
- public override int GetColumn (int offset) { return offset == 0 ? this.startCol : this.endCol; }
- public override int GetLine (int offset) { return offset == 0 ? this.startLine : this.endLine; }
- }
- #endif
- #if UseSingularityPDB
- internal class PdbDocument : Document {
- internal PdbDocument(PdbLines lines) {
- this.Name = lines.file.name;
- this.lines = lines;
- }
- PdbLines lines;
- public override int GetColumn(int position) {
- PdbLine line = this.lines.lines[position/2];
- if (position%2 == 0)
- return line.colBegin;
- else
- return line.colEnd;
- }
- public override int GetLine(int position) {
- PdbLine line = this.lines.lines[position/2];
- return (int)line.line;
- }
- }
- #elif !ROTOR
- internal class UnmanagedDocument: Document{
- internal UnmanagedDocument(IntPtr ptrToISymUnmanagedDocument){
- //^ base();
- ISymUnmanagedDocument idoc =
- (ISymUnmanagedDocument)System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown(ptrToISymUnmanagedDocument, typeof(ISymUnmanagedDocument));
- if (idoc != null){
- try{
- #if !FxCop
- idoc.GetDocumentType(out this.DocumentType);
- idoc.GetLanguage(out this.Language);
- idoc.GetLanguageVendor(out this.LanguageVendor);
- #endif
- uint capacity = 1024;
- uint len = 0;
- char[] buffer = new char[capacity];
- while (capacity >= 1024){
- idoc.GetURL(capacity, out len, buffer);
- if (len < capacity) break;
- capacity += 1024;
- buffer = new char[capacity];
- }
- if (len > 0)
- this.Name = new String(buffer, 0, (int)len-1);
- }finally{
- System.Runtime.InteropServices.Marshal.ReleaseComObject(idoc);
- }
- }
- #if !FxCop
- this.LineNumber = -1;
- this.Text = null;
- #endif
- }
-
- private Int32List/*!*/ lineList = new Int32List();
- private Int32List/*!*/ columnList = new Int32List();
- #if !FxCop
- public override int GetLine(int offset){
- return this.lineList[offset];
- }
- public override int GetColumn(int offset){
- return this.columnList[offset];
- }
- public override void GetOffsets(int startLine, int startColumn, int endLine, int endColumn, out int startCol, out int endCol){
- int i = UnmanagedDocument.BinarySearch(this.lineList, startLine);
- Int32List columnList = this.columnList;
- startCol = 0;
- for (int j = i, n = columnList.Count; j < n; j++){
- if (columnList[j] >= startColumn){ startCol = j; break;}
- }
- endCol = 0;
- i = UnmanagedDocument.BinarySearch(this.lineList, endLine);
- for (int j = i, n = columnList.Count; j < n; j++){
- if (columnList[j] >= endColumn){ endCol = j; break;}
- }
- }
- private static int BinarySearch(Int32List/*!*/ list, int value){
- int mid = 0;
- int low = 0;
- int high = list.Count-1;
- while (low < high){
- mid = low + (high-low)/2;
- if (list[mid] <= value){
- if (list[mid+1] > value)
- return mid;
- else
- low = mid + 1;
- }else
- high = mid;
- }
- return low;
- }
- public override void InsertOrDeleteLines(int offset, int lineCount){
- Debug.Assert(false); //Caller should not be modifying an umanaged document
- }
- #endif
- internal int GetOffset(uint line, uint column){
- this.lineList.Add((int)line);
- this.columnList.Add((int)column);
- return this.lineList.Count-1;
- }
- }
- #endif // !ROTOR
- #if FxCop
- class Document{
- internal string Name;
- }
- public struct SourceContext{
- private string name;
- private int startLine;
- private int endLine;
- private int startColumn;
- private int endColumn;
- internal SourceContext(string name, uint startLine, uint endLine, uint startColumn, uint endColumn){
- this.name = name;
- checked {
- this.startLine = (int)startLine;
- this.endLine = (int)endLine;
- this.startColumn = (int)startColumn;
- this.endColumn = (int)endColumn;
- }
- }
- public string FileName{
- get{return this.name;}
- }
- public int StartLine{
- get{return this.startLine;}
- }
- public int EndLine{
- get{return this.endLine;}
- }
- public int StartColumn{
- get{return this.startColumn;}
- }
- public int EndColumn{
- get{return this.endColumn;}
- }
- }
- #else
- /// <summary>
- /// Records a location within a source document that corresponds to an Abstract Syntax Tree node.
- /// </summary>
- public struct SourceContext{
- /// <summary>The source document within which the AST node is located. Null if the node is not derived from a source document.</summary>
- public Document Document;
- /// <summary>
- /// The zero based index of the first character beyond the last character in the source document that corresponds to the AST node.
- /// </summary>
- public int EndPos;
- /// <summary>
- /// The zero based index of the first character in the source document that corresponds to the AST node.
- /// </summary>
- public int StartPos;
- public SourceContext(Document document)
- : this(document, 0, document == null ? 0 : (document.Text == null ? 0 : document.Text.Length)){
- }
- public SourceContext(Document document, int startPos, int endPos){
- this.Document = document;
- this.StartPos = startPos;
- this.EndPos = endPos;
- }
- public SourceContext(Document/*!*/ document,
- int startLine, int startColumn, int endLine, int endColumn){
- this.Document = document;
- this.Document.GetOffsets(startLine, startColumn, endLine, endColumn, out this.StartPos, out this.EndPos);
- }
- /// <summary>
- /// The number (counting from Document.LineNumber) of the line containing the first character in the source document that corresponds to the AST node.
- /// </summary>
- public int StartLine{
- get{
- if (this.Document == null) return 0;
- return this.Document.GetLine(this.StartPos);
- }
- }
- /// <summary>
- /// The number (counting from one) of the line column containing the first character in the source document that corresponds to the AST node.
- /// </summary>
- public int StartColumn{
- get{
- if (this.Document == null) return 0;
- return this.Document.GetColumn(this.StartPos);
- }
- }
- /// <summary>
- /// The number (counting from Document.LineNumber) of the line containing the first character beyond the last character in the source document that corresponds to the AST node.
- /// </summary>
- public int EndLine{
- get{
- #if UseSingularityPDB
- if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
- #elif !ROTOR
- if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
- #else
- if (this.Document == null || this.Document.Text == null) return 0;
- #endif
- if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
- return this.Document.GetLine(this.EndPos);
- }
- }
- /// <summary>
- /// The number (counting from one) of the line column containing first character beyond the last character in the source document that corresponds to the AST node.
- /// </summary>
- public int EndColumn{
- get{
- #if UseSingularityPDB
- if (this.Document == null || (this.Document.Text == null && !(this.Document is PdbDocument))) return 0;
- #elif !ROTOR
- if (this.Document == null || (this.Document.Text == null && !(this.Document is UnmanagedDocument))) return 0;
- #else
- if (this.Document == null || this.Document.Text == null) return 0;
- #endif
- if (this.Document.Text != null && this.EndPos >= this.Document.Text.Length) this.EndPos = this.Document.Text.Length;
- return this.Document.GetColumn(this.EndPos);
- }
- }
- /// <summary>
- /// Returns true if the line and column is greater than or equal the position of the first character
- /// and less than or equal to the position of the last character
- /// of the source document that corresponds to the AST node.
- /// </summary>
- /// <param name="line">A line number(counting from Document.LineNumber)</param>
- /// <param name="column">A column number (counting from one)</param>
- /// <returns></returns>
- public bool Encloses(int line, int column){
- if (line < this.StartLine || line > this.EndLine) return false;
- if (line == this.StartLine) return column >= this.StartColumn && (column <= this.EndColumn || line < this.EndLine);
- if (line == this.EndLine) return column <= this.EndColumn;
- return true;
- }
- public bool Encloses(SourceContext sourceContext){
- return this.StartPos <= sourceContext.StartPos && this.EndPos >= sourceContext.EndPos && this.EndPos > sourceContext.StartPos;
- }
- /// <summary>
- /// The substring of the source document that corresponds to the AST node.
- /// </summary>
- public string SourceText{
- get{
- if (this.Document == null) return null;
- return this.Document.Substring(this.StartPos, this.EndPos-this.StartPos);
- }
- }
- }
- #endif
- #if !MinimalReader
- public struct SourceChange{
- public SourceContext SourceContext;
- public string ChangedText;
- }
- /// <summary>
- /// Allows a compilation to output progress messages and to query if cancellation was requested.
- /// </summary>
- public class CompilerSite{
- public virtual void OutputMessage(string message){
- }
- public virtual bool ShouldCancel{
- get{
- return false;
- }
- }
- }
- #endif
- #if !NoWriter
- public enum PlatformType{notSpecified, v1, v11, v2, cli1}
- public class CompilerOptions: System.CodeDom.Compiler.CompilerParameters{
- public StringCollection AliasesForReferencedAssemblies;
- public ModuleKindFlags ModuleKind = ModuleKindFlags.ConsoleApplication;
- public bool EmitManifest = true;
- public StringList DefinedPreProcessorSymbols;
- public string XMLDocFileName;
- public string RecursiveWildcard;
- public StringList ReferencedModules;
- public string Win32Icon;
- #if !WHIDBEY
- private StringCollection embeddedResources = new StringCollection();
- public StringCollection EmbeddedResources{
- get{return this.embeddedResources;}
- }
- private StringCollection linkedResources = new StringCollection();
- public StringCollection LinkedResources{
- get{return this.linkedResources;}
- }
- #endif
- #if VS7
- private System.Security.Policy.Evidence evidence;
- public System.Security.Policy.Evidence Evidence{
- get{return this.evidence;}
- set{this.evidence = value;}
- }
- #endif
- public bool PDBOnly;
- public bool Optimize;
- public bool IncrementalCompile;
- public Int32List SuppressedWarnings;
- public bool CheckedArithmetic;
- public bool AllowUnsafeCode;
- public bool DisplayCommandLineHelp;
- public bool SuppressLogo;
- public long BaseAddress; //TODO: default value
- public string BugReportFileName;
- public object CodePage; //must be an int if not null
- public bool EncodeOutputInUTF8;
- public bool FullyQualifyPaths;
- public int FileAlignment;
- public bool NoStandardLibrary;
- public StringList AdditionalSearchPaths;
- public bool HeuristicReferenceResolution;
- public string RootNamespace;
- public bool CompileAndExecute;
- public object UserLocaleId; //must be an int if not null
- public string StandardLibraryLocation;
- public PlatformType TargetPlatform; //TODO: rename this to TargetRuntime
- #if !MinimalReader
- public ProcessorType TargetProcessor;
- #endif
- public string TargetPlatformLocation;
- public string AssemblyKeyFile;
- public string AssemblyKeyName;
- public bool DelaySign;
- public TargetInformation TargetInformation;
- public Int32List SpecificWarningsToTreatAsErrors;
- public Int32List SpecificWarningsNotToTreatAsErrors;
- public string OutputPath;
- public string ExplicitOutputExtension;
- public AppDomain TargetAppDomain;
- public bool MayLockFiles;
- public string ShadowedAssembly;
- public bool UseStandardConfigFile;
- #if !MinimalReader
- public CompilerSite Site;
- #endif
- #if ExtendedRuntime
- /// <summary>
- /// True if the source code for the assembly specify only contracts.
- /// </summary>
- public bool IsContractAssembly;
- /// <summary>
- /// Do not emit run-time checks for requires clauses of non-externally-accessible methods, assert statements, loop invariants, and ensures clauses.
- /// </summary>
- public bool DisableInternalChecks;
- /// <summary>
- /// Do not emit run-time checks for assume statements.
- /// </summary>
- public bool DisableAssumeChecks;
- /// <summary>
- /// Do not emit run-time checks for requires clauses of externally accessible methods.
- /// Do not emit run-time checks that enforce checked exception policy.
- /// </summary>
- public bool DisableDefensiveChecks;
- /// <summary>
- /// Disable the guarded classes feature, which integrates run-time enforcement of object invariants, ownership, and safe concurrency.
- /// </summary>
- public bool DisableGuardedClassesChecks;
- public bool DisableInternalContractsMetadata;
- public bool DisablePublicContractsMetadata;
- /// <summary>
- /// Disable the runtime test against null on non-null typed parameters on public methods
- /// </summary>
- public bool DisableNullParameterValidation;
- public virtual bool LoadDebugSymbolsForReferencedAssemblies {
- get { return false; }
- }
-
- /// <summary>
- /// If set, the compiler will only parse and then emit an xml file with detailed source contexts
- /// about what is parsed.
- /// </summary>
- public bool EmitSourceContextsOnly = false;
-
- #endif
- public CompilerOptions(){
- }
- public CompilerOptions(CompilerOptions source){
- if (source == null){Debug.Assert(false); return;}
- this.AdditionalSearchPaths = source.AdditionalSearchPaths; //REVIEW: clone the list?
- this.AliasesForReferencedAssemblies = source.AliasesForReferencedAssemblies;
- this.AllowUnsafeCode = source.AllowUnsafeCode;
- this.AssemblyKeyFile = source.AssemblyKeyFile;
- this.AssemblyKeyName = source.AssemblyKeyName;
- this.BaseAddress = source.BaseAddress;
- this.BugReportFileName = source.BugReportFileName;
- this.CheckedArithmetic = source.CheckedArithmetic;
- this.CodePage = source.CodePage;
- this.CompileAndExecute = source.CompileAndExecute;
- this.CompilerOptions = source.CompilerOptions;
- this.DefinedPreProcessorSymbols = source.DefinedPreProcessorSymbols;
- this.DelaySign = source.DelaySign;
- #if ExtendedRuntime
- this.DisableAssumeChecks = source.DisableAssumeChecks;
- this.DisableDefensiveChecks = source.DisableDefensiveChecks;
- this.DisableGuardedClassesChecks = source.DisableGuardedClassesChecks;
- this.DisableInternalChecks = source.DisableInternalChecks;
- this.DisableInternalContractsMetadata = source.DisableInternalContractsMetadata;
- this.DisablePublicContractsMetadata = source.DisablePublicContractsMetadata;
- #endif
- this.DisplayCommandLineHelp = source.DisplayCommandLineHelp;
- if (source.EmbeddedResources != null)
- foreach (string s in source.EmbeddedResources) this.EmbeddedResources.Add(s);
- this.EmitManifest = source.EmitManifest;
- this.EncodeOutputInUTF8 = source.EncodeOutputInUTF8;
- this.Evidence = source.Evidence;
- this.ExplicitOutputExtension = source.ExplicitOutputExtension;
- this.FileAlignment = source.FileAlignment;
- this.FullyQualifyPaths = source.FullyQualifyPaths;
- this.GenerateExecutable = source.GenerateExecutable;
- this.GenerateInMemory = source.GenerateInMemory;
- this.HeuristicReferenceResolution = source.HeuristicReferenceResolution;
- this.IncludeDebugInformation = source.IncludeDebugInformation;
- this.IncrementalCompile = source.IncrementalCompile;
- #if ExtendedRuntime
- this.IsContractAssembly = source.IsContractAssembly;
- #endif
- if (source.LinkedResources != null)
- foreach (string s in source.LinkedResources) this.LinkedResources.Add(s);
- this.MainClass = source.MainClass;
- this.MayLockFiles = source.MayLockFiles;
- this.ModuleKind = source.ModuleKind;
- this.NoStandardLibrary = source.NoStandardLibrary;
- this.Optimize = source.Optimize;
- this.OutputAssembly = source.OutputAssembly;
- this.OutputPath = source.OutputPath;
- this.PDBOnly = source.PDBOnly;
- this.RecursiveWildcard = source.RecursiveWildcard;
- if (source.ReferencedAssemblies != null)
- foreach (string s in source.ReferencedAssemblies) this.ReferencedAssemblies.Add(s);
- this.ReferencedModules = source.ReferencedModules;
- this.RootNamespace = source.RootNamespace;
- this.ShadowedAssembly = source.ShadowedAssembly;
- this.SpecificWarningsToTreatAsErrors = source.SpecificWarningsToTreatAsErrors;
- this.StandardLibraryLocation = source.StandardLibraryLocation;
- this.SuppressLogo = source.SuppressLogo;
- this.SuppressedWarnings = source.SuppressedWarnings;
- this.TargetAppDomain = source.TargetAppDomain;
- this.TargetInformation = source.TargetInformation;
- this.TargetPlatform = source.TargetPlatform;
- this.TargetPlatformLocation = source.TargetPlatformLocation;
- this.TreatWarningsAsErrors = source.TreatWarningsAsErrors;
- this.UserLocaleId = source.UserLocaleId;
- this.UserToken = source.UserToken;
- this.WarningLevel = source.WarningLevel;
- this.Win32Icon = source.Win32Icon;
- this.Win32Resource = source.Win32Resource;
- this.XMLDocFileName = source.XMLDocFileName;
- }
- public virtual string GetOptionHelp(){
- return null;
- }
- public virtual CompilerOptions Clone() {
- return (CompilerOptions)this.MemberwiseClone();
- }
- }
- #endif
- public sealed class MarshallingInformation{
- private string @class;
- private string cookie;
- private int elementSize;
- private NativeType elementType;
- private NativeType nativeType;
- private int numberOfElements;
- private int paramIndex;
- private int size;
- public MarshallingInformation Clone(){
- return (MarshallingInformation)base.MemberwiseClone();
- }
- public string Class{
- get{return this.@class;}
- set{this.@class = value;}
- }
- public string Cookie{
- get{return this.cookie;}
- set{this.cookie = value;}
- }
- public int ElementSize{
- get{return this.elementSize;}
- set{this.elementSize = value;}
- }
- public NativeType ElementType{
- get{return this.elementType;}
- set{this.elementType = value;}
- }
- public NativeType NativeType{
- get{return this.nativeType;}
- set{this.nativeType = value;}
- }
- public int NumberOfElements{
- get{return this.numberOfElements;}
- set{this.numberOfElements = value;}
- }
- public int ParamIndex{
- get{return this.paramIndex;}
- set{this.paramIndex = value;}
- }
- public int Size{
- get{return this.size;}
- set{this.size = value;}
- }
- }
- #if !NoWriter
- public struct TargetInformation{
- public string Company;
- public string Configuration;
- public string Copyright;
- public string Culture;
- public string Description;
- public string Product;
- public string ProductVersion;
- public string Title;
- public string Trademark;
- public string Version;
- }
- #endif
- public enum NativeType{
- Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
- I1 = 0x3, // 1 byte signed value
- U1 = 0x4, // 1 byte unsigned value
- I2 = 0x5, // 2 byte signed value
- U2 = 0x6, // 2 byte unsigned value
- I4 = 0x7, // 4 byte signed value
- U4 = 0x8, // 4 byte unsigned value
- I8 = 0x9, // 8 byte signed value
- U8 = 0xa, // 8 byte unsigned value
- R4 = 0xb, // 4 byte floating point
- R8 = 0xc, // 8 byte floating point
- Currency = 0xf, // A currency
- BStr = 0x13, // OLE Unicode BSTR
- LPStr = 0x14, // Ptr to SBCS string
- LPWStr = 0x15, // Ptr to Unicode string
- LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
- ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in st…
Large files files are truncated, but you can click here to view the full file