private static ParsedModule CreateModuleFor(RuntimeModelContext context, ISourceFile sourceFile) { const string ModuleName = "ModuleWith1File"; var specPath = sourceFile.GetAbsolutePath(context.PathTable); var moduleRootDirectory = specPath.GetParent(context.PathTable); var moduleDefinition = ModuleDefinition.CreateModuleDefinitionWithImplicitReferences( new ModuleDescriptor( id: ModuleId.Create(context.StringTable, ModuleName), name: ModuleName, displayName: ModuleName, version: "1.0.0", resolverKind: KnownResolverKind.SourceResolverKind, resolverName: "DScriptExpression"), moduleRootDirectory: moduleRootDirectory, moduleConfigFile: moduleRootDirectory.Combine(context.PathTable, "package.config.dsc"), specs: new [] { specPath }, allowedModuleDependencies: null, cyclicalFriendModules: null ); return(new ParsedModule(moduleDefinition, new Dictionary <AbsolutePath, ISourceFile>() { [specPath] = sourceFile })); }
private ISourceFile ReportDiagnosticsAndValidateSourceFile(RuntimeModelContext runtimeModelContext, AbsolutePath path, ISourceFile result) { ReportParseDiagnosticsIfNeeded(runtimeModelContext, result, path); return(ValidateSourceFile(path, result, runtimeModelContext, runtimeModelContext.LoggingContext)); }
/// <nodoc /> public Expression ParseExpression(RuntimeModelContext runtimeModelContext, AbsolutePath path, string expression) { Contract.Requires(runtimeModelContext != null); Contract.Requires(expression != null); return(ParseExpression(runtimeModelContext, path, expression, localScope: FunctionScope.Empty(), useSemanticNameResolution: true)); }
private static IAstConverter CreateAstConverter(ISourceFile sourceFile, FileModuleLiteral module, RuntimeModelContext runtimeModelContext, AbsolutePath specPath, AstConversionConfiguration conversionConfiguration, Workspace workspace) { var conversionContext = new AstConversionContext(runtimeModelContext, specPath, sourceFile, module); return(AstConverter.Create(runtimeModelContext.QualifierTable, conversionContext, conversionConfiguration, workspace)); }
/// <nodoc /> private Binder(RuntimeModelContext runtimeModelContext) { Contract.Requires(runtimeModelContext != null); m_runtimeModelContext = runtimeModelContext; m_runtimeRootNamespaceSymbol = SymbolAtom.Create(runtimeModelContext.StringTable, Constants.Names.RuntimeRootNamespaceAlias); }
private Task ScheduleSavePublicFacadeAndAstAsync( RuntimeModelContext runtimeModelContext, AbsolutePath path, string specPath, FileContent publicFacadeContent, SourceFileParseResult result) { Task savePublicFacadeTask = null; // Serializing public facade if available if (publicFacadeContent.IsValid) { m_statistics.PublicFacadeSerializationBlobSize.AddAtomic(publicFacadeContent.Length); using (m_statistics.PublicFacadeSaves.Start(specPath)) { savePublicFacadeTask = runtimeModelContext.FrontEndHost.FrontEndArtifactManager.SavePublicFacadeAsync(path, publicFacadeContent); } } else { savePublicFacadeTask = Task.FromResult <object>(null); } // Serializing AST var serializeAstTask = SerializeAndSaveAst(result, runtimeModelContext, specPath, path); return(Task.WhenAll(savePublicFacadeTask, serializeAstTask)); }
private async Task SerializeAndSaveAst(SourceFileParseResult result, RuntimeModelContext runtimeModelContext, string specPath, AbsolutePath path) { // Pooled stream can be released only when the blob is saved to disk using (var pooledStream = BuildXL.Utilities.Pools.MemoryStreamPool.GetInstance()) { byte[] serializedAst; using (m_statistics.SpecAstSerialization.Start(specPath)) { var stream = pooledStream.Instance; // TODO: change to a regular BuildXLWriter when we start serializing the qualifier table using (var writer = new QualifierTableAgnosticWriter( runtimeModelContext.QualifierTable, debug: false, stream: stream, leaveOpen: true, logStats: false)) { result.Serialize(writer); writer.Flush(); serializedAst = stream.GetBuffer(); } } // Saving AST using (m_statistics.AstSerializationSaves.Start(specPath)) { m_statistics.AstSerializationBlobSize.AddAtomic(pooledStream.Instance.Position); await runtimeModelContext.FrontEndHost.FrontEndArtifactManager.SaveAstAsync(path, ByteContent.Create(serializedAst, pooledStream.Instance.Position)); } } }
/// <summary> /// Runs AST conversion on the given target path. /// </summary> /// <remarks> /// The target path is assumed to already be part of the workspace contained by the given host /// </remarks> public static Task <SourceFileParseResult> RunAstConversionAsync(FrontEndHost host, FrontEndContext context, Script.Tracing.Logger logger, IFrontEndStatistics stats, Package package, AbsolutePath conversionTarget) { Contract.RequiresNotNull(host); Contract.RequiresNotNull(context); Contract.RequiresNotNull(logger); Contract.RequiresNotNull(stats); Contract.RequiresNotNull(package); Contract.Requires(conversionTarget.IsValid); var configuration = AstConversionConfiguration.FromConfiguration(host.Configuration.FrontEnd); var linter = DiagnosticAnalyzer.Create( logger, context.LoggingContext, new HashSet <string>(configuration.PolicyRules), configuration.DisableLanguagePolicies); var workspace = (Workspace)host.Workspace; var factory = new RuntimeModelFactory(stats, configuration, linter, workspace); var parserContext = new RuntimeModelContext( host, frontEndContext: context, logger, package: package, origin: default(LocationData)); var sourceFile = workspace.GetSourceFile(conversionTarget); return(factory.ConvertSourceFileAsync(parserContext, sourceFile)); }
private FileModuleLiteral ConvertAndRegisterSourceFile(RuntimeModelContext runtimeModelContext, Workspace workspace, ISourceFile sourceFile, AbsolutePath path, bool isConfig) { var moduleLiteral = ModuleLiteral.CreateFileModule(path, FrontEndHost.ModuleRegistry, runtimeModelContext.Package, sourceFile.LineMap); var conversionContext = new AstConversionContext(runtimeModelContext, path, sourceFile, moduleLiteral); var converter = AstConverter.Create(Context.QualifierTable, conversionContext, ConversionConfiguration, workspace); Script.SourceFile convertedSourceFile = null; if (!isConfig) { convertedSourceFile = converter.ConvertSourceFile().SourceFile; } else if (Kind == ConfigurationKind.PrimaryConfig) { converter.ConvertConfiguration(); } else if (Kind == ConfigurationKind.ModuleConfig) { converter.ConvertPackageConfiguration(); } else { throw Contract.AssertFailure(UnimplementedOperationForConfigKindErrorMessage); } runtimeModelContext.Package.AddParsedProject(path); if (!Logger.HasErrors) { RegisterSuccessfullyParsedModule(convertedSourceFile, moduleLiteral, runtimeModelContext.Package); } return(moduleLiteral); }
/// <nodoc /> public Task <SourceFileParseResult> ConvertSourceFileAsync(RuntimeModelContext runtimeModelContext, ISourceFile sourceFile) { Contract.Requires(runtimeModelContext != null); Contract.Requires(sourceFile != null); Contract.Assert(m_workspace != null); var path = AbsolutePath.Create(runtimeModelContext.PathTable, sourceFile.FileName); return(Task.FromResult(ValidateAndConvert(runtimeModelContext, path, sourceFile))); }
public AstConversionContext( RuntimeModelContext runtimeModelContext, AbsolutePath currentSpecPath, ISourceFile currentSourceFile, FileModuleLiteral currentFileModule) { RuntimeModelContext = runtimeModelContext; CurrentSpecPath = currentSpecPath; CurrentSourceFile = currentSourceFile; CurrentFileModule = currentFileModule; }
private static Location GetLocation(Diagnostic diagnostic, RuntimeModelContext runtimeModelContext, ISourceFile parsedSourceFile, AbsolutePath path) { var lineAndColumn = diagnostic.GetLineAndColumn(parsedSourceFile); var location = new Location { Line = lineAndColumn.Line, Position = lineAndColumn.Character, File = path.ToString(runtimeModelContext.PathTable), }; return(location); }
private static void ReportParseDiagnosticsIfNeeded(RuntimeModelContext runtimeModelContext, ISourceFile parsedSourceFile, AbsolutePath path) { foreach (var diagnostic in parsedSourceFile.ParseDiagnostics.AsStructEnumerable()) { var location = GetLocation(diagnostic, runtimeModelContext, parsedSourceFile, path); runtimeModelContext.Logger.ReportTypeScriptSyntaxError(runtimeModelContext.LoggingContext, location, diagnostic.MessageText.ToString()); } foreach (var diagnostic in parsedSourceFile.BindDiagnostics) { var location = GetLocation(diagnostic, runtimeModelContext, parsedSourceFile, path); runtimeModelContext.Logger.ReportTypeScriptBindingError(runtimeModelContext.LoggingContext, location, diagnostic.MessageText.ToString()); } }
private SourceFileParseResult ValidateAndConvert(RuntimeModelContext runtimeModelContext, AbsolutePath path, ISourceFile parsedSourceFile) { // AddConfigurationDeclaration runtimeModelContext.CancellationToken.ThrowIfCancellationRequested(); ISourceFile fileForAnalysis = parsedSourceFile; if (!m_conversionConfiguration.UnsafeOptions.DisableAnalysis) { // Validate fileForAnalysis = ReportDiagnosticsAndValidateSourceFile(runtimeModelContext, path, parsedSourceFile); } // Convert return(ConvertSourceFile(runtimeModelContext, path, fileForAnalysis)); }
public AstConversionContext( RuntimeModelContext runtimeModelContext, AbsolutePath currentSpecPath, ISourceFile currentSourceFile, FileModuleLiteral currentFileModule) { RuntimeModelContext = runtimeModelContext; CurrentSpecPath = currentSpecPath; CurrentSourceFile = currentSourceFile; CurrentFileModule = currentFileModule; QualifierDeclarationKeyword = CreateSymbol(Constants.Names.CurrentQualifier); WithQualifierKeyword = CreateSymbol(Constants.Names.WithQualifierFunction); UndefinedLiteral = CreateSymbol(Constants.Names.Undefined); LegacyPackageKeyword = CreateSymbol(Constants.Names.LegacyModuleConfigurationFunctionCall); ModuleKeyword = CreateSymbol(Constants.Names.ModuleConfigurationFunctionCall); TemplateReference = CreateSymbol(Constants.Names.TemplateReference); RuntimeRootNamespaceSymbol = CreateSymbol(Constants.Names.RuntimeRootNamespaceAlias); }
/// <nodoc/> public Expression ParseExpression(RuntimeModelContext runtimeModelContext, AbsolutePath path, string spec, FunctionScope localScope, bool useSemanticNameResolution) { Contract.Requires(runtimeModelContext != null); Contract.Requires(spec != null); var parser = new TypeScript.Net.Parsing.Parser(); // Wrap expression in a function call to make the parser happy. // Currently an object literal '{...};' is not a valid statement. var sourceFile = parser.ParseSourceFileContent( path.ToString(runtimeModelContext.PathTable), @"function createExpression(a: any) {} createExpression(" + spec + ");"); if (sourceFile.ParseDiagnostics.Count != 0) { ReportParseDiagnosticsIfNeeded(runtimeModelContext, sourceFile, path); return(null); } var workspaceConfiguration = WorkspaceConfiguration.CreateForTesting(); var workspace = new Workspace( provider: null, workspaceConfiguration: workspaceConfiguration, modules: new[] { CreateModuleFor(runtimeModelContext, sourceFile) }, failures: Enumerable.Empty <Failure>(), preludeModule: null, configurationModule: null); workspace = SemanticWorkspaceProvider.ComputeSemanticWorkspace(runtimeModelContext.PathTable, workspace, workspaceConfiguration).GetAwaiter().GetResult(); // Because we just created source file to parse, we know exactly what the AST is there. // This information helped to simplify analysis logic and migrate to semantic-base name resolution. var invocation = sourceFile.Statements[1].Cast <IExpressionStatement>().Expression.Cast <ICallExpression>(); // Only for expressions, full names should be preserved. // Only for expressions, no checks for definition before use to avoid contract assertion in location computation. m_conversionConfiguration.UnsafeOptions.DisableDeclarationBeforeUseCheck = true; var converter = CreateAstConverter(sourceFile, runtimeModelContext, path, m_conversionConfiguration, workspace: workspace); return(converter.ConvertExpression(invocation, localScope, useSemanticNameResolution)); }
private static SourceFileParseResult DeserializeAst(RuntimeModelContext runtimeModelContext, ByteContent ast) { var stream = new MemoryStream(ast.Content, 0, ast.Length); // TODO: change to a regular BuildXLReader when we start serializing the qualifier table using (var reader = new QualifierTableAgnosticReader( runtimeModelContext.QualifierTable, stream: stream, debug: false, leaveOpen: false)) { var deserializedResult = SourceFileParseResult.Read( reader, runtimeModelContext.Globals, runtimeModelContext.ModuleRegistry, runtimeModelContext.PathTable); return(deserializedResult); } }
/// <summary> /// Evaluates an expression in the current debugger state context /// </summary> internal Possible <ObjectContext, EvaluateFailure> EvaluateExpression(FrameContext frameContext, string expressionString) { var evalState = (EvaluationState)m_state.GetThreadState(frameContext.ThreadId); var context = evalState.Context; var moduleLiteral = evalState.GetEnvForFrame(frameContext.FrameIndex); var frontEnd = new DScriptFrontEnd(new FrontEndStatistics()); frontEnd.InitializeFrontEnd(context.FrontEndHost, context.FrontEndContext, s_configuration); // We clear the logger before using it. var isClear = m_logger.TryClearCapturedDiagnostics(); // This logger should only be used in the context of one thread, so it should always be possible to clear it Contract.Assert(isClear); RuntimeModelContext runtimeModelContext = new RuntimeModelContext( context.FrontEndHost, context.FrontEndContext, m_logger, context.Package); // We recreate the local scope so the expression is parsed using the same local variables indexes // than the context where it is going to be evaluated var localScope = BuildLocalScopeForLocalVars(context, evalState.GetStackEntryForFrame(frameContext.FrameIndex)); var expression = s_parser.ParseExpression(runtimeModelContext, context.Package.Path, expressionString, localScope, useSemanticNameResolution: false); // If parsing failed, we report it and return // VS code only displays the first error that is sent. So we only send the first one. // An alternative would be to concatenate all errors and send them as a single message, but new lines are not respected by VS Code, // so the concatenation is not very legible. // Anyway, the first error should be good enough for almost all cases if (expression == null) { Contract.Assert(runtimeModelContext.Logger.CapturedDiagnostics.Count > 0); var diagnostic = runtimeModelContext.Logger.CapturedDiagnostics[0]; return(new EvaluateFailure(diagnostic)); } // We clear the logger again since it may contain warnings that didn't prevent the parser from finishing successfully isClear = m_logger.TryClearCapturedDiagnostics(); Contract.Assert(isClear); object expressionResult; // We temporary override the context logger so it doesn't affect the normal evaluation using (var expressionContext = new SnippetEvaluationContext(context, m_logger)) { expressionResult = expression.Eval(expressionContext.GetContextForSnippetEvaluation(), moduleLiteral, evalState.GetArgsForFrame(frameContext.FrameIndex)).Value; // If evaluation failed, we report it and return if (expressionResult.IsErrorValue()) { Contract.Assert(context.Logger.CapturedDiagnostics.Count > 0); var diagnostic = context.Logger.CapturedDiagnostics[0]; return(new EvaluateFailure(diagnostic)); } } return(new ObjectContext(context, expressionResult)); }
private ISourceFile ValidateSourceFile(AbsolutePath path, ISourceFile sourceFile, RuntimeModelContext runtimeModelContext, LoggingContext loggingContext) { var sw = Stopwatch.StartNew(); // Should not analyze file with parser errors, but it is ok to analyze with binding errors. if (!sourceFile.HasDiagnostics()) { m_linter.AnalyzeSpecFile(sourceFile, runtimeModelContext.Logger, loggingContext, runtimeModelContext.PathTable, m_workspace); } m_statistics.AnalysisCompleted(path, sw.Elapsed); return(sourceFile); }
internal static Expression ResolvePath(RuntimeModelContext context, AbsolutePath specPath, string path, in UniversalLocation location)
private SourceFileParseResult ConvertSourceFile(RuntimeModelContext runtimeModelContext, AbsolutePath path, ISourceFile sourceFile) { runtimeModelContext.CancellationToken.ThrowIfCancellationRequested(); // This means that if there is any parse or binding errors conversion won't happen. if (runtimeModelContext.Logger.HasErrors) { return(new SourceFileParseResult(runtimeModelContext.Logger.ErrorCount)); } string specPath = sourceFile.Path.AbsolutePath; // If the serialized AST is available for this file, retrieve it and return instead of converting it if (sourceFile.IsPublicFacade) { var ast = ByteContent.Create(sourceFile.SerializedAst.Item1, sourceFile.SerializedAst.Item2); using (m_statistics.SpecAstDeserialization.Start(specPath)) { return(DeserializeAst(runtimeModelContext, ast)); } } Contract.Assert(!sourceFile.IsPublicFacade, "We are about to do AST conversion, so the corresponding spec file can't be a public facade, we need the real thing"); var converter = CreateAstConverter(sourceFile, runtimeModelContext, path, m_conversionConfiguration, m_workspace); SourceFileParseResult result; using (m_statistics.SpecAstConversion.Start(specPath)) { result = converter.ConvertSourceFile(); } if (runtimeModelContext.Logger.HasErrors) { // Skip serialization step if the error has occurred. return(result); } // At this point we have the computed AST, so we are in a position to generate the public surface of the file (if possible) // and serialize the AST for future reuse. var semanticModel = m_workspace.GetSemanticModel(); Contract.Assert(semanticModel != null); // Observe that here instead of using FrontEndHost.CanUseSpecPublicFacadeAndAst (that we checked for retrieving) we only require // that the associated flag is on. This is because, even though a partial reuse may not have happened, // saving is always a safe operation and the saved results may be available for future builds if (runtimeModelContext.FrontEndHost.FrontEndConfiguration.UseSpecPublicFacadeAndAstWhenAvailable()) { FileContent publicFacadeContent = CreatePublicFacadeContent(sourceFile, semanticModel); #pragma warning disable 4014 ScheduleSavePublicFacadeAndAstAsync(runtimeModelContext, path, sourceFile.Path.AbsolutePath, publicFacadeContent, result).ContinueWith( t => { runtimeModelContext.Logger.ReportFailedToPersistPublicFacadeOrEvaluationAst( runtimeModelContext.LoggingContext, #pragma warning disable SA1129 // Do not use default value type constructor new Location(), #pragma warning restore SA1129 // Do not use default value type constructor t.Exception.ToString()); }, TaskContinuationOptions.OnlyOnFaulted); #pragma warning restore 4014 } return(result); }
/// <summary> /// Factory method that creates a binder. /// </summary> public static Binder Create(RuntimeModelContext runtimeModelContext) { return(new Binder(runtimeModelContext)); }
private IAstConverter CreateAstConverter(ISourceFile sourceFile, RuntimeModelContext runtimeModelContext, AbsolutePath path, AstConversionConfiguration conversionConfiguration, Workspace workspace) { var module = ModuleLiteral.CreateFileModule(path, runtimeModelContext.FrontEndHost.ModuleRegistry, runtimeModelContext.Package, sourceFile.LineMap); return(CreateAstConverter(sourceFile, module, runtimeModelContext, path, conversionConfiguration, workspace)); }
/// <nodoc /> private Binder(RuntimeModelContext runtimeModelContext) { Contract.Requires(runtimeModelContext != null); m_runtimeModelContext = runtimeModelContext; }