private IEnumerable <AutocompleteItem> BuildList() { var context = ParseOutContext(menu.Fragment.Start + 1, menu.Fragment.Text.Length - 1); if (!context.IsValid) { yield break; } var targetSchemas = JsonSchemaTools.GetSchemasForPath(schema, context.Path, context.ObjectAroundCursor, context.ActivePropertyName); if (targetSchemas.Count == 0) { yield break; } List <KeyValuePair <AnnotatedSchema, List <AutocompleteItem> > > sections = context.IsSuggestingValue ? SuggestValues(targetSchemas) : SuggestProperties(context.ObjectAroundCursor as JObject ?? new JObject(), targetSchemas); if (sections.Count == 1 || sections.All(p => p.Value.Count == 1)) { // No headers/dividers required. foreach (var section in sections) { foreach (var item in section.Value) { yield return(item); } } } else { // Add headers to sections. foreach (var section in sections) { if (section.Value.Count == 1) { yield return(section.Value.First()); } else { yield return(new HeaderItem(section.Key.Title)); foreach (var item in section.Value) { item.MenuText = " " + item.MenuText; yield return(item); } } } } }
public PropertySuggestItem(string name, JsonSchema4 schema, bool isAlreadyExisting) { this.isAlreadyExisting = isAlreadyExisting; MenuText = string.IsNullOrEmpty(name) ? schema.Title ?? "\"\":" : name; ToolTipTitle = (schema.Title ?? name) + (isAlreadyExisting ? " (already exists)" : ""); ToolTipText = schema.Description ?? JsonSchemaTools.DescribeSchema(schema); Text = "\"" + name + "\": "; if (schema.Enumeration.Count == 1) { var value = JsonSchemaTools.FormatEnumValue(schema.Enumeration.First()); MenuText += ": " + value; Text += value; } }
public void Load() { mDefaultJson = ExtractTextRange(mPath, "<StonehearthEditor>", "</StonehearthEditor>"); var schemaText = ExtractTextRange(mPath, "<StonehearthEditorSchema>", "</StonehearthEditorSchema>"); if (schemaText.Length > 0) { try { mSchema = JsonSchemaTools.ParseSchema(schemaText, Application.StartupPath + "/schemas/encounters/tmp.json"); } catch (System.Exception e) { MessageBox.Show("Encounter type specifies a schema, but it isn't valid.\nFile: " + mPath + "\nError: " + e.Message); } } }
public void Load() { ParseGenericEncounterScripts(MainForm.kModsDirectoryPath + "/stonehearth/services/server/game_master/controllers"); var defaultSchemaPath = Application.StartupPath + "/schemas/encounters/encounter.json"; using (StreamReader sr = new StreamReader(defaultSchemaPath, System.Text.Encoding.UTF8)) { mDefaultSchema = JsonSchemaTools.ParseSchema(sr.ReadToEnd(), defaultSchemaPath); } // get the game master index location foreach (Module module in ModuleDataManager.GetInstance().GetAllModules()) { ModuleFile gmIndex = module.GetAliasFile("data:gm_index"); if (gmIndex != null) { string folder = JsonHelper.NormalizeSystemPath(System.IO.Path.GetDirectoryName(gmIndex.ResolvedPath)); ParseEncounterScripts(module.Name, folder); ParseNodeGraph(module.Name, folder); } } }
private void ValidateSchema() { textBox.Styles[Style.LineNumber].BackColor = Color.LightGray; if (textBox.Lexer != ScintillaNET.Lexer.Json) { // No validation possible. return; } // Find errors. var result = JsonSchemaTools.Validate(jsonValidationSchema, textBox.Text); validationErrors = result.Item2; textBox.Styles[Style.LineNumber].BackColor = Color.LightGreen; if (result.Item1 == JsonSchemaTools.ValidationResult.Valid) { var hasBespokeSchema = jsonValidationSchema != null && ((mFileData as JsonFileData).Json.Value <string>("encounter_type") == "none" || jsonValidationSchema != GameMasterDataManager.GetInstance().GetEncounterSchema(null)); textBox.Styles[Style.LineNumber].BackColor = hasBespokeSchema ? Color.LightGreen : Color.LightGray; } else { textBox.Styles[Style.LineNumber].BackColor = (result.Item1 == JsonSchemaTools.ValidationResult.InvalidJson) ? Color.IndianRed : Color.Orange; } // Display errors. textBox.MarkerDeleteAll(kErrorMarkerNumber); if (validationErrors.Count > 0) { foreach (var error in validationErrors) { textBox.Lines[error.Key].MarkerAdd(kErrorMarkerNumber); } } }
private IEnumerable <AutocompleteItem> SuggestValues(AnnotatedSchema annotatedSchema) { // Help text. var title = annotatedSchema.Title ?? annotatedSchema.Name; var description = annotatedSchema.Description ?? JsonSchemaTools.DescribeSchema(annotatedSchema); var targetSchema = annotatedSchema.Schema; if (targetSchema.Id != null && customSourcesBySchemeId.ContainsKey(targetSchema.Id)) { // Special handling for sources set by the environment (edge names, node names, files, etc.). foreach (var value in customSourcesBySchemeId[targetSchema.Id]()) { yield return(new ValueSuggestItem(value, title != null ? title + ": " + value : value, description)); } } else if (targetSchema.Id == "http://stonehearth.net/schemas/encounters/elements/file.json") { // Special handling for files (alias or file insertion prompts). yield return(new AliasSuggestItem(title, description)); yield return(new FileSuggestItem(title, description, filePath)); } else if (targetSchema.Enumeration.Count > 0) { // Suggest enumeration alternatives. foreach (var alternative in targetSchema.Enumeration) { yield return(new ValueSuggestItem(JsonSchemaTools.FormatEnumValue(alternative), title, description)); } } else if (targetSchema.Type == JsonObjectType.Boolean) { // Suggest the two alternatives of bool. yield return(new ValueSuggestItem("true", title, description)); yield return(new ValueSuggestItem("false", title, description)); } else if (targetSchema.Default != null) { // If there's a default value, suggest that. yield return(new ValueSuggestItem(JsonSchemaTools.FormatEnumValue(targetSchema.Default), title, description)); } else if (targetSchema.Type == JsonObjectType.Object || targetSchema.ActualProperties.Count > 0) { // Construct as much of an object as required. var left = "{\n "; var right = "\n}"; var addedAnyToLeft = false; foreach (var property in targetSchema.ActualProperties) { if (property.Value.IsRequired) { if (addedAnyToLeft) { left += ",\n "; } left += "\"" + property.Key + "\": "; if (property.Value.Default != null) { left += JsonSchemaTools.FormatEnumValue(property.Value.Default); } else if (property.Value.Enumeration.Count == 1) { left += JsonSchemaTools.FormatEnumValue(property.Value.Enumeration.First()); } else if (property.Value.Type == JsonObjectType.Number || property.Value.Type == JsonObjectType.Integer) { left += "0"; } else if (property.Value.Type == JsonObjectType.Boolean) { left += "false"; } else if (property.Value.Type == JsonObjectType.Null) { left += "null"; } else if (property.Value.Type == JsonObjectType.Object) { left += "{}"; } else if (property.Value.Type == JsonObjectType.Array) { left += "[]"; } else if (property.Value.Type == JsonObjectType.String) { left += "\"\""; } addedAnyToLeft = true; } } if (addedAnyToLeft) { right = "," + right; } yield return(new ValueSuggestItem(left, right, title, description)); } else if (targetSchema.Type == JsonObjectType.Array) { // Trivial array form. yield return(new ValueSuggestItem("[\n ", "\n]", title, description)); } else if (targetSchema.Type == JsonObjectType.String) { // Trivial string form. yield return(new ValueSuggestItem("\"", "\"", title ?? "\"...\"", description)); } else if (targetSchema.Type == JsonObjectType.Number || targetSchema.Type == JsonObjectType.Integer) { // Trivial number. yield return(new ValueSuggestItem((targetSchema.Minimum ?? 0).ToString(), title, description)); } else if (targetSchema.Type == JsonObjectType.Null) { // Null has only one option. yield return(new ValueSuggestItem("null", title, description)); } }
private Tuple <string, int> GetTooltipAt(int x, int y) { // Translate mouse x,y to character position. var position = this.textBox.CharPositionFromPoint(x, y); var line = this.textBox.LineFromPosition(position); // Sometimes CharPositionFromPoint() returns out of range values (looks like when replacing few lines with many). if (position < 0 || position >= textBox.Text.Length) { return(new Tuple <string, int>(null, kAnchorNone)); } // Are we are hovering over an error icon in the margin? var isInErrorMargin = x > textBox.Margins[0].Width && x <= textBox.Margins[0].Width + textBox.Margins[kErrorMarginNumber].Width; if (isInErrorMargin && validationErrors != null && validationErrors.ContainsKey(line)) { return(new Tuple <string, int>(WordWrapString(validationErrors[line]), kAnchorError)); } // Are we hovering over an indicator? var currentAnchor = this.getIndicatorStartPosition(position); var hoveredIndicator = this.getIndicatorAt(position); if (hoveredIndicator == kFileIndicator) { return(new Tuple <string, int>("Ctrl-click to open file.", currentAnchor)); } else if (hoveredIndicator == kI18nIndicator) { var locKey = this.getLocKey(position); if (string.IsNullOrEmpty(locKey)) { return(new Tuple <string, int>("No such i18n entry found!", currentAnchor)); } mI18nLocKey = locKey; try { // Translate and display it as a tip. var translated = ModuleDataManager.GetInstance().LocalizeString(locKey); translated = JsonHelper.WordWrap(translated, 100).Trim(); return(new Tuple <string, int>(translated + "\n\nCtrl-click to edit.", currentAnchor)); } catch (Exception) { return(new Tuple <string, int>($"(Uncaught exception while trying to find i18n for {locKey})", currentAnchor)); } } // For JSON, display tips about the property or value being hovered over. if (jsonSuggester != null && !char.IsWhiteSpace(textBox.Text[position])) { var contextParsingPosition = position; // Find a following (or as a fallback, preceding) colon or open square bracket on the same line. // Could fail for colons/brackets embedded in strings, but that's good enough for now. while (contextParsingPosition < textBox.Lines[line].EndPosition && (textBox.Text[contextParsingPosition] != ':' && textBox.Text[contextParsingPosition] != '[')) { contextParsingPosition++; } if (contextParsingPosition == textBox.Lines[line].EndPosition) { contextParsingPosition = position; while (contextParsingPosition >= textBox.Lines[line].Position && (textBox.Text[contextParsingPosition] != ':' && textBox.Text[contextParsingPosition] != '[')) { contextParsingPosition--; } } if (contextParsingPosition >= 0 && (textBox.Text[contextParsingPosition] != ':' || textBox.Text[contextParsingPosition] != '[')) { var context = jsonSuggester.ParseOutContext(contextParsingPosition + 1, 0); if (context.IsValid) { var targetSchemas = JsonSchemaTools.GetSchemasForPath(jsonValidationSchema, context.Path, context.ObjectAroundCursor, context.ActivePropertyName); if (targetSchemas.Count > 0) { var schemaDescriptions = new HashSet <string>(targetSchemas.Select( annotated => JsonSchemaTools.DescribeSchema(annotated) + (annotated.Description != null ? "\n" + annotated.Description : ""))); var tipText = context.ActivePropertyName ?? context.Path.LastOrDefault() ?? "0"; if (schemaDescriptions.Count == 1) { tipText = (tipText == "0" ? "" : tipText + ": ") + schemaDescriptions.First(); } else { tipText = (tipText == "0" ? "One" : tipText + ", one") + " of:\n- " + string.Join("\n- ", schemaDescriptions.Select(s => s.Replace("\n", "\n "))); } return(new Tuple <string, int>(WordWrapString(tipText), contextParsingPosition)); } } } } return(new Tuple <string, int>(null, kAnchorNone)); }