Beispiel #1
0
        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
            }));
        }
Beispiel #2
0
        private ISourceFile ReportDiagnosticsAndValidateSourceFile(RuntimeModelContext runtimeModelContext, AbsolutePath path,
                                                                   ISourceFile result)
        {
            ReportParseDiagnosticsIfNeeded(runtimeModelContext, result, path);

            return(ValidateSourceFile(path, result, runtimeModelContext, runtimeModelContext.LoggingContext));
        }
Beispiel #3
0
        /// <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));
        }
Beispiel #4
0
        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));
        }
Beispiel #5
0
        /// <nodoc />
        private Binder(RuntimeModelContext runtimeModelContext)
        {
            Contract.Requires(runtimeModelContext != null);

            m_runtimeModelContext        = runtimeModelContext;
            m_runtimeRootNamespaceSymbol = SymbolAtom.Create(runtimeModelContext.StringTable, Constants.Names.RuntimeRootNamespaceAlias);
        }
Beispiel #6
0
        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));
        }
Beispiel #7
0
        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));
                }
            }
        }
Beispiel #8
0
        /// <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));
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        /// <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;
 }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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());
            }
        }
Beispiel #14
0
        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);
        }
Beispiel #16
0
        /// <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));
        }
Beispiel #17
0
        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);
            }
        }
Beispiel #18
0
        /// <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));
        }
Beispiel #19
0
        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);
        }
Beispiel #20
0
 internal static Expression ResolvePath(RuntimeModelContext context, AbsolutePath specPath, string path, in UniversalLocation location)
Beispiel #21
0
        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);
        }
Beispiel #22
0
 /// <summary>
 /// Factory method that creates a binder.
 /// </summary>
 public static Binder Create(RuntimeModelContext runtimeModelContext)
 {
     return(new Binder(runtimeModelContext));
 }
Beispiel #23
0
        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));
        }
Beispiel #24
0
        /// <nodoc />
        private Binder(RuntimeModelContext runtimeModelContext)
        {
            Contract.Requires(runtimeModelContext != null);

            m_runtimeModelContext = runtimeModelContext;
        }