public static CompilerMessage[] ParseCompilerOutput(NodeFinishedMessage nodeResult) { // TODO: future improvement opportunity: write a single parser that can parse warning, errors files from all tools that we use. if (nodeResult.Node.Annotation.StartsWith("CopyFiles")) { if (nodeResult.ExitCode == 0) { return(Array.Empty <CompilerMessage>()); } return(new[] { new CompilerMessage { file = nodeResult.Node.OutputFile, message = $"{nodeResult.Node.OutputFile}: {nodeResult.Output}", type = CompilerMessageType.Error } }); } var parser = nodeResult.Node.Annotation.StartsWith("ILPostProcess") ? (CompilerOutputParserBase) new PostProcessorOutputParser() : (CompilerOutputParserBase) new MicrosoftCSharpCompilerOutputParser(); return(parser .Parse( (nodeResult.Output ?? string.Empty).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries), nodeResult.ExitCode != 0).ToArray()); }
public static bool IsAnyPotentiallyUpdatable(CompilerMessage[] messages, NodeFinishedMessage nodeResult, ObjectsFromDisk dataFromBuildProgram) { var matches = messages.Select(m => MicrosoftCSharpCompilerOutputParser.sCompilerOutput.Match(m.message)).Where(m => m.Success).ToArray(); var typeNames = matches.Select(MissingTypeNameFor).Where(t => t != null).ToArray(); if (!typeNames.Any()) { return(false); } var assemblyData = Helpers.FindOutputDataAssemblyInfoFor(nodeResult, dataFromBuildProgram); var lines = new NPath(assemblyData.MovedFromExtractorFile).ReadAllLines(); return(typeNames.Any(t => lines.Contains(t))); }
static CanUpdateAny ContainsUpdatableCompilerMessage(NodeFinishedMessage nodeResult, ObjectsFromDisk dataFromBuildProgram) { if (!nodeResult.Node.Annotation.StartsWith("Csc")) { return(CanUpdateAny.No); } var compilerMessages = BeeScriptCompilation.ParseCompilerOutput(nodeResult); bool IsOnlyMessageForThisFileLineAndColumn(CompilerMessage compilerMessage) { //we want to see if this is the only error on this location. we will make an enumerable that matches all compilermessages that match this location //We do Skip(1).Any() as a bit of an unconventional way to express what we care about: is there more than 1 or not. return(!compilerMessages.Where(m => MatchesFileLineAndColumn(compilerMessage, m)).Skip(1).Any()); } var upgradableMessages = compilerMessages.Where(c => c.message.Contains("(UnityUpgradable")).ToArray(); //Some (UnityUpgradable) errors can be paired with a genuine user error on the same line/column. When this happens it is a known problem //that we are unable to upgrade the UnityUpgradable error. So we'll only return Certainly if there is not an other compilermessage pointing to the //same file,line,column. otherwise, we return maybe, so that a failure to do the update won't print a console message saying there is a bug. if (upgradableMessages.Any(IsOnlyMessageForThisFileLineAndColumn)) { return(CanUpdateAny.Certainly); } if (upgradableMessages.Any()) { return(CanUpdateAny.Maybe); } //The "unknown type or namespace" genre of messages we are not sure about. Some of these are legit user programming errors, some of them //are caused because we moved/renamed a type. In this case we will run the script updater to figure out, and if no updates were produced then //apparently it was a real user programming mistake instead of an updatable error; if (PotentiallyUpdatableErrorMessages.IsAnyPotentiallyUpdatable(compilerMessages, nodeResult, dataFromBuildProgram)) { return(CanUpdateAny.Maybe); } return(CanUpdateAny.No); }