示例#1
0
        protected override void VisitValueExpression(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, MSBuildValueKind kind, ExpressionNode node)
        {
            if (kind.GetScalarType() != MSBuildValueKind.TargetName)
            {
                return;
            }
            bool isDeclaration = !kind.AllowExpressions();

            switch (node)
            {
            case ListExpression list:
                foreach (var c in list.Nodes)
                {
                    if (c is ExpressionText l)
                    {
                        CheckMatch(l, isDeclaration);
                    }
                }
                break;

            case ExpressionText lit:
                CheckMatch(lit, isDeclaration);
                break;
            }
        }
 protected override void VisitResolvedAttribute(
     XElement element, XAttribute attribute,
     MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute)
 {
     VisitAttributeValue(element, attribute, resolvedElement, resolvedAttribute);
     base.VisitResolvedAttribute(element, attribute, resolvedElement, resolvedAttribute);
 }
示例#3
0
        protected override void VisitValueExpression(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, MSBuildValueKind kind, ExpressionNode node)
        {
            //these are things like <Foo Include="@(Bar)" RemoveMetadata="SomeBarMetadata" />
            if (kind.GetScalarType() == MSBuildValueKind.MetadataName)
            {
                var expr = GetIncludeExpression(element);
                if (expr != null && expr
                    .WithAllDescendants()
                    .OfType <ExpressionItemName> ()
                    .Any(n => IsItemNameMatch(n.ItemName))
                    )
                {
                    switch (node)
                    {
                    case ListExpression list:
                        foreach (var c in list.Nodes)
                        {
                            if (c is ExpressionText l)
                            {
                                CheckMatch(l);
                                break;
                            }
                        }
                        break;

                    case ExpressionText lit:
                        CheckMatch(lit);
                        break;
                    }
                }

                void CheckMatch(ExpressionText t)
                {
                    //FIXME: get rid of this trim
                    if (t.IsPure && IsMatch(t.Value.Trim()))
                    {
                        Results.Add((t.Offset, t.Length, ReferenceUsage.Read));
                    }
                }

                return;
            }

            foreach (var n in node.WithAllDescendants())
            {
                switch (n)
                {
                case ExpressionMetadata em:
                    var iname = em.GetItemName();
                    if (iname != null && IsItemNameMatch(iname) && IsMatch(em.MetadataName))
                    {
                        Results.Add((em.MetadataNameOffset, em.MetadataName.Length, ReferenceUsage.Read));
                    }
                    break;
                }
            }
        }
        public void Run(XElement element, MSBuildLanguageElement resolvedElement, string filename, ITextSource textDocument, MSBuildDocument document, int offset = 0, int length = 0)
        {
            Filename  = filename;
            Document  = document;
            Extension = System.IO.Path.GetExtension(filename);

            //HACK: we should really use the ITextSource directly, but since the XML parser positions are
            //currently line/col, we need a TextDocument to convert to offsets
            TextDocument = textDocument as IReadonlyTextDocument
                           ?? TextEditorFactory.CreateNewReadonlyDocument(
                textDocument, filename, MSBuildTextEditorExtension.MSBuildMimeType
                );

            range = new DocumentRegion(
                TextDocument.OffsetToLocation(offset),
                length > 0
                                        ? TextDocument.OffsetToLocation(length + offset)
                                        : new DocumentLocation(int.MaxValue, int.MaxValue));

            if (resolvedElement != null)
            {
                VisitResolvedElement(element, resolvedElement);
            }
            else if (element != null)
            {
                ResolveAndVisit(element, null);
            }
        }
        public void Build(
            XDocument doc, ITextSource textSource,
            MSBuildParserContext context)
        {
            var project = doc.Nodes.OfType <XElement> ().FirstOrDefault(x => x.Name == xnProject);

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

            var sdks = ResolveSdks(context, project).ToList();

            var pel = MSBuildLanguageElement.Get("Project");

            GetPropertiesToTrack(context.PropertyCollector, project);

            var importResolver = context.CreateImportResolver(Filename);

            AddSdkProps(sdks, context.PropertyCollector, importResolver);

            var resolver = new MSBuildSchemaBuilder(IsToplevel, context, importResolver);

            resolver.Run(doc, textSource, this);

            AddSdkTargets(sdks, context.PropertyCollector, importResolver);
        }
