public static IEnumerable <string> EvaluateExpressionAsPaths(ExpressionNode expression, MSBuildRootDocument doc, int skipEndChars = 0)
        {
            if (expression == null)
            {
                yield return(Path.GetDirectoryName(doc.Filename));

                yield break;
            }

            if (expression is ListExpression list)
            {
                expression = list.Nodes[list.Nodes.Count - 1];
            }

            if (expression is ExpressionText lit)
            {
                var path = TrimEndChars(lit.GetUnescapedValue());
                //FIXME handle encoding
                yield return(MSBuildEscaping.FromMSBuildPath(path, Path.GetDirectoryName(doc.Filename)));

                yield break;
            }

            if (!(expression is ConcatExpression expr))
            {
                yield break;
            }

            //FIXME evaluate directly without the MSBuildEvaluationContext
            var sb = new StringBuilder();

            for (int i = 0; i < expr.Nodes.Count; i++)
            {
                var node = expr.Nodes[i];
                if (node is ExpressionText l)
                {
                    var val = l.GetUnescapedValue();
                    if (i == expr.Nodes.Count - 1)
                    {
                        val = TrimEndChars(val);
                    }
                    sb.Append(val);
                }
                else if (node is ExpressionProperty p)
                {
                    sb.Append($"$({p.Name})");
                }
                else
                {
                    yield break;
                }
            }

            foreach (var variant in doc.FileEvaluationContext.EvaluatePathWithPermutation(sb.ToString(), Path.GetDirectoryName(doc.Filename)))
            {
                yield return(variant);
            }

            string TrimEndChars(string s) => s.Substring(0, Math.Min(s.Length, s.Length - skipEndChars));
        }
Exemplo n.º 2
0
        public MSBuildRuntimeEvaluationContext(IRuntimeInformation runtime)
        {
            if (runtime is Editor.Completion.NullRuntimeInformation)
            {
                return;
            }

            string binPath   = MSBuildEscaping.ToMSBuildPath(runtime.BinPath);
            string toolsPath = MSBuildEscaping.ToMSBuildPath(runtime.ToolsPath);

            Convert("MSBuildExtensionsPath");
            Convert("MSBuildExtensionsPath32");
            Convert("MSBuildExtensionsPath64");

            void Convert(string name)
            {
                if (runtime.SearchPaths.TryGetValue(name, out var vals))
                {
                    values[name] = new MSBuildPropertyValue(vals.ToArray());
                }
            }

            values["MSBuildBinPath"]      = binPath;
            values["MSBuildToolsPath"]    = toolsPath;
            values["MSBuildToolsPath32"]  = toolsPath;
            values["MSBuildToolsPath64"]  = toolsPath;
            values["RoslynTargetsPath"]   = $"{binPath}\\Roslyn";
            values["MSBuildToolsVersion"] = runtime.ToolsVersion;
            values["VisualStudioVersion"] = "15.0";

            values["MSBuildProgramFiles32"] = MSBuildEscaping.ToMSBuildPath(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86));
            values["MSBuildProgramFiles64"] = MSBuildEscaping.ToMSBuildPath(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles));

            var defaultSdksPath = runtime.SdksPath;

            if (defaultSdksPath != null)
            {
                values["MSBuildSDKsPath"] = MSBuildEscaping.ToMSBuildPath(defaultSdksPath, null);
            }

            //these are read from a config file and may be described in terms of other properties
            void Collapse(string name)
            {
                if (values.TryGetValue(name, out var val))
                {
                    values["name"] = val.Collapse(this);
                }
            }

            Collapse("MSBuildExtensionsPath");
            Collapse("MSBuildExtensionsPath32");
            Collapse("MSBuildExtensionsPath64");
        }
Exemplo n.º 3
0
        public static IEnumerable <string> EvaluateExpressionAsPaths(ExpressionNode expression, MSBuildRootDocument doc, int skipEndChars = 0, string baseDir = null)
        {
            baseDir = baseDir ?? Path.GetDirectoryName(doc.Filename);

            if (expression == null)
            {
                yield return(baseDir);

                yield break;
            }

            if (expression is ListExpression list)
            {
                expression = list.Nodes[list.Nodes.Count - 1];
            }

            if (expression is ExpressionText lit)
            {
                if (lit.Length == 0)
                {
                    yield return(baseDir);

                    yield break;
                }
                var path = TrimEndChars(lit.GetUnescapedValue());
                if (string.IsNullOrEmpty(path))
                {
                    yield return(baseDir);

                    yield break;
                }
                //FIXME handle encoding
                if (MSBuildEscaping.FromMSBuildPath(path, baseDir, out var res))
                {
                    yield return(res);
                }
                yield break;
            }

            if (!(expression is ConcatExpression expr && expr.Nodes.All(n => n is ExpressionText || (n is ExpressionProperty p && p.IsSimpleProperty))))
            {
                yield break;
            }

            foreach (var variant in doc.FileEvaluationContext.EvaluatePathWithPermutation(expr, baseDir))
            {
                yield return(variant);
            }

            string TrimEndChars(string s) => s.Substring(0, Math.Min(s.Length, s.Length - skipEndChars));
        }
