public static ServiceMemberInfo GetMemberReferencedAtPosition(this ServiceInfo service, Position requestPosition) { return(( from field in service.GetDescendants().OfType <ServiceFieldInfo>() let part = field.GetPart(ServicePartKind.TypeName) where part != null && requestPosition >= part.Position && requestPosition < part.EndPosition let type = service.GetFieldType(field) where type != null let name = type.GetMemberTypeName() where name != null select service.FindMember(name)).FirstOrDefault()); }
/// <summary> /// Implements TryParseDefinition. /// </summary> protected override bool TryParseDefinitionCore(ServiceDefinitionText source, out ServiceInfo service, out IReadOnlyList <ServiceDefinitionError> errors) { var errorList = new List <ServiceDefinitionError>(); var definitionLines = new List <string>(); var remarksSectionsByName = new Dictionary <string, FsdRemarksSection>(StringComparer.OrdinalIgnoreCase); var interleavedRemarksSections = new List <FsdRemarksSection>(); if (!s_interleavedMarkdown.IsMatch(source.Text)) { ReadRemarksAfterDefinition(source, definitionLines, remarksSectionsByName, errorList); } else { ReadInterleavedRemarks(source, definitionLines, interleavedRemarksSections, errorList); } source = new ServiceDefinitionText(source.Name, string.Join("\n", definitionLines)); service = null; try { service = FsdParsers.ParseDefinition(source, remarksSectionsByName); errorList.AddRange(service.GetValidationErrors()); // check for unused remarks sections foreach (var remarksSectionPair in remarksSectionsByName) { string sectionName = remarksSectionPair.Key; if (service.Name != sectionName && service.FindMember(sectionName) == null) { errorList.Add(new ServiceDefinitionError($"Unused remarks heading: {sectionName}", remarksSectionPair.Value.Position)); } } // check for interleaved remarks sections foreach (var remarksSection in interleavedRemarksSections) { var remarksLineNumber = remarksSection.Position.LineNumber; if (remarksLineNumber > service.GetPart(ServicePartKind.Name).Position.LineNumber&& remarksLineNumber < service.GetPart(ServicePartKind.End).Position.LineNumber) { ServiceMemberInfo targetMember = service; int targetLineNumber = 0; foreach (var member in service.Members) { int memberLineNumber = member.GetPart(ServicePartKind.Name).Position.LineNumber; if (remarksLineNumber > memberLineNumber && memberLineNumber > targetLineNumber) { targetMember = member; targetLineNumber = memberLineNumber; } } if (targetMember.Remarks.Count == 0) { targetMember.Remarks = remarksSection.Lines; } else { targetMember.Remarks = targetMember.Remarks.Concat(new[] { "" }).Concat(remarksSection.Lines).ToList(); } } } } catch (ParseException exception) { var expectation = exception .Result .GetNamedFailures() .Distinct() .GroupBy(x => x.Position) .Select(x => new { LineColumn = x.Key.GetLineColumn(), Names = x.Select(y => y.Name) }) .OrderByDescending(x => x.LineColumn.LineNumber) .ThenByDescending(x => x.LineColumn.ColumnNumber) .First(); int getExpectationNameRank(string name) => name == "')'" || name == "']'" || name == "'}'" || name == "';'" ? 1 : 2; errorList.Add(new ServiceDefinitionError( "expected " + string.Join(" or ", expectation.Names.Distinct().OrderBy(getExpectationNameRank).ThenBy(x => x, StringComparer.Ordinal)), new ServiceDefinitionPosition(source.Name, expectation.LineColumn.LineNumber, expectation.LineColumn.ColumnNumber))); } errors = errorList; return(errorList.Count == 0); }