Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/fsharp/TypedTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3013,6 +3013,11 @@ let superOfTycon (g: TcGlobals) (tycon: Tycon) =
| None -> g.obj_ty
| Some ty -> ty

/// walk a TyconRef's inheritance tree, yielding any parent types as an array
let supersOfTyconRef (tcref: TyconRef) =
Array.unfold (fun (tcref: TyconRef) -> match tcref.TypeContents.tcaug_super with Some (TType_app(sup, _)) -> Some(sup, sup) | _ -> None) tcref


//----------------------------------------------------------------------------
// Detect attributes
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -3119,12 +3124,16 @@ let TryFindTyconRefBoolAttribute g m attribSpec tcref =
| ([ Some ((:? bool as v) : obj) ], _) -> Some v
| _ -> None)

/// Try to find the resolved attributeusage for an type by walking its inheritance tree and picking the correct attribute usage value
let TryFindAttributeUsageAttribute g m tcref =
TryBindTyconRefAttribute g m g.attrib_AttributeUsageAttribute tcref
[| yield tcref
yield! supersOfTyconRef tcref |]
|> Array.tryPick (fun tcref ->
TryBindTyconRefAttribute g m g.attrib_AttributeUsageAttribute tcref
(fun (_, named) -> named |> List.tryPick (function ("AllowMultiple", _, _, ILAttribElem.Bool res) -> Some res | _ -> None))
(fun (Attrib(_, _, _, named, _, _, _)) -> named |> List.tryPick (function AttribNamedArg("AllowMultiple", _, _, AttribBoolArg res ) -> Some res | _ -> None))
(fun (_, named) -> named |> List.tryPick (function ("AllowMultiple", Some ((:? bool as res) : obj)) -> Some res | _ -> None))

)

/// Try to find a specific attribute on a type definition, where the attribute accepts a string argument.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<Compile Include="ErrorMessages\WrongSyntaxInForLoop.fs" />
<Compile Include="ErrorMessages\ConfusingTypeName.fs" />
<Compile Include="Language\RegressionTests.fs" />
<Compile Include="Language\AttributeCheckingTests.fs" />
<Compile Include="Language\XmlComments.fs" />
<Compile Include="Language\CompilerDirectiveTests.fs" />
<Compile Include="Language\CodeQuotationTests.fs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.

namespace FSharp.Compiler.ComponentTests.AttributeChecking

open Xunit
open FSharp.Test.Utilities.Compiler

module AttributeCheckingTests =

[<Fact>]
let ``attributes check inherited AllowMultiple`` () =
Fsx """
open System

[<AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)>]
type HttpMethodAttribute() = inherit Attribute()
type HttpGetAttribute() = inherit HttpMethodAttribute()

[<HttpGet; HttpGet>] // this shouldn't error like
[<HttpMethod; HttpMethod>] // this doesn't
type C() =
member _.M() = ()
"""
|> ignoreWarnings
|> compile
|> shouldSucceed