示例#1
0
        public void AddCppSyntax()
        {
            //
            // Params Syntaxes
            //

            project.ParamSyntax.Add(new ParamSyntax(
                                        @"^(?:\s*)(?:description[s]?)?\:\n(?<content>(?!\n{2,})(?:.|\n[^\n])*)",
                                        @"^(?:[\n\s]*)(?<content>[^\n]+)",
                                        @"description",
                                        @"cpp")
                                    );

            project.ParamSyntax.Add(new ParamSyntax(
                                        @"^(?:\s*)(?:exemple|example|sample?)?\:\n(?<content>(?!\n{2,})(?:.|\n[^\n])*)",
                                        @"(?<content>[^\0]*)",
                                        @"exemple",
                                        @"cpp")
                                    );

            project.ParamSyntax.Add(new ParamSyntax(
                                        @"^(?:\s*)(?:param[eè]tre[s]|parameter[s]?)?\:\n(?<content>(?!\n{2,})(?:.|\n[^\n])*)",
                                        @"^(?:[\n\s]*)(?<content>[^\n]+)",
                                        @"param",
                                        @"cpp")
                                    );

            project.ParamSyntax.Add(new ParamSyntax(
                                        @"^(?:\s*)(?:remarque[s]?|remark[s]?)?\:\n(?<content>(?!\n{2,})(?:.|\n[^\n])*)",
                                        @"^(?:[\n\s]*)(?<content>[^\n]+)",
                                        @"remark",
                                        @"cpp")
                                    );

            project.ParamSyntax.Add(new ParamSyntax(
                                        @"^(?:\s*)(?:retourne|return)?\:\n(?<content>(?!\n{2,})(?:.|\n[^\n])*)",
                                        @"^(?:[\n\s]*)(?<content>[^\n]+)",
                                        @"return",
                                        @"cpp")
                                    );

            //
            // Objets Syntaxes
            //
            ObjectSyntax objSyntax;

            // Fonction
            objSyntax = new ObjectSyntax(
                @"^(?:\s*\/\*\*)(?:[\n\s]+)(?<description>[^\n]*)[\n]+(?<content>(?:[^*]|\*[^\/])+)(?:\*\/)(?:[\n\s]*)(?<return_type>[A-Za-z_]+)(?:[\n\s]+)(?<name>[A-Za-z_]+)(?:[\n\s]*)\((?<params>[^\)]*)\)",
                @"^(?:\s*)\@(?<type>[A-Za-z]+)(?:\s+)(?<content>[^@])+",
                @"function",
                @"Fonction",
                @"cpp");
            project.ObjectSyntax.Add(objSyntax);

            // Structure
            objSyntax = new ObjectSyntax(
                @"^(?:\s*\/\*\*)(?:[\n\s]+)(?<description>[^\n]*)[\n]+(?<content>(?:[^*]|\*[^\/])*)(?:\*\/)(?:[\n\s]*)typedef(?:[\n\s]+)struct(?:[\n\s]+)(?<name>[A-Za-z_]+)(?:[\n\s]*)\{",
                @"^(?:\s*)\@(?<type>[A-Za-z]+)(?:\s+)(?<content>[^@])+",
                @"struct",
                @"Structure de données",
                @"cpp");
            project.ObjectSyntax.Add(objSyntax);
        }
示例#2
0
        private static TypeSymbol NarrowDiscriminatedObjectType(ITypeManager typeManager, ObjectSyntax expression, DiscriminatedObjectType targetType, IDiagnosticWriter diagnosticWriter, bool skipConstantCheck)
        {
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                return(LanguageConstants.Any);
            }

            var discriminatorProperty = expression.Properties.FirstOrDefault(x => LanguageConstants.IdentifierComparer.Equals(x.TryGetKeyText(), targetType.DiscriminatorKey));

            if (discriminatorProperty == null)
            {
                // object doesn't contain the discriminator field
                diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).MissingRequiredProperty(ShouldWarn(targetType), targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType));

                var propertyKeys = expression.Properties
                                   .Select(x => x.TryGetKeyText())
                                   .Where(key => !string.IsNullOrEmpty(key))
                                   .Select(key => key !);

                // do a reverse lookup to check if there's any misspelled discriminator key
                var misspelledDiscriminatorKey = SpellChecker.GetSpellingSuggestion(targetType.DiscriminatorKey, propertyKeys);

                if (misspelledDiscriminatorKey != null)
                {
                    diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).DisallowedPropertyWithSuggestion(ShouldWarn(targetType), misspelledDiscriminatorKey, targetType.DiscriminatorKeysUnionType, targetType.DiscriminatorKey));
                }


                return(LanguageConstants.Any);
            }

            // At some point in the future we may want to relax the expectation of a string literal key, and allow a generic string.
            // In this case, the best we can do is validate against the union of all the settable properties.
            // Let's not do this just yet, and see if a use-case arises.

            var discriminatorType = typeManager.GetTypeInfo(discriminatorProperty.Value);

            if (!(discriminatorType is StringLiteralType stringLiteralDiscriminator))
            {
                diagnosticWriter.Write(DiagnosticBuilder.ForPosition(expression).PropertyTypeMismatch(ShouldWarn(targetType), targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, discriminatorType));
                return(LanguageConstants.Any);
            }

            if (!targetType.UnionMembersByKey.TryGetValue(stringLiteralDiscriminator.Name, out var selectedObjectReference))
            {
                // no matches
                var    discriminatorCandidates = targetType.UnionMembersByKey.Keys.OrderBy(x => x);
                string?suggestedDiscriminator  = SpellChecker.GetSpellingSuggestion(stringLiteralDiscriminator.Name, discriminatorCandidates);
                var    builder    = DiagnosticBuilder.ForPosition(discriminatorProperty.Value);
                bool   shouldWarn = ShouldWarn(targetType);

                diagnosticWriter.Write(suggestedDiscriminator != null
                    ? builder.PropertyStringLiteralMismatchWithSuggestion(shouldWarn, targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, stringLiteralDiscriminator.Name, suggestedDiscriminator)
                    : builder.PropertyTypeMismatch(shouldWarn, targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, discriminatorType));

                return(LanguageConstants.Any);
            }

            if (!(selectedObjectReference.Type is ObjectType selectedObjectType))
            {
                throw new InvalidOperationException($"Discriminated type {targetType.Name} contains non-object member");
            }

            // we have a match!
            return(NarrowObjectType(typeManager, expression, selectedObjectType, diagnosticWriter, skipConstantCheck));
        }
