static void GetPropertiesToTrack(PropertyValueCollector propertyVals, MSBuildProjectElement project)
        {
            foreach (var el in project.Elements)
            {
                if (el is MSBuildImportElement imp)
                {
                    var impAtt = imp.ProjectAttribute?.Value;
                    if (impAtt != null)
                    {
                        MarkProperties(impAtt);
                    }
                }
                else if (el is MSBuildUsingTaskElement ut)
                {
                    var afAtt = ut.AssemblyFileAttribute?.Value;
                    if (afAtt != null)
                    {
                        MarkProperties(afAtt);
                    }
                }
            }

            void MarkProperties(ExpressionNode expr)
            {
                foreach (var prop in expr.WithAllDescendants().OfType <ExpressionProperty> ())
                {
                    propertyVals.Mark(prop.Name);
                }
            }
        }
        void ResolveImports(MSBuildProjectElement project, MSBuildParserContext context)
        {
            var sdks = ResolveSdks(project, context).ToList();

            //tag the properties we need to track for the imports
            GetPropertiesToTrack(context.PropertyCollector, project);

            var importResolver = context.CreateImportResolver(Filename);

            AddSdkProps(sdks, context.PropertyCollector, importResolver);

            void ExtractProperties(MSBuildPropertyGroupElement pg)
            {
                foreach (var prop in pg.Elements)
                {
                    context.PropertyCollector.Collect(prop.ElementName, prop.Value);
                }
            }

            foreach (var el in project.Elements)
            {
                switch (el)
                {
                case MSBuildPropertyGroupElement pg:
                    ExtractProperties(pg);
                    break;

                case MSBuildChooseElement choose:
                    foreach (var c in choose.Elements)
                    {
                        foreach (var pg in c.GetElements <MSBuildPropertyGroupElement> ())
                        {
                            ExtractProperties(pg);
                        }
                    }
                    break;

                case MSBuildImportElement imp:
                    ResolveImport(imp, context, importResolver);
                    break;
                }
            }

            AddSdkTargets(sdks, context.PropertyCollector, importResolver);
        }
        IEnumerable <(string id, string path, TextSpan span)> ResolveSdks(MSBuildProjectElement project, MSBuildParserContext context)
        {
            var sdksAtt = project.SdkAttribute?.XAttribute;

            if (sdksAtt == null)
            {
                yield break;
            }

            string sdks = sdksAtt.Value;

            if (string.IsNullOrEmpty(sdks))
            {
                yield break;
            }

            int offset = IsToplevel ? sdksAtt.ValueOffset : sdksAtt.Span.Start;

            foreach (var sdk in SplitSdkValue(offset, sdksAtt.Value))
            {
                if (sdk.id == null)
                {
                    if (IsToplevel)
                    {
                        Diagnostics.Add(CoreDiagnostics.EmptySdkAttribute, sdk.span);
                    }
                }
                else
                {
                    var sdkPath = context.GetSdkPath(this, sdk.id, sdk.span);
                    if (sdkPath != null)
                    {
                        yield return(sdk.id, sdkPath, sdk.span);
                    }
                    if (IsToplevel)
                    {
                        Annotations.Add(sdksAtt, new NavigationAnnotation(sdkPath, sdk.span)
                        {
                            IsSdk = true
                        });
                    }
                }
            }
        }
        public void Build(XDocument doc, MSBuildParserContext context)
        {
            var project = doc.Nodes.OfType <XElement> ().FirstOrDefault(x => x.NameEquals("Project", true));

            if (project == null)
            {
                //TODO: error
                return;
            }

            var projectElement = new MSBuildProjectElement(project);

            if (IsToplevel)
            {
                ProjectElement = projectElement;
            }

            ResolveImports(projectElement, context);

            InferredSchema = MSBuildInferredSchema.Build(projectElement, Filename, IsToplevel, context);
        }