public static bool CanNavigate(MSBuildRootDocument doc, int offset, MSBuildResolveResult rr)
        {
            if (rr == null)
            {
                return(false);
            }

            var annotations = GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset);

            if (annotations != null && annotations.Any())
            {
                return(true);
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Target)
            {
                return(true);
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder)
            {
                return(true);
            }

            return(false);
        }
        public static List <MSBuildNavigationResult> ResolveAll(MSBuildRootDocument doc, int offset, int length)
        {
            var visitor = new MSBuildNavigationVisitor();

            visitor.Run(doc, offset, length);
            return(visitor.Navigations);
        }
Ejemplo n.º 3
0
        public static IEnumerable <ISymbol> GetComparandCompletions(MSBuildRootDocument doc, IReadOnlyList <ExpressionNode> variables)
        {
            var names = new HashSet <string> ();

            foreach (var variable in variables)
            {
                VariableInfo info;
                switch (variable)
                {
                case ExpressionProperty ep:
                    if (ep.IsSimpleProperty)
                    {
                        info = doc.GetProperty(ep.Name, true) ?? new PropertyInfo(ep.Name, null, false);
                        break;
                    }
                    continue;

                case ExpressionMetadata em:
                    info = doc.GetMetadata(em.ItemName, em.MetadataName, true) ?? new MetadataInfo(em.MetadataName, null, false);
                    break;

                default:
                    continue;
                }

                if (info == null)
                {
                    continue;
                }

                IEnumerable <ISymbol> cinfos;
                if (info.CustomType != null && info.CustomType.Values.Count > 0)
                {
                    cinfos = info.CustomType.Values;
                }
                else
                {
                    var kind = info.InferValueKindIfUnknown();
                    cinfos = MSBuildCompletionExtensions.GetValueCompletions(kind, doc);
                }

                if (cinfos != null)
                {
                    foreach (var ci in cinfos)
                    {
                        if (names.Add(ci.Name))
                        {
                            yield return(ci);
                        }
                    }
                }
            }
        }
        public static IEnumerable <T> GetAnnotationsAtOffset <T> (MSBuildRootDocument doc, int offset)
        {
            var xobj = doc.XDocument.FindNodeAtOffset(offset);

            if (xobj == null)
            {
                return(null);
            }
            return(doc.Annotations
                   .GetMany <T> (xobj)
                   .Where(a => !(a is IRegionAnnotation ra) || ra.Span.Contains(offset)));
        }
 public static MSBuildNavigationResult GetPathFromNode(ExpressionNode node, MSBuildRootDocument document)
 {
     try {
         var path = MSBuildCompletionExtensions.EvaluateExpressionAsPaths(node, document).FirstOrDefault();
         if (path != null && File.Exists(path))
         {
             return(new MSBuildNavigationResult(
                        new[] { path }, node.Offset, node.Length
                        ));
         }
     } catch (Exception ex) {
         LoggingService.LogError($"Error checking path for file '{node}'", ex);
     }
     return(null);
 }