示例#3
0
 static object[] CreateRow(string name, ObjectSyntax @object) => new object[]
 {
     name, @object
 };
示例#4
0
        private static void GetObjectAssignmentDiagnostics(ITypeManager typeManager, ObjectSyntax expression, ObjectType targetType, IList <Diagnostic> diagnostics, bool skipConstantCheck)
        {
            // TODO: Short-circuit on any object to avoid unnecessary processing?
            // TODO: Consider doing the schema check even if there are parse errors
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                return;
            }

            var propertyMap = expression.ToPropertyDictionary();

            var missingRequiredProperties = targetType.Properties.Values
                                            .Where(p => p.Flags.HasFlag(TypePropertyFlags.Required) && propertyMap.ContainsKey(p.Name) == false)
                                            .Select(p => p.Name)
                                            .OrderBy(p => p)
                                            .ConcatString(LanguageConstants.ListSeparator);

            if (string.IsNullOrEmpty(missingRequiredProperties) == false)
            {
                diagnostics.Add(DiagnosticBuilder.ForPosition(expression).MissingRequiredProperties(missingRequiredProperties));
            }

            foreach (var declaredProperty in targetType.Properties.Values)
            {
                if (propertyMap.TryGetValue(declaredProperty.Name, out var declaredPropertySyntax))
                {
                    bool skipConstantCheckForProperty = skipConstantCheck;

                    // is the property marked as requiring compile-time constants and has the parent already validated this?
                    if (skipConstantCheck == false && declaredProperty.Flags.HasFlag(TypePropertyFlags.Constant))
                    {
                        // validate that values are compile-time constants
                        diagnostics.AddRange(GetCompileTimeConstantViolation(declaredPropertySyntax.Value));

                        // disable compile-time constant validation for children
                        skipConstantCheckForProperty = true;
                    }

                    if (declaredProperty.Flags.HasFlag(TypePropertyFlags.ReadOnly))
                    {
                        // the declared property is read-only
                        // value cannot be assigned to a read-only property
                        diagnostics.Add(DiagnosticBuilder.ForPosition(declaredPropertySyntax.Key).CannotAssignToReadOnlyProperty(declaredProperty.Name));
                    }

                    // declared property is specified in the value object
                    // validate type
                    GetExpressionAssignmentDiagnosticsInternal(
                        typeManager,
                        declaredPropertySyntax.Value,
                        declaredProperty.TypeReference.Type,
                        diagnostics,
                        (expectedType, actualType, errorExpression) => DiagnosticBuilder.ForPosition(errorExpression).PropertyTypeMismatch(declaredProperty.Name, expectedType, actualType),
                        skipConstantCheckForProperty,
                        skipTypeErrors: true);
                }
            }

            // find properties that are specified on in the expression object but not declared in the schema
            var extraProperties = expression.Properties
                                  .Select(p => p.GetKeyText())
                                  .Except(targetType.Properties.Values.Select(p => p.Name), LanguageConstants.IdentifierComparer)
                                  .Select(name => propertyMap[name]);

            if (targetType.AdditionalProperties == null)
            {
                var validUnspecifiedProperties = targetType.Properties.Values
                                                 .Where(p => !p.Flags.HasFlag(TypePropertyFlags.ReadOnly))
                                                 .Select(p => p.Name)
                                                 .Except(expression.Properties.Select(p => p.GetKeyText()), LanguageConstants.IdentifierComparer)
                                                 .OrderBy(x => x);

                // extra properties are not allowed by the type
                foreach (var extraProperty in extraProperties)
                {
                    var error = validUnspecifiedProperties.Any() ?
                                DiagnosticBuilder.ForPosition(extraProperty.Key).DisallowedPropertyWithPermissibleProperties(extraProperty.GetKeyText(), targetType.Name, validUnspecifiedProperties) :
                                DiagnosticBuilder.ForPosition(extraProperty.Key).DisallowedProperty(extraProperty.GetKeyText(), targetType.Name);

                    diagnostics.AddRange(error.AsEnumerable());
                }
            }
            else
            {
                // extra properties must be assignable to the right type
                foreach (ObjectPropertySyntax extraProperty in extraProperties)
                {
                    bool skipConstantCheckForProperty = skipConstantCheck;

                    // is the property marked as requiring compile-time constants and has the parent already validated this?
                    if (skipConstantCheckForProperty == false && targetType.AdditionalPropertiesFlags.HasFlag(TypePropertyFlags.Constant))
                    {
                        // validate that values are compile-time constants
                        diagnostics.AddRange(GetCompileTimeConstantViolation(extraProperty.Value));

                        // disable compile-time constant validation for children
                        skipConstantCheckForProperty = true;
                    }

                    GetExpressionAssignmentDiagnosticsInternal(
                        typeManager,
                        extraProperty.Value,
                        targetType.AdditionalProperties.Type,
                        diagnostics,
                        (expectedType, actualType, errorExpression) => DiagnosticBuilder.ForPosition(errorExpression).PropertyTypeMismatch(extraProperty.GetKeyText(), expectedType, actualType),
                        skipConstantCheckForProperty,
                        skipTypeErrors: true);
                }
            }
        }