示例#6
0
 public ElementDiagnosticContext(MSBuildDocument document, MSBuildLanguageElement element, Action <MSBuildDiagnostic> reportDiagnostic, CancellationToken cancellationToken)
 {
     Document = document;
     Element  = element;
     this.reportDiagnostic = reportDiagnostic;
     CancellationToken     = cancellationToken;
 }
        void ResolveAttributesAndValue(XElement element, MSBuildLanguageElement resolved)
        {
            foreach (var att in element.Attributes)
            {
                if (att.Region.End < range.Begin)
                {
                    continue;
                }
                if (att.Region.Begin > range.End)
                {
                    return;
                }
                var resolvedAtt = resolved.GetAttribute(att.Name.FullName);
                if (resolvedAtt != null)
                {
                    VisitResolvedAttribute(element, att, resolved, resolvedAtt);
                    continue;
                }
                VisitUnknownAttribute(element, att);
            }

            if (resolved.ValueKind != MSBuildValueKind.Nothing && resolved.ValueKind != MSBuildValueKind.Data)
            {
                VisitElementValue(element, resolved);
                return;
            }
        }
示例#8
0
        public void Build(
            XDocument doc, ITextDocument textDocument,
            IRuntimeInformation runtime, PropertyValueCollector propVals,
            TaskMetadataBuilder taskBuilder,
            ImportResolver resolveImport)
        {
            var project = doc.Nodes.OfType <XElement> ().FirstOrDefault(x => x.Name == xnProject);

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

            var sdks = ResolveSdks(runtime, project, textDocument).ToList();

            var pel = MSBuildLanguageElement.Get("Project");

            GetPropertiesToTrack(propVals, project);

            AddSdkProps(sdks, propVals, resolveImport);

            var resolver = new MSBuildSchemaBuilder(IsToplevel, runtime, propVals, taskBuilder, resolveImport);

            resolver.Run(doc, Filename, textDocument, this);

            AddSdkTargets(sdks, propVals, resolveImport);
        }
示例#9
0
        void VisitElementValue(XElement element, MSBuildLanguageElement resolved)
        {
            if (element.IsSelfClosing || !element.IsEnded)
            {
                return;
            }

            var begin = element.Span.End;
            int end   = begin;

            if (element.IsClosed && element.FirstChild == null)
            {
                end = element.ClosingTag.Span.Start;
            }
            else
            {
                //HACK: in some cases GetCharAt can throw at the end of the document even with TextDocument.Length check
                try {
                    for (; end < (TextSource.Length + 1) && TextSource.GetCharAt(end) != '<'; end++)
                    {
                    }
                } catch {
                    end--;
                }
            }
            var text = TextSource.GetTextBetween(begin, end);

            VisitElementValue(element, resolved, text, begin);
        }
示例#10
0
        protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
        {
            switch (resolved.SyntaxKind)
            {
            case MSBuildSyntaxKind.Task:
                if (IsMatch(element.Name.Name))
                {
                    Results.Add((element.NameOffset, element.Name.Name.Length, ReferenceUsage.Read));
                }
                break;

            case MSBuildSyntaxKind.UsingTask:
                var nameAtt = element.Attributes.Get(new XName("TaskName"), true);
                if (nameAtt != null && !string.IsNullOrEmpty(nameAtt.Value))
                {
                    var    nameIdx = nameAtt.Value.LastIndexOf('.') + 1;
                    string name    = nameIdx > 0 ? nameAtt.Value.Substring(nameIdx) : nameAtt.Value;
                    if (IsMatch(name))
                    {
                        Results.Add((nameAtt.ValueOffset + nameIdx, name.Length, ReferenceUsage.Declaration));
                    }
                }
                break;
            }
            base.VisitResolvedElement(element, resolved);
        }
示例#11
0
 protected override void VisitValueExpression(
     XElement element, XAttribute attribute,
     MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
     ValueInfo info, MSBuildValueKind kind, ExpressionNode node)
 {
     foreach (var n in node.WithAllDescendants())
     {
         switch (n)
         {
         case ExpressionFunctionName func:
             if (func.Parent is ExpressionPropertyFunctionInvocation inv)
             {
                 string baseName = StripGetPrefix(func.Name);
                 if (IsMatch(baseName))
                 {
                     //TODO: should we be fuzzy here and accept "unknown"?
                     var resolvedKind = functionTypeProvider.ResolveType(inv);
                     if (resolvedKind == MSBuildValueKind.Unknown)
                     {
                         resolvedKind = MSBuildValueKind.String;
                     }
                     if (resolvedKind == valueKind)
                     {
                         Results.Add((func.Offset, func.Length, ReferenceUsage.Read));
                     }
                 }
             }
             break;
         }
     }
 }
