using Microsoft.CodeAnalysis; namespace Ariadne.Generator { /// /// Script errors the generator can't write correct code around. /// public static class ScriptDiagnostics { private const string Category = "Ariadne"; // ARI0006 refused a nested or generic script, and ARI0032 a generic passage that called a passage or was // called on another arc. ARI0010 refused a passage in a cycle of calls, and ARI0033 a generic one in a cycle // that built its type arguments from its own. All of those are written now. Don't reuse them. // ARI0008 and ARI0014 to ARI0017 checked saveability, which is the save library's job now. ARI0020 refused a // variable declared in a condition, which hoisting handles now. ARI0024 refused a passage called on another // object, and ARI0026 one inherited from a base class. Both run now. Don't reuse them. public static readonly DiagnosticDescriptor NotPartial = new DiagnosticDescriptor( "ARI0001", "Script class must be partial", "'{0}' overrides Arc.Run, so it must be partial: Ariadne.Generator writes the rest of it", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor UnlabeledPause = new DiagnosticDescriptor( "ARI0002", "A pause needs a step label", "Put a label before this pause's step: the label names where the script is paused, in saves", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor MisplacedYield = new DiagnosticDescriptor( "ARI0003", "Yield() is in a place that can't pause", "Yield() can't pause inside {0}. {1}", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor MisplacedPassageCall = new DiagnosticDescriptor( "ARI0004", "A passage call must be its own statement", "'{0}' pauses, so it can't be called inside {1}. {2}", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor DuplicateKey = new DiagnosticDescriptor( "ARI0005", "Two pauses share a key", "'{0}' already names a pause in this passage. Label one of them differently, or label repeated calls to " + "the same passage.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor DuplicateFileName = new DiagnosticDescriptor( "ARI0007", "Two script files differ only in case", "'{0}' has the same path as another script file but for case, so their code-behinds would be one file", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor UnsupportedLocal = new DiagnosticDescriptor( "ARI0009", "A local used across a pause must be a plain declaration", "'{0}' is used on both sides of a pause, so it's kept in a field, and only a plain local declaration or " + "a by-value parameter can be", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor GeneratedCodePlumbing = new DiagnosticDescriptor( "ARI0011", "Scripts can't use the generated code's plumbing", "'{0}' is for the code Ariadne.Generator writes, and a script using it could lose track of where it's " + "paused", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor OverloadedPassage = new DiagnosticDescriptor( "ARI0012", "Passages can't be overloaded", "Another passage is also named '{0}', and a passage's name keys where it's paused and its saved locals", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor PassageShape = new DiagnosticDescriptor( "ARI0013", "A passage must have a block body and can't return by reference", "'{0}' pauses, so it must have a block body and can't return by reference", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor UnsupportedSavingClass = new DiagnosticDescriptor( "ARI0018", "An arc class must be partial", "'{0}' is an arc, so it must be partial: Ariadne.Generator writes the code that saves and loads it", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor DuplicateSaveKey = new DiagnosticDescriptor( "ARI0019", "Two saved fields share a key", "A base class of '{1}' already saves a field or auto-property named '{0}'. Rename one, or mark one " + "[Scratch].", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor UsingDeclarationAcrossPause = new DiagnosticDescriptor( "ARI0021", "A using declaration can't be in scope across a pause", "A pause leaves the method, which disposes this using declaration's resource, and a resource can't be " + "saved. Dispose it yourself before the pause.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor WrongLoaderAccess = new DiagnosticDescriptor( "ARI0022", "An arc's loading constructor must be private, or protected on a class others derive from", "'{0}' loads from a save through this constructor, which must be {1}, so nothing outside the class can " + "build a half-loaded arc", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor MovingReference = new DiagnosticDescriptor( "ARI0023", "A ref or out argument to a passage must be a plain variable", "The argument to '{0}' is worked out again each time the passage resumes, so a ref or out argument can " + "only be a name, a field or a declaration, which can't end up pointing somewhere else after a pause", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor UnsupportedPassageModifier = new DiagnosticDescriptor( "ARI0025", "A passage can't be static, async, unsafe, an iterator or an override of a plain method", "'{0}' pauses, so it can't be {1}.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: "Ariadne.Generator writes a copy of a passage that is none of those."); public static readonly DiagnosticDescriptor UnsavableLocalType = new DiagnosticDescriptor( "ARI0027", "A local kept across a pause needs a type a field can have", "'{0}' is kept in a field across a pause, but {1}", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor ParamsCollection = new DiagnosticDescriptor( "ARI0028", "A passage's params parameter must be an array", "'{0}' is a params collection, but a passage's params arguments are made once into an array. Declare it " + "as an array, eg: 'params int[] {0}'.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor NotPartialContainer = new DiagnosticDescriptor( "ARI0029", "A type holding an arc class must be partial", "'{0}' holds the arc class '{1}', so it must be partial: Ariadne.Generator writes the rest of '{1}' " + "inside it", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor TimeOutsideAPassage = new DiagnosticDescriptor( "ARI0030", "DeltaTime and GameTime can only be read in a passage, on this arc", "'{0}' is read where the tick's time isn't available: only a passage is handed it, and only through " + "this arc. Pass it to any other method as an argument.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor MisplacedWait = new DiagnosticDescriptor( "ARI0031", "Wait() is in a place that can't pause", "Wait() can't pause inside {0}. {1}", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor BadTriggerList = new DiagnosticDescriptor( "ARI0034", "A wait needs its triggers or its conditions listed", "{0}", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor UnsavableEvent = new DiagnosticDescriptor( "ARI0035", "A field-like event can't be saved", "The subscribers of '{0}' are delegates, which can't be saved, so it would come back empty after a load. " + "Mark it [Scratch] to say so, or keep the subscribers in a saved field.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor RunByNameBehindAnOverride = new DiagnosticDescriptor( "ARI0036", "A call to Run by name stays on its own class's Run", "'{0}' reaches a call to Run in '{1}', which runs the Run of '{1}' here, not the override that C# would " + "call. Move the shared work into a passage with another name, and call that from both.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor PassageAsDelegate = new DiagnosticDescriptor( "ARI0037", "A passage can't be used as a delegate", "'{0}' pauses, so it can only be called. A delegate carries no frame or cursor for it, and can't be " + "saved. Call it from a passage instead.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); public static readonly DiagnosticDescriptor VirtualPassageNeedsOwnFrame = new DiagnosticDescriptor( "ARI0038", "A virtual passage can't be generic or call itself", "'{0}' is virtual, so it runs on the arc's frame, which {1} Put the recursion or the type parameter in a " + "passage that isn't virtual, and make only the step it calls virtual.", Category, DiagnosticSeverity.Error, isEnabledByDefault: true); } }