/// <inheritdoc/>
        public ApiProfileOverride Translate(ApiProfileOverride overrides)
        {
            var enumerations = overrides.AddedEnumerations;

            var identifierTranslator = new NativeIdentifierTranslator();

            var newEnumerations = new List <EnumerationOverride>();

            foreach (var enumeration in enumerations)
            {
                var newEnumerationName = identifierTranslator.Translate(enumeration.Name);

                var newTokens = new List <TokenSignature>();
                foreach (var token in enumeration.DirectTokens)
                {
                    var newTokenName = identifierTranslator.Translate(token.Name);

                    newTokens.Add(new TokenSignature(newTokenName, token.Value, token.DeprecatedIn, token.Remarks));
                }

                newEnumerations.Add(new EnumerationOverride(newEnumerationName, newTokens));
            }

            return(new ApiProfileOverride
                   (
                       overrides.Name,
                       overrides.Versions,
                       newEnumerations,
                       overrides.ReplacedFunctions,
                       overrides.RemovedFunctions
                   ));
        }
Beispiel #2
0
        private static IEnumerable <TokenSignature> ResolveReuseEnumerationToken
        (
            [NotNull] string reusedEnumeration,
            [NotNull] ApiProfile coalescedProfile,
            [NotNull] ApiProfileOverride coalescedOverrides
        )
        {
            var profileEnum = coalescedProfile.Enumerations.FirstOrDefault(e => e.Name == reusedEnumeration);

            if (!(profileEnum is null))
            {
                return(profileEnum.Tokens);
            }

            var overrideEnum = coalescedOverrides.AddedEnumerations.FirstOrDefault(e => e.Name == reusedEnumeration);

            if (overrideEnum is null)
            {
                throw new InvalidDataException("Enumeration reuse directive could not be resolved.");
            }

            var results = overrideEnum.DirectTokens;

            foreach (var recursiveReuse in overrideEnum.ReuseEnumerations)
            {
                results = results.Concat
                          (
                    ResolveReuseEnumerationToken(recursiveReuse.Enumeration, coalescedProfile, coalescedOverrides)
                          ).ToList();
            }

            return(results);
        }
Beispiel #3
0
        /// <summary>
        /// Resolves all external token references in the override enumerations, recursively searching for them as
        /// needed. This method modifies the contents of the <paramref name="coalescedOverrides"/> parameter.
        /// </summary>
        /// <param name="coalescedOverrides">The override profile to resolve the enumerations in.</param>
        /// <param name="coalescedProfile">The profile that the overrides are applicable to.</param>
        private void ResolveEnumerationOverrides([NotNull] ApiProfileOverride coalescedOverrides, [NotNull] ApiProfile coalescedProfile)
        {
            // Resolve the various token references in the enumeration overrides
            foreach (var enumeration in coalescedOverrides.AddedEnumerations.Where(e => e.UseTokens.Any()))
            {
                var resolvedTokens = new List <TokenSignature>();
                foreach (var useToken in enumeration.UseTokens)
                {
                    var tokenName      = useToken.Token;
                    var targetEnumName = useToken.Enumeration;

                    var foundToken =
                        ResolveEnumerationTokenReference(tokenName, targetEnumName, coalescedProfile, coalescedOverrides);

                    if (foundToken is null)
                    {
                        throw new InvalidDataException
                              (
                                  $"Failed to resolve token \"{tokenName}\". Consider using the optional attribute to " +
                                  "suppress this message, or fix the override."
                              );
                    }

                    resolvedTokens.Add(foundToken);
                }

                enumeration.DirectTokens = enumeration.DirectTokens
                                           .Concat(resolvedTokens)
                                           .DistinctBy(t => t.Name)
                                           .ToList();

                enumeration.UseTokens = new List <UseTokenOverride>();
            }

            // Resolve enumeration reuses in the enumeration overrides
            foreach (var enumeration in coalescedOverrides.AddedEnumerations.Where(e => e.ReuseEnumerations.Any()))
            {
                var resolvedTokens = new List <TokenSignature>();
                foreach (var reuseToken in enumeration.ReuseEnumerations)
                {
                    var foundTokens =
                        ResolveReuseEnumerationToken(reuseToken.Enumeration, coalescedProfile, coalescedOverrides);
                    resolvedTokens.AddRange(foundTokens);
                }

                enumeration.DirectTokens = enumeration.DirectTokens
                                           .Concat(resolvedTokens)
                                           .DistinctBy(t => t.Name)
                                           .ToList();

                enumeration.ReuseEnumerations = new List <ReuseEnumerationOverride>();
            }
        }
