xronos /Microsoft.Scripting/SourceUnit.cs

Language C# Lines 276
MD5 Hash 4eb2d209e8ea98ec21bdba367b62d95a Estimated Cost $4,359 (why?)
Repository https://bitbucket.org/stefanrusek/xronos View Raw File
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 *
 * ***************************************************************************/

#if CODEPLEX_40
using System;
#else
using System; using Microsoft;
#endif
using System.Collections.Generic;
using System.Diagnostics;
#if CODEPLEX_40
using System.Linq.Expressions;
using System.Dynamic;
#else
using Microsoft.Linq.Expressions;
using Microsoft.Scripting;
#endif
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using System.Text;

namespace Microsoft.Scripting {
    [DebuggerDisplay("{_path ?? \"<anonymous>\"}")]
    public sealed class SourceUnit {
        private readonly SourceCodeKind _kind;
        private readonly string _path;
        private readonly LanguageContext _language;
        private readonly TextContentProvider _contentProvider;

        // SourceUnit is serializable => updated parse result is transmitted
        // back to the host unless the unit is passed by-ref
        private ScriptCodeParseResult? _parseResult;
        private KeyValuePair<int, int>[] _lineMap;

        /// <summary>
        /// Identification of the source unit. Assigned by the host. 
        /// The format and semantics is host dependent (could be a path on file system or URL).
        /// Empty string for anonymous source units.
        /// </summary>
        public string Path {
            get { return _path; }
        }

        public bool HasPath {
            get { return _path != null; }
        }

        public SourceCodeKind Kind {
            get { return _kind; }
        }

        public SymbolDocumentInfo Document {
            get {
                // _path is valid to be null. In that case we cannot create a valid SymbolDocumentInfo.
                return _path == null ? null : Expression.SymbolDocument(_path, _language.LanguageGuid, _language.VendorGuid);
            }
        }

        /// <summary>
        /// LanguageContext of the language of the unit.
        /// </summary>
        public LanguageContext LanguageContext {
            get { return _language; }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public ScriptCodeParseResult GetCodeProperties() {
            return GetCodeProperties(_language.GetCompilerOptions());
        }

        public ScriptCodeParseResult GetCodeProperties(CompilerOptions options) {
            ContractUtils.RequiresNotNull(options, "options");

            _language.CompileSourceCode(this, options, ErrorSink.Null);
            return _parseResult ?? ScriptCodeParseResult.Complete;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")] // TODO: fix
        public ScriptCodeParseResult? CodeProperties {
            get { return _parseResult; }
            set { _parseResult = value; }
        }

        public SourceUnit(LanguageContext context, TextContentProvider contentProvider, string path, SourceCodeKind kind) {
            Assert.NotNull(context, contentProvider);
            Debug.Assert(path == null || path.Length > 0);
            Debug.Assert(context.CanCreateSourceCode);

            _language = context;
            _contentProvider = contentProvider;
            _kind = kind;
            _path = path;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public SourceCodeReader GetReader() {
            return _contentProvider.GetReader();
        }

        /// <summary>
        /// Reads specified range of lines (or less) from the source unit. 
        /// Line numbers starts with 1.
        /// </summary>
        public string[] GetCodeLines(int start, int count) {
            ContractUtils.Requires(start > 0, "start");
            ContractUtils.Requires(count > 0, "count");

            List<string> result = new List<string>(count);

            using (SourceCodeReader reader = GetReader()) {
                reader.SeekLine(start);
                while (count > 0) {
                    string line = reader.ReadLine();
                    if (line == null) break;
                    result.Add(line);
                    count--;
                }
            }

            return result.ToArray();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public string GetCodeLine(int line) {
            string[] lines = GetCodeLines(line, 1);
            return (lines.Length > 0) ? lines[0] : null;
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public string GetCode() {
            using (SourceCodeReader reader = GetReader()) {
                return reader.ReadToEnd();
            }
        }

        #region Line/File mapping

        public SourceLocation MakeLocation(int index, int line, int column) {
            return new SourceLocation(index, MapLine(line), column);
        }
        public SourceLocation MakeLocation(SourceLocation loc) {
            return new SourceLocation(loc.Index, MapLine(loc.Line), loc.Column);
        }

        public int MapLine(int line) {
            if (_lineMap != null) {
                int match = BinarySearch(_lineMap, line);
                int delta = line - _lineMap[match].Key;
                line = _lineMap[match].Value + delta;
                if (line < 1) {
                    line = 1; // this is the minimum value
                }
            }

            return line;
        }

        private static int BinarySearch<T>(KeyValuePair<int, T>[] array, int line) {
            int match = Array.BinarySearch(array, new KeyValuePair<int, T>(line, default(T)), new KeyComparer<T>());
            if (match < 0) {
                // If we couldn't find an exact match for this line number, get the nearest
                // matching line number less than this one
                match = ~match - 1;

                // If our index = -1, it means that this line is before any line numbers that
                // we know about. If that's the case, use the first entry in the list
                if (match == -1) {
                    match = 0;
                }
            }
            return match;
        }


        private class KeyComparer<T1> : IComparer<KeyValuePair<int, T1>> {
            public int Compare(KeyValuePair<int, T1> x, KeyValuePair<int, T1> y) {
                return x.Key - y.Key;
            }
        }

        #endregion

        #region Parsing, Compilation, Execution

        public bool EmitDebugSymbols {
            get {
                return HasPath && LanguageContext.DomainManager.Configuration.DebugMode;
            }
        }

        public ScriptCode Compile() {
            return Compile(ErrorSink.Default);
        }

        public ScriptCode Compile(ErrorSink errorSink) {
            return Compile(_language.GetCompilerOptions(), errorSink);
        }

        /// <summary>
        /// Errors are reported to the specified sink. 
        /// Returns <c>null</c> if the parser cannot compile the code due to error(s).
        /// </summary>
        public ScriptCode Compile(CompilerOptions options, ErrorSink errorSink) {
            ContractUtils.RequiresNotNull(errorSink, "errorSink");
            ContractUtils.RequiresNotNull(options, "options");

            return _language.CompileSourceCode(this, options, errorSink);
        }

        /// <summary>
        /// Executes against a specified scope.
        /// </summary>
        public object Execute(Scope scope) {
            return Execute(scope, ErrorSink.Default);
        }

        /// <summary>
        /// Executes against a specified scope and reports errors to the given error sink.
        /// </summary>
        public object Execute(Scope scope, ErrorSink errorSink) {
            ContractUtils.RequiresNotNull(scope, "scope");

            ScriptCode compiledCode = Compile(_language.GetCompilerOptions(scope), errorSink);

            if (compiledCode == null) {
                throw new SyntaxErrorException();
            }

            return compiledCode.Run(scope);
        }

        /// <summary>
        /// Executes in a new scope created by the language.
        /// </summary>
        public object Execute() {
            return Compile().Run();
        }

        /// <summary>
        /// Executes in a new scope created by the language.
        /// </summary>
        public object Execute(ErrorSink errorSink) {
            return Compile(errorSink).Run();
        }

        /// <summary>
        /// Executes in a new scope created by the language.
        /// </summary>
        public object Execute(CompilerOptions options, ErrorSink errorSink) {
            return Compile(options, errorSink).Run();
        }

        public int ExecuteProgram() {
            return _language.ExecuteProgram(this);
        }

        #endregion

        public void SetLineMapping(KeyValuePair<int, int>[] lineMap) {
            _lineMap = (lineMap == null || lineMap.Length == 0) ? null : lineMap;
        }
    }
}
Back to Top