示例#5
0
        private static TypeSymbol NarrowObjectType(ITypeManager typeManager, ObjectSyntax expression, ObjectType targetType, IDiagnosticWriter diagnosticWriter, bool skipConstantCheck)
        {
            // TODO: Short-circuit on any object to avoid unnecessary processing?
            // TODO: Consider doing the schema check even if there are parse errors
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                return(targetType);
            }

            var namedPropertyMap = expression.ToNamedPropertyDictionary();

            var missingRequiredProperties = targetType.Properties.Values
                                            .Where(p => p.Flags.HasFlag(TypePropertyFlags.Required) && !namedPropertyMap.ContainsKey(p.Name))
                                            .Select(p => p.Name)
                                            .OrderBy(p => p);

            if (missingRequiredProperties.Any())
            {
                IPositionable positionable = expression;
                string        blockName    = "object";

                var parent = typeManager.GetParent(expression);
                if (parent is ObjectPropertySyntax objectPropertyParent)
                {
                    positionable = objectPropertyParent.Key;
                    blockName    = "object";
                }
                else if (parent is INamedDeclarationSyntax declarationParent)
                {
                    positionable = declarationParent.Name;
                    blockName    = declarationParent.Keyword.Text;
                }

                diagnosticWriter.Write(DiagnosticBuilder.ForPosition(positionable).MissingRequiredProperties(ShouldWarn(targetType), missingRequiredProperties, blockName));
            }

            var narrowedProperties = new List <TypeProperty>();

            foreach (var declaredProperty in targetType.Properties.Values)
            {
                if (namedPropertyMap.TryGetValue(declaredProperty.Name, out var declaredPropertySyntax))
                {
                    bool skipConstantCheckForProperty = skipConstantCheck;

                    // is the property marked as requiring compile-time constants and has the parent already validated this?
                    if (skipConstantCheck == false && declaredProperty.Flags.HasFlag(TypePropertyFlags.Constant))
                    {
                        // validate that values are compile-time constants
                        GetCompileTimeConstantViolation(declaredPropertySyntax.Value, diagnosticWriter);

                        // disable compile-time constant validation for children
                        skipConstantCheckForProperty = true;
                    }

                    if (declaredProperty.Flags.HasFlag(TypePropertyFlags.ReadOnly))
                    {
                        // the declared property is read-only
                        // value cannot be assigned to a read-only property
                        diagnosticWriter.Write(DiagnosticBuilder.ForPosition(declaredPropertySyntax.Key).CannotAssignToReadOnlyProperty(ShouldWarn(targetType), declaredProperty.Name));
                        narrowedProperties.Add(new TypeProperty(declaredProperty.Name, declaredProperty.TypeReference.Type, declaredProperty.Flags));
                        continue;
                    }

                    // declared property is specified in the value object
                    // validate type
                    var narrowedType = NarrowTypeInternal(
                        typeManager,
                        declaredPropertySyntax.Value,
                        declaredProperty.TypeReference.Type,
                        diagnosticWriter,
                        GetPropertyMismatchErrorFactory(ShouldWarn(targetType), declaredProperty.Name),
                        skipConstantCheckForProperty,
                        skipTypeErrors: true);

                    narrowedProperties.Add(new TypeProperty(declaredProperty.Name, narrowedType, declaredProperty.Flags));
                }
                else
                {
                    narrowedProperties.Add(declaredProperty);
                }
            }

            // find properties that are specified on in the expression object but not declared in the schema
            var extraProperties = expression.Properties
                                  .Where(p => !(p.TryGetKeyText() is string keyName) || !targetType.Properties.ContainsKey(keyName));

            if (targetType.AdditionalPropertiesType == null)
            {
                bool shouldWarn = ShouldWarn(targetType);
                var  validUnspecifiedProperties = targetType.Properties.Values
                                                  .Where(p => !p.Flags.HasFlag(TypePropertyFlags.ReadOnly) && !namedPropertyMap.ContainsKey(p.Name))
                                                  .Select(p => p.Name)
                                                  .OrderBy(x => x);

                // extra properties are not allowed by the type
                foreach (var extraProperty in extraProperties)
                {
                    Diagnostic error;
                    var        builder = DiagnosticBuilder.ForPosition(extraProperty.Key);

                    if (extraProperty.TryGetKeyText() is string keyName)
                    {
                        error = validUnspecifiedProperties.Any() switch
                        {
                            true => SpellChecker.GetSpellingSuggestion(keyName, validUnspecifiedProperties) switch
                            {
                                string suggestedKeyName when suggestedKeyName != null
                                => builder.DisallowedPropertyWithSuggestion(shouldWarn, keyName, targetType, suggestedKeyName),
                                _ => builder.DisallowedPropertyWithPermissibleProperties(shouldWarn, keyName, targetType, validUnspecifiedProperties)
                            },
示例#6
0
        public void Variousobjects_ShouldProduceAnErrorWhenAssignedToString(string displayName, ObjectSyntax @object)
        {
            var errors = TypeValidator.GetExpressionAssignmentDiagnostics(CreateTypeManager(), @object, LanguageConstants.Int).ToList();

            errors.Should().HaveCount(1);
            errors.Single().Message.Should().Be("Expected a value of type int but the provided value is of type object.");
        }
示例#7
0
        public void Variousobjects_ShouldProduceAnErrorWhenAssignedToString(string displayName, ObjectSyntax @object)
        {
            var hierarchy = new SyntaxHierarchy();

            hierarchy.AddRoot(@object);

            var(narrowedType, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, @object, LanguageConstants.Int);

            diagnostics.Should().HaveCount(1);
            diagnostics.Single().Message.Should().Be("Expected a value of type \"int\" but the provided value is of type \"object\".");
        }
示例#8
0
            private void VisitResourceOrModuleDeclaration(SyntaxBase declaringSyntax, ObjectSyntax body)
            {
                var dependsOnProperty = body.SafeGetPropertyByName(LanguageConstants.ResourceDependsOnPropertyName);

                if (dependsOnProperty?.Value is ArraySyntax declaredDependencies)
                {
                    if (model.GetSymbolInfo(declaringSyntax) is DeclaredSymbol thisResource)
                    {
                        // If this resource has no implicit dependencies, than all explicit dependsOn entries must be valid, so don't bother checking
                        if (inferredDependenciesMap.Value.TryGetValue(thisResource, out ImmutableHashSet <ResourceDependency>?inferredDependencies))
                        {
                            foreach (ArrayItemSyntax declaredDependency in declaredDependencies.Items)
                            {
                                // Is this a simple reference to a resource collection?
                                if (model.GetSymbolInfo(declaredDependency.Value) is ResourceSymbol referencedResource)
                                {
                                    if (referencedResource.IsCollection)
                                    {
                                        // Ignore dependsOn entries pointing to a resource collection - dependency analyis would
                                        // be complex and user probably knows what they're doing.
                                        continue;
                                    }

                                    if (inferredDependencies.Any(d => d.Resource == referencedResource))
                                    {
                                        this.diagnostics.Add(
                                            parent.CreateDiagnosticForSpan(
                                                declaredDependency.Span,
                                                referencedResource.Name));
                                    }
                                }
                            }
                        }
                    }
                }
            }
示例#9
0
文件: Model.cs 项目: Ace4teaM/Syntaxi
        /// <summary>
        /// Importe des syntaxes d'objets depuis un dossier
        /// </summary>
        /// <param name="path"></param>
        public void ImportSyntaxDirectory(string path)
        {
            string groupName = Path.GetFileNameWithoutExtension(path);

            // Scan les objets
            if (Directory.Exists(path))
            {
                string[] groupsPaths = Directory.GetFiles(path, "*");
                foreach (var syntaxFile in groupsPaths)
                {
                    using (StreamReader streamReader = new StreamReader(syntaxFile, Encoding.UTF8))
                    {
                        try
                        {
                            ObjectSyntax syntax = new ObjectSyntax();
                            this.Add(syntax);
                            syntax.ObjectType   = Path.GetFileNameWithoutExtension(syntaxFile);
                            syntax.ContentRegEx = streamReader.ReadLine();
                            syntax.ParamRegEx   = streamReader.ReadLine();
                            syntax.ObjectDesc   = String.Empty;
                            syntax.GroupName    = groupName;
                            project.AddObjectSyntax(syntax);
                            Console.WriteLine("Add syntax object " + syntax.ObjectType);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Ignore object file '" + syntaxFile + "'. " + ex.Message);
                        }
                        streamReader.Close();
                    }
                }
            }

            // Scan les groupes
            if (Directory.Exists(path + @"\groups"))
            {
                string[] groupsPaths = Directory.GetFiles(path + @"\groups", "*");
                foreach (var syntaxFile in groupsPaths)
                {
                    using (StreamReader streamReader = new StreamReader(syntaxFile, Encoding.UTF8))
                    {
                        try
                        {
                            ParamSyntax syntax = new ParamSyntax();
                            this.Add(syntax);
                            syntax.ParamType    = Path.GetFileNameWithoutExtension(syntaxFile);
                            syntax.ContentRegEx = streamReader.ReadLine();
                            syntax.ParamRegEx   = streamReader.ReadLine();
                            syntax.GroupName    = groupName;
                            project.AddParamSyntax(syntax);
                            Console.WriteLine("Add syntax param " + syntax.ParamType);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine("Ignore param file '" + syntaxFile + "'. " + ex.Message);
                        }
                        streamReader.Close();
                    }
                }
            }
        }
示例#10
0
        public void VariousObjects_ShouldProduceNoDiagnosticsWhenAssignedToObjectType(string displayName, ObjectSyntax @object)
        {
            var hierarchy = new SyntaxHierarchy();

            hierarchy.AddRoot(@object);

            var(narrowedType, diagnostics) = NarrowTypeAndCollectDiagnostics(hierarchy, @object, LanguageConstants.Object);

            diagnostics.Should().BeEmpty();
        }
示例#11
0
文件: Model.cs 项目: Ace4teaM/Syntaxi
        /// <summary>
        /// Scan un fichier à la recherche d'objets
        /// </summary>
        /// <param name="groupName">Nom du groupe de syntaxe à scanner</param>
        /// <param name="text">Texte du code à analyser</param>
        /// <param name="filePath">Chemin d'accès relatif au fichier analysé</param>
        /// <param name="syntax">Syntaxe utilisé pour scaner le texte</param>
        public void ScanFile(string groupName, string text, string filePath, ObjectSyntax syntax, List <ObjectContent> objList)
        {
            // Convertie en expression reguliere
            Regex content = new Regex(syntax.ContentRegEx, RegexOptions.Multiline | RegexOptions.IgnoreCase);
            Regex param   = new Regex(syntax.ParamRegEx, RegexOptions.Multiline | RegexOptions.IgnoreCase);

            MatchCollection matches = content.Matches(text);

            foreach (Match match in matches)
            {
                // Initialise l'objet
                ObjectContent o = new ObjectContent();
                this.project.AddObjectContent(o);
//                this.Add(o);
                o.ObjectType = syntax.ObjectType;
                o.Filename   = filePath;
                o.Position   = match.Index;
                o.Id         = Guid.NewGuid().ToString("N");

                // Extrer les paramètres implicite de l'expression régulière
                foreach (string regexGroupName in content.GetGroupNames())
                {
                    if (regexGroupName != "content" && regexGroupName != "0")
                    {
                        o.AddParamContent(new ParamContent(Guid.NewGuid().ToString("N"), regexGroupName, match.Groups[regexGroupName].Value));
                        //Log(String.Format("\tAdd param '{0}' as '{1}'", groupName, match.Groups[groupName].Value));
                    }
                }

                // Recherche des paramètres dans le contenu de l'objet
                string objet_text = match.Groups["content"].Value;

                // Extrer les groupes de parametres
                foreach (ParamSyntax g in project.ParamSyntax.Where(p => p.GroupName.ToLower() == groupName.ToLower()).ToList())
                {
                    // Convertie en expression reguliere
                    Regex pContent = new Regex(g.ContentRegEx, RegexOptions.Multiline | RegexOptions.IgnoreCase);
                    Regex pParam   = new Regex(g.ParamRegEx, RegexOptions.Multiline | RegexOptions.IgnoreCase);

                    MatchCollection pMatches = pContent.Matches(objet_text);
                    foreach (Match pMatch in pMatches)
                    {
                        MatchCollection gParamMatches = pParam.Matches(pMatch.Groups["content"].Value);
                        foreach (Match paramMatch in gParamMatches)
                        {
                            o.AddParamContent(new ParamContent(Guid.NewGuid().ToString("N"), g.ParamType, paramMatch.Groups["content"].Value));
                        }
                    }
                }

                // Extrer les parametres d'objet
                MatchCollection paramMatches = param.Matches(objet_text);
                foreach (Match paramMatch in paramMatches)
                {
                    o.AddParamContent(new ParamContent(Guid.NewGuid().ToString("N"), paramMatch.Groups["type"].Value, paramMatch.Groups["content"].Value));
                }

                // Ajoute à la liste des objets
                objList.Add(o);
            }
        }
        protected override SyntaxBase ReplaceResourceDeclarationSyntax(ResourceDeclarationSyntax syntax)
        {
            if (syntax.TryGetBody() is not ObjectSyntax resourceBody ||
                resourceBody.SafeGetPropertyByName("name") is not ObjectPropertySyntax resourceNameProp ||
                resourceNameProp.Value is not StringSyntax resourceName)
            {
                return(syntax);
            }

            if (semanticModel.GetSymbolInfo(syntax) is not ResourceSymbol resourceSymbol ||
                resourceSymbol.Type is not ResourceType resourceType)
            {
                return(syntax);
            }

            if (resourceType.TypeReference.Types.Length < 2)
            {
                // we're only looking for child resources here
                return(syntax);
            }

            foreach (var otherResource in semanticModel.AllResources)
            {
                var otherResourceSymbol = otherResource.Symbol;

                if (otherResourceSymbol.Type is not ResourceType otherResourceType ||
                    otherResourceType.TypeReference.Types.Length != resourceType.TypeReference.Types.Length - 1 ||
                    !resourceType.TypeReference.TypesString.StartsWith($"{otherResourceType.TypeReference.TypesString}/", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                // The other resource is a parent type to this one. check if we can refactor the name.
                if (otherResourceSymbol.DeclaringResource.TryGetBody() is not ObjectSyntax otherResourceBody ||
                    otherResourceBody.SafeGetPropertyByName("name") is not ObjectPropertySyntax otherResourceNameProp)
                {
                    continue;
                }

                if (TryGetReplacementChildName(resourceName, otherResourceNameProp.Value, otherResourceSymbol) is not {
                } newName)
                {
                    continue;
                }

                var replacementNameProp = new ObjectPropertySyntax(resourceNameProp.Key, resourceNameProp.Colon, newName);
                var parentProp          = new ObjectPropertySyntax(
                    SyntaxFactory.CreateIdentifier(LanguageConstants.ResourceParentPropertyName),
                    SyntaxFactory.ColonToken,
                    SyntaxFactory.CreateVariableAccess(otherResourceSymbol.Name));

                var replacementBody = new ObjectSyntax(
                    resourceBody.OpenBrace,
                    // parent prop comes first!
                    parentProp.AsEnumerable().Concat(resourceBody.Children.Replace(resourceNameProp, replacementNameProp)),
                    resourceBody.CloseBrace);

                // at the top we just checked if there is a legitimate body
                // but to do the replacement correctly we may need to wrap it inside an IfConditionSyntax
                SyntaxBase replacementValue = syntax.Value switch
                {
                    ObjectSyntax => replacementBody,
                    IfConditionSyntax ifCondition => new IfConditionSyntax(ifCondition.Keyword, ifCondition.ConditionExpression, replacementBody),

                    // should not be possible
                    _ => throw new NotImplementedException($"Unexpected resource value type '{syntax.Value.GetType().Name}'.")
                };

                return(new ResourceDeclarationSyntax(
                           syntax.LeadingNodes,
                           syntax.Keyword,
                           syntax.Name,
                           syntax.Type,
                           syntax.ExistingKeyword,
                           syntax.Assignment,
                           replacementValue));
            }

            return(syntax);
        }
示例#13
0
        //-----------------------------------------------------------------------------------------
        // Evénements
        //-----------------------------------------------------------------------------------------
        #region IEventProcess
        // Traite les événements
        public void ProcessEvent(object from, object _this, IEvent e)
        {
            //
            // Model Change
            // Après le changement du model
            //
            if (e is ModelChangeEvent)
            {
                ModelChangeEvent ev = e as ModelChangeEvent;
                //Actualise l'interface
                UpdateUI();
                // Notifie les vues
                this.NotifyEvent(e);
            }

            //
            // Entity Change
            // Après le changement d'une entité
            //
            if (e is EntityChangeEvent)
            {
                EntityChangeEvent ev = e as EntityChangeEvent;
                //Actualise l'interface
                OnEntityChange(ev.Model, ev.Entity, ev.BaseEvent);
                // Notifie les vues
                this.NotifyEvent(e);
            }

            //
            // Pré-Create
            // Préprare la création d'une nouvelle entité (avant édition des champs)
            //
            if (e is EntityPreCreateEvent)
            {
                EntityPreCreateEvent ev = e as EntityPreCreateEvent;

                // Allocation
                if (ev.Entity == null)
                {
                    ev.Entity = app.appModel.CreateEntity(ev.EntityName);
                }

                // Affecte le status de création
                ev.Entity.EntityState = EntityState.Added;

                // Initialise les données par défaut
                if (ev.Entity is IEntityPersistent)
                {
                    IEntityPersistent p = ev.Entity as IEntityPersistent;
                    //Affecte la source de données à la nouvelle entitée
                    p.Factory = app.appModel.project.Factory;
                }

                if (ev.Entity is ObjectSyntax)
                {
                    ObjectSyntax entity = ev.Entity as ObjectSyntax;
                    // Ajoute au projet en cours
                    app.Project.AddObjectSyntax(entity);
                }


                if (ev.Entity is ParamSyntax)
                {
                    ParamSyntax entity = ev.Entity as ParamSyntax;
                    // Ajoute au projet en cours
                    app.Project.AddParamSyntax(entity);
                }

                if (ev.Entity is ObjectContent)
                {
                    ObjectContent entity = ev.Entity as ObjectContent;
                    // Ajoute au projet en cours
                    app.Project.AddObjectContent(entity);
                    // Génére un identifiant unique
                    entity.Id = Guid.NewGuid().ToString("N");
                    foreach (var p in entity.ParamContent)
                    {
                        p.Id = Guid.NewGuid().ToString("N");
                    }
                }

                if (ev.Entity is ParamContent)
                {
                    ParamContent entity = ev.Entity as ParamContent;
                    CurObjectContent.AddParamContent(entity);
                    // Génére un identifiant unique
                    entity.Id = Guid.NewGuid().ToString("N");
                }

                if (ev.Entity is SearchParams)
                {
                    SearchParams entity = ev.Entity as SearchParams;
                    app.Project.AddSearchParams(entity);
                }

                if (ev.Entity is DatabaseSource)
                {
                    DatabaseSource entity = ev.Entity as DatabaseSource;
                    app.Project.AddDatabaseSource(entity);

                    if (app.States.SelectedDatabaseSourceId == null)
                    {
                        app.States.SelectedDatabaseSourceId = app.Project.DatabaseSource.First().Id;
                    }
                }

                // Ajoute l'instance au model (notifie le controleur)
                app.appModel.Add(ev.Entity);
            }

            // Implémente la gestion du copier coller
            EventProcess.ProcessCopyPasteEvents(app, this, app.appModel, from, _this, e);

            /*
             *
             * //
             * // Change
             * // Action après le changement d'une entité
             * //
             * if (e is EntityChangeEvent)
             * {
             *  EntityChangeEvent ev = e as EntityChangeEvent;
             *  // Concerne ce model ?
             *  if (ev.Model == app.appModel)
             *  {
             *      if (ev.Entity is ObjectContent)
             *      {
             *          OnPropertyChanged("ObjectContentList");
             *      }
             *      if (ev.Entity is ParamContent)
             *      {
             *          CurParamContentList = new ObservableCollection<ParamContent>(curObjectContent.ParamContent);
             *      }
             *      if (ev.Entity is DatabaseSource)
             *      {
             *          OnPropertyChanged("CurDatabaseSource");
             *      }
             *  }
             * }*/
        }
示例#14
0
        private static TypeSymbol NarrowObjectType(ITypeManager typeManager, ObjectSyntax expression, ObjectType targetType, IList <Diagnostic> diagnostics, bool skipConstantCheck)
        {
            // TODO: Short-circuit on any object to avoid unnecessary processing?
            // TODO: Consider doing the schema check even if there are parse errors
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                return(targetType);
            }

            var namedPropertyMap = expression.ToNamedPropertyDictionary();

            var missingRequiredProperties = targetType.Properties.Values
                                            .Where(p => p.Flags.HasFlag(TypePropertyFlags.Required) && !namedPropertyMap.ContainsKey(p.Name))
                                            .Select(p => p.Name)
                                            .OrderBy(p => p);

            if (missingRequiredProperties.Any())
            {
                diagnostics.Add(DiagnosticBuilder.ForPosition(expression).MissingRequiredProperties(ShouldWarn(targetType), missingRequiredProperties));
            }

            var narrowedProperties = new List <TypeProperty>();

            foreach (var declaredProperty in targetType.Properties.Values)
            {
                if (namedPropertyMap.TryGetValue(declaredProperty.Name, out var declaredPropertySyntax))
                {
                    bool skipConstantCheckForProperty = skipConstantCheck;

                    // is the property marked as requiring compile-time constants and has the parent already validated this?
                    if (skipConstantCheck == false && declaredProperty.Flags.HasFlag(TypePropertyFlags.Constant))
                    {
                        // validate that values are compile-time constants
                        diagnostics.AddRange(GetCompileTimeConstantViolation(declaredPropertySyntax.Value));

                        // disable compile-time constant validation for children
                        skipConstantCheckForProperty = true;
                    }

                    if (declaredProperty.Flags.HasFlag(TypePropertyFlags.ReadOnly))
                    {
                        // the declared property is read-only
                        // value cannot be assigned to a read-only property
                        diagnostics.Add(DiagnosticBuilder.ForPosition(declaredPropertySyntax.Key).CannotAssignToReadOnlyProperty(ShouldWarn(targetType), declaredProperty.Name));
                    }

                    // declared property is specified in the value object
                    // validate type
                    var narrowedType = NarrowTypeInternal(
                        typeManager,
                        declaredPropertySyntax.Value,
                        declaredProperty.TypeReference.Type,
                        diagnostics,
                        (expectedType, actualType, errorExpression) => DiagnosticBuilder.ForPosition(errorExpression).PropertyTypeMismatch(ShouldWarn(targetType), declaredProperty.Name, expectedType, actualType),
                        skipConstantCheckForProperty,
                        skipTypeErrors: true);

                    narrowedProperties.Add(new TypeProperty(declaredProperty.Name, narrowedType, declaredProperty.Flags));
                }
                else
                {
                    narrowedProperties.Add(declaredProperty);
                }
            }

            // find properties that are specified on in the expression object but not declared in the schema
            var extraProperties = expression.Properties
                                  .Where(p => !(p.TryGetKeyText() is string keyName) || !targetType.Properties.ContainsKey(keyName));

            if (targetType.AdditionalPropertiesType == null)
            {
                var validUnspecifiedProperties = targetType.Properties.Values
                                                 .Where(p => !p.Flags.HasFlag(TypePropertyFlags.ReadOnly))
                                                 .Where(p => !namedPropertyMap.ContainsKey(p.Name))
                                                 .Select(p => p.Name)
                                                 .OrderBy(x => x);

                // extra properties are not allowed by the type
                foreach (var extraProperty in extraProperties)
                {
                    Diagnostic error;
                    if (extraProperty.TryGetKeyText() is string keyName)
                    {
                        error = validUnspecifiedProperties.Any() ?
                                DiagnosticBuilder.ForPosition(extraProperty.Key).DisallowedPropertyWithPermissibleProperties(ShouldWarn(targetType), keyName, targetType, validUnspecifiedProperties) :
                                DiagnosticBuilder.ForPosition(extraProperty.Key).DisallowedProperty(ShouldWarn(targetType), keyName, targetType);
                    }
                    else
                    {
                        error = validUnspecifiedProperties.Any() ?
                                DiagnosticBuilder.ForPosition(extraProperty.Key).DisallowedInterpolatedKeyPropertyWithPermissibleProperties(ShouldWarn(targetType), targetType, validUnspecifiedProperties) :
                                DiagnosticBuilder.ForPosition(extraProperty.Key).DisallowedInterpolatedKeyProperty(ShouldWarn(targetType), targetType);
                    }

                    diagnostics.AddRange(error.AsEnumerable());
                }
            }
            else
            {
                // extra properties must be assignable to the right type
                foreach (ObjectPropertySyntax extraProperty in extraProperties)
                {
                    bool skipConstantCheckForProperty = skipConstantCheck;

                    // is the property marked as requiring compile-time constants and has the parent already validated this?
                    if (skipConstantCheckForProperty == false && targetType.AdditionalPropertiesFlags.HasFlag(TypePropertyFlags.Constant))
                    {
                        // validate that values are compile-time constants
                        diagnostics.AddRange(GetCompileTimeConstantViolation(extraProperty.Value));

                        // disable compile-time constant validation for children
                        skipConstantCheckForProperty = true;
                    }

                    TypeMismatchErrorFactory typeMismatchErrorFactory;
                    if (extraProperty.TryGetKeyText() is string keyName)
                    {
                        typeMismatchErrorFactory = (expectedType, actualType, errorExpression) => DiagnosticBuilder.ForPosition(errorExpression).PropertyTypeMismatch(ShouldWarn(targetType), keyName, expectedType, actualType);
                    }
                    else
                    {
                        typeMismatchErrorFactory = (expectedType, actualType, errorExpression) => DiagnosticBuilder.ForPosition(errorExpression).ExpectedValueTypeMismatch(ShouldWarn(targetType), expectedType, actualType);
                    }

                    var narrowedProperty = NarrowTypeInternal(
                        typeManager,
                        extraProperty.Value,
                        targetType.AdditionalPropertiesType.Type,
                        diagnostics,
                        typeMismatchErrorFactory,
                        skipConstantCheckForProperty,
                        skipTypeErrors: true);

                    // TODO should we try and narrow the additional properties type? May be difficult
                }
            }

            return(new NamedObjectType(targetType.Name, targetType.ValidationFlags, narrowedProperties, targetType.AdditionalPropertiesType, targetType.AdditionalPropertiesFlags));
        }
示例#15
0
        private static IEnumerable <ErrorDiagnostic> GetDiscriminatedObjectAssignmentDiagnostics(ITypeManager typeManager, ObjectSyntax expression, DiscriminatedObjectType targetType, bool skipConstantCheck)
        {
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                yield break;
            }

            var propertyMap = expression.ToPropertyDictionary();

            if (!propertyMap.TryGetValue(targetType.DiscriminatorKey, out var discriminatorProperty))
            {
                // object doesn't contain the discriminator field
                yield return(DiagnosticBuilder.ForPosition(expression).MissingRequiredProperty(targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType));

                yield break;
            }

            // At some point in the future we may want to relax the expectation of a string literal key, and allow a generic string.
            // In this case, the best we can do is validate against the union of all the settable properties.
            // Let's not do this just yet, and see if a use-case arises.

            var discriminatorType = typeManager.GetTypeInfo(discriminatorProperty.Value, new TypeManagerContext());

            if (!(discriminatorType is StringLiteralType stringLiteralDiscriminator))
            {
                yield return(DiagnosticBuilder.ForPosition(expression).PropertyTypeMismatch(targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, discriminatorType));

                yield break;
            }

            if (!targetType.UnionMembersByKey.TryGetValue(stringLiteralDiscriminator.Name, out var selectedObjectType))
            {
                // no matches
                yield return(DiagnosticBuilder.ForPosition(discriminatorProperty.Value).PropertyTypeMismatch(targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, discriminatorType));

                yield break;
            }

            // we have a match!
            foreach (var diagnostic in GetObjectAssignmentDiagnostics(typeManager, expression, selectedObjectType, skipConstantCheck))
            {
                yield return(diagnostic);
            }
            yield break;
        }
示例#16
0
        private static TypeSymbol NarrowObjectType(ITypeManager typeManager, ObjectSyntax expression, ObjectType targetType, IList <Diagnostic> diagnostics, bool skipConstantCheck)
        {
            // TODO: Short-circuit on any object to avoid unnecessary processing?
            // TODO: Consider doing the schema check even if there are parse errors
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                return(targetType);
            }

            var namedPropertyMap = expression.ToNamedPropertyDictionary();

            var missingRequiredProperties = targetType.Properties.Values
                                            .Where(p => p.Flags.HasFlag(TypePropertyFlags.Required) && !namedPropertyMap.ContainsKey(p.Name))
                                            .Select(p => p.Name)
                                            .OrderBy(p => p);

            if (missingRequiredProperties.Any())
            {
                diagnostics.Add(DiagnosticBuilder.ForPosition(expression).MissingRequiredProperties(ShouldWarn(targetType), missingRequiredProperties));
            }

            var narrowedProperties = new List <TypeProperty>();

            foreach (var declaredProperty in targetType.Properties.Values)
            {
                if (namedPropertyMap.TryGetValue(declaredProperty.Name, out var declaredPropertySyntax))
                {
                    bool skipConstantCheckForProperty = skipConstantCheck;

                    // is the property marked as requiring compile-time constants and has the parent already validated this?
                    if (skipConstantCheck == false && declaredProperty.Flags.HasFlag(TypePropertyFlags.Constant))
                    {
                        // validate that values are compile-time constants
                        diagnostics.AddRange(GetCompileTimeConstantViolation(declaredPropertySyntax.Value));

                        // disable compile-time constant validation for children
                        skipConstantCheckForProperty = true;
                    }

                    if (declaredProperty.Flags.HasFlag(TypePropertyFlags.ReadOnly))
                    {
                        // the declared property is read-only
                        // value cannot be assigned to a read-only property
                        diagnostics.Add(DiagnosticBuilder.ForPosition(declaredPropertySyntax.Key).CannotAssignToReadOnlyProperty(ShouldWarn(targetType), declaredProperty.Name));
                    }

                    TypeMismatchErrorFactory typeMismatchErrorFactory = (expectedType, actualType, errorExpression) =>
                    {
                        var builder    = DiagnosticBuilder.ForPosition(errorExpression);
                        var shouldWarn = ShouldWarn(targetType);

                        if (actualType is StringLiteralType)
                        {
                            string?suggestedStringLiteral = null;

                            if (expectedType is StringLiteralType)
                            {
                                suggestedStringLiteral = SpellChecker.GetSpellingSuggestion(actualType.Name, expectedType.Name.AsEnumerable());
                            }

                            if (expectedType is UnionType unionType && unionType.Members.All(typeReference => typeReference.Type is StringLiteralType))
                            {
                                var stringLiteralCandidates = unionType.Members.Select(typeReference => typeReference.Type.Name).OrderBy(x => x);
                                suggestedStringLiteral = SpellChecker.GetSpellingSuggestion(actualType.Name, stringLiteralCandidates);
                            }

                            if (suggestedStringLiteral != null)
                            {
                                return(builder.PropertyStringLiteralMismatchWithSuggestion(shouldWarn, declaredProperty.Name, expectedType, actualType.Name, suggestedStringLiteral));
                            }
                        }

                        return(builder.PropertyTypeMismatch(shouldWarn, declaredProperty.Name, expectedType, actualType));
                    };

                    // declared property is specified in the value object
                    // validate type
                    var narrowedType = NarrowTypeInternal(
                        typeManager,
                        declaredPropertySyntax.Value,
                        declaredProperty.TypeReference.Type,
                        diagnostics,
                        typeMismatchErrorFactory,
                        skipConstantCheckForProperty,
                        skipTypeErrors: true);

                    narrowedProperties.Add(new TypeProperty(declaredProperty.Name, narrowedType, declaredProperty.Flags));
                }
                else
                {
                    narrowedProperties.Add(declaredProperty);
                }
            }

            // find properties that are specified on in the expression object but not declared in the schema
            var extraProperties = expression.Properties
                                  .Where(p => !(p.TryGetKeyText() is string keyName) || !targetType.Properties.ContainsKey(keyName));

            if (targetType.AdditionalPropertiesType == null)
            {
                bool shouldWarn = ShouldWarn(targetType);
                var  validUnspecifiedProperties = targetType.Properties.Values
                                                  .Where(p => !p.Flags.HasFlag(TypePropertyFlags.ReadOnly) && !namedPropertyMap.ContainsKey(p.Name))
                                                  .Select(p => p.Name)
                                                  .OrderBy(x => x);

                // extra properties are not allowed by the type
                foreach (var extraProperty in extraProperties)
                {
                    Diagnostic error;
                    var        builder = DiagnosticBuilder.ForPosition(extraProperty.Key);

                    if (extraProperty.TryGetKeyText() is string keyName)
                    {
                        error = validUnspecifiedProperties.Any() switch
                        {
                            true => SpellChecker.GetSpellingSuggestion(keyName, validUnspecifiedProperties) switch
                            {
                                string suggestedKeyName when suggestedKeyName != null
                                => builder.DisallowedPropertyWithSuggestion(shouldWarn, keyName, targetType, suggestedKeyName),
                                _ => builder.DisallowedPropertyWithPermissibleProperties(shouldWarn, keyName, targetType, validUnspecifiedProperties)
                            },
示例#17
0
 public void VariousObjects_ShouldProduceNoDiagnosticsWhenAssignedToObjectType(string displayName, ObjectSyntax @object)
 {
     TypeValidator.GetExpressionAssignmentDiagnostics(CreateTypeManager(), @object, LanguageConstants.Object).Should().BeEmpty();
 }
示例#18
0
        private static TypeSymbol NarrowDiscriminatedObjectType(ITypeManager typeManager, ObjectSyntax expression, DiscriminatedObjectType targetType, IList <Diagnostic> diagnostics, bool skipConstantCheck)
        {
            // if we have parse errors, there's no point to check assignability
            // we should not return the parse errors however because they will get double collected
            if (expression.HasParseErrors())
            {
                return(LanguageConstants.Any);
            }

            var discriminatorProperty = expression.Properties.FirstOrDefault(x => LanguageConstants.IdentifierComparer.Equals(x.TryGetKeyText(), targetType.DiscriminatorKey));

            if (discriminatorProperty == null)
            {
                // object doesn't contain the discriminator field
                diagnostics.Add(DiagnosticBuilder.ForPosition(expression).MissingRequiredProperty(ShouldWarn(targetType), targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType));
                return(LanguageConstants.Any);
            }

            // At some point in the future we may want to relax the expectation of a string literal key, and allow a generic string.
            // In this case, the best we can do is validate against the union of all the settable properties.
            // Let's not do this just yet, and see if a use-case arises.

            var discriminatorType = typeManager.GetTypeInfo(discriminatorProperty.Value);

            if (!(discriminatorType is StringLiteralType stringLiteralDiscriminator))
            {
                diagnostics.Add(DiagnosticBuilder.ForPosition(expression).PropertyTypeMismatch(ShouldWarn(targetType), targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, discriminatorType));
                return(LanguageConstants.Any);
            }

            if (!targetType.UnionMembersByKey.TryGetValue(stringLiteralDiscriminator.Name, out var selectedObjectReference))
            {
                // no matches
                diagnostics.Add(DiagnosticBuilder.ForPosition(discriminatorProperty.Value).PropertyTypeMismatch(ShouldWarn(targetType), targetType.DiscriminatorKey, targetType.DiscriminatorKeysUnionType, discriminatorType));
                return(LanguageConstants.Any);
            }

            if (!(selectedObjectReference.Type is ObjectType selectedObjectType))
            {
                throw new InvalidOperationException($"Discriminated type {targetType.Name} contains non-object member");
            }

            // we have a match!
            return(NarrowObjectType(typeManager, expression, selectedObjectType, diagnostics, skipConstantCheck));
        }
        public static void AnalyzeObjectCaption(SyntaxNodeAnalysisContext context)
        {
            ObjectSyntax syntax = context.Node as ObjectSyntax;

            AnalyzeObjectCaptions(context, syntax);
        }