/// <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 )); }
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); }
/// <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>(); } }
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()); }
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 )); }
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); }