Skip to content

Commit

Permalink
Some string error
Browse files Browse the repository at this point in the history
  • Loading branch information
nimrodshn committed Dec 11, 2024
1 parent 3fc89e6 commit e4374af
Show file tree
Hide file tree
Showing 12 changed files with 548 additions and 17 deletions.
8 changes: 8 additions & 0 deletions pkg/concepts/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,14 @@ func (t *Type) IsScalar() bool {
return t.kind == ScalarType || t.kind == EnumType || t.kind == InterfaceType
}

func (t *Type) IsBasicType() bool {
if t == nil {
return false
}

return t.kind == ScalarType
}

// IsStruct returns true iff this type is an struct type. Note that class types are also considered
// struct types.
func (t *Type) IsStruct() bool {
Expand Down
1 change: 1 addition & 0 deletions pkg/generators/golang/types_calculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ func (c *TypesCalculator) ValueReference(typ *concepts.Type) *TypeReference {
"Don't know how to calculate value reference for type '%s'",
typ,
)

ref = &TypeReference{}
}
return ref
Expand Down
45 changes: 28 additions & 17 deletions pkg/language/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,6 @@ func (r *Reader) Read() (model *concepts.Model, err error) {
listType.SetName(listName)
listType.SetElement(typ)
version.AddType(listType)
} else {
// The list type was previously defined from a cross reference.
// we thus need to redefine it.
listType.SetOwner(version)
}
}
}
Expand Down Expand Up @@ -422,7 +418,11 @@ func (r *Reader) ExitClassDecl(ctx *ClassDeclContext) {
// }
// some_type.model - an overriding decleration.
// Class SomeType {...}
typ.SetOwner(r.version)
r.version.AddType(typ)
listName := names.Cat(typ.Name(), nomenclator.List)
if listType := r.version.FindType(listName); listType != nil {
r.version.AddType(listType)
}
}

