Exemple #1
0
        Import ParseImport(
            HashSet <string> importedFiles, Import import, string projectPath,
            PropertyValueCollector propVals, TaskMetadataBuilder taskBuilder, MSBuildSchemaProvider schemaProvider,
            CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

            var           xmlParser = new XmlParser(new XmlRootState(), true);
            ITextDocument textDoc;

            try {
                textDoc = TextEditorFactory.CreateNewDocument(import.Filename, MSBuildTextEditorExtension.MSBuildMimeType);
                xmlParser.Parse(textDoc.CreateReader());
            } catch (Exception ex) {
                LoggingService.LogError("Unhandled error parsing xml document", ex);
                return(import);
            }

            var doc = xmlParser.Nodes.GetRoot();

            import.Document = new MSBuildDocument(import.Filename, false);
            import.Document.Build(
                doc, textDoc, RuntimeInformation, propVals, taskBuilder,
                (imp, sdk) => ResolveImport(importedFiles, null, projectPath, import.Filename, imp, sdk, propVals, taskBuilder, schemaProvider, token)
                );

            import.Document.Schema = schemaProvider.GetSchema(import.Filename, import.Sdk);

            return(import);
        }
        public void LoadCoreSchemas(string name, string sdk)
        {
            var schema = provider.GetSchema(name, sdk, out var loadErrors);

            Assert.NotNull(schema);
            Assert.Zero(loadErrors.Count);
        }
Exemple #3
0
        public static MSBuildRootDocument Parse(
            ITextSource textSource, string filePath, MSBuildRootDocument previous,
            MSBuildSchemaProvider schemaProvider, IRuntimeInformation runtimeInfo,
            ITaskMetadataBuilder taskBuilder,
            CancellationToken token)
        {
            var xmlParser = new XmlTreeParser(new XmlRootState());

            var(xdocument, _) = xmlParser.Parse(textSource.CreateReader());

            var propVals = new PropertyValueCollector(true);

            var doc = new MSBuildRootDocument(filePath)
            {
                XDocument          = xdocument,
                Text               = textSource,
                RuntimeInformation = runtimeInfo
            };

            var importedFiles = new HashSet <string> (StringComparer.OrdinalIgnoreCase);

            if (filePath != null)
            {
                try {
                    doc.Schema = previous?.Schema ?? schemaProvider.GetSchema(filePath, null);
                } catch (Exception ex) {
                    LoggingService.LogError("Error loading schema", ex);
                }
                importedFiles.Add(filePath);
            }

            var parseContext = new MSBuildParserContext(
                runtimeInfo,
                doc,
                previous,
                importedFiles,
                filePath,
                propVals,
                taskBuilder,
                schemaProvider,
                token);

            if (filePath != null)
            {
                doc.FileEvaluationContext = new MSBuildFileEvaluationContext(parseContext.RuntimeEvaluationContext, filePath, filePath);
            }
            else
            {
                doc.FileEvaluationContext = parseContext.RuntimeEvaluationContext;
            }

            string MakeRelativeMSBuildPathAbsolute(string path)
            {
                var dir = Path.GetDirectoryName(doc.Filename);

                path = path.Replace('\\', Path.DirectorySeparatorChar);
                return(Path.GetFullPath(Path.Combine(dir, path)));
            }

            Import TryImportFile(string label, string possibleFile)
            {
                try {
                    var fi = new FileInfo(possibleFile);
                    if (fi.Exists)
                    {
                        var imp = parseContext.GetCachedOrParse(label, possibleFile, null, fi.LastWriteTimeUtc);
                        doc.AddImport(imp);
                        return(imp);
                    }
                } catch (Exception ex) when(parseContext.IsNotCancellation(ex))
                {
                    LoggingService.LogError($"Error importing '{possibleFile}'", ex);
                }
                return(null);
            }

            Import TryImportSibling(string ifHasThisExtension, string thenTryThisExtension)
            {
                if (filePath == null)
                {
                    return(null);
                }
                var extension = Path.GetExtension(filePath);

                if (string.Equals(ifHasThisExtension, extension, StringComparison.OrdinalIgnoreCase))
                {
                    var siblingFilename = Path.ChangeExtension(filePath, thenTryThisExtension);
                    return(TryImportFile("(implicit)", siblingFilename));
                }
                return(null);
            }

            void TryImportIntellisenseImports(MSBuildSchema schema)
            {
                foreach (var intellisenseImport in schema.IntelliSenseImports)
                {
                    TryImportFile("(from schema)", MakeRelativeMSBuildPathAbsolute(intellisenseImport));
                }
            }

            try {
                //if this is a targets file, try to import the props _at the top_
                var propsImport = TryImportSibling(".targets", ".props");

                // this currently only happens in the root file
                // it's a quick hack to allow files to get some basic intellisense by
                // importing the files _that they themselves expect to be imported from_.
                // we also try to load them from the sibling props, as a paired targets/props
                // will likely share a schema file.
                var schema = doc.Schema ?? propsImport?.Document?.Schema;
                if (schema != null)
                {
                    TryImportIntellisenseImports(doc.Schema);
                }

                doc.Build(xdocument, textSource, parseContext);

                //if this is a props file, try to import the targets _at the bottom_
                var targetsImport = TryImportSibling(".props", ".targets");

                //and if we didn't load intellisense import already, try to load them from the sibling targets
                if (schema == null && targetsImport?.Document?.Schema != null)
                {
                    TryImportIntellisenseImports(targetsImport.Document.Schema);
                }
            } catch (Exception ex) when(parseContext.IsNotCancellation(ex))
            {
                LoggingService.LogError($"Error building document '{filePath ?? "[unnamed]"}'", ex);
            }

            try {
                var binpath = parseContext.RuntimeInformation.BinPath;
                foreach (var t in Directory.GetFiles(binpath, "*.tasks"))
                {
                    doc.LoadTasks(parseContext, "(core tasks)", t);
                }
                foreach (var t in Directory.GetFiles(binpath, "*.overridetasks"))
                {
                    doc.LoadTasks(parseContext, "(core overridetasks)", t);
                }
            } catch (Exception ex) when(parseContext.IsNotCancellation(ex))
            {
                LoggingService.LogError("Error resolving tasks", ex);
            }

            try {
                if (previous != null)
                {
                    // try to recover some values that may have been collected from the imports, as they
                    // will not have been re-evaluated
                    var fx = previous.Frameworks.FirstOrDefault();
                    if (fx != null)
                    {
                        propVals.Collect("TargetFramework", fx.GetShortFolderName());
                        propVals.Collect("TargetFrameworkVersion", FrameworkInfoProvider.FormatDisplayVersion(fx.Version));
                        propVals.Collect("TargetFrameworkIdentifier", fx.Framework);
                    }
                }
                doc.Frameworks = propVals.GetFrameworks();
            } catch (Exception ex) {
                LoggingService.LogError("Error determining project framework", ex);
                doc.Frameworks = new List <NuGetFramework> ();
            }

            try {
                //this has to run in a second pass so that it runs after all the schemas are loaded
                var validator = new MSBuildDocumentValidator();
                validator.Run(doc.XDocument, textSource, doc);
            } catch (Exception ex) when(parseContext.IsNotCancellation(ex))
            {
                LoggingService.LogError("Error in validation", ex);
            }

            return(doc);
        }