示例#12
0
        protected override void VisitValueExpression(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, MSBuildValueKind kind, ExpressionNode node)
        {
            foreach (var n in node.WithAllDescendants())
            {
                switch (n)
                {
                case ExpressionItemName ei:
                    if (IsMatch(ei.Name))
                    {
                        Results.Add((ei.Offset, ei.Name.Length, ReferenceUsage.Read));
                    }
                    break;

                case ExpressionMetadata em:
                    if (em.IsQualified && IsMatch(em.ItemName))
                    {
                        Results.Add((em.ItemNameOffset, em.ItemName.Length, ReferenceUsage.Read));
                    }
                    break;
                }
            }
        }
        void VisitElementValue(XElement element, MSBuildLanguageElement resolved)
        {
            if (element.FirstChild != null || resolved.ValueKind == MSBuildValueKind.Data || resolved.ValueKind == MSBuildValueKind.Nothing)
            {
                return;
            }

            if (element.IsSelfClosing || !(element.ClosingTag is XClosingTag closing))
            {
                return;
            }

            var begin = element.Span.End;
            int end   = element.ClosingTag.Span.Start;
            var value = TextSource.GetTextBetween(begin, end);

            var info = Document.GetSchemas().GetElementInfo(resolved, (element.Parent as XElement)?.Name.Name, element.Name.Name, true);

            if (info == null)
            {
                return;
            }

            VisitValue(element, null, resolved, null, info, value, begin);
        }
示例#14
0
        protected override void VisitValueExpression(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, MSBuildValueKind kind, ExpressionNode node)
        {
            if (kind.GetScalarType() != MSBuildValueKind.TargetName)
            {
                return;
            }

            switch (node)
            {
            case ExpressionList list:
                foreach (var c in list.Nodes)
                {
                    if (c is ExpressionLiteral l)
                    {
                        CheckMatch(l);
                        break;
                    }
                }
                break;

            case ExpressionLiteral lit:
                CheckMatch(lit);
                break;
            }
        }
示例#15
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     if ((resolved.Kind == MSBuildKind.Property) && IsMatch(element.Name.Name))
     {
         Results.Add((element.GetNameStartOffset(TextDocument), element.Name.Name.Length, ReferenceUsage.Write));
     }
     base.VisitResolvedElement(element, resolved);
 }
示例#16
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     if (resolved.SyntaxKind == MSBuildSyntaxKind.Metadata && IsMatch(element.Name.Name) && IsItemNameMatch(element.ParentElement.Name.Name))
     {
         Results.Add((element.NameOffset, element.Name.Name.Length, ReferenceUsage.Write));
     }
     base.VisitResolvedElement(element, resolved);
 }
示例#17
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     if (resolved.Kind == MSBuildKind.Metadata && IsMatch(element.Name.Name) && IsItemNameMatch(element.ParentElement().Name.Name))
     {
         AddNameResult(element, ReferenceUsage.Write);
     }
     base.VisitResolvedElement(element, resolved);
 }
 protected virtual void VisitResolvedAttribute(
     XElement element, XAttribute attribute,
     MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute)
 {
     if (attribute.Value != null)
     {
         VisitAttributeValue(element, attribute, resolvedElement, resolvedAttribute, attribute.Value, attribute.GetValueStartOffset(TextDocument));
     }
 }
示例#19
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     try {
         ValidateResolvedElement(element, resolved);
         base.VisitResolvedElement(element, resolved);
     } catch (Exception ex) {
         AddError($"Internal error: {ex.Message}", element.GetNameRegion());
         LoggingService.LogError("Internal error in MSBuildDocumentValidator", ex);
     }
 }
