/// <summary>
        /// Throws an InvalidProjectFileException using the given data.
        ///
        /// PERF WARNING: calling a method that takes a variable number of arguments
        /// is expensive, because memory is allocated for the array of arguments -- do
        /// not call this method repeatedly in performance-critical scenarios
        ///
        /// </summary>
        /// <param name="errorSubCategoryResourceName">The resource string for the
        /// error sub-category (can be null).</param>
        /// <param name="elementLocation">The <see cref="IElementLocation"/> of the element.</param>
        /// <param name="resourceName">The resource string for the error message.</param>
        /// <param name="args">Extra arguments for formatting the error message.</param>
        private static void ThrowInvalidProject
        (
            string errorSubCategoryResourceName,
            IElementLocation elementLocation,
            string resourceName,
            params object[] args
        )
        {
            ErrorUtilities.VerifyThrowInternalNull(elementLocation, nameof(elementLocation));
#if DEBUG
            if (errorSubCategoryResourceName != null)
            {
                ResourceUtilities.VerifyResourceStringExists(errorSubCategoryResourceName);
            }

            ResourceUtilities.VerifyResourceStringExists(resourceName);
#endif
            string errorSubCategory = null;

            if (errorSubCategoryResourceName != null)
            {
                errorSubCategory = AssemblyResources.GetString(errorSubCategoryResourceName);
            }

            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);
        }
        /// <summary>
        /// Throws an InvalidProjectFileException using the given data.
        ///
        /// PERF WARNING: calling a method that takes a variable number of arguments
        /// is expensive, because memory is allocated for the array of arguments -- do
        /// not call this method repeatedly in performance-critical scenarios
        ///
        /// </summary>
        /// <param name="errorSubCategoryResourceName">The resource string for the
        /// error sub-category (can be null).</param>
        /// <param name="elementLocation">The <see cref="IElementLocation"/> of the element.</param>
        /// <param name="resourceName">The resource string for the error message.</param>
        /// <param name="args">Extra arguments for formatting the error message.</param>
        private static void ThrowInvalidProject
        (
            string errorSubCategoryResourceName,
            IElementLocation elementLocation,
            string resourceName,
            params object[] args
        )
        {
            ErrorUtilities.VerifyThrowInternalNull(elementLocation, "elementLocation");
#if DEBUG
            if (errorSubCategoryResourceName != null)
            {
                ResourceUtilities.VerifyResourceStringExists(errorSubCategoryResourceName);
            }

            ResourceUtilities.VerifyResourceStringExists(resourceName);
#endif
            string errorSubCategory = null;

            if (errorSubCategoryResourceName != null)
            {
                errorSubCategory = AssemblyResources.GetString(errorSubCategoryResourceName);
            }

            string errorCode;
            string helpKeyword;
            string message = ResourceUtilities.FormatResourceString(out errorCode, out helpKeyword, resourceName, args);

            Exception exceptionToThrow = new InvalidProjectFileException(elementLocation.File, elementLocation.Line, elementLocation.Column, 0 /* Unknown end line */, 0 /* Unknown end column */, message, errorSubCategory, errorCode, helpKeyword);

#if FEATURE_MSBUILD_DEBUGGER
            if (!DebuggerManager.DebuggingEnabled)
            {
                throw exceptionToThrow;
            }

            try
            {
                throw exceptionToThrow;
            }
            catch (InvalidProjectFileException ex)
            {
                // To help out the user debugging their project, break into the debugger here.
                // That's because otherwise, since they're debugging our optimized code with JMC on,
                // they may not be able to break on this exception at all themselves.
                // Also, dump the exception information, as it's hard to see in optimized code.
                // Note that we use Trace as Debug.WriteLine is not compiled in release builds, which is
                // what we are in here.
                Trace.WriteLine(ex.ToString());
                Debugger.Break();
                throw;
            }
#else
            throw exceptionToThrow;
#endif
        }
        /// <summary>
        /// This method is used to flag errors in the project file being processed. Do NOT use this method in place of
        /// ErrorUtilities.VerifyThrow(), because ErrorUtilities.VerifyThrow() is used to flag internal/programming errors.
        ///
        /// PERF WARNING: calling a method that takes a variable number of arguments is expensive, because memory is allocated for
        /// the array of arguments -- do not call this method repeatedly in performance-critical scenarios
        /// </summary>
        /// <param name="condition">The condition to check.</param>
        /// <param name="errorSubCategoryResourceName">The resource string for the error sub-category (can be null).</param>
        /// <param name="projectFile">The invalid project file.</param>
        /// <param name="innerException">The inner <see cref="Exception"/>.</param>
        /// <param name="resourceName">The resource string for the error message.</param>
        /// <param name="args">Extra arguments for formatting the error message.</param>
        internal static void VerifyThrowInvalidProjectFile
        (
            bool condition,
            string errorSubCategoryResourceName,
            BuildEventFileInfo projectFile,
            Exception innerException,
            string resourceName,
            params object[] args
        )
        {
            ErrorUtilities.VerifyThrow(projectFile != null, "Must specify the invalid project file. If project file is not available, use VerifyThrowInvalidProject() and pass in the XML node instead.");

#if DEBUG
            if (errorSubCategoryResourceName != null)
            {
                ResourceUtilities.VerifyResourceStringExists(errorSubCategoryResourceName);
            }

            ResourceUtilities.VerifyResourceStringExists(resourceName);
#endif
            if (!condition)
            {
                string errorSubCategory = null;

                if (errorSubCategoryResourceName != null)
                {
                    errorSubCategory = AssemblyResources.GetString(errorSubCategoryResourceName);
                }

                string errorCode;
                string helpKeyword;
                string message = ResourceUtilities.FormatResourceStringStripCodeAndKeyword(out errorCode, out helpKeyword, resourceName, args);

                throw new InvalidProjectFileException(projectFile.File, projectFile.Line, projectFile.Column, projectFile.EndLine, projectFile.EndColumn, message, errorSubCategory, errorCode, helpKeyword, innerException);
            }
        }