Exemplo n.º 4
0
 // FIXME: need to make this more efficient.
 // can we ignore results where a property was simply not found?
 // can we tokenize it and check each level of the path exists before drilling down?
 // can we cache the filesystem lookups?
 public static IEnumerable <string> EvaluatePathWithPermutation(
     this IMSBuildEvaluationContext context,
     ExpressionNode pathExpression,
     string baseDirectory)
 {
     foreach (var p in EvaluateWithPermutation(context, null, pathExpression, 0))
     {
         if (p == null)
         {
             continue;
         }
         yield return(MSBuildEscaping.FromMSBuildPath(p, baseDirectory));
     }
 }
        public MSBuildFileEvaluationContext(
            IMSBuildEvaluationContext runtimeContext,
            string projectPath,
            string thisFilePath)
        {
            this.runtimeContext = runtimeContext ?? throw new ArgumentNullException(nameof(runtimeContext));

            // this file path properties
            if (thisFilePath != null)
            {
                values["MSBuildThisFile"]          = MSBuildEscaping.EscapeString(Path.GetFileName(thisFilePath));
                values["MSBuildThisFileDirectory"] = MSBuildEscaping.ToMSBuildPath(Path.GetDirectoryName(thisFilePath)) + "\\";
                //"MSBuildThisFileDirectoryNoRoot" is this actually used for anything?
                values["MSBuildThisFileExtension"] = MSBuildEscaping.EscapeString(Path.GetExtension(thisFilePath));
                values["MSBuildThisFileFullPath"]  = MSBuildEscaping.ToMSBuildPath(Path.GetFullPath(thisFilePath));
                values["MSBuildThisFileName"]      = MSBuildEscaping.EscapeString(Path.GetFileNameWithoutExtension(thisFilePath));
            }

            if (projectPath == null)
            {
                return;
            }

            // project path properties
            string escapedProjectDir = MSBuildEscaping.ToMSBuildPath(Path.GetDirectoryName(projectPath));

            values["MSBuildProjectDirectory"] = escapedProjectDir;
            // "MSBuildProjectDirectoryNoRoot" is this actually used for anything?
            values["MSBuildProjectExtension"] = MSBuildEscaping.EscapeString(Path.GetExtension(projectPath));
            values["MSBuildProjectFile"]      = MSBuildEscaping.EscapeString(Path.GetFileName(projectPath));
            values["MSBuildProjectFullPath"]  = MSBuildEscaping.ToMSBuildPath(Path.GetFullPath(projectPath));
            values["MSBuildProjectName"]      = MSBuildEscaping.EscapeString(Path.GetFileNameWithoutExtension(projectPath));

            //don't have a better value, this is as good as anything
            values["MSBuildStartupDirectory"] = escapedProjectDir;

            //HACK: we don't get a usable value for this without real evaluation so hardcode 'obj'
            var projectExtensionsPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(projectPath), "obj"));

            values["MSBuildProjectExtensionsPath"] = MSBuildEscaping.ToMSBuildPath(projectExtensionsPath) + "\\";
        }
Exemplo n.º 6
0
#pragma warning disable 0169
        #region Functions
        // FIXME imported projects
        static bool Exists(string file, IExpressionContext context)
        {
            if (string.IsNullOrEmpty(file))
            {
                return(false);
            }

            string directory = context.FullDirectoryName;

            file = MSBuildEscaping.FromMSBuildPath(file, directory);
            bool res;

            lock (context.ExistsEvaluationCache) {
                if (context.ExistsEvaluationCache.TryGetValue(file, out res))
                {
                    return(res);
                }

                res = File.Exists(file) || Directory.Exists(file);
                context.ExistsEvaluationCache [file] = res;
            }
            return(res);
        }
Exemplo n.º 7
0
 public static string EvaluatePath(
     this IMSBuildEvaluationContext context,
     ExpressionNode expression,
     string baseDirectory)
 => MSBuildEscaping.FromMSBuildPath(context.Evaluate(expression), baseDirectory);