示例#20
0
        protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
        {
            foreach (var rat in resolved.Attributes)
            {
                if (rat.Required && !rat.IsAbstract)
                {
                    var xat = element.Attributes.Get(new XName(rat.Name), true);
                    if (xat == null)
                    {
                        AddError($"{element.Name.Name} must have attribute {rat.Name}", element.GetNameRegion());
                    }
                }
            }

            switch (resolved.Kind)
            {
            case MSBuildKind.Project:
                if (!Filename.EndsWith(".props", StringComparison.OrdinalIgnoreCase))
                {
                    ValidateProjectHasTarget(element);
                }
                break;

            case MSBuildKind.OnError:
                ValidateOnErrorOnlyFollowedByOnError(element);
                break;

            case MSBuildKind.Otherwise:
                ValidateOtherwiseIsLastElement(element);
                break;

            case MSBuildKind.Output:
                ValidateOutputHasPropertyOrItemName(element);
                break;

            case MSBuildKind.UsingTask:
                ValidateUsingTaskHasAssembly(element);
                break;

            case MSBuildKind.Import:
                ValidateImportOnlyHasVersionIfHasSdk(element);
                break;

            case MSBuildKind.Item:
                ValidateItemAttributes(resolved, element);
                break;

            case MSBuildKind.Task:
                ValidateTaskParameters(resolved, element);
                break;
            }

            base.VisitResolvedElement(element, resolved);
        }
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     try {
         CollectResolvedElement(element, resolved);
         base.VisitResolvedElement(element, resolved);
     } catch (Exception ex) when(isToplevel)
     {
         Document.Errors.Add(new XmlDiagnosticInfo(DiagnosticSeverity.Error, $"Internal error: {ex.Message}", element.NameSpan));
         LoggingService.LogError("Internal error in MSBuildDocumentValidator", ex);
     }
 }
示例#22
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     if (resolved.Kind == MSBuildKind.Target)
     {
         var nameAtt = element.Attributes.Get(new XName("Name"), true);
         if (nameAtt != null && IsMatch(nameAtt.Value))
         {
             AddValueResult(nameAtt, ReferenceUsage.Declaration);
         }
     }
     base.VisitResolvedElement(element, resolved);
 }
示例#23
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     if (resolved.SyntaxKind == MSBuildSyntaxKind.Target)
     {
         var nameAtt = element.Attributes.Get(new XName("Name"), true);
         if (nameAtt != null && IsMatch(nameAtt.Value))
         {
             Results.Add((nameAtt.Span.Start, nameAtt.Span.Length, ReferenceUsage.Declaration));
         }
     }
     base.VisitResolvedElement(element, resolved);
 }
示例#24
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     if (resolved.Kind == MSBuildKind.Target)
     {
         var nameAtt = element.Attributes.Get(new XName(Name), true);
         if (nameAtt != null && IsMatch(nameAtt.Value))
         {
             Results.Add((nameAtt.GetValueStartOffset(TextDocument), Name.Length, ReferenceUsage.Declaration));
         }
     }
     base.VisitResolvedElement(element, resolved);
 }
示例#25
0
        protected virtual void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
        {
            ResolveAttributesAndValue(element, resolved);

            if (resolved.ValueKind == MSBuildValueKind.Nothing)
            {
                foreach (var child in element.Elements)
                {
                    ResolveAndVisit(child, resolved);
                }
            }
        }