Exemple #4
0
        public static MSBuildRootDocument Parse(
            string filename, ITextSource textSource, MSBuildRootDocument previous,
            MSBuildSchemaProvider schemaProvider, IRuntimeInformation runtimeInfo,
            CancellationToken token)
        {
            var xmlParser = new XmlParser(new XmlRootState(), true);

            try {
                xmlParser.Parse(textSource.CreateReader());
            } catch (Exception ex) {
                LoggingService.LogError("Unhandled error parsing xml document", ex);
            }

            var xdocument = xmlParser.Nodes.GetRoot();

            if (xdocument != null && xdocument.RootElement != null)
            {
                if (!xdocument.RootElement.IsEnded)
                {
                    xdocument.RootElement.End(xmlParser.Location);
                }
            }

            //FIXME: unfortunately the XML parser's regions only have line+col locations, not offsets
            //so we need to create an ITextDocument to extract tag bodies
            //we should fix this by changing the parser to use offsets for the tag locations
            ITextDocument textDoc = textSource as ITextDocument
                                    ?? TextEditorFactory.CreateNewDocument(textSource, filename, MSBuildTextEditorExtension.MSBuildMimeType);

            var propVals = new PropertyValueCollector(true);

            string projectPath = filename;

            var doc = new MSBuildRootDocument(filename)
            {
                XDocument          = xdocument,
                Text               = textDoc,
                RuntimeInformation = runtimeInfo
            };

            doc.Errors.AddRange(xmlParser.Errors);

            try {
                doc.Schema = previous?.Schema ?? schemaProvider.GetSchema(filename, null);
            } catch (Exception ex) {
                LoggingService.LogError("Error loading schema", ex);
            }

            var importedFiles = new HashSet <string> (StringComparer.OrdinalIgnoreCase)
            {
                filename
            };

            var taskBuilder = new TaskMetadataBuilder(doc);

            var extension = Path.GetExtension(filename);

            string MakeRelativeMSBuildPathAbsolute(string path)
            {
                var dir = Path.GetDirectoryName(doc.Filename);

                path = path.Replace('\\', Path.DirectorySeparatorChar);
                return(Path.GetFullPath(Path.Combine(dir, path)));
            }

            Import TryImportFile(string possibleFile)
            {
                try {
                    var fi = new FileInfo(possibleFile);
                    if (fi.Exists)
                    {
                        var imp = doc.GetCachedOrParse(importedFiles, previous, possibleFile, null, fi.LastWriteTimeUtc, projectPath, propVals, taskBuilder, schemaProvider, token);
                        doc.Imports.Add(possibleFile, imp);
                        return(imp);
                    }
                } catch (Exception ex) {
                    LoggingService.LogError($"Error importing '{possibleFile}'", ex);
                }
                return(null);
            }

            Import TryImportSibling(string ifHasThisExtension, string thenTryThisExtension)
            {
                if (string.Equals(ifHasThisExtension, extension, StringComparison.OrdinalIgnoreCase))
                {
                    var siblingFilename = Path.ChangeExtension(filename, thenTryThisExtension);
                    return(TryImportFile(siblingFilename));
                }
                return(null);
            }

            void TryImportIntellisenseImports(MSBuildSchema schema)
            {
                foreach (var intellisenseImport in schema.IntelliSenseImports)
                {
                    TryImportFile(MakeRelativeMSBuildPathAbsolute(intellisenseImport));
                }
            }

            try {
                //if this is a targets file, try to import the props _at the top_
                var propsImport = TryImportSibling(".targets", ".props");

                // this currently only happens in the root file
                // it's a quick hack to allow files to get some basic intellisense by
                // importing the files _that they themselves expect to be imported from_.
                // we also try to load them from the sibling props, as a paired targets/props
                // will likely share a schema file.
                var schema = doc.Schema ?? propsImport?.Document?.Schema;
                if (schema != null)
                {
                    TryImportIntellisenseImports(doc.Schema);
                }

                doc.Build(
                    xdocument, textDoc, runtimeInfo, propVals, taskBuilder,
                    (imp, sdk) => doc.ResolveImport(importedFiles, previous, projectPath, filename, imp, sdk, propVals, taskBuilder, schemaProvider, token)
                    );

                //if this is a props file, try to import the targets _at the bottom_
                var targetsImport = TryImportSibling(".props", ".targets");

                //and if we didn't load intellisense import already, try to load them from the sibling targets
                if (schema == null && targetsImport?.Document?.Schema != null)
                {
                    TryImportIntellisenseImports(targetsImport.Document.Schema);
                }
            } catch (Exception ex) {
                LoggingService.LogError($"Error building document '{projectPath}'", ex);
            }

            try {
                var binpath = doc.RuntimeInformation.GetBinPath();
                foreach (var t in Directory.GetFiles(binpath, "*.tasks"))
                {
                    doc.LoadTasks(importedFiles, previous, t, propVals, taskBuilder, schemaProvider, token);
                }
                foreach (var t in Directory.GetFiles(binpath, "*.overridetasks"))
                {
                    doc.LoadTasks(importedFiles, previous, t, propVals, taskBuilder, schemaProvider, token);
                }
            } catch (Exception ex) {
                LoggingService.LogError("Error resolving tasks", ex);
            }

            try {
                if (previous != null)
                {
                    // try to recover some values that may have been collected from the imports, as they
                    // will not have been re-evaluated
                    var fx = previous.Frameworks.FirstOrDefault();
                    if (fx != null)
                    {
                        propVals.Collect("TargetFramework", fx.GetShortFolderName());
                        propVals.Collect("TargetFrameworkVersion", FrameworkInfoProvider.FormatDisplayVersion(fx.Version));
                        propVals.Collect("TargetFrameworkIdentifier", fx.Framework);
                    }
                }
                doc.Frameworks = propVals.GetFrameworks();
            } catch (Exception ex) {
                LoggingService.LogError("Error determining project framework", ex);
                doc.Frameworks = new List <NuGetFramework> ();
            }

            try {
                //this has to run in a second pass so that it runs after all the schemas are loaded
                var validator = new MSBuildDocumentValidator();
                validator.Run(doc.XDocument, filename, textDoc, doc);
            } catch (Exception ex) {
                LoggingService.LogError("Error in validation", ex);
            }

            return(doc);
        }
