/* Function: ScoreUsingInterpretation * A function used by <ScoreInterpretation()> to determine the C and S fields of the score for the passed interpretation * using only the using statements. Only those fields and the trailing 1 will be set in the returned score. If the interpretation * doesn't match using the using statements, it will return zero. */ private long ScoreUsingInterpretation(Topic topic, Link link, SymbolString interpretation) { // --C----- -------- -------- -SSSSSSS SSS----- -------- -------- -------1 // C - Whether the topic and link's capitalization match if it matters to the language. // S - How high on the scope list the symbol match is. IList <UsingString> usingStrings = link.Context.GetUsingStatements(); if (usingStrings == null || usingStrings.Count == 0) { return(0); } Language topicLanguage = EngineInstance.Languages.FromID(topic.LanguageID); CommentType commentType = EngineInstance.CommentTypes.FromID(topic.CommentTypeID); // Values of C: // Natural Docs links: // 1 - Topic is documentation, case matches // 1 - Topic is documentation, case differs // 1 - Topic is file, case matches // 1 - Topic is file, case differs // 1 - Topic is code, topic language is case sensitive, case matches // 0 - Topic is code, topic language is case sensitive, case differs // 1 - Topic is code, topic language is case insensitive, case matches // 1 - Topic is code, topic language is case insensitive, case differs // Type/Class Parent links: // Assuming they're the same language... // X - Topic is documentation, case matches // X - Topic is documentation, case differs // X - Topic is file, case matches // X - Topic is file, case differs // 1 - Topic is code, language is case sensitive, case matches // X - Topic is code, language is case sensitive, case differs // 1 - Topic is code, language is case insensitive, case matches // 1 - Topic is code, language is case insensitive, case differs bool caseFlagged; bool caseRequired; if (link.Type == LinkType.NaturalDocs) { caseRequired = false; caseFlagged = (commentType.IsCode && topicLanguage.CaseSensitive); } else { if (commentType.IsCode == false) { return(0); } caseRequired = topicLanguage.CaseSensitive; caseFlagged = false; } // Find the scope list index to start at, since the actual scopes come before the using statements. // Scope list: // 0 - A.B.C.Link // 1 - A.B.Link // 2 - A.Link // 3 - Link // 4 - Link + first using statement // So if there's a scope, the starting index is the number of separators in the scope + 2. Otherwise it's one. // Scope list: // 0 - Link // 1 - Link + first using statement int scopeListIndex; if (link.Context.ScopeIsGlobal) { scopeListIndex = 1; } else { int scopeIndex, scopeLength; link.Context.GetRawTextScope(out scopeIndex, out scopeLength); scopeListIndex = link.Context.RawText.Count(SymbolString.SeparatorChar, scopeIndex, scopeLength) + 2; } // Go through each using statement looking for the best score. long bestScore = 0; foreach (var usingString in usingStrings) { SymbolString newInterpretation; bool newInterpretationPossible; if (usingString.Type == UsingString.UsingType.AddPrefix) { newInterpretation = usingString.PrefixToAdd + interpretation; newInterpretationPossible = true; } else if (usingString.Type == UsingString.UsingType.ReplacePrefix) { SymbolString prefixToRemove = usingString.PrefixToRemove; string prefixToRemoveString = prefixToRemove.ToString(); string interpretationString = interpretation.ToString(); if (interpretationString.Length > prefixToRemoveString.Length && interpretation.StartsWith(prefixToRemove, !caseRequired)) { newInterpretation = usingString.PrefixToAdd + SymbolString.FromExportedString(interpretationString.Substring(prefixToRemoveString.Length + 1)); newInterpretationPossible = true; } else { newInterpretation = new SymbolString(); // to make the compiler shut up newInterpretationPossible = false; } } else { throw new NotImplementedException(); } if (newInterpretationPossible && string.Compare(newInterpretation, topic.Symbol, !caseRequired) == 0) { // --C----- -------- -------- -SSSSSSS SSS----- -------- -------- -------1 // Our baseline. long score = 0x0000000000000001; // --C----- -------- -------- -SSSSSSS SSS----- -------- -------- -------= // Encode the scope index. We want lower indexes to have a higher score. if (scopeListIndex > 1023) { scopeListIndex = 1023; } long scopeListBits = 1023 - scopeListIndex; scopeListBits <<= 29; score |= scopeListBits; // --C----- -------- -------- -======= ===----- -------- -------- -------= // Determine C. If C is set we can quit early because it would be impossible for a later using statement to // generate a higher score. if (!caseFlagged || string.Compare(newInterpretation, topic.Symbol, false) == 0) { score |= 0x2000000000000000; bestScore = score; break; } else { if (score > bestScore) { bestScore = score; } } } scopeListIndex++; } return(bestScore); }