Beispiel #4
0
        private static ApiProfile ApplyOverridesToProfile
        (
            [NotNull] ApiProfile coalescedProfile,
            [NotNull] ApiProfileOverride coalescedOverrides
        )
        {
            var newEnums = coalescedOverrides.AddedEnumerations
                           .Select(
                overrideEnum =>
                new EnumerationSignature(overrideEnum.Name, overrideEnum.DirectTokens))
                           .Concat(coalescedProfile.Enumerations)
                           .ToList();

            var newFunctions = coalescedProfile.NativeSignatures.ToList();

            foreach (var functionReplacement in coalescedOverrides.ReplacedFunctions)
            {
                var baseFunctions = FindBaseFunctions(newFunctions, functionReplacement);
                foreach (var baseFunction in baseFunctions)
                {
                    var overriddenFunction = CreateOverriddenFunction(baseFunction, functionReplacement);

                    newFunctions.Remove(baseFunction);
                    newFunctions.Add(overriddenFunction);
                }
            }

            foreach (var functionRemovals in coalescedOverrides.RemovedFunctions)
            {
                var baseFunctions = FindBaseFunctions(newFunctions, functionRemovals);
                foreach (var baseFunction in baseFunctions.ToList())
                {
                    newFunctions.Remove(baseFunction);
                }
            }

            return(new ApiProfileBuilder(coalescedProfile)
                   .WithNativeSignatures(newFunctions)
                   .WithEnumerations(newEnums)
                   .Build());
        }
Beispiel #5
0
        private ApiProfileOverride TrimDeprecatedOverrides
        (
            [NotNull] ApiProfileOverride coalescedOverrides,
            [NotNull] string baseProfileName
        )
        {
            var coalescedBaseProfile = CoalesceProfile(baseProfileName, coalescedOverrides.Versions);
            var deprecatedTokens     = coalescedBaseProfile.Enumerations
                                       .SelectMany(e => e.Tokens)
                                       .Where(t => t.IsDeprecated)
                                       .Where(t => t.DeprecatedIn < coalescedOverrides.Versions.Maximum)
                                       .ToList();

            var deprecatedFunctions = coalescedBaseProfile.NativeSignatures
                                      .Where(f => f.IsDeprecated)
                                      .Where(t => t.DeprecatedIn < coalescedOverrides.Versions.Maximum)
                                      .ToList();

            var newEnumerations = new List <EnumerationOverride>();

            foreach (var addedEnumeration in coalescedOverrides.AddedEnumerations)
            {
                var newDirectTokens = new List <TokenSignature>();
                foreach (var directToken in addedEnumeration.DirectTokens)
                {
                    if (deprecatedTokens.Any(dt => dt.Name == directToken.Name))
                    {
                        continue;
                    }

                    newDirectTokens.Add(directToken);
                }

                var newUseTokens = new List <UseTokenOverride>();
                foreach (var useToken in addedEnumeration.UseTokens)
                {
                    if (deprecatedTokens.Any(dt => dt.Name == useToken.Token))
                    {
                        continue;
                    }

                    newUseTokens.Add(useToken);
                }

                var newEnumeration = new EnumerationOverride
                                     (
                    addedEnumeration.Name,
                    newDirectTokens,
                    newUseTokens,
                    addedEnumeration.ReuseEnumerations
                                     );

                newEnumerations.Add(newEnumeration);
            }

            var newFunctionReplacements = new List <FunctionOverride>();

            foreach (var functionReplacement in coalescedOverrides.ReplacedFunctions)
            {
                var nameVariations = Utilities.GetNameVariations(functionReplacement);

                var isReplacementDeprecated = nameVariations.Any(variation => deprecatedFunctions.Any(df => df.Name == variation));
                if (!isReplacementDeprecated)
                {
                    newFunctionReplacements.Add(functionReplacement);
                }
            }

            var newFunctionRemovals = new List <RemoveOverride>();

            foreach (var functionRemoval in coalescedOverrides.RemovedFunctions)
            {
                var nameVariations = Utilities.GetNameVariations(functionRemoval);

                var isReplacementDeprecated = nameVariations.Any(variation => deprecatedFunctions.Any(df => df.Name == variation));
                if (!isReplacementDeprecated)
                {
                    newFunctionRemovals.Add(functionRemoval);
                }
            }

            return(new ApiProfileOverride
                   (
                       coalescedOverrides.Name,
                       coalescedOverrides.Versions,
                       newEnumerations,
                       newFunctionReplacements,
                       newFunctionRemovals
                   ));
        }
