Пример #1
0
        protected override void ExecuteCore(RazorCodeDocument codeDocument, DocumentIntermediateNode documentNode)
        {
            if (documentNode.Options == null || documentNode.Options.SuppressMetadataAttributes)
            {
                // Metadata attributes are turned off (or options not populated), nothing to do.
                return;
            }

            // We need to be able to compute the data we need for the [RazorCompiledItem] attribute - that includes
            // a full type name, and a document kind, and optionally an identifier.
            //
            // If we can't use [RazorCompiledItem] then we don't care about the rest of the attributes.
            var @namespace = documentNode.FindPrimaryNamespace();

            if (@namespace == null || string.IsNullOrEmpty(@namespace.Content))
            {
                // No namespace node or it's incomplete. Skip.
                return;
            }

            var @class = documentNode.FindPrimaryClass();

            if (@class == null || string.IsNullOrEmpty(@class.ClassName))
            {
                // No class node or it's incomplete. Skip.
                return;
            }

            if (documentNode.DocumentKind == null)
            {
                // No document kind. Skip.
                return;
            }

            var identifier = codeDocument.GetIdentifier();

            if (identifier == null)
            {
                // No identifier. Skip
                return;
            }

            // [RazorCompiledItem] is an [assembly: ... ] attribute, so it needs to be applied at the global scope.
            documentNode.Children.Insert(0, new RazorCompiledItemAttributeIntermediateNode()
            {
                TypeName   = @namespace.Content + "." + @class.ClassName,
                Kind       = documentNode.DocumentKind,
                Identifier = identifier,
            });

            // Now we need to add a [RazorSourceChecksum] for the source and for each import
            // these are class attributes, so we need to find the insertion point to put them
            // right before the class.
            var insert = (int?)null;

            for (var j = 0; j < @namespace.Children.Count; j++)
            {
                if (object.ReferenceEquals(@namespace.Children[j], @class))
                {
                    insert = j;
                    break;
                }
            }

            if (insert == null)
            {
                // Can't find a place to put the attributes, just bail.
                return;
            }

            // Checksum of the main source
            AddChecksum(codeDocument.Source.GetChecksum(), codeDocument.Source.GetChecksumAlgorithm(), identifier);

            // Now process the checksums of the imports
            //
            // It's possible that the counts of these won't match, just process as many as we can.
            var importIdentifiers = codeDocument.GetImportIdentifiers() ?? Array.Empty <string>();

            for (var i = 0; i < codeDocument.Imports.Count && i < importIdentifiers.Count; i++)
            {
                var import = codeDocument.Imports[i];
                AddChecksum(import.GetChecksum(), import.GetChecksumAlgorithm(), importIdentifiers[i]);
            }

            void AddChecksum(byte[] checksum, string checksumAlgorithm, string id)
            {
                if (checksum == null || checksum.Length == 0 || checksumAlgorithm == null || id == null)
                {
                    // Don't generate anything unless we have all of the required information.
                    return;
                }

                // Checksum of the main source
                @namespace.Children.Insert((int)insert++, new RazorSourceChecksumAttributeIntermediateNode()
                {
                    Checksum          = checksum,
                    ChecksumAlgorithm = checksumAlgorithm,
                    Identifier        = id,
                });
            }
        }