// Add the documentation:
Expand Down Expand Up @@ -451,7 +451,6 @@ func (r *Reader) handleClassRef(typ *concepts.Type, path string) {
if len(r.inputs) > 1 {
panic("referenced service with multiple inputs in undefined")
}

input := r.inputs[0]
path = strings.TrimPrefix(path, "/")
components := strings.Split(path, "/")
Expand All @@ -474,25 +473,37 @@ func (r *Reader) handleClassRef(typ *concepts.Type, path string) {
refVersion := refReader.service.FindVersion(names.ParseUsingSeparator(referencedVersion, "_"))
// Once loading the service, we find the reference type
// then recursively iterate the type tree and add the types to the current version.
for _, referencedType := range refVersion.Types() {
if strings.Compare(referencedType.Name().String(), referencedTypeName) == 0 {
r.recursivelyAddTypeToVersion(typ, referencedType)
}
if referencedType := refVersion.FindType(names.ParseUsingSeparator(referencedTypeName, "_")); referencedType != nil {
r.recursivelyAddTypeToVersion(typ, referencedType)
}
}

// A helper function to recursively add types to a version
func (r *Reader) recursivelyAddTypeToVersion(currType *concepts.Type,
referencedType *concepts.Type) {
if referencedType.IsBasicType() {
return
}
for _, attribute := range referencedType.Attributes() {
if attribute.Link() {
r.version.AddTypeWithoutOwner(attribute.Type())
}
if attribute.Type().IsList() || attribute.Type().IsMap() {
r.version.AddTypeWithoutOwner(attribute.Type())
r.version.AddTypeWithoutOwner(attribute.Type().Element())
}
if r.version.FindType(attribute.Type().Name()) == nil {
if attribute.Type().IsList() {
if r.version.FindType(attribute.Type().Element().Name()) == nil {
r.version.AddTypeWithoutOwner(attribute.Type())
r.version.AddTypeWithoutOwner(attribute.Type().Element())
} else {
elementOwner := r.version.FindType(attribute.Type().Element().Name()).Owner()
if attribute.Type().Owner() != elementOwner {
attribute.Type().SetOwner(elementOwner)
attribute.Type().Element().SetOwner(elementOwner)
}
}
} else if r.version.FindType(attribute.Type().Name()) == nil {
r.version.AddTypeWithoutOwner(attribute.Type())
}
} else if attribute.Type().IsList() || attribute.Type().IsMap() {
r.version.AddType(attribute.Type())
r.recursivelyAddTypeToVersion(currType, attribute.Type().Element())
} else {
r.recursivelyAddTypeToVersion(currType, attribute.Type())
}
}
Expand Down
210 changes: 210 additions & 0 deletions pkg/language/ref_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
Copyright (c) 2024 Red Hat, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package language

import (
"github.com/openshift-online/ocm-api-metamodel/pkg/names"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("Read Model with ref annotation", func() {

It("Reads referenced class scalar attribute", func() {
model := MakeModel(
"my_service/v1_alpha1/root.model",
`
resource Root {
}
`,
"my_service/v1_alpha1/my_class.model",
`
@ref(path="other_service/v1/my_class")
class MyClass {
}
`,
"other_service/v1/root.model",
`
resource Root{
}
`,
"other_service/v1/my_class.model",
`
class MyClass {
MyAttribute Integer
}
`,
)
// Check the attribute and its owner
service := model.FindService(names.ParseUsingSeparator("my_service", "_"))
Expect(service).ToNot(BeNil())
version := service.FindVersion(names.ParseUsingSeparator("v1_alpha1", "_"))
Expect(version).ToNot(BeNil())
class := version.FindType(names.ParseUsingCase("MyClass"))
Expect(class).ToNot(BeNil())
attribute := class.FindAttribute(names.ParseUsingCase("MyAttribute"))
Expect(attribute).ToNot(BeNil())
Expect(attribute.Type().Owner().Name().String()).To(Equal("v1"))
})

It("References respect link attribute", func() {
model := MakeModel(
"my_service/v1_alpha1/root.model",
`
resource Root {
}
`,
"my_service/v1_alpha1/my_class.model",
`
@ref(path="other_service/v1/my_class")
class MyClass {
}
`,
"other_service/v1/root.model",
`
resource Root{
}
`,
"other_service/v1/my_class.model",
`
class MyClass {
link MyAttribute MyAttribute
}
`,
"other_service/v1/my_attribute.model",
`
class MyAttribute{
}
`,
)
// Check the attribute and its owner
service := model.FindService(names.ParseUsingSeparator("my_service", "_"))
Expect(service).ToNot(BeNil())
version := service.FindVersion(names.ParseUsingSeparator("v1_alpha1", "_"))
Expect(version).ToNot(BeNil())
class := version.FindType(names.ParseUsingCase("MyClass"))
Expect(class).ToNot(BeNil())
myAttribute := class.FindAttribute(names.ParseUsingCase("MyAttribute"))
Expect(myAttribute).ToNot(BeNil())
Expect(myAttribute.Type().Owner().Name().String()).To(Equal("v1"))
Expect(myAttribute.Link()).To(BeTrue())
})

It("Reads referenced class list attribute", func() {
model := MakeModel(
"my_service/v1_alpha1/root.model",
`
resource Root {
}
`,
"my_service/v1_alpha1/my_class.model",
`
@ref(path="other_service/v1/my_class")
class MyClass {
}
`,
"other_service/v1/root.model",
`
resource Root{
}
`,
"other_service/v1/my_class.model",
`
class MyClass {
Foo []MyAttribute
}`,
"other_service/v1/my_attribute.model",
`
class MyAttribute{
}
`,
)
// Check the attribute and its owner
service := model.FindService(names.ParseUsingSeparator("my_service", "_"))
Expect(service).ToNot(BeNil())
version := service.FindVersion(names.ParseUsingSeparator("v1_alpha1", "_"))
Expect(version).ToNot(BeNil())
class := version.FindType(names.ParseUsingCase("MyClass"))
Expect(class).ToNot(BeNil())
attributeType := version.FindType(names.ParseUsingCase("MyAttribute"))
Expect(attributeType).ToNot(BeNil())
Expect(attributeType.Owner().Name().String()).To(Equal("v1_alpha1"))
attributeList := class.FindAttribute(names.ParseUsingCase("Foo"))
Expect(attributeList).ToNot(BeNil())
Expect(attributeList.Type().IsList()).To(BeTrue())
Expect(attributeList.Type().Owner().Name().String()).To(Equal("v1_alpha1"))
})

It("Overrides class with other class definition", func() {
model := MakeModel(
"my_service/v1_alpha1/root.model",
`
resource Root {
}
`,
"my_service/v1_alpha1/my_class.model",
`
@ref(path="other_service/v1/my_class")
class MyClass {
}
`,
"my_service/v1_alpha1/my_attribute.model",
`
@ref(path="other_service/v1/my_attribute")
class MyAttribute {
}
`,
"other_service/v1/root.model",
`
resource Root{
}
`,
"other_service/v1/my_class.model",
`
class MyClass {
link Foo []MyAttribute
}`,
"other_service/v1/my_attribute.model",
`
class MyAttribute{
Goo Bar
}
`,
"other_service/v1/bar.model",
`
class Bar {
}
`,
)
// Check the attribute and its owner
service := model.FindService(names.ParseUsingSeparator("my_service", "_"))
Expect(service).ToNot(BeNil())
version := service.FindVersion(names.ParseUsingSeparator("v1_alpha1", "_"))
Expect(version).ToNot(BeNil())
class := version.FindType(names.ParseUsingCase("MyClass"))
Expect(class).ToNot(BeNil())
Expect(class.Owner().Name().String()).To(Equal("v1_alpha1"))
attributeList := class.FindAttribute(names.ParseUsingCase("Foo"))
Expect(attributeList).ToNot(BeNil())
Expect(attributeList.Type().IsList()).To(BeTrue())
Expect(attributeList.Type().Owner().Name().String()).To(Equal("v1_alpha1"))
Expect(attributeList.Type().Element().Owner().Name().String()).To(Equal("v1_alpha1"))
barType := version.FindType(names.ParseUsingCase("Bar"))
Expect(barType.Owner().Name().String()).To(Equal("v1_alpha1"))
})
})
42 changes: 42 additions & 0 deletions tests/model/aro_hcp/v1_alpha1/cluster_resource.model
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
Copyright (c) 2024 Red Hat, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Manages a specific cluster.
resource Cluster {
// Retrieves the details of the cluster.
method Get {
out Body Cluster
}

// Updates the cluster.
method Update {
in out Body Cluster
}

// Deletes the cluster.
method Delete {
// Dry run flag is used to check if the operation can be completed, but won't delete.
in DryRun Boolean = false

// BestEffort flag is used to check if the cluster deletion should be best-effort mode or not.
in BestEffort Boolean = false
}

// Reference to the resource that manages the collection of node pool resources.
locator NodePools {
target NodePools
}
}
19 changes: 19 additions & 0 deletions tests/model/aro_hcp/v1_alpha1/cluster_type.model
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
Copyright (c) 2024 Red Hat, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

@ref(path = "/clusters_mgmt/v1/cluster")
class Cluster {
}
Loading

0 comments on commit e4374af

Please sign in to comment.