From 6c831ecb8e1ee16ea3dd2051ca3fcba8a5bc3384 Mon Sep 17 00:00:00 2001 From: "Yue (Felix) Huang" Date: Mon, 11 Oct 2021 14:00:50 -0700 Subject: [PATCH 01/10] Micro perf improvements --- src/Build/Construction/ProjectElement.cs | 30 ++++++++++++++++---- src/Build/ElementLocation/ElementLocation.cs | 5 ++-- src/Build/Evaluation/Evaluator.cs | 10 ++++--- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/Build/Construction/ProjectElement.cs b/src/Build/Construction/ProjectElement.cs index 8327feda09e..54df6827192 100644 --- a/src/Build/Construction/ProjectElement.cs +++ b/src/Build/Construction/ProjectElement.cs @@ -50,6 +50,7 @@ internal ProjectElement(ProjectElementLink link) ErrorUtilities.VerifyThrowArgumentNull(link, nameof(link)); _xmlSource = link; + _xmlSource_Link = _xmlSource.Link; } /// @@ -62,6 +63,7 @@ internal ProjectElement(XmlElement xmlElement, ProjectElementContainer parent, P ErrorUtilities.VerifyThrowArgumentNull(containingProject, nameof(containingProject)); _xmlSource = (XmlElementWithLocation)xmlElement; + _xmlSource_Link = _xmlSource.Link; _parent = parent; ContainingProject = containingProject; } @@ -88,7 +90,7 @@ internal virtual bool ExpressedAsAttribute _expressedAsAttribute = value; Parent?.AddToXml(this); MarkDirty("Set express as attribute: {0}", value.ToString()); - } + } } } @@ -208,7 +210,7 @@ public IEnumerable AllParents public ProjectElement PreviousSibling { [DebuggerStepThrough] - get => Link != null? Link.PreviousSibling : _previousSibling; + get => Link != null ? Link.PreviousSibling : _previousSibling; [DebuggerStepThrough] internal set => _previousSibling = value; } @@ -289,15 +291,29 @@ internal set /// In the case of an unsaved edit, the location only /// contains the path to the file that the element originates from. /// - public ElementLocation Location => Link != null ? Link.Location : XmlElement.Location; + public ElementLocation Location + { + get + { + if (_location == null) + { + _location = Link != null ? Link.Location : XmlElement.Location; + } + + return _location; + } + } + + private ElementLocation _location = null; /// - public string ElementName => Link != null? Link.ElementName : XmlElement.Name; + public string ElementName => Link != null ? Link.ElementName : XmlElement.Name; // Using ILinkedXml to share single field for either Linked (external) and local (XML backed) nodes. private ILinkedXml _xmlSource; + private ProjectElementLink _xmlSource_Link; - internal ProjectElementLink Link => _xmlSource?.Link; + internal ProjectElementLink Link => _xmlSource_Link; /// /// @@ -329,7 +345,7 @@ internal XmlDocumentWithLocation XmlDocument [DebuggerStepThrough] get { - return (XmlDocumentWithLocation) XmlElement?.OwnerDocument; + return (XmlDocumentWithLocation)XmlElement?.OwnerDocument; } } @@ -428,6 +444,7 @@ public virtual void CopyFrom(ProjectElement element) internal void SetProjectRootElementFromParser(XmlElementWithLocation xmlElement, ProjectRootElement projectRootElement) { _xmlSource = xmlElement; + _xmlSource_Link = _xmlSource.Link; ContainingProject = projectRootElement; } @@ -462,6 +479,7 @@ internal void ReplaceElement(XmlElementWithLocation newElement) } _xmlSource = newElement; + _xmlSource_Link = _xmlSource.Link; MarkDirty("Replace element {0}", newElement.Name); } diff --git a/src/Build/ElementLocation/ElementLocation.cs b/src/Build/ElementLocation/ElementLocation.cs index 3b5a286956a..18e34b17440 100644 --- a/src/Build/ElementLocation/ElementLocation.cs +++ b/src/Build/ElementLocation/ElementLocation.cs @@ -171,7 +171,7 @@ internal static ElementLocation FactoryForDeserialization(ITranslator translator /// internal static ElementLocation Create(string file) { - return Create(file, 0, 0); + return new ElementLocation.SmallElementLocation(file, 0, 0); } /// @@ -185,7 +185,8 @@ internal static ElementLocation Create(string file) /// internal static ElementLocation Create(string file, int line, int column) { - if (string.IsNullOrEmpty(file) && line == 0 && column == 0) + // return EmptyLocation; + if (line == 0 && column == 0 && string.IsNullOrEmpty(file)) { return EmptyLocation; } diff --git a/src/Build/Evaluation/Evaluator.cs b/src/Build/Evaluation/Evaluator.cs index 712307191f4..aaeb329f765 100644 --- a/src/Build/Evaluation/Evaluator.cs +++ b/src/Build/Evaluation/Evaluator.cs @@ -2374,7 +2374,8 @@ private bool EvaluateCondition(ProjectElement element, string condition, Expande return true; } - using (_evaluationProfiler.TrackCondition(element.ConditionLocation, condition)) + ElementLocation location = element.ConditionLocation; + using (_evaluationProfiler.TrackCondition(location, condition)) { bool result = ConditionEvaluator.EvaluateCondition ( @@ -2383,7 +2384,7 @@ private bool EvaluateCondition(ProjectElement element, string condition, Expande _expander, expanderOptions, GetCurrentDirectoryForConditionEvaluation(element), - element.ConditionLocation, + location, _evaluationLoggingContext.LoggingService, _evaluationLoggingContext.BuildEventContext, _evaluationContext.FileSystem @@ -2413,7 +2414,8 @@ private bool EvaluateConditionCollectingConditionedProperties(ProjectElement ele return EvaluateCondition(element, condition, expanderOptions, parserOptions); } - using (_evaluationProfiler.TrackCondition(element.ConditionLocation, condition)) + ElementLocation location = element.ConditionLocation; + using (_evaluationProfiler.TrackCondition(location, condition)) { bool result = ConditionEvaluator.EvaluateConditionCollectingConditionedProperties ( @@ -2423,7 +2425,7 @@ private bool EvaluateConditionCollectingConditionedProperties(ProjectElement ele expanderOptions, _data.ConditionedProperties, GetCurrentDirectoryForConditionEvaluation(element), - element.ConditionLocation, + location, _evaluationLoggingContext.LoggingService, _evaluationLoggingContext.BuildEventContext, _evaluationContext.FileSystem, From d8f477c7d75543e0cfb43b9eb65b4377824fd2cc Mon Sep 17 00:00:00 2001 From: "Yue (Felix) Huang" Date: Mon, 11 Oct 2021 15:53:43 -0700 Subject: [PATCH 02/10] Remove comment --- src/Build/ElementLocation/ElementLocation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Build/ElementLocation/ElementLocation.cs b/src/Build/ElementLocation/ElementLocation.cs index 18e34b17440..ced2ed9f41c 100644 --- a/src/Build/ElementLocation/ElementLocation.cs +++ b/src/Build/ElementLocation/ElementLocation.cs @@ -185,7 +185,6 @@ internal static ElementLocation Create(string file) /// internal static ElementLocation Create(string file, int line, int column) { - // return EmptyLocation; if (line == 0 && column == 0 && string.IsNullOrEmpty(file)) { return EmptyLocation; From 1f66e251f6e4db01f9a2a2f900ae1078626a5539 Mon Sep 17 00:00:00 2001 From: "Yue (Felix) Huang" Date: Mon, 11 Oct 2021 17:20:58 -0700 Subject: [PATCH 03/10] Fix tests --- src/Build/Construction/ProjectElement.cs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Build/Construction/ProjectElement.cs b/src/Build/Construction/ProjectElement.cs index 54df6827192..747ecf9e72b 100644 --- a/src/Build/Construction/ProjectElement.cs +++ b/src/Build/Construction/ProjectElement.cs @@ -291,20 +291,7 @@ internal set /// In the case of an unsaved edit, the location only /// contains the path to the file that the element originates from. /// - public ElementLocation Location - { - get - { - if (_location == null) - { - _location = Link != null ? Link.Location : XmlElement.Location; - } - - return _location; - } - } - - private ElementLocation _location = null; + public ElementLocation Location => Link != null ? Link.Location : XmlElement.Location; /// public string ElementName => Link != null ? Link.ElementName : XmlElement.Name; From 2ea86c4262d89088774f0e19572ecaad0c29741a Mon Sep 17 00:00:00 2001 From: "Yue (Felix) Huang" Date: Tue, 12 Oct 2021 12:31:49 -0700 Subject: [PATCH 04/10] Add back string null check. --- src/Build/ElementLocation/ElementLocation.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Build/ElementLocation/ElementLocation.cs b/src/Build/ElementLocation/ElementLocation.cs index ced2ed9f41c..5f3bfde2c26 100644 --- a/src/Build/ElementLocation/ElementLocation.cs +++ b/src/Build/ElementLocation/ElementLocation.cs @@ -171,7 +171,7 @@ internal static ElementLocation FactoryForDeserialization(ITranslator translator /// internal static ElementLocation Create(string file) { - return new ElementLocation.SmallElementLocation(file, 0, 0); + return string.IsNullOrEmpty(file) ? EmptyLocation : new ElementLocation.SmallElementLocation(file, 0, 0); } /// From 1e20d62c760f8834199aa136553e03e4c51ec8cb Mon Sep 17 00:00:00 2001 From: "Yue (Felix) Huang" Date: Tue, 12 Oct 2021 15:19:06 -0700 Subject: [PATCH 05/10] use cached link instead of .Link --- src/Build/Construction/ProjectElement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Build/Construction/ProjectElement.cs b/src/Build/Construction/ProjectElement.cs index 747ecf9e72b..815ad8194be 100644 --- a/src/Build/Construction/ProjectElement.cs +++ b/src/Build/Construction/ProjectElement.cs @@ -291,7 +291,7 @@ internal set /// In the case of an unsaved edit, the location only /// contains the path to the file that the element originates from. /// - public ElementLocation Location => Link != null ? Link.Location : XmlElement.Location; + public ElementLocation Location => _xmlSource_Link != null ? _xmlSource_Link.Location : XmlElement.Location; /// public string ElementName => Link != null ? Link.ElementName : XmlElement.Name; From d41fcde647e18ba39fb884c4c8abfc54f52fbee6 Mon Sep 17 00:00:00 2001 From: "Yue (Felix) Huang" Date: Thu, 21 Oct 2021 16:34:58 -0700 Subject: [PATCH 06/10] WIP Delay Creation of ElementLocation when not needed. --- ref/Microsoft.Build/net/Microsoft.Build.cs | 1 + .../netstandard/Microsoft.Build.cs | 1 + .../RequestBuilder/BatchingEngine.cs | 12 +- .../IntrinsicTasks/ItemGroupIntrinsicTask.cs | 13 +- .../PropertyGroupIntrinsicTask.cs | 9 +- .../Components/RequestBuilder/TargetEntry.cs | 4 +- .../RequestBuilder/TargetUpToDateChecker.cs | 14 +- .../Components/RequestBuilder/TaskBuilder.cs | 33 ++-- .../Construction/ProjectChooseElement.cs | 2 +- src/Build/Construction/ProjectElement.cs | 25 ++- .../Construction/ProjectElementContainer.cs | 2 +- .../ProjectItemDefinitionElement.cs | 2 +- src/Build/Construction/ProjectItemElement.cs | 2 +- .../Construction/ProjectMetadataElement.cs | 6 +- src/Build/Construction/ProjectRootElement.cs | 2 +- src/Build/Definition/Project.cs | 2 +- src/Build/Definition/ProjectItem.cs | 2 +- src/Build/Definition/ProjectMetadata.cs | 4 +- src/Build/Definition/Toolset.cs | 2 +- src/Build/ElementLocation/ElementLocation.cs | 24 ++- src/Build/ElementLocation/RegistryLocation.cs | 2 + .../XmlAttributeWithLocation.cs | 9 +- .../ElementLocation/XmlElementWithLocation.cs | 7 +- src/Build/Evaluation/ConditionEvaluator.cs | 17 ++- src/Build/Evaluation/Conditionals/Parser.cs | 33 ++-- src/Build/Evaluation/Evaluator.cs | 57 ++++--- src/Build/Evaluation/Expander.cs | 142 +++++++++--------- src/Build/Evaluation/ItemSpec.cs | 9 +- src/Build/Evaluation/LazyItemEvaluator.cs | 13 +- .../Evaluation/Profiler/EvaluationProfiler.cs | 4 +- src/Build/Evaluation/ProjectParser.cs | 74 ++++----- .../ProjectItemGroupTaskMetadataInstance.cs | 4 +- ...rojectPropertyGroupTaskPropertyInstance.cs | 4 +- src/Build/Instance/ProjectPropertyInstance.cs | 6 +- src/Build/Instance/ProjectTargetInstance.cs | 4 +- .../Instance/ProjectTargetInstanceChild.cs | 4 +- .../TaskFactories/AssemblyTaskFactory.cs | 3 +- src/Build/Instance/TaskRegistry.cs | 2 +- ...ectXmlUtilities.XmlElementChildIterator.cs | 2 +- src/Build/Xml/ProjectXmlUtilities.cs | 12 +- src/Shared/IElementLocation.cs | 2 +- src/Shared/ProjectErrorUtilities.cs | 37 ++--- src/Shared/XmlUtilities.cs | 14 +- 43 files changed, 339 insertions(+), 284 deletions(-) diff --git a/ref/Microsoft.Build/net/Microsoft.Build.cs b/ref/Microsoft.Build/net/Microsoft.Build.cs index fb5b4b8da5e..03aaa748076 100644 --- a/ref/Microsoft.Build/net/Microsoft.Build.cs +++ b/ref/Microsoft.Build/net/Microsoft.Build.cs @@ -17,6 +17,7 @@ protected ElementLocation() { } public abstract int Column { get; } public abstract string File { get; } public abstract int Line { get; } + public Microsoft.Build.Construction.ElementLocation Location { get { throw null; } } public string LocationString { get { throw null; } } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } diff --git a/ref/Microsoft.Build/netstandard/Microsoft.Build.cs b/ref/Microsoft.Build/netstandard/Microsoft.Build.cs index b387429467c..a2669f62b2a 100644 --- a/ref/Microsoft.Build/netstandard/Microsoft.Build.cs +++ b/ref/Microsoft.Build/netstandard/Microsoft.Build.cs @@ -17,6 +17,7 @@ protected ElementLocation() { } public abstract int Column { get; } public abstract string File { get; } public abstract int Line { get; } + public Microsoft.Build.Construction.ElementLocation Location { get { throw null; } } public string LocationString { get { throw null; } } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } diff --git a/src/Build/BackEnd/Components/RequestBuilder/BatchingEngine.cs b/src/Build/BackEnd/Components/RequestBuilder/BatchingEngine.cs index 3e676950ea5..1e41d597a96 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/BatchingEngine.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/BatchingEngine.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using Microsoft.Build.Collections; -using ElementLocation = Microsoft.Build.Construction.ElementLocation; using Microsoft.Build.Evaluation; using Microsoft.Build.Execution; using Microsoft.Build.Shared; +using Microsoft.Build.Construction; namespace Microsoft.Build.BackEnd { @@ -80,7 +80,7 @@ internal static List PrepareBatchingBuckets ( List batchableObjectParameters, Lookup lookup, - ElementLocation elementLocation + IInternalLocation elementLocation ) { return PrepareBatchingBuckets(batchableObjectParameters, lookup, null, elementLocation); @@ -101,7 +101,7 @@ internal static List PrepareBatchingBuckets List batchableObjectParameters, Lookup lookup, string implicitBatchableItemType, - ElementLocation elementLocation + IInternalLocation elementLocation ) { if (batchableObjectParameters == null) @@ -204,7 +204,7 @@ private static Dictionary> GetItemLists // Value is [struct MetadataReference] HashSet consumedItemReferenceNames, Lookup lookup, - ElementLocation elementLocation + IInternalLocation elementLocation ) { // The keys in this hashtable are the names of the items that we will batch on. @@ -299,7 +299,7 @@ private static List BucketConsumedItems Lookup lookup, Dictionary> itemListsToBeBatched, Dictionary consumedMetadataReferences, - ElementLocation elementLocation + IInternalLocation elementLocation ) { ErrorUtilities.VerifyThrow(itemListsToBeBatched.Count > 0, "Need item types consumed by the batchable object."); @@ -382,7 +382,7 @@ private static Dictionary GetItemMetadataValues ( ProjectItemInstance item, Dictionary consumedMetadataReferences, - ElementLocation elementLocation + IInternalLocation elementLocation ) { var itemMetadataValues = new Dictionary(consumedMetadataReferences.Count, MSBuildNameIgnoreCaseComparer.Default); diff --git a/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs b/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs index 109cb49b9bf..06560f5c3f4 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/ItemGroupIntrinsicTask.cs @@ -6,7 +6,6 @@ using System.Collections.Immutable; using System.Linq; using Microsoft.Build.Collections; -using ElementLocation = Microsoft.Build.Construction.ElementLocation; using Microsoft.Build.Execution; using Microsoft.Build.Framework; using Microsoft.Build.Shared; @@ -15,6 +14,7 @@ using ProjectItemInstanceFactory = Microsoft.Build.Execution.ProjectItemInstance.TaskItem.ProjectItemInstanceFactory; using EngineFileUtilities = Microsoft.Build.Internal.EngineFileUtilities; using TargetLoggingContext = Microsoft.Build.BackEnd.Logging.TargetLoggingContext; +using Microsoft.Build.Construction; namespace Microsoft.Build.BackEnd { @@ -50,6 +50,7 @@ public ItemGroupIntrinsicTask(ProjectItemGroupTaskInstance taskInstance, TargetL /// The lookup used for evaluation and as a destination for these items. internal override void ExecuteTask(Lookup lookup) { + var location = _taskInstance.Location; foreach (ProjectItemGroupTaskItemInstance child in _taskInstance.Items) { List buckets = null; @@ -58,7 +59,7 @@ internal override void ExecuteTask(Lookup lookup) { List parameterValues = new List(); GetBatchableValuesFromBuildItemGroupChild(parameterValues, child); - buckets = BatchingEngine.PrepareBatchingBuckets(parameterValues, lookup, child.ItemType, _taskInstance.Location); + buckets = BatchingEngine.PrepareBatchingBuckets(parameterValues, lookup, child.ItemType, location); // "Execute" each bucket foreach (ItemBucket bucket in buckets) @@ -177,14 +178,14 @@ private void ExecuteAdd(ProjectItemGroupTaskItemInstance child, ItemBucket bucke bucket.Expander, ExpanderOptions.ExpandAll, Project.Directory, - metadataInstance.Location, + metadataInstance, LoggingContext.LoggingService, LoggingContext.BuildEventContext, FileSystems.Default); if (condition) { - string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(metadataInstance.Value, ExpanderOptions.ExpandAll, metadataInstance.Location); + string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(metadataInstance.Value, ExpanderOptions.ExpandAll, metadataInstance); // This both stores the metadata so we can add it to all the items we just created later, and // exposes this metadata to further metadata evaluations in subsequent loop iterations. @@ -322,7 +323,7 @@ private void ExecuteModify(ProjectItemGroupTaskItemInstance child, ItemBucket bu if (condition) { - string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(metadataInstance.Value, ExpanderOptions.ExpandAll, metadataInstance.Location); + string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(metadataInstance.Value, ExpanderOptions.ExpandAll, metadataInstance); metadataToSet[metadataInstance.Name] = Lookup.MetadataModification.CreateFromNewValue(evaluatedValue); } } @@ -515,7 +516,7 @@ private List FindItemsMatchingSpecification ( ICollection items, string specification, - ElementLocation specificationLocation, + IInternalLocation specificationLocation, Expander expander ) { diff --git a/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/PropertyGroupIntrinsicTask.cs b/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/PropertyGroupIntrinsicTask.cs index 14feb6aa094..e430005655c 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/PropertyGroupIntrinsicTask.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/IntrinsicTasks/PropertyGroupIntrinsicTask.cs @@ -50,7 +50,8 @@ internal override void ExecuteTask(Lookup lookup) // Find all the metadata references in order to create buckets List parameterValues = new List(); GetBatchableValuesFromProperty(parameterValues, property); - buckets = BatchingEngine.PrepareBatchingBuckets(parameterValues, lookup, property.Location); + buckets = BatchingEngine.PrepareBatchingBuckets(parameterValues, lookup, property); + var propertyLocation = property.ConditionLocation; // "Execute" each bucket foreach (ItemBucket bucket in buckets) @@ -62,7 +63,7 @@ internal override void ExecuteTask(Lookup lookup) bucket.Expander, ExpanderOptions.ExpandAll, Project.Directory, - property.ConditionLocation, + propertyLocation, LoggingContext.LoggingService, LoggingContext.BuildEventContext, FileSystems.Default); @@ -74,12 +75,12 @@ internal override void ExecuteTask(Lookup lookup) ProjectErrorUtilities.VerifyThrowInvalidProject ( !ReservedPropertyNames.IsReservedProperty(property.Name), - property.Location, + property, "CannotModifyReservedProperty", property.Name ); - string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(property.Value, ExpanderOptions.ExpandAll, property.Location); + string evaluatedValue = bucket.Expander.ExpandIntoStringLeaveEscaped(property.Value, ExpanderOptions.ExpandAll, property); if (LogTaskInputs && !LoggingContext.LoggingService.OnlyLogCriticalEvents) { diff --git a/src/Build/BackEnd/Components/RequestBuilder/TargetEntry.cs b/src/Build/BackEnd/Components/RequestBuilder/TargetEntry.cs index d3a925b34a8..40e4add4def 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/TargetEntry.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/TargetEntry.cs @@ -424,7 +424,7 @@ internal async Task ExecuteTarget(ITaskBuilder taskBuilder, BuildRequestEntry re // Generate the batching buckets. Note that each bucket will get a lookup based on the baseLookup. This lookup will be in its // own scope, which we will collapse back down into the baseLookup at the bottom of the function. - List buckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target.Location); + List buckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target); WorkUnitResult aggregateResult = new WorkUnitResult(); TargetLoggingContext targetLoggingContext = null; @@ -617,7 +617,7 @@ internal async Task ExecuteTarget(ITaskBuilder taskBuilder, BuildRequestEntry re // Also, we are using the baseLookup, which has possibly had changes made to it since the project started. Because of this, the // set of outputs calculated here may differ from those which would have been calculated at the beginning of the target. It is // assumed the user intended this. - List batchingBuckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target.Location); + List batchingBuckets = BatchingEngine.PrepareBatchingBuckets(GetBatchableParametersForTarget(), _baseLookup, _target); if (keepDupes) { diff --git a/src/Build/BackEnd/Components/RequestBuilder/TargetUpToDateChecker.cs b/src/Build/BackEnd/Components/RequestBuilder/TargetUpToDateChecker.cs index 9013bc11272..220dc17e282 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/TargetUpToDateChecker.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/TargetUpToDateChecker.cs @@ -7,12 +7,12 @@ using System.Linq; using Microsoft.Build.Collections; +using Microsoft.Build.Construction; using Microsoft.Build.Evaluation; using Microsoft.Build.Execution; using Microsoft.Build.Framework; using Microsoft.Build.Shared; -using ElementLocation = Microsoft.Build.Construction.ElementLocation; using ProjectItemInstanceFactory = Microsoft.Build.Execution.ProjectItemInstance.TaskItem.ProjectItemInstanceFactory; namespace Microsoft.Build.BackEnd @@ -391,8 +391,10 @@ out List targetOutputItemSpecs { // break down the input/output specifications along the standard separator, after expanding all embedded properties // and item metadata - var targetInputs = bucket.Expander.ExpandIntoStringListLeaveEscaped(TargetInputSpecification, ExpanderOptions.ExpandPropertiesAndMetadata, _targetToAnalyze.InputsLocation); - var targetOutputs = bucket.Expander.ExpandIntoStringListLeaveEscaped(TargetOutputSpecification, ExpanderOptions.ExpandPropertiesAndMetadata, _targetToAnalyze.OutputsLocation); + var inputLocation = _targetToAnalyze.InputsLocation; + var outputLocation = _targetToAnalyze.OutputsLocation; + var targetInputs = bucket.Expander.ExpandIntoStringListLeaveEscaped(TargetInputSpecification, ExpanderOptions.ExpandPropertiesAndMetadata, inputLocation); + var targetOutputs = bucket.Expander.ExpandIntoStringListLeaveEscaped(TargetOutputSpecification, ExpanderOptions.ExpandPropertiesAndMetadata, outputLocation); itemVectorTransformsInTargetInputs = new ItemVectorPartitionCollection(MSBuildNameIgnoreCaseComparer.Default); @@ -406,7 +408,7 @@ out List targetOutputItemSpecs out itemVectorsInTargetInputs, itemVectorTransformsInTargetInputs, out discreteItemsInTargetInputs, - _targetToAnalyze.InputsLocation); + inputLocation); // figure out which of the outputs are: // 1) item vectors (with or without transforms) @@ -417,7 +419,7 @@ out List targetOutputItemSpecs out itemVectorsInTargetOutputs, null /* don't want transforms separated */, out discreteItemsInTargetOutputs, - _targetToAnalyze.OutputsLocation); + outputLocation); // list out all the output item-specs targetOutputItemSpecs = GetItemSpecsFromItemVectors(itemVectorsInTargetOutputs); @@ -785,7 +787,7 @@ private void SeparateItemVectorsFromDiscreteItems out ItemVectorPartitionCollection itemVectors, ItemVectorPartitionCollection itemVectorTransforms, out Dictionary discreteItems, - ElementLocation elementLocation + IInternalLocation elementLocation ) { itemVectors = new ItemVectorPartitionCollection(MSBuildNameIgnoreCaseComparer.Default); diff --git a/src/Build/BackEnd/Components/RequestBuilder/TaskBuilder.cs b/src/Build/BackEnd/Components/RequestBuilder/TaskBuilder.cs index 5fdd1a3e145..9bbc0b814f7 100644 --- a/src/Build/BackEnd/Components/RequestBuilder/TaskBuilder.cs +++ b/src/Build/BackEnd/Components/RequestBuilder/TaskBuilder.cs @@ -306,7 +306,7 @@ private async Task ExecuteTask(TaskExecutionMode mode, Lookup lo } List taskParameterValues = CreateListOfParameterValues(); - buckets = BatchingEngine.PrepareBatchingBuckets(taskParameterValues, lookup, _targetChildInstance.Location); + buckets = BatchingEngine.PrepareBatchingBuckets(taskParameterValues, lookup, _targetChildInstance); Dictionary lookupHash = null; @@ -645,7 +645,7 @@ private async Task InitializeAndExecuteTask(TaskLoggingContext t { if (!_taskExecutionHost.InitializeForBatch(taskLoggingContext, bucket, taskIdentityParameters)) { - ProjectErrorUtilities.ThrowInvalidProject(_targetChildInstance.Location, "TaskDeclarationOrUsageError", _taskNode.Name); + ProjectErrorUtilities.ThrowInvalidProject(_targetChildInstance, "TaskDeclarationOrUsageError", _taskNode.Name); } try @@ -740,7 +740,7 @@ private async Task ExecuteInstantiatedTask(ITaskExecutionHost ta if (!taskExecutionHost.SetTaskParameters(_taskNode.ParametersForBuild)) { // The task cannot be initialized. - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _targetChildInstance.Location, "TaskParametersError", _taskNode.Name, String.Empty); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _targetChildInstance, "TaskParametersError", _taskNode.Name, String.Empty); } else { @@ -866,7 +866,7 @@ private async Task ExecuteInstantiatedTask(ITaskExecutionHost ta else if (type == typeof(CircularDependencyException)) { _continueOnError = ContinueOnError.ErrorAndStop; - ProjectErrorUtilities.ThrowInvalidProject(taskLoggingContext.Task.Location, "CircularDependency", taskLoggingContext.TargetLoggingContext.Target.Name); + ProjectErrorUtilities.ThrowInvalidProject(taskLoggingContext.Task, "CircularDependency", taskLoggingContext.TargetLoggingContext.Target.Name); } else if (type == typeof(InvalidProjectFileException)) { @@ -1084,14 +1084,15 @@ private bool GatherTaskOutputs(ITaskExecutionHost taskExecutionHost, TaskExecuti if (taskOutputItemInstance != null) { // expand all embedded properties, item metadata and item vectors in the item type name + var itemTypeLocation = taskOutputItemInstance.ItemTypeLocation; outputTargetIsItem = true; - outputTargetName = bucket.Expander.ExpandIntoStringAndUnescape(taskOutputItemInstance.ItemType, ExpanderOptions.ExpandAll, taskOutputItemInstance.ItemTypeLocation); + outputTargetName = bucket.Expander.ExpandIntoStringAndUnescape(taskOutputItemInstance.ItemType, ExpanderOptions.ExpandAll, itemTypeLocation); taskParameterName = taskOutputItemInstance.TaskParameter; ProjectErrorUtilities.VerifyThrowInvalidProject ( outputTargetName.Length > 0, - taskOutputItemInstance.ItemTypeLocation, + itemTypeLocation, "InvalidEvaluatedAttributeValue", outputTargetName, taskOutputItemInstance.ItemType, @@ -1105,13 +1106,14 @@ private bool GatherTaskOutputs(ITaskExecutionHost taskExecutionHost, TaskExecuti outputTargetIsItem = false; // expand all embedded properties, item metadata and item vectors in the property name - outputTargetName = bucket.Expander.ExpandIntoStringAndUnescape(taskOutputPropertyInstance.PropertyName, ExpanderOptions.ExpandAll, taskOutputPropertyInstance.PropertyNameLocation); + var propertyNameLocation = taskOutputPropertyInstance.PropertyNameLocation; + outputTargetName = bucket.Expander.ExpandIntoStringAndUnescape(taskOutputPropertyInstance.PropertyName, ExpanderOptions.ExpandAll, propertyNameLocation); taskParameterName = taskOutputPropertyInstance.TaskParameter; ProjectErrorUtilities.VerifyThrowInvalidProject ( outputTargetName.Length > 0, - taskOutputPropertyInstance.PropertyNameLocation, + propertyNameLocation, "InvalidEvaluatedAttributeValue", outputTargetName, taskOutputPropertyInstance.PropertyName, @@ -1121,12 +1123,13 @@ private bool GatherTaskOutputs(ITaskExecutionHost taskExecutionHost, TaskExecuti } string unexpandedTaskParameterName = taskParameterName; - taskParameterName = bucket.Expander.ExpandIntoStringAndUnescape(taskParameterName, ExpanderOptions.ExpandAll, taskOutputSpecification.TaskParameterLocation); + var taskParaLocation = taskOutputSpecification.TaskParameterLocation; + taskParameterName = bucket.Expander.ExpandIntoStringAndUnescape(taskParameterName, ExpanderOptions.ExpandAll, taskParaLocation); ProjectErrorUtilities.VerifyThrowInvalidProject ( taskParameterName.Length > 0, - taskOutputSpecification.TaskParameterLocation, + taskParaLocation, "InvalidEvaluatedAttributeValue", taskParameterName, unexpandedTaskParameterName, @@ -1184,14 +1187,15 @@ ItemBucket bucket ProjectTaskOutputItemInstance taskItemInstance = taskOutputSpecification as ProjectTaskOutputItemInstance; if (taskItemInstance != null) { + var taskParaLocation = taskItemInstance.TaskParameterLocation; // This is an output item. // Expand only with properties first, so that expressions like Include="@(foo)" will transfer the metadata of the "foo" items as well, not just their item specs. - var outputItemSpecs = bucket.Expander.ExpandIntoStringListLeaveEscaped(taskParameterAttribute, ExpanderOptions.ExpandPropertiesAndMetadata, taskItemInstance.TaskParameterLocation); + var outputItemSpecs = bucket.Expander.ExpandIntoStringListLeaveEscaped(taskParameterAttribute, ExpanderOptions.ExpandPropertiesAndMetadata, taskParaLocation); ProjectItemInstanceFactory itemFactory = new ProjectItemInstanceFactory(_buildRequestEntry.RequestConfiguration.Project, itemName); foreach (string outputItemSpec in outputItemSpecs) { - ICollection items = bucket.Expander.ExpandIntoItemsLeaveEscaped(outputItemSpec, itemFactory, ExpanderOptions.ExpandItems, taskItemInstance.TaskParameterLocation); + ICollection items = bucket.Expander.ExpandIntoItemsLeaveEscaped(outputItemSpec, itemFactory, ExpanderOptions.ExpandItems, taskParaLocation); lookup.AddNewItemsOfItemType(itemName, items); } @@ -1201,11 +1205,12 @@ ItemBucket bucket // This is an output property. ProjectTaskOutputPropertyInstance taskPropertyInstance = (ProjectTaskOutputPropertyInstance)taskOutputSpecification; - string taskParameterValue = bucket.Expander.ExpandIntoStringAndUnescape(taskParameterAttribute, ExpanderOptions.ExpandAll, taskPropertyInstance.TaskParameterLocation); + var taskPropertyLocation = taskPropertyInstance.TaskParameterLocation; + string taskParameterValue = bucket.Expander.ExpandIntoStringAndUnescape(taskParameterAttribute, ExpanderOptions.ExpandAll, taskPropertyLocation); if (!String.IsNullOrEmpty(taskParameterValue)) { - lookup.SetProperty(ProjectPropertyInstance.Create(propertyName, taskParameterValue, taskPropertyInstance.TaskParameterLocation, _buildRequestEntry.RequestConfiguration.Project.IsImmutable)); + lookup.SetProperty(ProjectPropertyInstance.Create(propertyName, taskParameterValue, taskPropertyLocation, _buildRequestEntry.RequestConfiguration.Project.IsImmutable)); } } } diff --git a/src/Build/Construction/ProjectChooseElement.cs b/src/Build/Construction/ProjectChooseElement.cs index def7d686cff..f15667f40fc 100644 --- a/src/Build/Construction/ProjectChooseElement.cs +++ b/src/Build/Construction/ProjectChooseElement.cs @@ -116,7 +116,7 @@ internal override void VerifyThrowInvalidOperationAcceptableLocation(ProjectElem nestingDepth++; // This should really be an OM error, with no error number. But it's so obscure, it's not worth a new string. - ProjectErrorUtilities.VerifyThrowInvalidProject(nestingDepth <= ProjectParser.MaximumChooseNesting, immediateParent.Location, "ChooseOverflow", ProjectParser.MaximumChooseNesting); + ProjectErrorUtilities.VerifyThrowInvalidProject(nestingDepth <= ProjectParser.MaximumChooseNesting, immediateParent, "ChooseOverflow", ProjectParser.MaximumChooseNesting); } } diff --git a/src/Build/Construction/ProjectElement.cs b/src/Build/Construction/ProjectElement.cs index 815ad8194be..5aeb09a6e81 100644 --- a/src/Build/Construction/ProjectElement.cs +++ b/src/Build/Construction/ProjectElement.cs @@ -15,7 +15,7 @@ namespace Microsoft.Build.Construction /// /// Abstract base class for MSBuild construction object model elements. /// - public abstract class ProjectElement : IProjectElement, ILinkableObject + public abstract class ProjectElement : IPublicLocation, IInternalLocation, IProjectElement, ILinkableObject { /// /// Parent container object. @@ -50,7 +50,6 @@ internal ProjectElement(ProjectElementLink link) ErrorUtilities.VerifyThrowArgumentNull(link, nameof(link)); _xmlSource = link; - _xmlSource_Link = _xmlSource.Link; } /// @@ -63,7 +62,6 @@ internal ProjectElement(XmlElement xmlElement, ProjectElementContainer parent, P ErrorUtilities.VerifyThrowArgumentNull(containingProject, nameof(containingProject)); _xmlSource = (XmlElementWithLocation)xmlElement; - _xmlSource_Link = _xmlSource.Link; _parent = parent; ContainingProject = containingProject; } @@ -90,7 +88,7 @@ internal virtual bool ExpressedAsAttribute _expressedAsAttribute = value; Parent?.AddToXml(this); MarkDirty("Set express as attribute: {0}", value.ToString()); - } + } } } @@ -210,7 +208,7 @@ public IEnumerable AllParents public ProjectElement PreviousSibling { [DebuggerStepThrough] - get => Link != null ? Link.PreviousSibling : _previousSibling; + get => Link != null? Link.PreviousSibling : _previousSibling; [DebuggerStepThrough] internal set => _previousSibling = value; } @@ -291,16 +289,17 @@ internal set /// In the case of an unsaved edit, the location only /// contains the path to the file that the element originates from. /// - public ElementLocation Location => _xmlSource_Link != null ? _xmlSource_Link.Location : XmlElement.Location; + public ElementLocation Location => Link != null ? Link.Location : XmlElement.Location; /// - public string ElementName => Link != null ? Link.ElementName : XmlElement.Name; + public string ElementName => Link != null? Link.ElementName : XmlElement.Name; // Using ILinkedXml to share single field for either Linked (external) and local (XML backed) nodes. private ILinkedXml _xmlSource; - private ProjectElementLink _xmlSource_Link; - internal ProjectElementLink Link => _xmlSource_Link; + internal ProjectElementLink Link => _xmlSource?.Link; + + IElementLocation ILocation.Location => Location; /// /// @@ -332,7 +331,7 @@ internal XmlDocumentWithLocation XmlDocument [DebuggerStepThrough] get { - return (XmlDocumentWithLocation)XmlElement?.OwnerDocument; + return (XmlDocumentWithLocation) XmlElement?.OwnerDocument; } } @@ -431,7 +430,6 @@ public virtual void CopyFrom(ProjectElement element) internal void SetProjectRootElementFromParser(XmlElementWithLocation xmlElement, ProjectRootElement projectRootElement) { _xmlSource = xmlElement; - _xmlSource_Link = _xmlSource.Link; ContainingProject = projectRootElement; } @@ -466,7 +464,6 @@ internal void ReplaceElement(XmlElementWithLocation newElement) } _xmlSource = newElement; - _xmlSource_Link = _xmlSource.Link; MarkDirty("Replace element {0}", newElement.Name); } @@ -536,12 +533,12 @@ internal static ProjectElement CreateNewInstance(ProjectElement xml, ProjectRoot internal ElementLocation GetAttributeLocation(string attributeName) { - return Link != null ? Link.GetAttributeLocation(attributeName) : XmlElement.GetAttributeLocation(attributeName); + return _xmlSource?.Link?.GetAttributeLocation(attributeName) ?? XmlElement.GetAttributeLocation(attributeName); } internal string GetAttributeValue(string attributeName, bool nullIfNotExists = false) { - return Link != null ? Link.GetAttributeValue(attributeName, nullIfNotExists) : + return _xmlSource?.Link?.GetAttributeValue(attributeName, nullIfNotExists) ?? ProjectXmlUtilities.GetAttributeValue(XmlElement, attributeName, nullIfNotExists); } diff --git a/src/Build/Construction/ProjectElementContainer.cs b/src/Build/Construction/ProjectElementContainer.cs index 3c4c0d6f269..fb3083a0928 100644 --- a/src/Build/Construction/ProjectElementContainer.cs +++ b/src/Build/Construction/ProjectElementContainer.cs @@ -464,7 +464,7 @@ internal void AddToXml(ProjectElement child) // Make sure we're not trying to add multiple attributes with the same name ProjectErrorUtilities.VerifyThrowInvalidProject(!XmlElement.HasAttribute(child.XmlElement.Name), - XmlElement.Location, "InvalidChildElementDueToDuplication", child.XmlElement.Name, ElementName); + XmlElement, "InvalidChildElementDueToDuplication", child.XmlElement.Name, ElementName); SetElementAsAttributeValue(child); } diff --git a/src/Build/Construction/ProjectItemDefinitionElement.cs b/src/Build/Construction/ProjectItemDefinitionElement.cs index 2f93312bc32..62f3fa7b371 100644 --- a/src/Build/Construction/ProjectItemDefinitionElement.cs +++ b/src/Build/Construction/ProjectItemDefinitionElement.cs @@ -77,7 +77,7 @@ public ProjectMetadataElement AddMetadata(string name, string unevaluatedValue, if (expressAsAttribute) { - ProjectMetadataElement.ValidateValidMetadataAsAttributeName(name, ElementName, Location); + ProjectMetadataElement.ValidateValidMetadataAsAttributeName(name, ElementName, this); } ProjectMetadataElement metadata = ContainingProject.CreateMetadataElement(name); diff --git a/src/Build/Construction/ProjectItemElement.cs b/src/Build/Construction/ProjectItemElement.cs index dd7f7f6ea6c..0d1460108af 100644 --- a/src/Build/Construction/ProjectItemElement.cs +++ b/src/Build/Construction/ProjectItemElement.cs @@ -394,7 +394,7 @@ public ProjectMetadataElement AddMetadata(string name, string unevaluatedValue, if (expressAsAttribute) { - ProjectMetadataElement.ValidateValidMetadataAsAttributeName(name, ElementName, Location); + ProjectMetadataElement.ValidateValidMetadataAsAttributeName(name, ElementName, this); } ProjectMetadataElement metadata = ContainingProject.CreateMetadataElement(name); diff --git a/src/Build/Construction/ProjectMetadataElement.cs b/src/Build/Construction/ProjectMetadataElement.cs index 9657cc1a647..423badd0907 100644 --- a/src/Build/Construction/ProjectMetadataElement.cs +++ b/src/Build/Construction/ProjectMetadataElement.cs @@ -65,7 +65,7 @@ public string Name { if (value) { - ValidateValidMetadataAsAttributeName(Name, Parent?.ElementName ?? "null" , Parent?.Location); + ValidateValidMetadataAsAttributeName(Name, Parent?.ElementName ?? "null" , Parent); } base.ExpressedAsAttribute = value; } @@ -129,7 +129,7 @@ internal void ChangeName(string newName) if (ExpressedAsAttribute) { - ValidateValidMetadataAsAttributeName(newName, Parent.ElementName, Parent.Location); + ValidateValidMetadataAsAttributeName(newName, Parent.ElementName, Parent); } // Because the element was created from our special XmlDocument, we know it's @@ -139,7 +139,7 @@ internal void ChangeName(string newName) ReplaceElement(newElement); } - internal static void ValidateValidMetadataAsAttributeName(string name, string parentName, IElementLocation parentLocation) + internal static void ValidateValidMetadataAsAttributeName(string name, string parentName, IInternalLocation parentLocation) { if (!AttributeNameIsValidMetadataName(name)) { diff --git a/src/Build/Construction/ProjectRootElement.cs b/src/Build/Construction/ProjectRootElement.cs index 389f1f3cf6e..3bf2d95f3ab 100644 --- a/src/Build/Construction/ProjectRootElement.cs +++ b/src/Build/Construction/ProjectRootElement.cs @@ -1900,7 +1900,7 @@ internal List GetImplicitImportNodes(ProjectRootElement cu return nodes; } - private static IEnumerable ParseSdks(string sdks, IElementLocation sdkLocation) + private static IEnumerable ParseSdks(string sdks, IInternalLocation sdkLocation) { foreach (string sdk in sdks.Split(MSBuildConstants.SemicolonChar).Select(i => i.Trim())) { diff --git a/src/Build/Definition/Project.cs b/src/Build/Definition/Project.cs index d842373c86c..0c83e1ab744 100644 --- a/src/Build/Definition/Project.cs +++ b/src/Build/Definition/Project.cs @@ -2717,7 +2717,7 @@ private List GetItemProvenance(string itemToMatch, IEnumerable // TODO: cache result? private ProvenanceResult ComputeProvenanceResult(string itemToMatch, ProjectItemElement itemElement) { - ProvenanceResult SingleItemSpecProvenance(string itemSpec, IElementLocation elementLocation, Operation operation) + ProvenanceResult SingleItemSpecProvenance(string itemSpec, IInternalLocation elementLocation, Operation operation) { if (elementLocation != null && !string.IsNullOrEmpty(itemSpec)) { diff --git a/src/Build/Definition/ProjectItem.cs b/src/Build/Definition/ProjectItem.cs index 0b3c28e1562..abdcab3e213 100644 --- a/src/Build/Definition/ProjectItem.cs +++ b/src/Build/Definition/ProjectItem.cs @@ -492,7 +492,7 @@ string IItem.GetMetadataValueEscaped(string name) { Expander expander = new Expander(null, null, new BuiltInMetadataTable(this), FileSystems.Default); - value = expander.ExpandIntoStringLeaveEscaped(metadatum.EvaluatedValueEscaped, ExpanderOptions.ExpandBuiltInMetadata, metadatum.Location); + value = expander.ExpandIntoStringLeaveEscaped(metadatum.EvaluatedValueEscaped, ExpanderOptions.ExpandBuiltInMetadata, metadatum); } else if (metadatum != null) { diff --git a/src/Build/Definition/ProjectMetadata.cs b/src/Build/Definition/ProjectMetadata.cs index 2e5f4c958ae..f7eea44b954 100644 --- a/src/Build/Definition/ProjectMetadata.cs +++ b/src/Build/Definition/ProjectMetadata.cs @@ -18,7 +18,7 @@ namespace Microsoft.Build.Evaluation /// Never used to represent built-in metadata, like %(Filename). There is always a backing XML object. /// [DebuggerDisplay("{Name}={EvaluatedValue} [{_xml.Value}]")] - public class ProjectMetadata : IEquatable, IMetadatum + public class ProjectMetadata : IEquatable, IMetadatum, IPublicLocation, IInternalLocation { /// /// Parent item or item definition that this metadatum lives in. @@ -266,6 +266,8 @@ internal string EvaluatedValueEscaped get => Link != null ? Link.EvaluatedValueEscaped : _evaluatedValueEscaped; } + IElementLocation ILocation.Location => Location; + #region IEquatable Members /// diff --git a/src/Build/Definition/Toolset.cs b/src/Build/Definition/Toolset.cs index 77d32963bf6..ecc61d9828f 100644 --- a/src/Build/Definition/Toolset.cs +++ b/src/Build/Definition/Toolset.cs @@ -1065,7 +1065,7 @@ private void LoadAndRegisterFromTasksFile(string[] defaultTaskFiles, ILoggingSer { ProjectErrorUtilities.ThrowInvalidProject ( - elementXml.Location, + elementXml, "UnrecognizedElement", elementXml.XmlElement.Name ); diff --git a/src/Build/ElementLocation/ElementLocation.cs b/src/Build/ElementLocation/ElementLocation.cs index 5f3bfde2c26..95ff1e2307d 100644 --- a/src/Build/ElementLocation/ElementLocation.cs +++ b/src/Build/ElementLocation/ElementLocation.cs @@ -18,7 +18,7 @@ namespace Microsoft.Build.Construction /// DO NOT make these objects any larger. There are huge numbers of them and they are transmitted between nodes. /// [Serializable] - public abstract class ElementLocation : IElementLocation, ITranslatable, IImmutable + public abstract class ElementLocation : IElementLocation, IPublicLocation, ITranslatable, IImmutable { /// /// The singleton empty element location. @@ -83,6 +83,10 @@ internal static ElementLocation EmptyLocation get { return s_emptyElementLocation; } } + public ElementLocation Location => this; + + IElementLocation ILocation.Location => this; + /// /// Get reasonable hash code. /// @@ -371,4 +375,22 @@ public override int Column } } } + + + + // internal interface + internal interface ILocation + { + public T Location { get; } + } + + // public interface + internal interface IPublicLocation : ILocation + { + } + + // internal interface + internal interface IInternalLocation : ILocation + { + } } diff --git a/src/Build/ElementLocation/RegistryLocation.cs b/src/Build/ElementLocation/RegistryLocation.cs index d6577196d97..81dbd388596 100644 --- a/src/Build/ElementLocation/RegistryLocation.cs +++ b/src/Build/ElementLocation/RegistryLocation.cs @@ -74,6 +74,8 @@ public string LocationString get { return registryPath; } } + public IElementLocation Location => this; + #region INodePacketTranslatable Members /// diff --git a/src/Build/ElementLocation/XmlAttributeWithLocation.cs b/src/Build/ElementLocation/XmlAttributeWithLocation.cs index 25820d1d1bb..deb655d4700 100644 --- a/src/Build/ElementLocation/XmlAttributeWithLocation.cs +++ b/src/Build/ElementLocation/XmlAttributeWithLocation.cs @@ -4,13 +4,14 @@ using System; using System.Xml; using System.Diagnostics; +using Microsoft.Build.Shared; namespace Microsoft.Build.Construction { /// /// Derivation of XmlAttribute to implement IXmlLineInfo /// - internal class XmlAttributeWithLocation : XmlAttribute, IXmlLineInfo + internal class XmlAttributeWithLocation : XmlAttribute, IPublicLocation, IInternalLocation, IXmlLineInfo { /// /// Line, column, file information @@ -66,7 +67,7 @@ public int LinePosition /// even if it wasn't loaded from disk, or has been edited since. That's because we set that /// path on our XmlDocumentWithLocation wrapper class. /// - internal ElementLocation Location + public ElementLocation Location { get { @@ -81,6 +82,8 @@ internal ElementLocation Location } } + IElementLocation ILocation.Location => Location; + /// /// Whether location is available. /// IXmlLineInfo member. @@ -90,4 +93,4 @@ public bool HasLineInfo() return Location.Line != 0; } } -} \ No newline at end of file +} diff --git a/src/Build/ElementLocation/XmlElementWithLocation.cs b/src/Build/ElementLocation/XmlElementWithLocation.cs index 7da601d28b2..b2ed1acd175 100644 --- a/src/Build/ElementLocation/XmlElementWithLocation.cs +++ b/src/Build/ElementLocation/XmlElementWithLocation.cs @@ -5,6 +5,7 @@ using System.Xml; using System.Diagnostics; using Microsoft.Build.ObjectModelRemoting; +using Microsoft.Build.Shared; namespace Microsoft.Build.Construction { @@ -17,7 +18,7 @@ namespace Microsoft.Build.Construction /// C# doesn't currently allow covariance in method overloading, only on delegates. /// The caller must bravely downcast. /// - internal class XmlElementWithLocation : XmlElement, IXmlLineInfo, ILinkedXml + internal class XmlElementWithLocation : XmlElement, IPublicLocation, IInternalLocation, IXmlLineInfo, ILinkedXml { /// /// Line, column, file information @@ -86,7 +87,7 @@ public int LinePosition /// even if it wasn't loaded from disk, or has been edited since. That's because we set that /// path on our XmlDocumentWithLocation wrapper class. /// - internal ElementLocation Location + public ElementLocation Location { get { @@ -101,6 +102,8 @@ internal ElementLocation Location } } + IElementLocation ILocation.Location => Location; + /// /// Whether location is available. /// IXmlLineInfo member. diff --git a/src/Build/Evaluation/ConditionEvaluator.cs b/src/Build/Evaluation/ConditionEvaluator.cs index 8eb493e6398..ae03b1fb43f 100644 --- a/src/Build/Evaluation/ConditionEvaluator.cs +++ b/src/Build/Evaluation/ConditionEvaluator.cs @@ -15,6 +15,7 @@ namespace Microsoft.Build.Evaluation using ElementLocation = Microsoft.Build.Construction.ElementLocation; using Microsoft.Build.Shared; using Microsoft.Build.Shared.FileSystem; + using Microsoft.Build.Construction; internal static class ConditionEvaluator { @@ -175,7 +176,7 @@ internal static bool EvaluateCondition Expander expander, ExpanderOptions expanderOptions, string evaluationDirectory, - ElementLocation elementLocation, + IInternalLocation location, ILoggingService loggingServices, BuildEventContext buildEventContext, IFileSystem fileSystem, @@ -190,7 +191,7 @@ internal static bool EvaluateCondition expanderOptions, null /* do not collect conditioned properties */, evaluationDirectory, - elementLocation, + location, loggingServices, buildEventContext, fileSystem, @@ -212,7 +213,7 @@ internal static bool EvaluateConditionCollectingConditionedProperties ExpanderOptions expanderOptions, Dictionary> conditionedPropertiesTable, string evaluationDirectory, - ElementLocation elementLocation, + IInternalLocation elementLocation, ILoggingService loggingServices, BuildEventContext buildEventContext, IFileSystem fileSystem, @@ -337,7 +338,7 @@ internal interface IConditionEvaluationState string EvaluationDirectory { get; } - ElementLocation ElementLocation { get; } + IInternalLocation ElementLocation { get; } /// /// Table of conditioned properties and their values. @@ -390,7 +391,7 @@ internal class ConditionEvaluationState : IConditionEvaluationState public string EvaluationDirectory { get; } - public ElementLocation ElementLocation { get; } + public IInternalLocation ElementLocation { get; } public IFileSystem FileSystem { get; } @@ -414,7 +415,7 @@ internal ConditionEvaluationState ExpanderOptions expanderOptions, Dictionary> conditionedPropertiesInProject, string evaluationDirectory, - ElementLocation elementLocation, + IInternalLocation element, IFileSystem fileSystem, ProjectRootElementCacheBase projectRootElementCache = null ) @@ -422,14 +423,14 @@ internal ConditionEvaluationState ErrorUtilities.VerifyThrowArgumentNull(condition, nameof(condition)); ErrorUtilities.VerifyThrowArgumentNull(expander, nameof(expander)); ErrorUtilities.VerifyThrowArgumentNull(evaluationDirectory, nameof(evaluationDirectory)); - ErrorUtilities.VerifyThrowArgumentNull(elementLocation, nameof(elementLocation)); + ErrorUtilities.VerifyThrowArgumentNull(element, nameof(element)); Condition = condition; _expander = expander; _expanderOptions = expanderOptions; ConditionedPropertiesInProject = conditionedPropertiesInProject; // May be null EvaluationDirectory = evaluationDirectory; - ElementLocation = elementLocation; + ElementLocation = element; LoadedProjectsCache = projectRootElementCache; FileSystem = fileSystem; } diff --git a/src/Build/Evaluation/Conditionals/Parser.cs b/src/Build/Evaluation/Conditionals/Parser.cs index ac231b18964..98b6747419c 100644 --- a/src/Build/Evaluation/Conditionals/Parser.cs +++ b/src/Build/Evaluation/Conditionals/Parser.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Microsoft.Build.Construction; using Microsoft.Build.Framework; using Microsoft.Build.Shared; using ElementLocation = Microsoft.Build.Construction.ElementLocation; @@ -42,7 +43,7 @@ internal sealed class Parser { private Scanner _lexer; private ParserOptions _options; - private ElementLocation _elementLocation; + private IInternalLocation _element; internal int errorPosition = 0; // useful for unit tests #region REMOVE_COMPAT_WARNING @@ -93,7 +94,7 @@ internal Parser() // You pass in the expression you want to parse, and you get an // ExpressionTree out the back end. // - internal GenericExpressionNode Parse(string expression, ParserOptions optionSettings, ElementLocation elementLocation) + internal GenericExpressionNode Parse(string expression, ParserOptions optionSettings, IInternalLocation element) { // We currently have no support (and no scenarios) for disallowing property references // in Conditions. @@ -101,19 +102,19 @@ internal GenericExpressionNode Parse(string expression, ParserOptions optionSett "Properties should always be allowed."); _options = optionSettings; - _elementLocation = elementLocation; + _element = element; _lexer = new Scanner(expression, _options); if (!_lexer.Advance()) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, _lexer.GetErrorResource(), expression, errorPosition, _lexer.UnexpectedlyFound); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, _lexer.GetErrorResource(), expression, errorPosition, _lexer.UnexpectedlyFound); } GenericExpressionNode node = Expr(expression); if (!_lexer.IsNext(Token.TokenType.EndOfInput)) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } return node; } @@ -141,7 +142,7 @@ private GenericExpressionNode Expr(string expression) // Log a warning regarding the fact the expression may have been evaluated // incorrectly in earlier version of MSBuild - LoggingServices.LogWarning(_logBuildEventContext, null, new BuildEventFileInfo(_elementLocation), "ConditionMaybeEvaluatedIncorrectly", expression); + LoggingServices.LogWarning(_logBuildEventContext, null, new BuildEventFileInfo(_element.Location), "ConditionMaybeEvaluatedIncorrectly", expression); } #endregion @@ -177,7 +178,7 @@ private GenericExpressionNode BooleanTerm(string expression) if (node == null) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } if (!_lexer.IsNext(Token.TokenType.EndOfInput)) @@ -199,7 +200,7 @@ private GenericExpressionNode BooleanTermPrime(string expression, GenericExpress if (rhs == null) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } OperatorExpressionNode andNode = new AndExpressionNode(); @@ -221,7 +222,7 @@ private GenericExpressionNode RelationalExpr(string expression) if (lhs == null) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } OperatorExpressionNode node = RelationalOperation(expression); @@ -284,7 +285,7 @@ private GenericExpressionNode Factor(string expression) if (!Same(expression, Token.TokenType.LeftParenthesis)) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", _lexer.IsNextString(), errorPosition); return null; } var arglist = new List(); @@ -292,7 +293,7 @@ private GenericExpressionNode Factor(string expression) if (!Same(expression, Token.TokenType.RightParenthesis)) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); return null; } return new FunctionCallExpressionNode(current.String, arglist); @@ -305,7 +306,7 @@ private GenericExpressionNode Factor(string expression) else { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } } else if (Same(expression, Token.TokenType.Not)) @@ -315,7 +316,7 @@ private GenericExpressionNode Factor(string expression) if (expr == null) { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } notNode.LeftChild = expr; return notNode; @@ -323,7 +324,7 @@ private GenericExpressionNode Factor(string expression) else { errorPosition = _lexer.GetErrorPosition(); - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, "UnexpectedTokenInCondition", expression, _lexer.IsNextString(), errorPosition); } return null; } @@ -384,11 +385,11 @@ private bool Same(string expression, Token.TokenType token) errorPosition = _lexer.GetErrorPosition(); if (_lexer.UnexpectedlyFound != null) { - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, _lexer.GetErrorResource(), expression, errorPosition, _lexer.UnexpectedlyFound); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, _lexer.GetErrorResource(), expression, errorPosition, _lexer.UnexpectedlyFound); } else { - ProjectErrorUtilities.VerifyThrowInvalidProject(false, _elementLocation, _lexer.GetErrorResource(), expression, errorPosition); + ProjectErrorUtilities.VerifyThrowInvalidProject(false, _element, _lexer.GetErrorResource(), expression, errorPosition); } } return true; diff --git a/src/Build/Evaluation/Evaluator.cs b/src/Build/Evaluation/Evaluator.cs index aaeb329f765..bd418241b57 100644 --- a/src/Build/Evaluation/Evaluator.cs +++ b/src/Build/Evaluation/Evaluator.cs @@ -824,7 +824,7 @@ private void PerformDepthFirstPass(ProjectRootElement currentProjectOrImport) { foreach (string propertyName in _expander.ExpandIntoStringListLeaveEscaped(currentProjectOrImport.TreatAsLocalProperty, ExpanderOptions.ExpandProperties, currentProjectOrImport.TreatAsLocalPropertyLocation)) { - XmlUtilities.VerifyThrowProjectValidElementName(propertyName, currentProjectOrImport.Location); + XmlUtilities.VerifyThrowProjectValidElementName(propertyName, currentProjectOrImport); _data.GlobalPropertiesToTreatAsLocal.Add(propertyName); } } @@ -1273,21 +1273,21 @@ private void EvaluatePropertyElement(ProjectPropertyElement propertyElement) // it is the same as what we are setting the value on. Note: This needs to be set before we expand the property we are currently setting. _expander.UsedUninitializedProperties.CurrentlyEvaluatingPropertyElementName = propertyElement.Name; - string evaluatedValue = _expander.ExpandIntoStringLeaveEscaped(propertyElement.Value, ExpanderOptions.ExpandProperties, propertyElement.Location); + string evaluatedValue = _expander.ExpandIntoStringLeaveEscaped(propertyElement.Value, ExpanderOptions.ExpandProperties, propertyElement); // If we are going to set a property to a value other than null or empty we need to check to see if it has been used // during evaluation. if (evaluatedValue.Length > 0 && _expander.WarnForUninitializedProperties) { // Is the property we are currently setting in the list of properties which have been used but not initialized - IElementLocation elementWhichUsedProperty; + IInternalLocation elementWhichUsedProperty; bool isPropertyInList = _expander.UsedUninitializedProperties.Properties.TryGetValue(propertyElement.Name, out elementWhichUsedProperty); if (isPropertyInList) { // Once we are going to warn for a property once, remove it from the list so we do not add it again. _expander.UsedUninitializedProperties.Properties.Remove(propertyElement.Name); - _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(propertyElement.Location), "UsedUninitializedProperty", propertyElement.Name, elementWhichUsedProperty.LocationString); + _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(propertyElement.Location), "UsedUninitializedProperty", propertyElement.Name, elementWhichUsedProperty.Location.LocationString); } } @@ -1384,7 +1384,7 @@ private void EvaluateItemDefinitionElement(ProjectItemDefinitionElement itemDefi { if (EvaluateCondition(metadataElement, ExpanderOptions.ExpandPropertiesAndMetadata, ParserOptions.AllowPropertiesAndCustomMetadata)) { - string evaluatedValue = _expander.ExpandIntoStringLeaveEscaped(metadataElement.Value, ExpanderOptions.ExpandPropertiesAndCustomMetadata, itemDefinitionElement.Location); + string evaluatedValue = _expander.ExpandIntoStringLeaveEscaped(metadataElement.Value, ExpanderOptions.ExpandPropertiesAndCustomMetadata, itemDefinitionElement); M predecessor = itemDefinition.GetMetadata(metadataElement.Name); @@ -1752,7 +1752,7 @@ static bool HasProperty(string value, CompareInfo compareInfo) => if (mode == SdkReferencePropertyExpansionMode.DefaultExpand) mode = SdkReferencePropertyExpansionMode.ExpandUnescape; - static string EvaluateProperty(string value, IElementLocation location, + static string EvaluateProperty(string value, IInternalLocation location, Expander expander, SdkReferencePropertyExpansionMode mode) { if (value == null) @@ -1774,12 +1774,10 @@ static string EvaluateProperty(string value, IElementLocation location, } } - IElementLocation sdkReferenceOrigin = importElement.SdkLocation; - sdkReference = new SdkReference( - EvaluateProperty(sdkReference.Name, sdkReferenceOrigin, _expander, mode), - EvaluateProperty(sdkReference.Version, sdkReferenceOrigin, _expander, mode), - EvaluateProperty(sdkReference.MinimumVersion, sdkReferenceOrigin, _expander, mode) + EvaluateProperty(sdkReference.Name, importElement, _expander, mode), + EvaluateProperty(sdkReference.Version, importElement, _expander, mode), + EvaluateProperty(sdkReference.MinimumVersion, importElement, _expander, mode) ); } } @@ -1793,7 +1791,7 @@ static string EvaluateProperty(string value, IElementLocation location, { // We throw using e.Message because e.Message already contains the stack trace // https://github.com/dotnet/msbuild/pull/6763 - ProjectErrorUtilities.ThrowInvalidProject(importElement.SdkLocation, "SDKResolverCriticalFailure", e.Message); + ProjectErrorUtilities.ThrowInvalidProject(importElement, "SDKResolverCriticalFailure", e.Message); } if (!sdkResult.Success) @@ -1820,7 +1818,7 @@ static string EvaluateProperty(string value, IElementLocation location, return; } - ProjectErrorUtilities.ThrowInvalidProject(importElement.SdkLocation, "CouldNotResolveSdk", sdkReference.ToString()); + ProjectErrorUtilities.ThrowInvalidProject(importElement, "CouldNotResolveSdk", sdkReference.ToString()); } if (sdkResult.Path == null) @@ -1961,7 +1959,7 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri imports = new List(); string importExpressionEscaped = _expander.ExpandIntoStringLeaveEscaped(unescapedExpression, ExpanderOptions.ExpandProperties, importElement.ProjectLocation); - ElementLocation importLocationInProject = importElement.Location; + // ElementLocation importLocationInProject = importElement.Location; if (String.IsNullOrWhiteSpace(importExpressionEscaped)) { @@ -1989,7 +1987,7 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri return LoadImportsResult.ImportExpressionResolvedToNothing; } - ProjectErrorUtilities.ThrowInvalidProject(importLocationInProject, "InvalidAttributeValue", String.Empty, XMakeAttributes.project, XMakeElements.import); + ProjectErrorUtilities.ThrowInvalidProject(importElement, "InvalidAttributeValue", String.Empty, XMakeAttributes.project, XMakeElements.import); } bool atleastOneImportIgnored = false; @@ -2013,7 +2011,7 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri } catch (Exception ex) when (ExceptionHandling.IsIoRelatedException(ex)) { - ProjectErrorUtilities.ThrowInvalidProject(importLocationInProject, "InvalidAttributeValueWithException", EscapingUtilities.UnescapeAll(importExpressionEscapedItem), XMakeAttributes.project, XMakeElements.import, ex.Message); + ProjectErrorUtilities.ThrowInvalidProject(importElement, "InvalidAttributeValueWithException", EscapingUtilities.UnescapeAll(importExpressionEscapedItem), XMakeAttributes.project, XMakeElements.import, ex.Message); } if (importFilesEscaped.Length == 0) @@ -2058,14 +2056,14 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri } catch (Exception ex) when (ExceptionHandling.IsIoRelatedException(ex)) { - ProjectErrorUtilities.ThrowInvalidProject(importLocationInProject, "InvalidAttributeValueWithException", importFileUnescaped, XMakeAttributes.project, XMakeElements.import, ex.Message); + ProjectErrorUtilities.ThrowInvalidProject(importElement, "InvalidAttributeValueWithException", importFileUnescaped, XMakeAttributes.project, XMakeElements.import, ex.Message); } // If a file is included twice, or there is a cycle of imports, we ignore all but the first import // and issue a warning to that effect. if (String.Equals(_projectRootElement.FullPath, importFileUnescaped, StringComparison.OrdinalIgnoreCase) /* We are trying to import ourselves */) { - _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(importLocationInProject), "SelfImport", importFileUnescaped); + _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(importElement.Location), "SelfImport", importFileUnescaped); atleastOneImportIgnored = true; continue; @@ -2082,12 +2080,12 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri // Get the full path of the MSBuild file that has this import. string importedBy = importElement.ContainingProject.FullPath ?? String.Empty; - _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(importLocationInProject), "ImportIntroducesCircularity", importFileUnescaped, importedBy); + _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(importElement.Location), "ImportIntroducesCircularity", importFileUnescaped, importedBy); // Throw exception if the project load settings requires us to stop the evaluation of a project when circular imports are detected. if ((_loadSettings & ProjectLoadSettings.RejectCircularImports) != 0) { - ProjectErrorUtilities.ThrowInvalidProject(importLocationInProject, "ImportIntroducesCircularity", importFileUnescaped, importedBy); + ProjectErrorUtilities.ThrowInvalidProject(importElement, "ImportIntroducesCircularity", importFileUnescaped, importedBy); } // Ignore this import and no more further processing on it. @@ -2109,7 +2107,7 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri parenthesizedProjectLocation = "[" + _projectRootElement.FullPath + "]"; } // TODO: Detect if the duplicate import came from an SDK attribute - _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(importLocationInProject), "DuplicateImport", importFileUnescaped, previouslyImportedAt.Location.LocationString, parenthesizedProjectLocation); + _evaluationLoggingContext.LogWarning(null, new BuildEventFileInfo(importElement.Location), "DuplicateImport", importFileUnescaped, previouslyImportedAt.Location.LocationString, parenthesizedProjectLocation); duplicateImport = true; } @@ -2227,7 +2225,7 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri continue; } - ProjectErrorUtilities.ThrowInvalidProject(importLocationInProject, "ImportedProjectNotFound", + ProjectErrorUtilities.ThrowInvalidProject(importElement, "ImportedProjectNotFound", importFileUnescaped, importExpressionEscaped); } else @@ -2280,7 +2278,7 @@ private LoadImportsResult ExpandAndLoadImportsFromUnescapedImportExpression(stri if (ex.InnerException != null) { // Otherwise a more generic message, still pointing to the location of the import tag - ProjectErrorUtilities.ThrowInvalidProject(importLocationInProject, "InvalidImportedProjectFile", + ProjectErrorUtilities.ThrowInvalidProject(importElement, "InvalidImportedProjectFile", importFileUnescaped, ex.InnerException.Message); } @@ -2374,8 +2372,8 @@ private bool EvaluateCondition(ProjectElement element, string condition, Expande return true; } - ElementLocation location = element.ConditionLocation; - using (_evaluationProfiler.TrackCondition(location, condition)) + IInternalLocation location = element.ConditionLocation; + using (_evaluationProfiler.TrackCondition(element, condition)) { bool result = ConditionEvaluator.EvaluateCondition ( @@ -2384,7 +2382,7 @@ private bool EvaluateCondition(ProjectElement element, string condition, Expande _expander, expanderOptions, GetCurrentDirectoryForConditionEvaluation(element), - location, + element, _evaluationLoggingContext.LoggingService, _evaluationLoggingContext.BuildEventContext, _evaluationContext.FileSystem @@ -2414,8 +2412,7 @@ private bool EvaluateConditionCollectingConditionedProperties(ProjectElement ele return EvaluateCondition(element, condition, expanderOptions, parserOptions); } - ElementLocation location = element.ConditionLocation; - using (_evaluationProfiler.TrackCondition(location, condition)) + using (_evaluationProfiler.TrackCondition(element, condition)) { bool result = ConditionEvaluator.EvaluateConditionCollectingConditionedProperties ( @@ -2425,7 +2422,7 @@ private bool EvaluateConditionCollectingConditionedProperties(ProjectElement ele expanderOptions, _data.ConditionedProperties, GetCurrentDirectoryForConditionEvaluation(element), - location, + element, _evaluationLoggingContext.LoggingService, _evaluationLoggingContext.BuildEventContext, _evaluationContext.FileSystem, @@ -2507,7 +2504,7 @@ private void ThrowForImportedProjectWithSearchPathsNotFound(ProjectImportPathMat stringifiedListOfSearchPaths, configLocation); #else - ProjectErrorUtilities.ThrowInvalidProject(importElement.ProjectLocation, "ImportedProjectFromExtensionsPathNotFound", + ProjectErrorUtilities.ThrowInvalidProject(importElement, "ImportedProjectFromExtensionsPathNotFound", importExpandedWithDefaultPath, relativeProjectPath, searchPathMatch.MsBuildPropertyFormat, diff --git a/src/Build/Evaluation/Expander.cs b/src/Build/Evaluation/Expander.cs index fe397e4469a..966f6bb0f1a 100644 --- a/src/Build/Evaluation/Expander.cs +++ b/src/Build/Evaluation/Expander.cs @@ -13,6 +13,7 @@ using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using Microsoft.Build.Collections; +using Microsoft.Build.Construction; using Microsoft.Build.Execution; using Microsoft.Build.Internal; using Microsoft.Build.Shared; @@ -388,7 +389,7 @@ internal static bool ExpressionContainsItemVector(string expression) /// /// If ExpanderOptions.BreakOnNotEmpty was passed, expression was going to be non-empty, and it broke out early, returns null. Otherwise the result can be trusted. /// - internal string ExpandIntoStringAndUnescape(string expression, ExpanderOptions options, IElementLocation elementLocation) + internal string ExpandIntoStringAndUnescape(string expression, ExpanderOptions options, IInternalLocation elementLocation) { string result = ExpandIntoStringLeaveEscaped(expression, options, elementLocation); @@ -402,7 +403,7 @@ internal string ExpandIntoStringAndUnescape(string expression, ExpanderOptions o /// /// If ExpanderOptions.BreakOnNotEmpty was passed, expression was going to be non-empty, and it broke out early, returns null. Otherwise the result can be trusted. /// - internal string ExpandIntoStringLeaveEscaped(string expression, ExpanderOptions options, IElementLocation elementLocation) + internal string ExpandIntoStringLeaveEscaped(string expression, ExpanderOptions options, IInternalLocation elementLocation) { if (expression.Length == 0) { @@ -423,7 +424,7 @@ internal string ExpandIntoStringLeaveEscaped(string expression, ExpanderOptions /// Used only for unit tests. Expands the property expression (including any metadata expressions) and returns /// the result typed (i.e. not converted into a string if the result is a function return). /// - internal object ExpandPropertiesLeaveTypedAndEscaped(string expression, ExpanderOptions options, IElementLocation elementLocation) + internal object ExpandPropertiesLeaveTypedAndEscaped(string expression, ExpanderOptions options, IInternalLocation elementLocation) { if (expression.Length == 0) { @@ -442,7 +443,7 @@ internal object ExpandPropertiesLeaveTypedAndEscaped(string expression, Expander /// Use this form when the result is going to be processed further, for example by matching against the file system, /// so literals must be distinguished, and you promise to unescape after that. /// - internal SemiColonTokenizer ExpandIntoStringListLeaveEscaped(string expression, ExpanderOptions options, IElementLocation elementLocation) + internal SemiColonTokenizer ExpandIntoStringListLeaveEscaped(string expression, ExpanderOptions options, IInternalLocation elementLocation) { ErrorUtilities.VerifyThrow((options & ExpanderOptions.BreakOnNotEmpty) == 0, "not supported"); @@ -455,7 +456,7 @@ internal SemiColonTokenizer ExpandIntoStringListLeaveEscaped(string expression, /// If the expression is empty, returns an empty list. /// If ExpanderOptions.BreakOnNotEmpty was passed, expression was going to be non-empty, and it broke out early, returns null. Otherwise the result can be trusted. /// - internal IList ExpandIntoTaskItemsLeaveEscaped(string expression, ExpanderOptions options, IElementLocation elementLocation) + internal IList ExpandIntoTaskItemsLeaveEscaped(string expression, ExpanderOptions options, IInternalLocation elementLocation) { return ExpandIntoItemsLeaveEscaped(expression, (IItemFactory)TaskItemFactory.Instance, options, elementLocation); } @@ -470,7 +471,7 @@ internal IList ExpandIntoTaskItemsLeaveEscaped(string expression, Expa /// so literals must be distinguished, and you promise to unescape after that. /// /// Type of items to return. - internal IList ExpandIntoItemsLeaveEscaped(string expression, IItemFactory itemFactory, ExpanderOptions options, IElementLocation elementLocation) + internal IList ExpandIntoItemsLeaveEscaped(string expression, IItemFactory itemFactory, ExpanderOptions options, IInternalLocation elementLocation) where T : class, IItem { if (expression.Length == 0) @@ -510,7 +511,7 @@ internal IList ExpandIntoItemsLeaveEscaped(string expression, IItemFactory { // The expression is not of the form @(itemName). Therefore, just // treat it as a string, and create a new item from that string. - T itemToAdd = itemFactory.CreateItem(split, elementLocation.File); + T itemToAdd = itemFactory.CreateItem(split, elementLocation.Location.File); result.Add(itemToAdd); } @@ -543,7 +544,7 @@ internal IList ExpandIntoItemsLeaveEscaped(string expression, IItemFactory /// have an item type set on it, it will be given the item type of the item vector to use. /// /// Type of the items that should be returned. - internal IList ExpandSingleItemVectorExpressionIntoItems(string expression, IItemFactory itemFactory, ExpanderOptions options, bool includeNullItems, out bool isTransformExpression, IElementLocation elementLocation) + internal IList ExpandSingleItemVectorExpressionIntoItems(string expression, IItemFactory itemFactory, ExpanderOptions options, bool includeNullItems, out bool isTransformExpression, IInternalLocation elementLocation) where T : class, IItem { if (expression.Length == 0) @@ -558,14 +559,14 @@ internal IList ExpandSingleItemVectorExpressionIntoItems(string expression } internal static ExpressionShredder.ItemExpressionCapture ExpandSingleItemVectorExpressionIntoExpressionCapture( - string expression, ExpanderOptions options, IElementLocation elementLocation) + string expression, ExpanderOptions options, IInternalLocation elementLocation) { return ItemExpander.ExpandSingleItemVectorExpressionIntoExpressionCapture(expression, options, elementLocation); } internal IList ExpandExpressionCaptureIntoItems( ExpressionShredder.ItemExpressionCapture expressionCapture, IItemProvider items, IItemFactory itemFactory, - ExpanderOptions options, bool includeNullEntries, out bool isTransformExpression, IElementLocation elementLocation) + ExpanderOptions options, bool includeNullEntries, out bool isTransformExpression, IInternalLocation elementLocation) where S : class, IItem where T : class, IItem { @@ -575,7 +576,7 @@ internal IList ExpandExpressionCaptureIntoItems( internal bool ExpandExpressionCapture( ExpressionShredder.ItemExpressionCapture expressionCapture, - IElementLocation elementLocation, + IInternalLocation elementLocation, ExpanderOptions options, bool includeNullEntries, out bool isTransformExpression, @@ -740,7 +741,7 @@ private static void AddArgument(List arguments, SpanBasedStringBuilder a /// Returns an array of unexpanded arguments. /// If there are no arguments, returns an empty array. /// - private static string[] ExtractFunctionArguments(IElementLocation elementLocation, string expressionFunction, string argumentsString) + private static string[] ExtractFunctionArguments(IInternalLocation elementLocation, string expressionFunction, string argumentsString) { int argumentsContentLength = argumentsString.Length; @@ -842,7 +843,7 @@ private static class MetadataExpander /// Used to specify what to expand. /// The location information for error reporting purposes. /// The string with item metadata expanded in-place, escaped. - internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTable metadata, ExpanderOptions options, IElementLocation elementLocation) + internal static string ExpandMetadataLeaveEscaped(string expression, IMetadataTable metadata, ExpanderOptions options, IInternalLocation elementLocation) { try { @@ -1044,7 +1045,7 @@ internal static string ExpandPropertiesLeaveEscaped( string expression, IPropertyProvider properties, ExpanderOptions options, - IElementLocation elementLocation, + IInternalLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties, IFileSystem fileSystem) { @@ -1080,7 +1081,7 @@ internal static object ExpandPropertiesLeaveTypedAndEscaped( string expression, IPropertyProvider properties, ExpanderOptions options, - IElementLocation elementLocation, + IInternalLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties, IFileSystem fileSystem) { @@ -1239,7 +1240,7 @@ internal static object ExpandPropertyBody( object propertyValue, IPropertyProvider properties, ExpanderOptions options, - IElementLocation elementLocation, + IInternalLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties, IFileSystem fileSystem) { @@ -1427,7 +1428,7 @@ internal static string ConvertToString(object valueToConvert) /// /// Look up a simple property reference by the name of the property, e.g. "Foo" when expanding $(Foo). /// - private static object LookupProperty(IPropertyProvider properties, string propertyName, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties) + private static object LookupProperty(IPropertyProvider properties, string propertyName, IInternalLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties) { return LookupProperty(properties, propertyName, 0, propertyName.Length - 1, elementLocation, usedUninitializedProperties); } @@ -1435,7 +1436,7 @@ private static object LookupProperty(IPropertyProvider properties, string pro /// /// Look up a simple property reference by the name of the property, e.g. "Foo" when expanding $(Foo). /// - private static object LookupProperty(IPropertyProvider properties, string propertyName, int startIndex, int endIndex, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties) + private static object LookupProperty(IPropertyProvider properties, string propertyName, int startIndex, int endIndex, IInternalLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties) { T property = properties.GetProperty(propertyName, startIndex, endIndex); @@ -1493,14 +1494,15 @@ private static object LookupProperty(IPropertyProvider properties, string pro /// never been saved) then returns empty string. /// If the property name is not one of those properties, returns empty string. /// - private static object ExpandMSBuildThisFileProperty(string propertyName, IElementLocation elementLocation) + private static object ExpandMSBuildThisFileProperty(string propertyName, IInternalLocation elementLocation) { if (!ReservedPropertyNames.IsReservedProperty(propertyName)) { return String.Empty; } - if (elementLocation.File.Length == 0) + var location = elementLocation.Location; + if (location.File.Length == 0) { return String.Empty; } @@ -1511,27 +1513,27 @@ private static object ExpandMSBuildThisFileProperty(string propertyName, IElemen // all different lengths, this sequence is efficient. if (String.Equals(propertyName, ReservedPropertyNames.thisFile, StringComparison.OrdinalIgnoreCase)) { - value = Path.GetFileName(elementLocation.File); + value = Path.GetFileName(location.File); } else if (String.Equals(propertyName, ReservedPropertyNames.thisFileName, StringComparison.OrdinalIgnoreCase)) { - value = Path.GetFileNameWithoutExtension(elementLocation.File); + value = Path.GetFileNameWithoutExtension(location.File); } else if (String.Equals(propertyName, ReservedPropertyNames.thisFileFullPath, StringComparison.OrdinalIgnoreCase)) { - value = FileUtilities.NormalizePath(elementLocation.File); + value = FileUtilities.NormalizePath(location.File); } else if (String.Equals(propertyName, ReservedPropertyNames.thisFileExtension, StringComparison.OrdinalIgnoreCase)) { - value = Path.GetExtension(elementLocation.File); + value = Path.GetExtension(location.File); } else if (String.Equals(propertyName, ReservedPropertyNames.thisFileDirectory, StringComparison.OrdinalIgnoreCase)) { - value = FileUtilities.EnsureTrailingSlash(Path.GetDirectoryName(elementLocation.File)); + value = FileUtilities.EnsureTrailingSlash(Path.GetDirectoryName(location.File)); } else if (String.Equals(propertyName, ReservedPropertyNames.thisFileDirectoryNoRoot, StringComparison.OrdinalIgnoreCase)) { - string directory = Path.GetDirectoryName(elementLocation.File); + string directory = Path.GetDirectoryName(location.File); int rootLength = Path.GetPathRoot(directory).Length; value = FileUtilities.EnsureTrailingNoLeadingSlash(directory, rootLength); } @@ -1548,7 +1550,7 @@ private static object ExpandMSBuildThisFileProperty(string propertyName, IElemen /// "TaskLocation" is the name of the value. The name of the value and the preceding "@" may be omitted if /// the default value is desired. /// - private static string ExpandRegistryValue(string registryExpression, IElementLocation elementLocation) + private static string ExpandRegistryValue(string registryExpression, IInternalLocation elementLocation) { // Remove "Registry:" prefix string registryLocation = registryExpression.Substring(9); @@ -1632,7 +1634,7 @@ private static string ExpandRegistryValue(string registryExpression, IElementLoc /// /// Given a string like "Registry:HKEY_LOCAL_MACHINE\Software\Vendor\Tools@TaskLocation", returns String.Empty, as FEATURE_WIN32_REGISTRY is off. /// - private static string ExpandRegistryValue(string registryExpression, IElementLocation elementLocation) + private static string ExpandRegistryValue(string registryExpression, IInternalLocation elementLocation) { return String.Empty; } @@ -1734,7 +1736,7 @@ internal static IEnumerable> Transform(Expander expande /// Type of the items that should be returned. internal static IList ExpandSingleItemVectorExpressionIntoItems( Expander expander, string expression, IItemProvider items, IItemFactory itemFactory, ExpanderOptions options, - bool includeNullEntries, out bool isTransformExpression, IElementLocation elementLocation) + bool includeNullEntries, out bool isTransformExpression, IInternalLocation elementLocation) where S : class, IItem where T : class, IItem { @@ -1751,7 +1753,7 @@ internal static IList ExpandSingleItemVectorExpressionIntoItems( } internal static ExpressionShredder.ItemExpressionCapture ExpandSingleItemVectorExpressionIntoExpressionCapture( - string expression, ExpanderOptions options, IElementLocation elementLocation) + string expression, ExpanderOptions options, IInternalLocation elementLocation) { if (((options & ExpanderOptions.ExpandItems) == 0) || (expression.Length == 0)) { @@ -1787,7 +1789,7 @@ internal static ExpressionShredder.ItemExpressionCapture ExpandSingleItemVectorE internal static IList ExpandExpressionCaptureIntoItems( ExpressionShredder.ItemExpressionCapture expressionCapture, Expander expander, IItemProvider items, IItemFactory itemFactory, - ExpanderOptions options, bool includeNullEntries, out bool isTransformExpression, IElementLocation elementLocation) + ExpanderOptions options, bool includeNullEntries, out bool isTransformExpression, IInternalLocation elementLocation) where S : class, IItem where T : class, IItem { @@ -1827,7 +1829,7 @@ internal static IList ExpandExpressionCaptureIntoItems( if (expandedItemVector.Length > 0) { - T newItem = itemFactory.CreateItem(expandedItemVector, elementLocation.File); + T newItem = itemFactory.CreateItem(expandedItemVector, elementLocation.Location.File); result.Add(newItem); } @@ -1853,13 +1855,13 @@ internal static IList ExpandExpressionCaptureIntoItems( if (itemSpec != null && originalItem == null) { // We have an itemspec, but no base item - result.Add(itemFactory.CreateItem(itemSpec, elementLocation.File)); + result.Add(itemFactory.CreateItem(itemSpec, elementLocation.Location.File)); } else if (itemSpec != null && originalItem != null) { result.Add(itemSpec.Equals(originalItem.EvaluatedIncludeEscaped) - ? itemFactory.CreateItem(originalItem, elementLocation.File) // itemspec came from direct item reference, no transforms - : itemFactory.CreateItem(itemSpec, originalItem, elementLocation.File)); // itemspec came from a transform and is different from its original item + ? itemFactory.CreateItem(originalItem, elementLocation.Location.File) // itemspec came from direct item reference, no transforms + : itemFactory.CreateItem(itemSpec, originalItem, elementLocation.Location.File)); // itemspec came from a transform and is different from its original item } else if (includeNullEntries) { @@ -1897,7 +1899,7 @@ internal static bool ExpandExpressionCapture( Expander expander, ExpressionShredder.ItemExpressionCapture expressionCapture, IItemProvider evaluatedItems, - IElementLocation elementLocation, + IInternalLocation elementLocation, ExpanderOptions options, bool includeNullEntries, out bool isTransformExpression, @@ -1976,7 +1978,7 @@ out List> itemsFromCapture /// If ExpanderOptions.BreakOnNotEmpty was passed, expression was going to be non-empty, and it broke out early, returns null. Otherwise the result can be trusted. /// /// Type of the items provided. - internal static string ExpandItemVectorsIntoString(Expander expander, string expression, IItemProvider items, ExpanderOptions options, IElementLocation elementLocation) + internal static string ExpandItemVectorsIntoString(Expander expander, string expression, IItemProvider items, ExpanderOptions options, IInternalLocation elementLocation) where T : class, IItem { if ((options & ExpanderOptions.ExpandItems) == 0 || expression.Length == 0) @@ -2029,7 +2031,7 @@ internal static string ExpandItemVectorsIntoString(Expander expander, s /// Prepare the stack of transforms that will be executed on a given set of items. /// /// class, IItem. - private static Stack> PrepareTransformStackFromMatch(IElementLocation elementLocation, ExpressionShredder.ItemExpressionCapture match) + private static Stack> PrepareTransformStackFromMatch(IInternalLocation elementLocation, ExpressionShredder.ItemExpressionCapture match) where S : class, IItem { // There's something wrong with the expression, and we ended up with no function names @@ -2077,7 +2079,7 @@ private static bool ExpandExpressionCaptureIntoStringBuilder( Expander expander, ExpressionShredder.ItemExpressionCapture capture, IItemProvider evaluatedItems, - IElementLocation elementLocation, + IInternalLocation elementLocation, SpanBasedStringBuilder builder, ExpanderOptions options ) @@ -2144,13 +2146,13 @@ internal static class IntrinsicItemFunctions /// Delegate that represents the signature of all item transformation functions /// This is used to support calling the functions by name. /// - public delegate IEnumerable> ItemTransformFunction(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments); + public delegate IEnumerable> ItemTransformFunction(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments); /// /// Get a delegate to the given item transformation function by supplying the name and the /// Item type that should be used. /// - internal static ItemTransformFunction GetItemTransformFunction(IElementLocation elementLocation, string functionName, Type itemType) + internal static ItemTransformFunction GetItemTransformFunction(IInternalLocation elementLocation, string functionName, Type itemType) { ItemTransformFunction transformFunction = null; string qualifiedFunctionName = itemType.FullName + "::" + functionName; @@ -2234,7 +2236,7 @@ var resultantItem in /// /// Intrinsic function that returns the number of items in the list. /// - internal static IEnumerable> Count(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> Count(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { yield return new Pair(Convert.ToString(itemsOfType.Count(), CultureInfo.InvariantCulture), null /* no base item */); } @@ -2243,7 +2245,7 @@ internal static IEnumerable> Count(Expander expander, IEle /// Intrinsic function that returns the specified built-in modifer value of the items in itemsOfType /// Tuple is {current item include, item under transformation}. /// - internal static IEnumerable> ItemSpecModifierFunction(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> ItemSpecModifierFunction(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2296,7 +2298,7 @@ internal static IEnumerable> ItemSpecModifierFunction(Expander