Ejemplo n.º 6
0
        public static IEnumerable <ISymbol> GetCompletionInfos(
            MSBuildResolveResult rr,
            TriggerState trigger, MSBuildValueKind kind,
            ExpressionNode triggerExpression, int triggerLength,
            MSBuildRootDocument doc, IFunctionTypeProvider functionTypeProvider)
        {
            switch (trigger)
            {
            case TriggerState.Value:
                return(MSBuildCompletionExtensions.GetValueCompletions(kind, doc, rr, triggerExpression));

            case TriggerState.ItemName:
                return(doc.GetItems());

            case TriggerState.MetadataName:
                return(doc.GetMetadata(null, true));

            case TriggerState.PropertyName:
                return(doc.GetProperties(true));

            case TriggerState.MetadataOrItemName:
                return(((IEnumerable <ISymbol>)doc.GetItems()).Concat(doc.GetMetadata(null, true)));

            case TriggerState.DirectorySeparator:
                return(MSBuildCompletionExtensions.GetFilenameCompletions(kind, doc, triggerExpression, triggerLength, rr));

            case TriggerState.PropertyFunctionName:
                return(functionTypeProvider.GetPropertyFunctionNameCompletions(triggerExpression));

            case TriggerState.ItemFunctionName:
                return(functionTypeProvider.GetItemFunctionNameCompletions());

            case TriggerState.PropertyFunctionClassName:
                return(functionTypeProvider.GetClassNameCompletions());

            case TriggerState.None:
                break;

            case TriggerState.BareFunctionArgumentValue:
                //FIXME: enum completion etc
                return(MSBuildValueKind.Bool.GetSimpleValues(true));

            case TriggerState.ConditionFunctionName:
                return(Builtins.ConditionFunctions.Values);
            }
            throw new InvalidOperationException($"Unhandled trigger type {trigger}");
        }
        public static MSBuildNavigationResult GetNavigation(
            MSBuildRootDocument doc, int offset, MSBuildResolveResult rr)
        {
            if (rr == null)
            {
                return(null);
            }

            var annotations     = GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset);
            var firstAnnotation = annotations.FirstOrDefault();

            if (firstAnnotation != null)
            {
                return(new MSBuildNavigationResult(
                           annotations.Select(a => a.Path).ToArray(), firstAnnotation.Span.Start, firstAnnotation.Span.Length
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Target)
            {
                return(new MSBuildNavigationResult(
                           MSBuildReferenceKind.Target, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder)
            {
                return(new MSBuildNavigationResult(
                           (string[])rr.Reference, rr.ReferenceOffset, rr.ReferenceLength
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Task)
            {
                var task = doc.GetTask((string)rr.Reference);
                if (task.DeclaredInFile != null)
                {
                    return(new MSBuildNavigationResult(
                               MSBuildReferenceKind.Task, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength,
                               task.DeclaredInFile, task.DeclaredAtOffset
                               ));
                }
            }

            return(null);
        }
        public MSBuildParserContext(
            IRuntimeInformation runtimeInformation,
            MSBuildRootDocument doc,
            MSBuildRootDocument previous,
            HashSet <string> importedFiles,
            string projectPath,
            PropertyValueCollector propVals,
            ITaskMetadataBuilder taskBuilder,
            MSBuildSchemaProvider schemaProvider,
            CancellationToken token)
        {
            RuntimeInformation   = runtimeInformation;
            RootDocument         = doc;
            PreviousRootDocument = previous;
            ImportedFiles        = importedFiles;
            ProjectPath          = projectPath;
            PropertyCollector    = propVals;
            TaskBuilder          = taskBuilder;
            SchemaProvider       = schemaProvider;
            Token = token;

            RuntimeEvaluationContext = new MSBuildRuntimeEvaluationContext(runtimeInformation);
        }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
 public void Run(MSBuildRootDocument doc, int offset = 0, int length = 0, CancellationToken token = default)
 {
     Run(doc.XDocument, doc.Text, doc, offset, length, token);
 }
Ejemplo n.º 11
0
 public void Run(MSBuildRootDocument doc, int offset = 0, int length = 0)
 {
     Run(doc.XDocument, doc.Text, doc, offset, length);
 }
Ejemplo n.º 12
0
        public static MSBuildNavigationResult GetNavigation(
            MSBuildRootDocument doc, int offset, MSBuildResolveResult rr)
        {
            if (rr == null)
            {
                return(null);
            }

            var annotations     = GetAnnotationsAtOffset <NavigationAnnotation> (doc, offset);
            var firstAnnotation = annotations.FirstOrDefault();

            if (firstAnnotation != null)
            {
                var arr = GetAnnotatedPaths().ToArray();
                if (arr.Length == 0)
                {
                    return(null);
                }
                return(new MSBuildNavigationResult(arr, firstAnnotation.Span.Start, firstAnnotation.Span.Length));
            }

            IEnumerable <string> GetAnnotatedPaths()
            {
                foreach (var a in annotations)
                {
                    if (a.IsSdk)
                    {
                        yield return(Path.Combine(a.Path, "Sdk.props"));

                        yield return(Path.Combine(a.Path, "Sdk.targets"));
                    }
                    else
                    {
                        yield return(a.Path);
                    }
                }
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Target)
            {
                return(new MSBuildNavigationResult(MSBuildReferenceKind.Target, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.FileOrFolder)
            {
                return(new MSBuildNavigationResult(
                           (string[])rr.Reference, rr.ReferenceOffset, rr.ReferenceLength
                           ));
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.Task)
            {
                var task = doc.GetTask((string)rr.Reference);
                if (task.DeclaredInFile != null)
                {
                    return(new MSBuildNavigationResult(
                               MSBuildReferenceKind.Task, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength,
                               task.DeclaredInFile, task.DeclaredAtOffset
                               ));
                }
            }

            if (rr.ReferenceKind == MSBuildReferenceKind.NuGetID)
            {
                return(new MSBuildNavigationResult(MSBuildReferenceKind.NuGetID, (string)rr.Reference, rr.ReferenceOffset, rr.ReferenceLength));
            }

            return(null);
        }