Ejemplo n.º 1
0
 public static void ThrowsServiceDefinitionException(Func <object> func, NamedTextPosition position)
 {
     ThrowsServiceDefinitionException(
         () =>
     {
         func();
     }, position);
 }
Ejemplo n.º 2
0
        internal static string GetDefinitionNameFromRef(string refValue, NamedTextPosition position)
        {
            const string refPrefix = "#/definitions/";

            if (!refValue.StartsWith(refPrefix, StringComparison.Ordinal))
            {
                throw new ServiceDefinitionException("Definition $ref must start with '#/definitions/'.", position);
            }
            return(UnescapeRefPart(refValue.Substring(refPrefix.Length)));
        }
Ejemplo n.º 3
0
 public static void ThrowsServiceDefinitionException(Action action, NamedTextPosition position)
 {
     try
     {
         action();
         throw new InvalidOperationException("Action did not throw.");
     }
     catch (ServiceDefinitionException exception)
     {
         Assert.AreSame(position, exception.Position);
     }
 }
Ejemplo n.º 4
0
        public void LineNumberOnly()
        {
            var position = new NamedTextPosition("source", 3);

            position.ToString().ShouldBe("source(3)");
        }
Ejemplo n.º 5
0
        public void InvalidTypeNameThrows()
        {
            var position = new NamedTextPosition("source", 1, 2);

            TestUtility.ThrowsServiceDefinitionException(() => new ServiceFieldInfo(name: "x", typeName: "4u", position: position), position);
        }
Ejemplo n.º 6
0
        private static void AddFieldsFromSchema(IList <ServiceFieldInfo> requestFields, SwaggerService swaggerService, NamedTextPosition position, KeyValuePair <string, SwaggerSchema> bodySchema)
        {
            if ((bodySchema.Value.Type ?? SwaggerSchemaType.Object) != SwaggerSchemaType.Object)
            {
                throw new NotImplementedException();
            }

            foreach (var property in bodySchema.Value.Properties.EmptyIfNull())
            {
                var attributes = new List <ServiceAttributeInfo>();

                if (property.Value.Obsolete.GetValueOrDefault())
                {
                    attributes.Add(new ServiceAttributeInfo("obsolete"));
                }

                string typeName = swaggerService.TryGetFacilityTypeName(property.Value, position);
                if (typeName != null)
                {
                    requestFields.Add(new ServiceFieldInfo(
                                          property.Key,
                                          typeName: typeName,
                                          attributes: attributes,
                                          summary: PrepareSummary(property.Value.Description),
                                          position: position));
                }
            }
        }