示例#26
0
        void ValidateResolvedElement(XElement element, MSBuildLanguageElement resolved)
        {
            foreach (var rat in resolved.Attributes)
            {
                if (rat.Required && !rat.IsAbstract)
                {
                    var xat = element.Attributes.Get(new XName(rat.Name), true);
                    if (xat == null)
                    {
                        AddError($"{element.Name.Name} must have attribute {rat.Name}", element.NameSpan);
                    }
                }
            }

            switch (resolved.SyntaxKind)
            {
            case MSBuildSyntaxKind.Project:
                if (!IsPropsFile)
                {
                    ValidateProjectHasTarget(element);
                }
                break;

            case MSBuildSyntaxKind.OnError:
                ValidateOnErrorOnlyFollowedByOnError(element);
                break;

            case MSBuildSyntaxKind.Otherwise:
                ValidateOtherwiseIsLastElement(element);
                break;

            case MSBuildSyntaxKind.Output:
                ValidateOutputHasPropertyOrItemName(element);
                break;

            case MSBuildSyntaxKind.UsingTask:
                ValidateUsingTaskHasAssembly(element);
                break;

            case MSBuildSyntaxKind.Import:
                ValidateImportOnlyHasVersionIfHasSdk(element);
                break;

            case MSBuildSyntaxKind.Item:
                ValidateItemAttributes(resolved, element);
                break;

            case MSBuildSyntaxKind.Task:
                ValidateTaskParameters(resolved, element);
                break;
            }
        }
            protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
            {
                var  start  = element.NameOffset;
                bool inName = element.IsNamed && IsIn(start, element.Name.Name.Length);

                if (inName)
                {
                    rr.ReferenceOffset = start;
                    rr.Reference       = element.Name.Name;
                    rr.ReferenceLength = element.Name.Name.Length;
                    switch (resolved.SyntaxKind)
                    {
                    case MSBuildSyntaxKind.Item:
                    case MSBuildSyntaxKind.ItemDefinition:
                        rr.ReferenceKind = MSBuildReferenceKind.Item;
                        return;

                    case MSBuildSyntaxKind.Metadata:
                        rr.ReferenceKind = MSBuildReferenceKind.Metadata;
                        rr.Reference     = (element.ParentElement.Name.Name, element.Name.Name);
                        return;

                    case MSBuildSyntaxKind.Task:
                        rr.ReferenceKind = MSBuildReferenceKind.Task;
                        return;

                    case MSBuildSyntaxKind.Parameter:
                        var taskName = element.ParentElement.ParentElement.Attributes.Get(new XName("TaskName"), true)?.Value;
                        if (!string.IsNullOrEmpty(taskName))
                        {
                            taskName         = taskName.Substring(taskName.LastIndexOf('.') + 1);
                            rr.ReferenceKind = MSBuildReferenceKind.TaskParameter;
                            rr.Reference     = (taskName, element.Name.Name);
                        }
                        return;

                    case MSBuildSyntaxKind.Property:
                        rr.ReferenceKind = MSBuildReferenceKind.Property;
                        return;

                    default:
                        if (!resolved.IsAbstract)
                        {
                            rr.ReferenceKind = MSBuildReferenceKind.Keyword;
                            rr.Reference     = resolved;
                        }
                        return;
                    }
                }

                base.VisitResolvedElement(element, resolved);
            }
        void ResolveAndVisit(XElement element, MSBuildLanguageElement parent)
        {
            var resolved = MSBuildLanguageElement.Get(element.Name.Name, parent);

            if (resolved != null)
            {
                VisitResolvedElement(element, resolved);
            }
            else
            {
                VisitUnknownElement(element);
            }
        }
示例#29
0
 protected override void VisitResolvedElement(XElement element, MSBuildLanguageElement resolved)
 {
     try {
         ValidateResolvedElement(element, resolved);
         //don't validate children of incomplete elements
         if (element.IsComplete)
         {
             base.VisitResolvedElement(element, resolved);
         }
     } catch (Exception ex) {
         AddError($"Internal error: {ex.Message}", element.NameSpan);
         LoggingService.LogError("Internal error in MSBuildDocumentValidator", ex);
     }
 }
示例#30
0
        protected override void VisitValueExpression(
            XElement element, XAttribute attribute,
            MSBuildLanguageElement resolvedElement, MSBuildLanguageAttribute resolvedAttribute,
            ValueInfo info, MSBuildValueKind kind, ExpressionNode node)
        {
            bool allowExpressions = kind.AllowExpressions();
            bool allowLists       = kind.AllowListsOrCommaLists();

            foreach (var n in node.WithAllDescendants())
            {
                switch (n)
                {
                case ExpressionList list:
                    if (!allowLists)
                    {
                        AddListWarning(list.Nodes [0].End, 1);
                    }
                    break;

                case ExpressionError err:
                    var msg = err.Kind.GetMessage(info, out bool isWarning);
                    AddError(
                        isWarning? ErrorType.Warning : ErrorType.Error,
                        msg,
                        err.Offset,
                        Math.Max(1, err.Length)
                        );
                    break;

                case ExpressionMetadata meta:
                case ExpressionProperty prop:
                case ExpressionItem item:
                    if (!allowExpressions)
                    {
                        AddExpressionWarning(node);
                    }
                    //TODO: can we validate property/metadata/items refs?
                    //maybe warn if they're not used anywhere outside of this expression?
                    break;

                case ExpressionText lit:
                    VisitPureLiteral(info, kind, lit.GetUnescapedValue(), lit.Offset);
                    break;
                }
            }

            string Name() => info.GetTitleCaseKindName();
            void AddExpressionWarning(ExpressionNode n) => AddWarning($"{Name ()} does not expect expressions", n.Offset, n.Length);
            void AddListWarning(int start, int length) => AddWarning($"{Name ()} does not expect lists", start, length);
        }