Beispiel #6
0
        private static TokenSignature ResolveEnumerationTokenReference
        (
            [NotNull] string tokenName,
            [CanBeNull] string targetEnumName,
            [NotNull] ApiProfile coalescedProfile,
            [NotNull] ApiProfileOverride coalescedOverrides,
            [CanBeNull] List <string> visitedEnumerations = null
        )
        {
            visitedEnumerations = visitedEnumerations ?? new List <string>();

            if (visitedEnumerations.Contains(targetEnumName))
            {
                Debug.WriteLine(
                    $"Cyclical dependency in enum found when resolving \"{tokenName}\" in \"{targetEnumName}\".");

                return(null);
            }

            var profileEnumCandidates = targetEnumName is null
                ? coalescedProfile.Enumerations
                : coalescedProfile.Enumerations.Where(e => e.Name == targetEnumName);

            var overrideEnumCandidates = targetEnumName is null
                ? coalescedOverrides.AddedEnumerations
                : coalescedOverrides.AddedEnumerations.Where(e => e.Name == targetEnumName);

            foreach (var profileEnum in profileEnumCandidates)
            {
                var token = profileEnum.Tokens.FirstOrDefault(t => t.Name == tokenName);

                if (!(token is null))
                {
                    return(token);
                }
            }

            foreach (var overrideEnum in overrideEnumCandidates)
            {
                var token = overrideEnum.DirectTokens.FirstOrDefault(t => t.Name == tokenName);

                if (!(token is null))
                {
                    return(token);
                }

                var nestedUseToken = overrideEnum.UseTokens.FirstOrDefault(t => t.Token == tokenName);
                if (!(nestedUseToken is null))
                {
                    visitedEnumerations.Add(targetEnumName);

                    // We'll recursively resolve that token until we find it or run out of options, in which case an
                    // exception will be thrown.
                    token = ResolveEnumerationTokenReference(
                        nestedUseToken.Token,
                        nestedUseToken.Enumeration,
                        coalescedProfile,
                        coalescedOverrides,
                        visitedEnumerations);

                    if (!(token is null))
                    {
                        return(token);
                    }
                }

                var reuseTokens = overrideEnum.ReuseEnumerations;
                foreach (var reuseToken in reuseTokens)
                {
                    visitedEnumerations.Add(targetEnumName);

                    // We'll recursively resolve that token until we find it or run out of options
                    token = ResolveEnumerationTokenReference(
                        tokenName,
                        reuseToken.Enumeration,
                        coalescedProfile,
                        coalescedOverrides,
                        visitedEnumerations);

                    if (!(token is null))
                    {
                        return(token);
                    }
                }
            }

            return(null);
        }