Example #1
0
        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);
                        }
                    }
                }
            }
        }
Example #2
0
 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);
                }
            }
        }
Example #5
0
        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);
                }
            }
        }
Example #6
0
        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));
            }
        }
Example #7
0
        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));
        }