Ejemplo n.º 7
0
        internal static string TryGetFacilityResultOfType(this SwaggerService swaggerService, KeyValuePair <string, SwaggerSchema> swaggerSchema, NamedTextPosition position)
        {
            const string nameSuffix = "Result";

            if (!swaggerSchema.Key.EndsWith(nameSuffix, StringComparison.Ordinal))
            {
                return(null);
            }

            var properties = swaggerSchema.Value.Properties.EmptyIfNull();

            if (!properties.Any(x => x.Key == "error" && x.Value.Ref == "#/definitions/Error"))
            {
                return(null);
            }

            var valueSchema = properties.Where(x => x.Key == "value").Select(x => x.Value).FirstOrDefault();

            if (valueSchema == null)
            {
                return(null);
            }

            return(swaggerService.TryGetFacilityTypeName(valueSchema, position));
        }
 private static Position ToLspPosition(NamedTextPosition position)
 {
     return(new Position(position.LineNumber - 1, position.ColumnNumber - 1));
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Parses Swagger (OpenAPI) 2.0 into a service definition.
        /// </summary>
        public ServiceInfo ParseDefinition(NamedText source)
        {
            if (string.IsNullOrWhiteSpace(source.Text))
            {
                throw new ServiceDefinitionException("Service definition is missing.", new NamedTextPosition(source.Name, 1, 1));
            }

            SwaggerService       swaggerService;
            SwaggerParserContext context;

            if (!s_detectJsonRegex.IsMatch(source.Text))
            {
                // parse YAML
                var yamlDeserializer = new DeserializerBuilder()
                                       .IgnoreUnmatchedProperties()
                                       .WithNamingConvention(new OurNamingConvention())
                                       .Build();
                using (var stringReader = new StringReader(source.Text))
                {
                    try
                    {
                        swaggerService = yamlDeserializer.Deserialize <SwaggerService>(stringReader);
                    }
                    catch (YamlException exception)
                    {
                        var          exceptionError  = exception.InnerException?.Message ?? exception.Message;
                        const string errorStart      = "): ";
                        int          errorStartIndex = exceptionError.IndexOf(errorStart, StringComparison.OrdinalIgnoreCase);
                        if (errorStartIndex != -1)
                        {
                            exceptionError = exceptionError.Substring(errorStartIndex + errorStart.Length);
                        }

                        var exceptionPosition = new NamedTextPosition(source.Name, exception.End.Line, exception.End.Column);
                        throw new ServiceDefinitionException(exceptionError, exceptionPosition);
                    }
                }
                if (swaggerService == null)
                {
                    throw new ServiceDefinitionException("Service definition is missing.", new NamedTextPosition(source.Name, 1, 1));
                }

                context = SwaggerParserContext.FromYaml(source);
            }
            else
            {
                // parse JSON
                using (var stringReader = new StringReader(source.Text))
                    using (var jsonTextReader = new JsonTextReader(stringReader))
                    {
                        try
                        {
                            swaggerService = JsonSerializer.Create(SwaggerUtility.JsonSerializerSettings).Deserialize <SwaggerService>(jsonTextReader);
                        }
                        catch (JsonException exception)
                        {
                            var exceptionPosition = new NamedTextPosition(source.Name, jsonTextReader.LineNumber, jsonTextReader.LinePosition);
                            throw new ServiceDefinitionException(exception.Message, exceptionPosition);
                        }

                        context = SwaggerParserContext.FromJson(source);
                    }
            }

            return(ConvertSwaggerService(swaggerService, context));
        }
Ejemplo n.º 10
0
        private void AddServiceDto(List <IServiceMemberInfo> members, string name, SwaggerSchema schema, SwaggerService swaggerService, NamedTextPosition position)
        {
            var attributes = new List <ServiceAttributeInfo>();

            if (schema.Obsolete.GetValueOrDefault())
            {
                attributes.Add(new ServiceAttributeInfo("obsolete"));
            }

            var fields = new List <ServiceFieldInfo>();

            foreach (var property in schema.Properties.EmptyIfNull())
            {
                var fieldAttributes = new List <ServiceAttributeInfo>();

                if (property.Value.Obsolete.GetValueOrDefault())
                {
                    fieldAttributes.Add(new ServiceAttributeInfo("obsolete"));
                }

                string typeName = swaggerService.TryGetFacilityTypeName(property.Value, position);
                if (typeName != null)
                {
                    fields.Add(new ServiceFieldInfo(
                                   property.Key,
                                   typeName: typeName,
                                   attributes: fieldAttributes,
                                   summary: PrepareSummary(property.Value.Description),
                                   position: position));
                }
            }

            members.Add(new ServiceDtoInfo(
                            name: name,
                            fields: fields,
                            attributes: attributes,
                            summary: PrepareSummary(schema.Description),
                            remarks: SplitRemarks(schema.Remarks),
                            position: position));
        }
Ejemplo n.º 11
0
 public FsdRemarksSection(string name, IReadOnlyList <string> lines, NamedTextPosition position)
 {
     Name     = name;
     Lines    = lines;
     Position = position;
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Parses an FSD file into a service definition.
        /// </summary>
        public ServiceInfo ParseDefinition(NamedText source)
        {
            IReadOnlyList <string> definitionLines = null;
            var remarksSections = new Dictionary <string, FsdRemarksSection>(StringComparer.OrdinalIgnoreCase);

            // read remarks after definition
            using (var reader = new StringReader(source.Text))
            {
                string name              = null;
                var    lines             = new List <string>();
                int    lineNumber        = 0;
                int    headingLineNumber = 0;

                while (true)
                {
                    string line = reader.ReadLine();
                    lineNumber++;

                    Match match = line == null ? null : s_markdownHeading.Match(line);
                    if (match == null || match.Success)
                    {
                        if (name == null)
                        {
                            definitionLines = lines;
                        }
                        else
                        {
                            while (lines.Count != 0 && string.IsNullOrWhiteSpace(lines[0]))
                            {
                                lines.RemoveAt(0);
                            }
                            while (lines.Count != 0 && string.IsNullOrWhiteSpace(lines[lines.Count - 1]))
                            {
                                lines.RemoveAt(lines.Count - 1);
                            }

                            var position = new NamedTextPosition(source.Name, headingLineNumber, 1);
                            if (remarksSections.ContainsKey(name))
                            {
                                throw new ServiceDefinitionException("Duplicate remarks heading: " + name, position);
                            }
                            remarksSections.Add(name, new FsdRemarksSection(name, lines, position));
                        }

                        if (match == null)
                        {
                            break;
                        }

                        name              = line.Substring(match.Index + match.Length).Trim();
                        lines             = new List <string>();
                        headingLineNumber = lineNumber;
                    }
                    else
                    {
                        lines.Add(line);
                    }
                }
            }

            source = new NamedText(source.Name, string.Join("\n", definitionLines));

            ServiceInfo service;

            try
            {
                service = FsdParsers.ParseDefinition(source, remarksSections);
            }
            catch (ParseException exception)
            {
                var expectation = exception
                                  .Result
                                  .GetNamedFailures()
                                  .Distinct()
                                  .GroupBy(x => x.Position)
                                  .Select(x => new { LineColumn = x.Key.GetLineColumn(), Names = x.Select(y => y.Name) })
                                  .OrderByDescending(x => x.LineColumn.LineNumber)
                                  .ThenByDescending(x => x.LineColumn.ColumnNumber)
                                  .First();

                throw new ServiceDefinitionException(
                          "expected " + string.Join(" or ", expectation.Names.Distinct().OrderBy(GetExpectationNameRank).ThenBy(x => x, StringComparer.Ordinal)),
                          new NamedTextPosition(source.Name, expectation.LineColumn.LineNumber, expectation.LineColumn.ColumnNumber),
                          exception);
            }

            // check for unused remarks sections
            foreach (var remarksSection in remarksSections.Values)
            {
                string sectionName = remarksSection.Name;
                if (service.Name != sectionName && service.FindMember(sectionName) == null)
                {
                    throw new ServiceDefinitionException($"Unused remarks heading: {sectionName}", remarksSection.Position);
                }
            }

            return(service);
        }
Ejemplo n.º 13
0
        internal static SwaggerResponse ResolveResponse(this SwaggerService swaggerService, SwaggerResponse swaggerResponse, NamedTextPosition position)
        {
            if (swaggerResponse.Ref != null)
            {
                const string refPrefix = "#/responses/";
                if (!swaggerResponse.Ref.StartsWith(refPrefix, StringComparison.Ordinal))
                {
                    throw new ServiceDefinitionException("Response $ref must start with '#/responses/'.", position);
                }

                string name = UnescapeRefPart(swaggerResponse.Ref.Substring(refPrefix.Length));
                if (!swaggerService.Responses.TryGetValue(name, out swaggerResponse))
                {
                    throw new ServiceDefinitionException($"Missing response named '{name}'.", position);
                }
            }

            return(swaggerResponse);
        }
Ejemplo n.º 14
0
        internal static KeyValuePair <string, SwaggerSchema> ResolveDefinition(this SwaggerService swaggerService, SwaggerSchema swaggerDefinition, NamedTextPosition position)
        {
            string name = null;

            if (swaggerDefinition.Ref != null)
            {
                name = GetDefinitionNameFromRef(swaggerDefinition.Ref, position);
                if (!swaggerService.Definitions.TryGetValue(name, out swaggerDefinition))
                {
                    throw new ServiceDefinitionException($"Missing definition named '{name}'.", position);
                }
            }

            return(new KeyValuePair <string, SwaggerSchema>(name, swaggerDefinition));
        }
Ejemplo n.º 15
0
        public void FullPosition()
        {
            var position = new NamedTextPosition("source", 3, 14);

            position.ToString().ShouldBe("source(3,14)");
        }
Ejemplo n.º 16
0
        private void AddRequestFields(IList <ServiceFieldInfo> requestFields, SwaggerParameter swaggerParameter, string serviceMethodName, string httpMethod, SwaggerService swaggerService, NamedTextPosition position)
        {
            string kind = swaggerParameter.In;

            if (kind == SwaggerParameterKind.Path || kind == SwaggerParameterKind.Query || kind == SwaggerParameterKind.Header)
            {
                string typeName = swaggerService.TryGetFacilityTypeName(swaggerParameter, position);
                if (typeName != null)
                {
                    if (typeName.EndsWith("[]", StringComparison.Ordinal))
                    {
                        typeName = "string";
                    }

                    var attributes = new List <ServiceAttributeInfo>();

                    if (swaggerParameter.Obsolete.GetValueOrDefault())
                    {
                        attributes.Add(new ServiceAttributeInfo("obsolete"));
                    }

                    string fieldName = swaggerParameter.Identifier ?? swaggerParameter.Name;
                    if (!ServiceDefinitionUtility.IsValidName(fieldName))
                    {
                        fieldName = CodeGenUtility.ToCamelCase(fieldName);
                    }

                    if (kind == SwaggerParameterKind.Query)
                    {
                        var parameters = new List <ServiceAttributeParameterInfo>();
                        if (httpMethod != "GET")
                        {
                            parameters.Add(new ServiceAttributeParameterInfo("from", "query"));
                        }
                        if (fieldName != swaggerParameter.Name)
                        {
                            parameters.Add(new ServiceAttributeParameterInfo("name", swaggerParameter.Name));
                        }
                        if (parameters.Count != 0)
                        {
                            attributes.Add(new ServiceAttributeInfo("http", parameters));
                        }
                    }
                    else if (kind == SwaggerParameterKind.Header)
                    {
                        attributes.Add(new ServiceAttributeInfo("http",
                                                                new[]
                        {
                            new ServiceAttributeParameterInfo("from", "header"),
                            new ServiceAttributeParameterInfo("name", swaggerParameter.Name),
                        }));
                    }

                    requestFields.Add(new ServiceFieldInfo(
                                          fieldName,
                                          typeName: typeName,
                                          attributes: attributes,
                                          summary: PrepareSummary(swaggerParameter.Description),
                                          position: position));
                }
            }
            else if (kind == SwaggerParameterKind.Body)
            {
                var bodySchema = swaggerService.ResolveDefinition(swaggerParameter.Schema, position);
                if ((bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object &&
                    (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Request", StringComparison.OrdinalIgnoreCase)))
                {
                    AddFieldsFromSchema(requestFields, swaggerService, position, bodySchema);
                }
                else
                {
                    string typeName = bodySchema.Key ?? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position));
                    if (typeName != null)
                    {
                        requestFields.Add(new ServiceFieldInfo(
                                              bodySchema.Value.Identifier ?? "body",
                                              typeName: typeName,
                                              attributes: new[] { new ServiceAttributeInfo("http", new[] { new ServiceAttributeParameterInfo("from", "body", position) }) },
                                              summary: PrepareSummary(swaggerParameter.Description),
                                              position: position));
                    }
                }
            }
        }
Ejemplo n.º 17
0
        public void SourceNameOnly()
        {
            var position = new NamedTextPosition("source");

            position.ToString().ShouldBe("source");
        }
Ejemplo n.º 18
0
        private void AddResponseFields(IList <ServiceFieldInfo> responseFields, string statusCode, SwaggerResponse swaggerResponse, string serviceMethodName, IList <ServiceAttributeParameterInfo> httpAttributeValues, bool isOnlyResponse, SwaggerService swaggerService, NamedTextPosition position)
        {
            var bodySchema = default(KeyValuePair <string, SwaggerSchema>);

            if (swaggerResponse.Schema != null)
            {
                bodySchema = swaggerService.ResolveDefinition(swaggerResponse.Schema, position);
            }

            if (bodySchema.Value != null && (bodySchema.Value.Type ?? SwaggerSchemaType.Object) == SwaggerSchemaType.Object &&
                (bodySchema.Key == null || bodySchema.Key.Equals(serviceMethodName + "Response", StringComparison.OrdinalIgnoreCase)))
            {
                httpAttributeValues.Add(new ServiceAttributeParameterInfo("code", statusCode, position));
                AddFieldsFromSchema(responseFields, swaggerService, position, bodySchema);
            }
            else if (swaggerResponse.Identifier == null && isOnlyResponse && swaggerResponse.Schema == null)
            {
                httpAttributeValues.Add(new ServiceAttributeParameterInfo("code", statusCode, position));
            }
            else
            {
                responseFields.Add(new ServiceFieldInfo(
                                       swaggerResponse.Identifier ?? CodeGenUtility.ToCamelCase(bodySchema.Key) ?? GetBodyFieldNameForStatusCode(statusCode),
                                       typeName: bodySchema.Key ?? (bodySchema.Value != null ? SwaggerUtility.FilterBodyTypeName(swaggerService.TryGetFacilityTypeName(bodySchema.Value, position)) : null) ?? "boolean",
                                       attributes: new[]
                {
                    new ServiceAttributeInfo("http",
                                             new[]
                    {
                        new ServiceAttributeParameterInfo("from", "body", position),
                        new ServiceAttributeParameterInfo("code", statusCode, position),
                    })
                },
                                       summary: PrepareSummary(swaggerResponse.Description),
                                       position: position));
            }
        }
Ejemplo n.º 19
0
        public void InvalidNameThrows()
        {
            var position = new NamedTextPosition("source");

            TestUtility.ThrowsServiceDefinitionException(() => new ServiceDtoInfo(name: "4u", position: position), position);
        }
Ejemplo n.º 20
0
        internal static string TryGetFacilityTypeName(this SwaggerService swaggerService, ISwaggerSchema swaggerSchema, NamedTextPosition position)
        {
            switch (swaggerSchema.Type ?? SwaggerSchemaType.Object)
            {
            case SwaggerSchemaType.String:
                return(swaggerSchema.Format == SwaggerSchemaTypeFormat.Byte ? "bytes" : "string");

            case SwaggerSchemaType.Number:
                return(swaggerSchema.Format == SwaggerSchemaTypeFormat.Decimal ? "decimal" : "double");

            case SwaggerSchemaType.Integer:
                return(swaggerSchema.Format == SwaggerSchemaTypeFormat.Int64 ? "int64" : "int32");

            case SwaggerSchemaType.Boolean:
                return("boolean");

            case SwaggerSchemaType.Array:
                return(swaggerSchema.Items?.Type == SwaggerSchemaType.Array ? null :
                       $"{swaggerService.TryGetFacilityTypeName(swaggerSchema.Items, position)}[]");

            case SwaggerSchemaType.Object:
                var fullSchema = swaggerSchema as SwaggerSchema;
                if (fullSchema != null)
                {
                    if (fullSchema.Ref != null)
                    {
                        var resolvedSchema = swaggerService.ResolveDefinition(fullSchema, position);

                        if (swaggerService.IsFacilityError(resolvedSchema))
                        {
                            return("error");
                        }

                        string resultOfType = swaggerService.TryGetFacilityResultOfType(resolvedSchema, position);
                        if (resultOfType != null)
                        {
                            return($"result<{resultOfType}>");
                        }

                        return(resolvedSchema.Key);
                    }

                    if (fullSchema.AdditionalProperties != null)
                    {
                        return($"map<{swaggerService.TryGetFacilityTypeName(fullSchema.AdditionalProperties, position)}>");
                    }
                }

                return("object");
            }

            return(null);
        }