/// Intrinsic function that returns the subset of items that actually exist on disk. /// - internal static IEnumerable> Exists(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> Exists(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2343,7 +2345,7 @@ internal static IEnumerable> Exists(Expander expander, IEl ///

/// Intrinsic function that combines the existing paths of the input items with a given relative path. /// - internal static IEnumerable> Combine(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> Combine(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments?.Length == 1, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2367,7 +2369,7 @@ internal static IEnumerable> Combine(Expander expander, IE /// /// Intrinsic function that returns all ancestor directories of the given items. /// - internal static IEnumerable> GetPathsOfAllDirectoriesAbove(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> GetPathsOfAllDirectoriesAbove(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2443,7 +2445,7 @@ internal static IEnumerable> GetPathsOfAllDirectoriesAbove(Expan /// Intrinsic function that returns the DirectoryName of the items in itemsOfType /// UNDONE: This can be removed in favor of a built-in %(DirectoryName) metadata in future. /// - internal static IEnumerable> DirectoryName(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> DirectoryName(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2510,7 +2512,7 @@ internal static IEnumerable> DirectoryName(Expander expand /// /// Intrinsic function that returns the contents of the metadata in specified in argument[0]. /// - internal static IEnumerable> Metadata(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> Metadata(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments?.Length == 1, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2567,7 +2569,7 @@ internal static IEnumerable> Metadata(Expander expander, I /// Intrinsic function that returns only the items from itemsOfType that have distinct Item1 in the Tuple /// Using a case sensitive comparison. /// - internal static IEnumerable> DistinctWithCase(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> DistinctWithCase(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { return DistinctWithComparer(expander, elementLocation, includeNullEntries, functionName, itemsOfType, arguments, StringComparer.Ordinal); } @@ -2576,7 +2578,7 @@ internal static IEnumerable> DistinctWithCase(Expander exp /// Intrinsic function that returns only the items from itemsOfType that have distinct Item1 in the Tuple /// Using a case insensitive comparison. /// - internal static IEnumerable> Distinct(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> Distinct(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { return DistinctWithComparer(expander, elementLocation, includeNullEntries, functionName, itemsOfType, arguments, StringComparer.OrdinalIgnoreCase); } @@ -2585,7 +2587,7 @@ internal static IEnumerable> Distinct(Expander expander, I /// Intrinsic function that returns only the items from itemsOfType that have distinct Item1 in the Tuple /// Using a case insensitive comparison. /// - internal static IEnumerable> DistinctWithComparer(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments, StringComparer comparer) + internal static IEnumerable> DistinctWithComparer(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments, StringComparer comparer) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2606,7 +2608,7 @@ internal static IEnumerable> DistinctWithComparer(Expander /// /// Intrinsic function reverses the item list. /// - internal static IEnumerable> Reverse(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> Reverse(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); foreach (Pair item in itemsOfType.Reverse()) @@ -2618,7 +2620,7 @@ internal static IEnumerable> Reverse(Expander expander, IE /// /// Intrinsic function that transforms expressions like the %(foo) in @(Compile->'%(foo)'). /// - internal static IEnumerable> ExpandQuotedExpressionFunction(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> ExpandQuotedExpressionFunction(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments?.Length == 1, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2660,7 +2662,7 @@ internal static IEnumerable> ExpandQuotedExpressionFunction(Expa /// internal static IEnumerable> ExecuteStringFunction( Expander expander, - IElementLocation elementLocation, + IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, @@ -2700,7 +2702,7 @@ internal static IEnumerable> ExecuteStringFunction( /// /// Intrinsic function that returns the items from itemsOfType with their metadata cleared, i.e. only the itemspec is retained. /// - internal static IEnumerable> ClearMetadata(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> ClearMetadata(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments == null || arguments.Length == 0, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2717,7 +2719,7 @@ internal static IEnumerable> ClearMetadata(Expander expand /// Intrinsic function that returns only those items that have a not-blank value for the metadata specified /// Using a case insensitive comparison. /// - internal static IEnumerable> HasMetadata(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> HasMetadata(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments?.Length == 1, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2754,7 +2756,7 @@ internal static IEnumerable> HasMetadata(Expander expander /// Intrinsic function that returns only those items have the given metadata value /// Using a case insensitive comparison. /// - internal static IEnumerable> WithMetadataValue(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> WithMetadataValue(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments?.Length == 2, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2790,7 +2792,7 @@ internal static IEnumerable> WithMetadataValue(Expander ex /// Intrinsic function that returns a boolean to indicate if any of the items have the given metadata value /// Using a case insensitive comparison. /// - internal static IEnumerable> AnyHaveMetadataValue(Expander expander, IElementLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) + internal static IEnumerable> AnyHaveMetadataValue(Expander expander, IInternalLocation elementLocation, bool includeNullEntries, string functionName, IEnumerable> itemsOfType, string[] arguments) { ProjectErrorUtilities.VerifyThrowInvalidProject(arguments?.Length == 2, elementLocation, "InvalidItemFunctionSyntax", functionName, arguments == null ? 0 : arguments.Length); @@ -2858,7 +2860,7 @@ internal class TransformFunction /// /// The element location of the transform expression. /// - private IElementLocation _elementLocation; + private IInternalLocation _elementLocation; /// /// The name of the function that this class will call. @@ -2868,7 +2870,7 @@ internal class TransformFunction /// /// TransformFunction constructor. /// - public TransformFunction(IElementLocation elementLocation, string functionName, IntrinsicItemFunctions.ItemTransformFunction transform, string[] arguments) + public TransformFunction(IInternalLocation elementLocation, string functionName, IntrinsicItemFunctions.ItemTransformFunction transform, string[] arguments) { _elementLocation = elementLocation; _functionName = functionName; @@ -2887,7 +2889,7 @@ public string[] Arguments /// /// The element location of the transform expression. /// - public IElementLocation ElementLocation + public IInternalLocation elementLocation { get { return _elementLocation; } } @@ -2921,12 +2923,12 @@ private class MetadataMatchEvaluator /// /// Location of the match. /// - private IElementLocation _elementLocation; + private IInternalLocation _elementLocation; /// /// Constructor. /// - internal MetadataMatchEvaluator(string itemSpec, IItem sourceOfMetadata, IElementLocation elementLocation) + internal MetadataMatchEvaluator(string itemSpec, IItem sourceOfMetadata, IInternalLocation elementLocation) { _itemSpec = itemSpec; _sourceOfMetadata = sourceOfMetadata; @@ -3203,7 +3205,7 @@ internal string Receiver /// internal static Function ExtractPropertyFunction( string expressionFunction, - IElementLocation elementLocation, + IInternalLocation elementLocation, object propertyValue, UsedUninitializedProperties usedUnInitializedProperties, IFileSystem fileSystem) @@ -3325,7 +3327,7 @@ internal static Function ExtractPropertyFunction( /// /// Execute the function on the given instance. /// - internal object Execute(object objectInstance, IPropertyProvider properties, ExpanderOptions options, IElementLocation elementLocation) + internal object Execute(object objectInstance, IPropertyProvider properties, ExpanderOptions options, IInternalLocation elementLocation) { object functionResult = String.Empty; object[] args = null; @@ -3424,7 +3426,7 @@ internal object Execute(object objectInstance, IPropertyProvider properties, // specified the file name. This is syntactic sugar so they don't have to always // include $(MSBuildThisFileDirectory) as a parameter. // - string startingDirectory = String.IsNullOrWhiteSpace(elementLocation.File) ? String.Empty : Path.GetDirectoryName(elementLocation.File); + string startingDirectory = String.IsNullOrWhiteSpace(elementLocation.Location.File) ? String.Empty : Path.GetDirectoryName(elementLocation.Location.File); args = new [] { @@ -4717,7 +4719,7 @@ private static Type GetTypeFromAssembly(string typeName, string candidateAssembl /// Extracts the name, arguments, binding flags, and invocation type for an indexer /// Also extracts the remainder of the expression that is not part of this indexer. /// - private static void ConstructIndexerFunction(string expressionFunction, IElementLocation elementLocation, object propertyValue, int methodStartIndex, int indexerEndIndex, ref FunctionBuilder functionBuilder) + private static void ConstructIndexerFunction(string expressionFunction, IInternalLocation elementLocation, object propertyValue, int methodStartIndex, int indexerEndIndex, ref FunctionBuilder functionBuilder) { string argumentsContent = expressionFunction.Substring(1, indexerEndIndex - 1); string remainder = expressionFunction.Substring(methodStartIndex); @@ -4760,7 +4762,7 @@ private static void ConstructIndexerFunction(string expressionFunction, IElement /// Extracts the name, arguments, binding flags, and invocation type for a static or instance function. /// Also extracts the remainder of the expression that is not part of this function. /// - private static void ConstructFunction(IElementLocation elementLocation, string expressionFunction, int argumentStartIndex, int methodStartIndex, ref FunctionBuilder functionBuilder) + private static void ConstructFunction(IInternalLocation elementLocation, string expressionFunction, int argumentStartIndex, int methodStartIndex, ref FunctionBuilder functionBuilder) { // The unevaluated and unexpanded arguments for this function string[] functionArguments; @@ -5142,13 +5144,13 @@ internal class UsedUninitializedProperties /// internal UsedUninitializedProperties() { - Properties = new Dictionary(StringComparer.OrdinalIgnoreCase); + Properties = new Dictionary(StringComparer.OrdinalIgnoreCase); } /// /// Hash set of properties which have been used before being initialized. /// - internal IDictionary Properties + internal IDictionary Properties { get; set; diff --git a/src/Build/Evaluation/ItemSpec.cs b/src/Build/Evaluation/ItemSpec.cs index fbc0b6f6b1a..bb396a1ef4b 100644 --- a/src/Build/Evaluation/ItemSpec.cs +++ b/src/Build/Evaluation/ItemSpec.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Microsoft.Build.Construction; using Microsoft.Build.Globbing; using Microsoft.Build.Internal; using Microsoft.Build.Shared; @@ -141,7 +142,7 @@ private bool InitReferencedItemsIfNecessary() /// /// The xml attribute where this itemspec comes from /// - public IElementLocation ItemSpecLocation { get; } + public IInternalLocation ItemSpecLocation { get; } /// The string containing item syntax /// Expects the expander to have a default item factory set @@ -151,7 +152,7 @@ private bool InitReferencedItemsIfNecessary() public ItemSpec( string itemSpec, Expander expander, - IElementLocation itemSpecLocation, + IInternalLocation itemSpecLocation, string projectDirectory, bool expandProperties = true) { @@ -162,7 +163,7 @@ public ItemSpec( Fragments = BuildItemFragments(itemSpecLocation, projectDirectory, expandProperties); } - private List BuildItemFragments(IElementLocation itemSpecLocation, string projectDirectory, bool expandProperties) + private List BuildItemFragments(IInternalLocation itemSpecLocation, string projectDirectory, bool expandProperties) { // Code corresponds to Evaluator.CreateItemsFromInclude var evaluatedItemspecEscaped = ItemSpecString; @@ -247,7 +248,7 @@ private List BuildItemFragments(IElementLocation itemSpecLocat private ItemExpressionFragment ProcessItemExpression( string expression, - IElementLocation elementLocation, + IInternalLocation elementLocation, string projectDirectory, out bool isItemListExpression) { diff --git a/src/Build/Evaluation/LazyItemEvaluator.cs b/src/Build/Evaluation/LazyItemEvaluator.cs index 9fd3eec87e7..a57206cbbc0 100644 --- a/src/Build/Evaluation/LazyItemEvaluator.cs +++ b/src/Build/Evaluation/LazyItemEvaluator.cs @@ -14,7 +14,6 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using System.Threading; @@ -84,8 +83,8 @@ LazyItemEvaluator lazyEvaluator return true; } MSBuildEventSource.Log.EvaluateConditionStart(condition); - - using (lazyEvaluator._evaluationProfiler.TrackCondition(element.ConditionLocation, condition)) + var conditionLocation = element.ConditionLocation; + using (lazyEvaluator._evaluationProfiler.TrackCondition(conditionLocation, condition)) { bool result = ConditionEvaluator.EvaluateCondition ( @@ -94,7 +93,7 @@ LazyItemEvaluator lazyEvaluator expander, expanderOptions, GetCurrentDirectoryForConditionEvaluation(element, lazyEvaluator), - element.ConditionLocation, + element, lazyEvaluator._loggingContext.LoggingService, lazyEvaluator._loggingContext.BuildEventContext, lazyEvaluator.FileSystem @@ -619,7 +618,7 @@ private RemoveOperation BuildRemoveOperation(string rootDirectory, ProjectItemEl return new RemoveOperation(operationBuilder, this); } - private void ProcessItemSpec(string rootDirectory, string itemSpec, IElementLocation itemSpecLocation, OperationBuilder builder) + private void ProcessItemSpec(string rootDirectory, string itemSpec, IInternalLocation itemSpecLocation, OperationBuilder builder) { builder.ItemSpec = new ItemSpec(itemSpec, _outerExpander, itemSpecLocation, rootDirectory); @@ -646,7 +645,7 @@ private static IEnumerable GetExpandedMetadataValuesAndConditions(IColle yield return expander.ExpandIntoStringLeaveEscaped( metadatumElement.Value, expanderOptions, - metadatumElement.Location); + metadatumElement); yield return expander.ExpandIntoStringLeaveEscaped( metadatumElement.Condition, @@ -672,7 +671,7 @@ private void ProcessMetadataElements(ProjectItemElement itemElement, OperationBu } } - private void AddItemReferences(string expression, OperationBuilder operationBuilder, IElementLocation elementLocation) + private void AddItemReferences(string expression, OperationBuilder operationBuilder, IInternalLocation elementLocation) { if (expression.Length == 0) { diff --git a/src/Build/Evaluation/Profiler/EvaluationProfiler.cs b/src/Build/Evaluation/Profiler/EvaluationProfiler.cs index 1082b9e2876..fbf3e8e5d10 100644 --- a/src/Build/Evaluation/Profiler/EvaluationProfiler.cs +++ b/src/Build/Evaluation/Profiler/EvaluationProfiler.cs @@ -72,9 +72,9 @@ public IDisposable TrackElement(ProjectElement element) /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IDisposable TrackCondition(IElementLocation location, string condition) + public IDisposable TrackCondition(IInternalLocation element, string condition) { - return _shouldTrackElements ? new EvaluationFrame(this, CurrentLocation.WithFileLineAndCondition(location.File, location.Line, condition)) : null; + return _shouldTrackElements ? new EvaluationFrame(this, CurrentLocation.WithFileLineAndCondition(element.Location.File, element.Location.Line, condition)) : null; } /// diff --git a/src/Build/Evaluation/ProjectParser.cs b/src/Build/Evaluation/ProjectParser.cs index 761ef477d6f..0e269e90b2a 100644 --- a/src/Build/Evaluation/ProjectParser.cs +++ b/src/Build/Evaluation/ProjectParser.cs @@ -128,13 +128,13 @@ private void Parse() XmlElementWithLocation element = _document.DocumentElement as XmlElementWithLocation; ProjectErrorUtilities.VerifyThrowInvalidProject(element != null, ElementLocation.Create(_document.FullPath), "NoRootProjectElement", XMakeElements.project); - ProjectErrorUtilities.VerifyThrowInvalidProject(element.Name != XMakeElements.visualStudioProject, element.Location, "ProjectUpgradeNeeded", _project.FullPath); - ProjectErrorUtilities.VerifyThrowInvalidProject(element.LocalName == XMakeElements.project, element.Location, "UnrecognizedElement", element.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(element.Name != XMakeElements.visualStudioProject, element, "ProjectUpgradeNeeded", _project.FullPath); + ProjectErrorUtilities.VerifyThrowInvalidProject(element.LocalName == XMakeElements.project, element, "UnrecognizedElement", element.Name); // If a namespace was specified it must be the default MSBuild namespace. if (!ProjectXmlUtilities.VerifyValidProjectNamespace(element)) { - ProjectErrorUtilities.ThrowInvalidProject(element.Location, "ProjectMustBeInMSBuildXmlNamespace", + ProjectErrorUtilities.ThrowInvalidProject(element, "ProjectMustBeInMSBuildXmlNamespace", XMakeAttributes.defaultXmlNamespace); } else @@ -195,11 +195,11 @@ private void Parse() case XMakeElements.error: case XMakeElements.warning: case XMakeElements.message: - ProjectErrorUtilities.ThrowInvalidProject(childElement.Location, "ErrorWarningMessageNotSupported", childElement.Name); + ProjectErrorUtilities.ThrowInvalidProject(childElement, "ErrorWarningMessageNotSupported", childElement.Name); break; default: - ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, childElement.ParentNode.Name, childElement.Location); + ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, childElement.ParentNode.Name, childElement); break; } } @@ -218,7 +218,7 @@ private ProjectPropertyGroupElement ParseProjectPropertyGroupElement(XmlElementW { ProjectXmlUtilities.VerifyThrowProjectAttributes(childElement, ValidAttributesOnlyConditionAndLabel); XmlUtilities.VerifyThrowProjectValidElementName(childElement); - ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(childElement.Name) && !ReservedPropertyNames.IsReservedProperty(childElement.Name), childElement.Location, "CannotModifyReservedProperty", childElement.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(childElement.Name) && !ReservedPropertyNames.IsReservedProperty(childElement.Name), childElement, "CannotModifyReservedProperty", childElement.Name); // All children inside a property are ignored, since they are only part of its value ProjectPropertyElement property = new ProjectPropertyElement(childElement, propertyGroup, _project); @@ -283,26 +283,26 @@ private ProjectItemElement ParseProjectItemElement(XmlElementWithLocation elemen if (exclusiveAttributeCount > 1) { XmlAttributeWithLocation errorAttribute = remove.Length > 0 ? (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.remove] : (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.update]; - ProjectErrorUtilities.ThrowInvalidProject(errorAttribute.Location, "InvalidAttributeExclusive"); + ProjectErrorUtilities.ThrowInvalidProject(errorAttribute, "InvalidAttributeExclusive"); } // Include, remove, or update must be present unless inside a target - ProjectErrorUtilities.VerifyThrowInvalidProject(exclusiveAttributeCount == 1 || belowTarget, element.Location, "IncludeRemoveOrUpdate", exclusiveItemOperation, itemType); + ProjectErrorUtilities.VerifyThrowInvalidProject(exclusiveAttributeCount == 1 || belowTarget, element, "IncludeRemoveOrUpdate", exclusiveItemOperation, itemType); // Exclude must be missing, unless Include exists ProjectXmlUtilities.VerifyThrowProjectInvalidAttribute(exclude.Length == 0 || include.Length > 0, (XmlAttributeWithLocation)element.Attributes[XMakeAttributes.exclude]); // If we have an Include attribute at all, it must have non-zero length - ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.include, itemType); + ProjectErrorUtilities.VerifyThrowInvalidProject(include.Length > 0 || element.Attributes[XMakeAttributes.include] == null, element, "MissingRequiredAttribute", XMakeAttributes.include, itemType); // If we have a Remove attribute at all, it must have non-zero length - ProjectErrorUtilities.VerifyThrowInvalidProject(remove.Length > 0 || element.Attributes[XMakeAttributes.remove] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.remove, itemType); + ProjectErrorUtilities.VerifyThrowInvalidProject(remove.Length > 0 || element.Attributes[XMakeAttributes.remove] == null, element, "MissingRequiredAttribute", XMakeAttributes.remove, itemType); // If we have an Update attribute at all, it must have non-zero length - ProjectErrorUtilities.VerifyThrowInvalidProject(update.Length > 0 || element.Attributes[XMakeAttributes.update] == null, element.Location, "MissingRequiredAttribute", XMakeAttributes.update, itemType); + ProjectErrorUtilities.VerifyThrowInvalidProject(update.Length > 0 || element.Attributes[XMakeAttributes.update] == null, element, "MissingRequiredAttribute", XMakeAttributes.update, itemType); XmlUtilities.VerifyThrowProjectValidElementName(element); - ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(itemType), element.Location, "CannotModifyReservedItem", itemType); + ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(itemType), element, "CannotModifyReservedItem", itemType); ProjectItemElement item = new ProjectItemElement(element, parent, _project); @@ -391,9 +391,9 @@ private ProjectMetadataElement ParseProjectMetadataElement(XmlElementWithLocatio XmlUtilities.VerifyThrowProjectValidElementName(element); - ProjectErrorUtilities.VerifyThrowInvalidProject(!(parent is ProjectItemElement) || ((ProjectItemElement)parent).Remove.Length == 0, element.Location, "ChildElementsBelowRemoveNotAllowed", element.Name); - ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.ItemSpecModifiers.IsItemSpecModifier(element.Name), element.Location, "ItemSpecModifierCannotBeCustomMetadata", element.Name); - ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(element.Name), element.Location, "CannotModifyReservedItemMetadata", element.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(!(parent is ProjectItemElement) || ((ProjectItemElement)parent).Remove.Length == 0, element, "ChildElementsBelowRemoveNotAllowed", element.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(!FileUtilities.ItemSpecModifiers.IsItemSpecModifier(element.Name), element, "ItemSpecModifierCannotBeCustomMetadata", element.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(!XMakeElements.ReservedItemNames.Contains(element.Name), element, "CannotModifyReservedItemMetadata", element.Name); ProjectMetadataElement metadatum = new ProjectMetadataElement(element, parent, _project); @@ -401,7 +401,7 @@ private ProjectMetadataElement ParseProjectMetadataElement(XmlElementWithLocatio if (parent is ProjectItemDefinitionElement) { bool containsItemVector = Expander.ExpressionContainsItemVector(metadatum.Value); - ProjectErrorUtilities.VerifyThrowInvalidProject(!containsItemVector, element.Location, "MetadataDefinitionCannotContainItemVectorExpression", metadatum.Value, metadatum.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(!containsItemVector, element, "MetadataDefinitionCannotContainItemVectorExpression", metadatum.Value, metadatum.Name); } return metadatum; @@ -424,7 +424,7 @@ private ProjectImportGroupElement ParseProjectImportGroupElement(XmlElementWithL ProjectErrorUtilities.VerifyThrowInvalidProject ( childElement.Name == XMakeElements.import, - childElement.Location, + childElement, "UnrecognizedChildElement", childElement.Name, element.Name @@ -446,7 +446,7 @@ private ProjectImportElement ParseProjectImportElement(XmlElementWithLocation el ProjectErrorUtilities.VerifyThrowInvalidProject ( parent is ProjectRootElement || parent is ProjectImportGroupElement, - element.Location, + element, "UnrecognizedParentElement", parent, element @@ -507,7 +507,7 @@ private UsingTaskParameterGroupElement ParseUsingTaskParameterGroupElement(XmlEl private ProjectUsingTaskElement ParseProjectUsingTaskElement(XmlElementWithLocation element) { ProjectXmlUtilities.VerifyThrowProjectAttributes(element, ValidAttributesOnUsingTask); - ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(XMakeAttributes.taskName).Length > 0, element.Location, "ProjectTaskNameEmpty"); + ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(XMakeAttributes.taskName).Length > 0, element, "ProjectTaskNameEmpty"); string assemblyName = element.GetAttribute(XMakeAttributes.assemblyName); string assemblyFile = element.GetAttribute(XMakeAttributes.assemblyFile); @@ -515,7 +515,7 @@ private ProjectUsingTaskElement ParseProjectUsingTaskElement(XmlElementWithLocat ProjectErrorUtilities.VerifyThrowInvalidProject ( (assemblyName.Length > 0) ^ (assemblyFile.Length > 0), - element.Location, + element, "UsingTaskAssemblySpecification", XMakeElements.usingTask, XMakeAttributes.assemblyName, @@ -557,7 +557,7 @@ private ProjectUsingTaskElement ParseProjectUsingTaskElement(XmlElementWithLocat foundTaskElement = true; break; default: - ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element.Location); + ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element); break; } @@ -596,7 +596,7 @@ private ProjectTargetElement ParseProjectTargetElement(XmlElementWithLocation el case XMakeElements.propertyGroup: if (onError != null) { - ProjectErrorUtilities.ThrowInvalidProject(onError.Location, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name); + ProjectErrorUtilities.ThrowInvalidProject(onError, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name); } child = ParseProjectPropertyGroupElement(childElement, target); @@ -605,7 +605,7 @@ private ProjectTargetElement ParseProjectTargetElement(XmlElementWithLocation el case XMakeElements.itemGroup: if (onError != null) { - ProjectErrorUtilities.ThrowInvalidProject(onError.Location, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name); + ProjectErrorUtilities.ThrowInvalidProject(onError, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name); } child = ParseProjectItemGroupElement(childElement, target); @@ -622,13 +622,13 @@ private ProjectTargetElement ParseProjectTargetElement(XmlElementWithLocation el break; case XMakeElements.itemDefinitionGroup: - ProjectErrorUtilities.ThrowInvalidProject(childElement.Location, "ItemDefinitionGroupNotLegalInsideTarget", childElement.Name); + ProjectErrorUtilities.ThrowInvalidProject(childElement, "ItemDefinitionGroupNotLegalInsideTarget", childElement.Name); break; default: if (onError != null) { - ProjectErrorUtilities.ThrowInvalidProject(onError.Location, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name); + ProjectErrorUtilities.ThrowInvalidProject(onError, "NodeMustBeLastUnderElement", XMakeElements.onError, XMakeElements.target, childElement.Name); } child = ParseProjectTaskElement(childElement, target); @@ -651,7 +651,7 @@ private ProjectTaskElement ParseProjectTaskElement(XmlElementWithLocation elemen ProjectErrorUtilities.VerifyThrowInvalidProject ( !XMakeAttributes.IsBadlyCasedSpecialTaskAttribute(attribute.Name), - attribute.Location, + attribute, "BadlyCasedSpecialTaskAttribute", attribute.Name, element.Name, @@ -663,7 +663,7 @@ private ProjectTaskElement ParseProjectTaskElement(XmlElementWithLocation elemen foreach (XmlElementWithLocation childElement in ProjectXmlUtilities.GetVerifyThrowProjectChildElements(element)) { - ProjectErrorUtilities.VerifyThrowInvalidProject(childElement.Name == XMakeElements.output, childElement.Location, "UnrecognizedChildElement", childElement.Name, task.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(childElement.Name == XMakeElements.output, childElement, "UnrecognizedChildElement", childElement.Name, task.Name); ProjectOutputElement output = ParseProjectOutputElement(childElement, task); @@ -688,7 +688,7 @@ private ProjectOutputElement ParseProjectOutputElement(XmlElementWithLocation el ProjectErrorUtilities.VerifyThrowInvalidProject ( (String.IsNullOrWhiteSpace(itemNameAttribute?.Value) && !String.IsNullOrWhiteSpace(propertyNameAttribute?.Value)) || (!String.IsNullOrWhiteSpace(itemNameAttribute?.Value) && String.IsNullOrWhiteSpace(propertyNameAttribute?.Value)), - element.Location, + element, "InvalidTaskOutputSpecification", parent.Name ); @@ -696,7 +696,7 @@ private ProjectOutputElement ParseProjectOutputElement(XmlElementWithLocation el ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, itemNameAttribute, XMakeAttributes.itemName); ProjectXmlUtilities.VerifyThrowProjectAttributeEitherMissingOrNotEmpty(element, propertyNameAttribute, XMakeAttributes.propertyName); - ProjectErrorUtilities.VerifyThrowInvalidProject(String.IsNullOrWhiteSpace(propertyNameAttribute?.Value) || !ReservedPropertyNames.IsReservedProperty(propertyNameAttribute.Value), element.Location, "CannotModifyReservedProperty", propertyNameAttribute?.Value); + ProjectErrorUtilities.VerifyThrowInvalidProject(String.IsNullOrWhiteSpace(propertyNameAttribute?.Value) || !ReservedPropertyNames.IsReservedProperty(propertyNameAttribute.Value), element, "CannotModifyReservedProperty", propertyNameAttribute?.Value); return new ProjectOutputElement(element, parent, _project); } @@ -773,7 +773,7 @@ private ProjectChooseElement ParseProjectChooseElement(XmlElementWithLocation el ProjectChooseElement choose = new ProjectChooseElement(element, parent, _project); nestingDepth++; - ProjectErrorUtilities.VerifyThrowInvalidProject(nestingDepth <= MaximumChooseNesting, element.Location, "ChooseOverflow", MaximumChooseNesting); + ProjectErrorUtilities.VerifyThrowInvalidProject(nestingDepth <= MaximumChooseNesting, element, "ChooseOverflow", MaximumChooseNesting); bool foundWhen = false; bool foundOtherwise = false; @@ -785,26 +785,26 @@ private ProjectChooseElement ParseProjectChooseElement(XmlElementWithLocation el switch (childElement.Name) { case XMakeElements.when: - ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise, childElement.Location, "WhenNotAllowedAfterOtherwise"); + ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise, childElement, "WhenNotAllowedAfterOtherwise"); child = ParseProjectWhenElement(childElement, choose, nestingDepth); foundWhen = true; break; case XMakeElements.otherwise: - ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise, childElement.Location, "MultipleOtherwise"); + ProjectErrorUtilities.VerifyThrowInvalidProject(!foundOtherwise, childElement, "MultipleOtherwise"); foundOtherwise = true; child = ParseProjectOtherwiseElement(childElement, choose, nestingDepth); break; default: - ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element.Location); + ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element); break; } choose.AppendParentedChildNoChecks(child); } - ProjectErrorUtilities.VerifyThrowInvalidProject(foundWhen, element.Location, "ChooseMustContainWhen"); + ProjectErrorUtilities.VerifyThrowInvalidProject(foundWhen, element, "ChooseMustContainWhen"); return choose; } @@ -861,7 +861,7 @@ private void ParseWhenOtherwiseChildren(XmlElementWithLocation element, ProjectE break; default: - ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element.Location); + ProjectXmlUtilities.ThrowProjectInvalidChildElement(childElement.Name, element.Name, element); break; } @@ -878,7 +878,7 @@ private ProjectExtensionsElement ParseProjectExtensionsElement(XmlElementWithLoc // files. We don't. ProjectXmlUtilities.VerifyThrowProjectNoAttributes(element); - ProjectErrorUtilities.VerifyThrowInvalidProject(!_seenProjectExtensions, element.Location, "DuplicateProjectExtensions"); + ProjectErrorUtilities.VerifyThrowInvalidProject(!_seenProjectExtensions, element, "DuplicateProjectExtensions"); _seenProjectExtensions = true; // All children inside ProjectExtensions are ignored, since they are only part of its value @@ -892,7 +892,7 @@ private ProjectSdkElement ParseProjectSdkElement(XmlElementWithLocation element) { if (string.IsNullOrEmpty(element.GetAttribute(XMakeAttributes.sdkName))) { - ProjectErrorUtilities.ThrowInvalidProject(element.Location, "InvalidSdkElementName", element.Name); + ProjectErrorUtilities.ThrowInvalidProject(element, "InvalidSdkElementName", element.Name); } return new ProjectSdkElement(element, _project, _project); diff --git a/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs b/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs index f414ad75367..a22cacc3dbe 100644 --- a/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs +++ b/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs @@ -14,7 +14,7 @@ namespace Microsoft.Build.Execution /// Immutable. /// [DebuggerDisplay("{_name} Value={_value} Condition={_condition}")] - public class ProjectItemGroupTaskMetadataInstance : ITranslatable + public class ProjectItemGroupTaskMetadataInstance : IPublicLocation, IInternalLocation, ITranslatable { /// /// Name of the metadatum @@ -123,6 +123,8 @@ public ElementLocation ConditionLocation { return _conditionLocation; } } + IElementLocation ILocation.Location => Location; + /// /// Deep clone /// diff --git a/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs b/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs index 33e254f876c..69c2174a93c 100644 --- a/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs +++ b/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs @@ -14,7 +14,7 @@ namespace Microsoft.Build.Execution /// Immutable. /// [DebuggerDisplay("{_name}={Value} Condition={_condition}")] - public class ProjectPropertyGroupTaskPropertyInstance : ITranslatable + public class ProjectPropertyGroupTaskPropertyInstance : IPublicLocation, IInternalLocation, ITranslatable { /// /// Name of the property @@ -121,6 +121,8 @@ public ElementLocation ConditionLocation get { return _conditionLocation; } } + IElementLocation ILocation.Location => Location; + /// /// Deep clone /// diff --git a/src/Build/Instance/ProjectPropertyInstance.cs b/src/Build/Instance/ProjectPropertyInstance.cs index 037cdac44a2..1d1e529a9e5 100644 --- a/src/Build/Instance/ProjectPropertyInstance.cs +++ b/src/Build/Instance/ProjectPropertyInstance.cs @@ -202,7 +202,7 @@ internal static ProjectPropertyInstance Create(string name, string escapedValue, /// an invalid project file exception. /// Creates mutable object. /// - internal static ProjectPropertyInstance Create(string name, string escapedValue, ElementLocation location) + internal static ProjectPropertyInstance Create(string name, string escapedValue, IInternalLocation location) { return Create(name, escapedValue, false, location, isImmutable: false); } @@ -211,7 +211,7 @@ internal static ProjectPropertyInstance Create(string name, string escapedValue, /// Called during project build time to create a property. Reserved properties will cause /// an invalid project file exception. /// - internal static ProjectPropertyInstance Create(string name, string escapedValue, ElementLocation location, bool isImmutable) + internal static ProjectPropertyInstance Create(string name, string escapedValue, IInternalLocation location, bool isImmutable) { return Create(name, escapedValue, false, location, isImmutable); } @@ -288,7 +288,7 @@ internal ProjectPropertyElement ToProjectPropertyElement(ProjectElementContainer /// as it should never be needed for any subsequent messages, and is just extra bulk. /// Inherits mutability from project if any. /// - private static ProjectPropertyInstance Create(string name, string escapedValue, bool mayBeReserved, ElementLocation location, bool isImmutable) + private static ProjectPropertyInstance Create(string name, string escapedValue, bool mayBeReserved, IInternalLocation location, bool isImmutable) { // Does not check immutability as this is only called during build (which is already protected) or evaluation ErrorUtilities.VerifyThrowArgumentNull(escapedValue, nameof(escapedValue)); diff --git a/src/Build/Instance/ProjectTargetInstance.cs b/src/Build/Instance/ProjectTargetInstance.cs index dd3dffc3cc5..3cdcce89288 100644 --- a/src/Build/Instance/ProjectTargetInstance.cs +++ b/src/Build/Instance/ProjectTargetInstance.cs @@ -20,7 +20,7 @@ namespace Microsoft.Build.Execution /// This is an immutable class. /// [DebuggerDisplay("Name={_name} Count={_children.Count} Condition={_condition} Inputs={_inputs} Outputs={_outputs} DependsOnTargets={_dependsOnTargets} BeforeTargets={_beforeTargets} AfterTargets={_afterTargets}")] - public sealed class ProjectTargetInstance : IImmutable, IKeyed, ITranslatable + public sealed class ProjectTargetInstance : IPublicLocation, IInternalLocation, IImmutable, IKeyed, ITranslatable { /// /// Name of the target @@ -460,6 +460,8 @@ internal bool ParentProjectSupportsReturnsAttribute { return _parentProjectSupportsReturnsAttribute; } } + IElementLocation ILocation.Location => Location; + /// /// Creates a ProjectTargetElement representing this instance. Attaches it to the specified root element. /// diff --git a/src/Build/Instance/ProjectTargetInstanceChild.cs b/src/Build/Instance/ProjectTargetInstanceChild.cs index 8c4a36af614..ecbdbe0c6e5 100644 --- a/src/Build/Instance/ProjectTargetInstanceChild.cs +++ b/src/Build/Instance/ProjectTargetInstanceChild.cs @@ -12,7 +12,7 @@ namespace Microsoft.Build.Execution /// Type for ProjectTaskInstance and ProjectPropertyGroupTaskInstance and ProjectItemGroupTaskInstance /// allowing them to be used in a single collection of target children /// - public abstract class ProjectTargetInstanceChild : ITranslatable + public abstract class ProjectTargetInstanceChild : IPublicLocation, IInternalLocation, ITranslatable { /// /// Condition on the element @@ -41,6 +41,8 @@ public string FullPath /// public abstract ElementLocation ConditionLocation { get; } + IElementLocation ILocation.Location => Location; + void ITranslatable.Translate(ITranslator translator) { // all subclasses should be translateable diff --git a/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs b/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs index 802539f6077..f665c90e4e5 100644 --- a/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs +++ b/src/Build/Instance/TaskFactories/AssemblyTaskFactory.cs @@ -6,6 +6,7 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Build.Construction; using Microsoft.Build.Execution; using Microsoft.Build.Framework; using Microsoft.Build.Shared; @@ -463,7 +464,7 @@ internal bool TaskNameCreatableByFactory(string taskName, IDictionary /// Validates the given set of parameters, logging the appropriate errors as necessary. /// - private static void VerifyThrowIdentityParametersValid(IDictionary identityParameters, IElementLocation errorLocation, string taskName, string runtimeName, string architectureName) + private static void VerifyThrowIdentityParametersValid(IDictionary identityParameters, IInternalLocation errorLocation, string taskName, string runtimeName, string architectureName) { // validate the task factory parameters if (identityParameters?.Count > 0) diff --git a/src/Build/Instance/TaskRegistry.cs b/src/Build/Instance/TaskRegistry.cs index a44626cccae..edce5604d37 100644 --- a/src/Build/Instance/TaskRegistry.cs +++ b/src/Build/Instance/TaskRegistry.cs @@ -363,7 +363,7 @@ IFileSystem fileSystem catch (ArgumentException ex) { // Invalid chars in AssemblyFile path - ProjectErrorUtilities.ThrowInvalidProject(projectUsingTaskXml.Location, "InvalidAttributeValueWithException", assemblyFile, XMakeAttributes.assemblyFile, XMakeElements.usingTask, ex.Message); + ProjectErrorUtilities.ThrowInvalidProject(projectUsingTaskXml, "InvalidAttributeValueWithException", assemblyFile, XMakeAttributes.assemblyFile, XMakeElements.usingTask, ex.Message); } RegisteredTaskRecord.ParameterGroupAndTaskElementRecord parameterGroupAndTaskElementRecord = null; diff --git a/src/Build/Xml/ProjectXmlUtilities.XmlElementChildIterator.cs b/src/Build/Xml/ProjectXmlUtilities.XmlElementChildIterator.cs index c139c1366fd..311abe04599 100644 --- a/src/Build/Xml/ProjectXmlUtilities.XmlElementChildIterator.cs +++ b/src/Build/Xml/ProjectXmlUtilities.XmlElementChildIterator.cs @@ -95,7 +95,7 @@ private XmlElementWithLocation GetNextNode(XmlNode child) } if (_throwForInvalidNodeTypes) { - ThrowProjectInvalidChildElement(child.Name, _element.Name, _element.Location); + ThrowProjectInvalidChildElement(child.Name, _element.Name, _element); } break; } diff --git a/src/Build/Xml/ProjectXmlUtilities.cs b/src/Build/Xml/ProjectXmlUtilities.cs index 3c1528a3064..d0a47a0bf47 100644 --- a/src/Build/Xml/ProjectXmlUtilities.cs +++ b/src/Build/Xml/ProjectXmlUtilities.cs @@ -38,7 +38,7 @@ internal static void VerifyThrowProjectNoChildElements(XmlElementWithLocation el { foreach (var child in GetVerifyThrowProjectChildElements(element)) { - ThrowProjectInvalidChildElement(child.Name, element.Name, element.Location); + ThrowProjectInvalidChildElement(child.Name, element.Name, element); } } @@ -48,13 +48,13 @@ internal static void VerifyThrowProjectNoChildElements(XmlElementWithLocation el /// internal static void ThrowProjectInvalidChildElementDueToDuplicate(XmlElementWithLocation child) { - ProjectErrorUtilities.ThrowInvalidProject(child.Location, "InvalidChildElementDueToDuplication", child.Name, child.ParentNode.Name); + ProjectErrorUtilities.ThrowInvalidProject(child, "InvalidChildElementDueToDuplication", child.Name, child.ParentNode.Name); } /// /// Throw an invalid project exception indicating that the child is not valid beneath the element /// - internal static void ThrowProjectInvalidChildElement(string name, string parentName, ElementLocation location) + internal static void ThrowProjectInvalidChildElement(string name, string parentName, IInternalLocation location) { ProjectErrorUtilities.ThrowInvalidProject(location, "UnrecognizedChildElement", name, parentName); } @@ -91,7 +91,7 @@ internal static void VerifyThrowProjectAttributeEitherMissingOrNotEmpty(XmlEleme ProjectErrorUtilities.VerifyThrowInvalidProject ( attribute == null || attribute.Value.Length > 0, - attribute?.Location, + attribute == null ? ElementLocation.EmptyLocation : attribute, "InvalidAttributeValue", String.Empty, attributeName, @@ -130,7 +130,7 @@ internal static void VerifyThrowProjectInvalidAttribute(bool condition, XmlAttri /// internal static void VerifyThrowProjectRequiredAttribute(XmlElementWithLocation element, string attributeName) { - ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(attributeName).Length > 0, element.Location, "MissingRequiredAttribute", attributeName, element.Name); + ProjectErrorUtilities.VerifyThrowInvalidProject(element.GetAttribute(attributeName).Length > 0, element, "MissingRequiredAttribute", attributeName, element.Name); } /// @@ -149,7 +149,7 @@ internal static void VerifyThrowProjectAttributes(XmlElementWithLocation element /// internal static void ThrowProjectInvalidAttribute(XmlAttributeWithLocation attribute) { - ProjectErrorUtilities.ThrowInvalidProject(attribute.Location, "UnrecognizedAttribute", attribute.Name, attribute.OwnerElement.Name); + ProjectErrorUtilities.ThrowInvalidProject(attribute, "UnrecognizedAttribute", attribute.Name, attribute.OwnerElement.Name); } /// diff --git a/src/Shared/IElementLocation.cs b/src/Shared/IElementLocation.cs index b9b26cfd74b..16fb1b291d1 100644 --- a/src/Shared/IElementLocation.cs +++ b/src/Shared/IElementLocation.cs @@ -13,7 +13,7 @@ namespace Microsoft.Build.Shared /// This is not public because the current implementation only provides correct data for unedited projects. /// DO NOT make it public without considering a solution to this problem. /// - internal interface IElementLocation : ITranslatable + internal interface IElementLocation : Construction.IInternalLocation, ITranslatable { /// /// The file from which this particular element originated. It may diff --git a/src/Shared/ProjectErrorUtilities.cs b/src/Shared/ProjectErrorUtilities.cs index 540b26f71d1..af0ae40d8e5 100644 --- a/src/Shared/ProjectErrorUtilities.cs +++ b/src/Shared/ProjectErrorUtilities.cs @@ -12,6 +12,7 @@ * * ******************************************************************************/ +using Microsoft.Build.Construction; using InvalidProjectFileException = Microsoft.Build.Exceptions.InvalidProjectFileException; namespace Microsoft.Build.Shared @@ -37,7 +38,7 @@ internal static class ProjectErrorUtilities internal static void VerifyThrowInvalidProject ( bool condition, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName ) { @@ -52,7 +53,7 @@ string resourceName /// internal static void ThrowInvalidProject ( - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0 ) @@ -70,7 +71,7 @@ T1 arg0 internal static void VerifyThrowInvalidProject ( bool condition, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0 ) @@ -87,7 +88,7 @@ T1 arg0 /// internal static void ThrowInvalidProject ( - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1 @@ -106,7 +107,7 @@ T2 arg1 /// internal static void ThrowInvalidProject ( - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1, @@ -127,7 +128,7 @@ T3 arg2 /// internal static void ThrowInvalidProject ( - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1, @@ -146,7 +147,7 @@ T4 arg3 /// internal static void ThrowInvalidProject ( - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, params object[] args ) @@ -165,7 +166,7 @@ params object[] args internal static void VerifyThrowInvalidProject ( bool condition, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1 @@ -186,7 +187,7 @@ T2 arg1 internal static void VerifyThrowInvalidProject ( bool condition, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1, @@ -209,7 +210,7 @@ T3 arg2 internal static void VerifyThrowInvalidProject ( bool condition, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1, @@ -234,7 +235,7 @@ internal static void VerifyThrowInvalidProject ( bool condition, string errorSubCategoryResourceName, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName ) { @@ -259,7 +260,7 @@ internal static void VerifyThrowInvalidProject ( bool condition, string errorSubCategoryResourceName, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0 ) @@ -287,7 +288,7 @@ internal static void VerifyThrowInvalidProject ( bool condition, string errorSubCategoryResourceName, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1 @@ -317,7 +318,7 @@ internal static void VerifyThrowInvalidProject ( bool condition, string errorSubCategoryResourceName, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1, @@ -349,7 +350,7 @@ internal static void VerifyThrowInvalidProject ( bool condition, string errorSubCategoryResourceName, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, T1 arg0, T2 arg1, @@ -382,7 +383,7 @@ T4 arg3 private static void ThrowInvalidProject ( string errorSubCategoryResourceName, - IElementLocation elementLocation, + IInternalLocation elementLocation, string resourceName, params object[] args ) @@ -406,8 +407,8 @@ params object[] args string errorCode; string helpKeyword; string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(out errorCode, out helpKeyword, resourceName, args); - - throw new InvalidProjectFileException(elementLocation.File, elementLocation.Line, elementLocation.Column, 0 /* Unknown end line */, 0 /* Unknown end column */, message, errorSubCategory, errorCode, helpKeyword); + var location = elementLocation.Location; + throw new InvalidProjectFileException(location.File, location.Line, location.Column, 0 /* Unknown end line */, 0 /* Unknown end column */, message, errorSubCategory, errorCode, helpKeyword); } } } diff --git a/src/Shared/XmlUtilities.cs b/src/Shared/XmlUtilities.cs index 2695d35d4b0..4c051bb5323 100644 --- a/src/Shared/XmlUtilities.cs +++ b/src/Shared/XmlUtilities.cs @@ -85,7 +85,7 @@ internal static void VerifyThrowArgumentValidElementName(string name) /// /// Note that our restrictions are more stringent than the XML Standard's restrictions. /// - internal static void VerifyThrowProjectValidElementName(string name, IElementLocation location) + internal static void VerifyThrowProjectValidElementName(string name, IInternalLocation location) { ErrorUtilities.VerifyThrowArgumentLength(name, nameof(name)); int firstInvalidCharLocation = LocateFirstInvalidElementNameCharacter(name); @@ -110,7 +110,7 @@ internal static void VerifyThrowProjectValidElementName(XmlElementWithLocation e if (-1 != firstInvalidCharLocation) { - ProjectErrorUtilities.ThrowInvalidProject(element.Location, "NameInvalid", name, name[firstInvalidCharLocation]); + ProjectErrorUtilities.ThrowInvalidProject(element, "NameInvalid", name, name[firstInvalidCharLocation]); } } @@ -142,10 +142,14 @@ internal static bool IsValidElementName(string name) /// internal static int LocateFirstInvalidElementNameCharacter(string name) { + // Create span to avoid the get_Char() func call. + var span = name.AsSpan(); + var len = name.Length; + // Check the first character. // Try capital letters first. // Optimize slightly for success. - if (!IsValidInitialElementNameCharacter(name[0])) + if (!IsValidInitialElementNameCharacter(span[0])) { return 0; } @@ -153,9 +157,9 @@ internal static int LocateFirstInvalidElementNameCharacter(string name) // Check subsequent characters. // Try lower case letters first. // Optimize slightly for success. - for (int i = 1; i < name.Length; i++) + for (int i = 1; i < len; i++) { - if (!IsValidSubsequentElementNameCharacter(name[i])) + if (!IsValidSubsequentElementNameCharacter(span[i])) { return i; } From 1c1797c030a17f77253497ae1232d93278d21992 Mon Sep 17 00:00:00 2001 From: Felix Huang Date: Mon, 25 Oct 2021 14:00:07 -0700 Subject: [PATCH 07/10] Fix tests and clean up code. --- src/Build/Construction/ProjectElement.cs | 8 ++++---- src/Build/Definition/ProjectMetadata.cs | 4 ++-- src/Build/ElementLocation/ElementLocation.cs | 20 ++++--------------- .../XmlAttributeWithLocation.cs | 4 ++-- .../ElementLocation/XmlElementWithLocation.cs | 4 ++-- .../ProjectItemGroupTaskMetadataInstance.cs | 4 ++-- ...rojectPropertyGroupTaskPropertyInstance.cs | 4 ++-- src/Build/Instance/ProjectTargetInstance.cs | 4 ++-- .../Instance/ProjectTargetInstanceChild.cs | 4 ++-- 9 files changed, 22 insertions(+), 34 deletions(-) diff --git a/src/Build/Construction/ProjectElement.cs b/src/Build/Construction/ProjectElement.cs index 5aeb09a6e81..0cb463bd72c 100644 --- a/src/Build/Construction/ProjectElement.cs +++ b/src/Build/Construction/ProjectElement.cs @@ -15,7 +15,7 @@ namespace Microsoft.Build.Construction /// /// Abstract base class for MSBuild construction object model elements. /// - public abstract class ProjectElement : IPublicLocation, IInternalLocation, IProjectElement, ILinkableObject + public abstract class ProjectElement : IInternalLocation, IProjectElement, ILinkableObject { /// /// Parent container object. @@ -299,7 +299,7 @@ internal set internal ProjectElementLink Link => _xmlSource?.Link; - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; /// /// @@ -533,12 +533,12 @@ internal static ProjectElement CreateNewInstance(ProjectElement xml, ProjectRoot internal ElementLocation GetAttributeLocation(string attributeName) { - return _xmlSource?.Link?.GetAttributeLocation(attributeName) ?? XmlElement.GetAttributeLocation(attributeName); + return Link != null ? Link.GetAttributeLocation(attributeName) : XmlElement.GetAttributeLocation(attributeName); } internal string GetAttributeValue(string attributeName, bool nullIfNotExists = false) { - return _xmlSource?.Link?.GetAttributeValue(attributeName, nullIfNotExists) ?? + return Link != null ? Link.GetAttributeValue(attributeName, nullIfNotExists) : ProjectXmlUtilities.GetAttributeValue(XmlElement, attributeName, nullIfNotExists); } diff --git a/src/Build/Definition/ProjectMetadata.cs b/src/Build/Definition/ProjectMetadata.cs index f7eea44b954..1d80c10fa40 100644 --- a/src/Build/Definition/ProjectMetadata.cs +++ b/src/Build/Definition/ProjectMetadata.cs @@ -18,7 +18,7 @@ namespace Microsoft.Build.Evaluation /// Never used to represent built-in metadata, like %(Filename). There is always a backing XML object. /// [DebuggerDisplay("{Name}={EvaluatedValue} [{_xml.Value}]")] - public class ProjectMetadata : IEquatable, IMetadatum, IPublicLocation, IInternalLocation + public class ProjectMetadata : IEquatable, IMetadatum, IInternalLocation { /// /// Parent item or item definition that this metadatum lives in. @@ -266,7 +266,7 @@ internal string EvaluatedValueEscaped get => Link != null ? Link.EvaluatedValueEscaped : _evaluatedValueEscaped; } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; #region IEquatable Members diff --git a/src/Build/ElementLocation/ElementLocation.cs b/src/Build/ElementLocation/ElementLocation.cs index 95ff1e2307d..0d1275c7e57 100644 --- a/src/Build/ElementLocation/ElementLocation.cs +++ b/src/Build/ElementLocation/ElementLocation.cs @@ -18,7 +18,7 @@ namespace Microsoft.Build.Construction /// DO NOT make these objects any larger. There are huge numbers of them and they are transmitted between nodes. /// [Serializable] - public abstract class ElementLocation : IElementLocation, IPublicLocation, ITranslatable, IImmutable + public abstract class ElementLocation : IElementLocation, ITranslatable, IImmutable { /// /// The singleton empty element location. @@ -85,7 +85,7 @@ internal static ElementLocation EmptyLocation public ElementLocation Location => this; - IElementLocation ILocation.Location => this; + IElementLocation IInternalLocation.Location => this; /// /// Get reasonable hash code. @@ -376,21 +376,9 @@ public override int Column } } - - - // internal interface - internal interface ILocation - { - public T Location { get; } - } - - // public interface - internal interface IPublicLocation : ILocation - { - } - // internal interface - internal interface IInternalLocation : ILocation + internal interface IInternalLocation { + public IElementLocation Location { get; } } } diff --git a/src/Build/ElementLocation/XmlAttributeWithLocation.cs b/src/Build/ElementLocation/XmlAttributeWithLocation.cs index deb655d4700..b4bcbefc1ad 100644 --- a/src/Build/ElementLocation/XmlAttributeWithLocation.cs +++ b/src/Build/ElementLocation/XmlAttributeWithLocation.cs @@ -11,7 +11,7 @@ namespace Microsoft.Build.Construction /// /// Derivation of XmlAttribute to implement IXmlLineInfo /// - internal class XmlAttributeWithLocation : XmlAttribute, IPublicLocation, IInternalLocation, IXmlLineInfo + internal class XmlAttributeWithLocation : XmlAttribute, IInternalLocation, IXmlLineInfo { /// /// Line, column, file information @@ -82,7 +82,7 @@ public ElementLocation Location } } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; /// /// Whether location is available. diff --git a/src/Build/ElementLocation/XmlElementWithLocation.cs b/src/Build/ElementLocation/XmlElementWithLocation.cs index b2ed1acd175..ef0e3d888da 100644 --- a/src/Build/ElementLocation/XmlElementWithLocation.cs +++ b/src/Build/ElementLocation/XmlElementWithLocation.cs @@ -18,7 +18,7 @@ namespace Microsoft.Build.Construction /// C# doesn't currently allow covariance in method overloading, only on delegates. /// The caller must bravely downcast. /// - internal class XmlElementWithLocation : XmlElement, IPublicLocation, IInternalLocation, IXmlLineInfo, ILinkedXml + internal class XmlElementWithLocation : XmlElement, IInternalLocation, IXmlLineInfo, ILinkedXml { /// /// Line, column, file information @@ -102,7 +102,7 @@ public ElementLocation Location } } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; /// /// Whether location is available. diff --git a/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs b/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs index a22cacc3dbe..c287cb7b9b6 100644 --- a/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs +++ b/src/Build/Instance/ProjectItemGroupTaskMetadataInstance.cs @@ -14,7 +14,7 @@ namespace Microsoft.Build.Execution /// Immutable. /// [DebuggerDisplay("{_name} Value={_value} Condition={_condition}")] - public class ProjectItemGroupTaskMetadataInstance : IPublicLocation, IInternalLocation, ITranslatable + public class ProjectItemGroupTaskMetadataInstance : IInternalLocation, ITranslatable { /// /// Name of the metadatum @@ -123,7 +123,7 @@ public ElementLocation ConditionLocation { return _conditionLocation; } } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; /// /// Deep clone diff --git a/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs b/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs index 69c2174a93c..41879cf8239 100644 --- a/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs +++ b/src/Build/Instance/ProjectPropertyGroupTaskPropertyInstance.cs @@ -14,7 +14,7 @@ namespace Microsoft.Build.Execution /// Immutable. /// [DebuggerDisplay("{_name}={Value} Condition={_condition}")] - public class ProjectPropertyGroupTaskPropertyInstance : IPublicLocation, IInternalLocation, ITranslatable + public class ProjectPropertyGroupTaskPropertyInstance : IInternalLocation, ITranslatable { /// /// Name of the property @@ -121,7 +121,7 @@ public ElementLocation ConditionLocation get { return _conditionLocation; } } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; /// /// Deep clone diff --git a/src/Build/Instance/ProjectTargetInstance.cs b/src/Build/Instance/ProjectTargetInstance.cs index 3cdcce89288..861bf175719 100644 --- a/src/Build/Instance/ProjectTargetInstance.cs +++ b/src/Build/Instance/ProjectTargetInstance.cs @@ -20,7 +20,7 @@ namespace Microsoft.Build.Execution /// This is an immutable class. /// [DebuggerDisplay("Name={_name} Count={_children.Count} Condition={_condition} Inputs={_inputs} Outputs={_outputs} DependsOnTargets={_dependsOnTargets} BeforeTargets={_beforeTargets} AfterTargets={_afterTargets}")] - public sealed class ProjectTargetInstance : IPublicLocation, IInternalLocation, IImmutable, IKeyed, ITranslatable + public sealed class ProjectTargetInstance : IInternalLocation, IImmutable, IKeyed, ITranslatable { /// /// Name of the target @@ -460,7 +460,7 @@ internal bool ParentProjectSupportsReturnsAttribute { return _parentProjectSupportsReturnsAttribute; } } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; /// /// Creates a ProjectTargetElement representing this instance. Attaches it to the specified root element. diff --git a/src/Build/Instance/ProjectTargetInstanceChild.cs b/src/Build/Instance/ProjectTargetInstanceChild.cs index ecbdbe0c6e5..7e0de6001e8 100644 --- a/src/Build/Instance/ProjectTargetInstanceChild.cs +++ b/src/Build/Instance/ProjectTargetInstanceChild.cs @@ -12,7 +12,7 @@ namespace Microsoft.Build.Execution /// Type for ProjectTaskInstance and ProjectPropertyGroupTaskInstance and ProjectItemGroupTaskInstance /// allowing them to be used in a single collection of target children /// - public abstract class ProjectTargetInstanceChild : IPublicLocation, IInternalLocation, ITranslatable + public abstract class ProjectTargetInstanceChild : IInternalLocation, ITranslatable { /// /// Condition on the element @@ -41,7 +41,7 @@ public string FullPath /// public abstract ElementLocation ConditionLocation { get; } - IElementLocation ILocation.Location => Location; + IElementLocation IInternalLocation.Location => Location; void ITranslatable.Translate(ITranslator translator) { From c1aaac4aad47a6ac01f896d4b396e8fe3a6c8fa1 Mon Sep 17 00:00:00 2001 From: Felix Huang Date: Mon, 25 Oct 2021 15:00:33 -0700 Subject: [PATCH 08/10] Revert Xml change because span is not supported. --- src/Shared/XmlUtilities.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Shared/XmlUtilities.cs b/src/Shared/XmlUtilities.cs index 4c051bb5323..676af5e3fa5 100644 --- a/src/Shared/XmlUtilities.cs +++ b/src/Shared/XmlUtilities.cs @@ -142,14 +142,10 @@ internal static bool IsValidElementName(string name) /// internal static int LocateFirstInvalidElementNameCharacter(string name) { - // Create span to avoid the get_Char() func call. - var span = name.AsSpan(); - var len = name.Length; - // Check the first character. // Try capital letters first. // Optimize slightly for success. - if (!IsValidInitialElementNameCharacter(span[0])) + if (!IsValidInitialElementNameCharacter(name[0])) { return 0; } @@ -157,9 +153,9 @@ internal static int LocateFirstInvalidElementNameCharacter(string name) // Check subsequent characters. // Try lower case letters first. // Optimize slightly for success. - for (int i = 1; i < len; i++) + for (int i = 1; i < name.Length; i++) { - if (!IsValidSubsequentElementNameCharacter(span[i])) + if (!IsValidSubsequentElementNameCharacter(name[i])) { return i; } From fe6442c6dc7b811e21516531ba0258fbea782a3e Mon Sep 17 00:00:00 2001 From: Felix Huang Date: Mon, 25 Oct 2021 16:52:41 -0700 Subject: [PATCH 09/10] Remove unused get_Location() --- ref/Microsoft.Build/net/Microsoft.Build.cs | 1 - ref/Microsoft.Build/netstandard/Microsoft.Build.cs | 1 - src/Build/ElementLocation/ElementLocation.cs | 2 -- 3 files changed, 4 deletions(-) diff --git a/ref/Microsoft.Build/net/Microsoft.Build.cs b/ref/Microsoft.Build/net/Microsoft.Build.cs index b7463405425..9f42d2be544 100644 --- a/ref/Microsoft.Build/net/Microsoft.Build.cs +++ b/ref/Microsoft.Build/net/Microsoft.Build.cs @@ -17,7 +17,6 @@ protected ElementLocation() { } public abstract int Column { get; } public abstract string File { get; } public abstract int Line { get; } - public Microsoft.Build.Construction.ElementLocation Location { get { throw null; } } public string LocationString { get { throw null; } } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } diff --git a/ref/Microsoft.Build/netstandard/Microsoft.Build.cs b/ref/Microsoft.Build/netstandard/Microsoft.Build.cs index 4df7931e636..c12fdafce68 100644 --- a/ref/Microsoft.Build/netstandard/Microsoft.Build.cs +++ b/ref/Microsoft.Build/netstandard/Microsoft.Build.cs @@ -17,7 +17,6 @@ protected ElementLocation() { } public abstract int Column { get; } public abstract string File { get; } public abstract int Line { get; } - public Microsoft.Build.Construction.ElementLocation Location { get { throw null; } } public string LocationString { get { throw null; } } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } diff --git a/src/Build/ElementLocation/ElementLocation.cs b/src/Build/ElementLocation/ElementLocation.cs index 0d1275c7e57..ccd02a7c515 100644 --- a/src/Build/ElementLocation/ElementLocation.cs +++ b/src/Build/ElementLocation/ElementLocation.cs @@ -83,8 +83,6 @@ internal static ElementLocation EmptyLocation get { return s_emptyElementLocation; } } - public ElementLocation Location => this; - IElementLocation IInternalLocation.Location => this; /// From 81a99b267c09d3c5236e18baccd7a37bde54d53c Mon Sep 17 00:00:00 2001 From: Felix Huang Date: Mon, 25 Oct 2021 17:12:18 -0700 Subject: [PATCH 10/10] Clean up --- src/Build/ElementLocation/XmlAttributeWithLocation.cs | 4 ++-- src/Build/ElementLocation/XmlElementWithLocation.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Build/ElementLocation/XmlAttributeWithLocation.cs b/src/Build/ElementLocation/XmlAttributeWithLocation.cs index b4bcbefc1ad..fdb1755615b 100644 --- a/src/Build/ElementLocation/XmlAttributeWithLocation.cs +++ b/src/Build/ElementLocation/XmlAttributeWithLocation.cs @@ -11,7 +11,7 @@ namespace Microsoft.Build.Construction /// /// Derivation of XmlAttribute to implement IXmlLineInfo /// - internal class XmlAttributeWithLocation : XmlAttribute, IInternalLocation, IXmlLineInfo + internal class XmlAttributeWithLocation : XmlAttribute, IInternalLocation, IXmlLineInfo { /// /// Line, column, file information @@ -67,7 +67,7 @@ public int LinePosition /// even if it wasn't loaded from disk, or has been edited since. That's because we set that /// path on our XmlDocumentWithLocation wrapper class. /// - public ElementLocation Location + internal ElementLocation Location { get { diff --git a/src/Build/ElementLocation/XmlElementWithLocation.cs b/src/Build/ElementLocation/XmlElementWithLocation.cs index ef0e3d888da..2a1ed223dc7 100644 --- a/src/Build/ElementLocation/XmlElementWithLocation.cs +++ b/src/Build/ElementLocation/XmlElementWithLocation.cs @@ -87,7 +87,7 @@ public int LinePosition /// even if it wasn't loaded from disk, or has been edited since. That's because we set that /// path on our XmlDocumentWithLocation wrapper class. /// - public ElementLocation Location + internal ElementLocation Location { get {