Exemple #5
0
        public static MSBuildRootDocument Parse(
            string filename, ITextSource textSource, MSBuildRootDocument previous,
            MSBuildSchemaProvider schemaProvider, IRuntimeInformation runtimeInfo,
            CancellationToken token)
        {
            var xmlParser = new XmlParser(new XmlRootState(), true);

            try {
                xmlParser.Parse(textSource.CreateReader());
            } catch (Exception ex) {
                LoggingService.LogError("Unhandled error parsing xml document", ex);
            }

            var xdocument = xmlParser.Nodes.GetRoot();

            if (xdocument != null && xdocument.RootElement != null)
            {
                if (!xdocument.RootElement.IsEnded)
                {
                    xdocument.RootElement.End(xmlParser.Location);
                }
            }

            //FIXME: unfortunately the XML parser's regions only have line+col locations, not offsets
            //so we need to create an ITextDocument to extract tag bodies
            //we should fix this by changing the parser to use offsets for the tag locations
            ITextDocument textDoc = textSource as ITextDocument
                                    ?? TextEditorFactory.CreateNewDocument(textSource, filename, MSBuildTextEditorExtension.MSBuildMimeType);

            var propVals = new PropertyValueCollector(true);

            string projectPath = filename;

            var doc = new MSBuildRootDocument(filename);

            doc.XDocument          = xdocument;
            doc.Text               = textDoc;
            doc.RuntimeInformation = runtimeInfo;
            doc.Errors.AddRange(xmlParser.Errors);

            var importedFiles = new HashSet <string> (StringComparer.OrdinalIgnoreCase);

            importedFiles.Add(filename);

            var taskBuilder = new TaskMetadataBuilder(doc);

            try {
                doc.Build(
                    xdocument, textDoc, runtimeInfo, propVals, taskBuilder,
                    (imp, sdk) => doc.ResolveImport(importedFiles, previous, projectPath, filename, imp, sdk, propVals, taskBuilder, schemaProvider, token)
                    );
            } catch (Exception ex) {
                LoggingService.LogError("Error building document", ex);
            }

            try {
                var binpath = doc.RuntimeInformation.GetBinPath();
                foreach (var t in Directory.GetFiles(binpath, "*.tasks"))
                {
                    doc.LoadTasks(importedFiles, previous, t, propVals, taskBuilder, schemaProvider, token);
                }
                foreach (var t in Directory.GetFiles(binpath, "*.overridetasks"))
                {
                    doc.LoadTasks(importedFiles, previous, t, propVals, taskBuilder, schemaProvider, token);
                }
            } catch (Exception ex) {
                LoggingService.LogError("Error resolving tasks", ex);
            }


            try {
                if (previous != null)
                {
                    // try to recover some values that may have been collected from the imports, as they
                    // will not have been re-evaluated
                    var fx = previous.Frameworks.FirstOrDefault();
                    if (fx != null)
                    {
                        propVals.Collect("TargetFramework", fx.GetShortFolderName());
                        propVals.Collect("TargetFrameworkVersion", FrameworkInfoProvider.FormatDisplayVersion(fx.Version));
                        propVals.Collect("TargetFrameworkIdentifier", fx.Framework);
                    }
                }
                doc.Frameworks = propVals.GetFrameworks();
            } catch (Exception ex) {
                LoggingService.LogError("Error determining project framework", ex);
                doc.Frameworks = new List <NuGetFramework> ();
            }

            try {
                doc.Schema = previous?.Schema ?? schemaProvider.GetSchema(filename, null);
            } catch (Exception ex) {
                LoggingService.LogError("Error loading schema", ex);
            }

            try {
                //this has to run in a second pass so that it runs after all the schemas are loaded
                var validator = new MSBuildDocumentValidator();
                validator.Run(doc.XDocument, filename, textDoc, doc);
            } catch (Exception ex) {
                LoggingService.LogError("Error in validation", ex);
            }

            return(doc);
        }