using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq.Expressions; using AspClassic.Scripting.Runtime; using AspClassic.Scripting.Utils; namespace AspClassic.Scripting; [DebuggerDisplay("{_path ?? \"\"}")] public sealed class SourceUnit { private class KeyComparer : IComparer> { public int Compare(KeyValuePair x, KeyValuePair y) { return x.Key - y.Key; } } private readonly SourceCodeKind _kind; private readonly string _path; private readonly LanguageContext _language; private readonly TextContentProvider _contentProvider; private ScriptCodeParseResult? _parseResult; private KeyValuePair[] _lineMap; public string Path => _path; public bool HasPath => _path != null; public SourceCodeKind Kind => _kind; public SymbolDocumentInfo Document { get { if (_path != null) { return Expression.SymbolDocument(_path, _language.LanguageGuid, _language.VendorGuid); } return null; } } public LanguageContext LanguageContext => _language; public ScriptCodeParseResult? CodeProperties { get { return _parseResult; } set { _parseResult = value; } } public bool EmitDebugSymbols { get { if (HasPath) { return LanguageContext.DomainManager.Configuration.DebugMode; } return false; } } 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; } public SourceUnit(LanguageContext context, TextContentProvider contentProvider, string path, SourceCodeKind kind) { _language = context; _contentProvider = contentProvider; _kind = kind; _path = path; } public SourceCodeReader GetReader() { return _contentProvider.GetReader(); } public string[] GetCodeLines(int start, int count) { ContractUtils.Requires(start > 0, "start"); ContractUtils.Requires(count > 0, "count"); List list = new List(count); using (SourceCodeReader sourceCodeReader = GetReader()) { sourceCodeReader.SeekLine(start); while (count > 0) { string text = sourceCodeReader.ReadLine(); if (text != null) { list.Add(text); count--; continue; } break; } } return list.ToArray(); } public string GetCodeLine(int line) { string[] codeLines = GetCodeLines(line, 1); if (codeLines.Length <= 0) { return null; } return codeLines[0]; } public string GetCode() { using SourceCodeReader sourceCodeReader = GetReader(); return sourceCodeReader.ReadToEnd(); } 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 num = BinarySearch(_lineMap, line); int num2 = line - _lineMap[num].Key; line = _lineMap[num].Value + num2; if (line < 1) { line = 1; } } return line; } private static int BinarySearch(KeyValuePair[] array, int line) { int num = Array.BinarySearch(array, new KeyValuePair(line, default(T)), new KeyComparer()); if (num < 0) { num = ~num - 1; if (num == -1) { num = 0; } } return num; } public ScriptCode Compile() { return Compile(ErrorSink.Default); } public ScriptCode Compile(ErrorSink errorSink) { return Compile(_language.GetCompilerOptions(), errorSink); } public ScriptCode Compile(CompilerOptions options, ErrorSink errorSink) { ContractUtils.RequiresNotNull(errorSink, "errorSink"); ContractUtils.RequiresNotNull(options, "options"); return _language.CompileSourceCode(this, options, errorSink); } public object Execute(Scope scope) { return Execute(scope, ErrorSink.Default); } public object Execute(Scope scope, ErrorSink errorSink) { ContractUtils.RequiresNotNull(scope, "scope"); ScriptCode scriptCode = Compile(_language.GetCompilerOptions(scope), errorSink); if (scriptCode == null) { throw new SyntaxErrorException(); } return scriptCode.Run(scope); } public object Execute() { return Compile().Run(); } public object Execute(ErrorSink errorSink) { return Compile(errorSink).Run(); } public object Execute(CompilerOptions options, ErrorSink errorSink) { return Compile(options, errorSink).Run(); } public int ExecuteProgram() { return _language.ExecuteProgram(this); } public void SetLineMapping(KeyValuePair[] lineMap) { _lineMap = ((lineMap == null || lineMap.Length == 0) ? null : lineMap); } }