/// <summary> /// Fetches the corresponding object definition for every object reference. /// </summary> /// <param name="objects"></param> /// <param name="resOpt"></param> internal void ResolveObjectDefinitions(ResolveOptions resOpt) { ResolveContext ctx = this.Ctx as ResolveContext; resOpt.IndexingDoc = this; foreach (var obj in this.InternalObjects) { switch (obj.ObjectType) { case CdmObjectType.AttributeRef: case CdmObjectType.AttributeGroupRef: case CdmObjectType.AttributeContextRef: case CdmObjectType.DataTypeRef: case CdmObjectType.EntityRef: case CdmObjectType.PurposeRef: case CdmObjectType.TraitRef: ctx.RelativePath = obj.DeclaredPath; CdmObjectReferenceBase reff = obj as CdmObjectReferenceBase; if (CdmObjectReferenceBase.offsetAttributePromise(reff.NamedReference) < 0) { CdmObjectDefinition resNew = reff.FetchObjectDefinition <CdmObjectDefinition>(resOpt); if (resNew == null) { // It's okay if references can't be resolved when shallow validation is enabled. if (resOpt.ShallowValidation) { Logger.Warning(ctx, Tag, nameof(ResolveObjectDefinitions), this.AtCorpusPath, CdmLogCode.WarnResolveReferenceFailure, reff.NamedReference); } else { Logger.Error(ctx, Tag, nameof(ResolveObjectDefinitions), this.AtCorpusPath, CdmLogCode.ErrResolveReferenceFailure, reff.NamedReference); // don't check in this file without both of these comments. handy for debug of failed lookups // CdmObjectDefinitionBase resTest = ref.FetchObjectDefinition(resOpt); } } else { Logger.Info(ctx, Tag, nameof(ResolveObjectDefinitions), this.AtCorpusPath, $"resolved '{reff.NamedReference}'"); } } break; case CdmObjectType.ParameterDef: // when a parameter has a datatype that is a cdm object, validate that any default value is the // right kind object CdmParameterDefinition parameter = obj as CdmParameterDefinition; parameter.ConstTypeCheck(resOpt, this, null); break; } } resOpt.IndexingDoc = null; }
internal CdmObject FetchObjectFromDocumentPath(string objectPath, ResolveOptions resOpt) { // in current document? if (this.InternalDeclarations.ContainsKey(objectPath)) { return(this.InternalDeclarations[objectPath]); } else { // this might be a request for an object def drill through of a reference. // path/(object)/paths // there can be several such requests in one path AND some of the requested // defintions might be defined inline inside a reference meaning the declared path // includes that reference name and could still be inside this document. example: // /path/path/refToInline/(object)/member1/refToSymbol/(object)/member2 // the full path is not in this doc but /path/path/refToInline/(object)/member1/refToSymbol // is declared in this document. we then need to go to the doc for refToSymbol and // search for refToSymbol/member2 // work backward until we find something in this document int lastObj = objectPath.LastIndexOf("/(object)"); string thisDocPart = objectPath; while (lastObj > 0) { thisDocPart = objectPath.Substring(0, lastObj); if (this.InternalDeclarations.ContainsKey(thisDocPart)) { CdmObjectReferenceBase thisDocObjRef = this.InternalDeclarations[thisDocPart] as CdmObjectReferenceBase; CdmObjectDefinitionBase thatDocObjDef = thisDocObjRef.FetchObjectDefinition <CdmObjectDefinitionBase>(resOpt); if (thatDocObjDef != null) { // get from other document. // but first fix the path to look like it is relative to that object as declared in that doc string thatDocPart = objectPath.Substring(lastObj + "/(object)".Length); thatDocPart = $"{thatDocObjDef.DeclaredPath}{thatDocPart}"; if (thatDocPart == objectPath) { // we got back to were we started. probably because something is just not found. return(null); } return(thatDocObjDef.InDocument.FetchObjectFromDocumentPath(thatDocPart, resOpt)); } return(null); } lastObj = thisDocPart.LastIndexOf("/(object)"); } } return(null); }