private bool TryReadElementString(string elementName, bool mustEndInWhitespace) { var fileContents = streamReader.Text; var readTo = streamReader.ReadIndex + elementName.Length; var eof = readTo == fileContents.Length; if (readTo <= fileContents.Length) { if (StringEqual(fileContents.Substring(streamReader.ReadIndex, elementName.Length), elementName)) { if (!mustEndInWhitespace || eof || FortranParseHelper.IsWhiteSpace(fileContents[streamReader.ReadIndex + elementName.Length])) { streamReader.ReadIndex += elementName.Length; if (!eof && fileContents[streamReader.ReadIndex] != '\n') { streamReader.ReadIndex += 1; //plus space } return(true); } } } return(false); }
private static LocationInFile FindFirstLocationOfElementNameInLines(IMember member, string variableName, string[] allLines, ref int lineHint) { for (var i = lineHint; i < allLines.Length; i++) { var line = allLines[i]; var startIndex = 0; int indexInLine; do { indexInLine = line.IndexOf(variableName, startIndex, StringComparison.InvariantCultureIgnoreCase); startIndex = indexInLine + 2; //+1 = space, so at least +2 if (indexInLine >= 0) { if (indexInLine > 0 && FortranParseHelper.IsWordCharacter(line[indexInLine - 1])) { continue; //part of other string } var endOfNameIndex = indexInLine + variableName.Length; if (endOfNameIndex < line.Length && FortranParseHelper.IsWordCharacter(line[endOfNameIndex])) { continue; } lineHint = i; return(new LocationInFile(member.Location.Line + i, indexInLine, -1)); } } while (indexInLine >= 0 && startIndex < line.Length); //while matches in line } throw new ArgumentException(string.Format("Cannot find variable {0} in variable declarations, in file {1}", variableName, member.Root.CodeFile.ProjectName)); }
private bool CheckNotFalsePositive(string line, int matchOffset, string searchString) { if (matchOffset > 0) { //begin of match is begin of word var previousChar = line[matchOffset - 1]; if (FortranParseHelper.IsWordCharacter(previousChar)) { return(false); } } var endOfMatch = searchString.Length + matchOffset; if (endOfMatch < line.Length) { //end of match is end of word var nextChar = line[endOfMatch]; if (FortranParseHelper.IsWordCharacter(nextChar)) { return(false); } } return(!FortranParseHelper.IsIndexInsideCharacterString(line, matchOffset)); }
public string FindEffectiveStatementAtOffset(string line, int offsetInLine, out int beginOfStatement) { var endOfStatement = offsetInLine - 1; var parenthesisLevel = 0; int i; var statement = new StringBuilder(); for (i = endOfStatement; i >= 0; i--) { var c = line[i]; if (c == ')') { if (statement.Length == 0) { break; } parenthesisLevel++; } else if (parenthesisLevel > 0) { //next if (c == '(') { parenthesisLevel--; } } else { if (FortranParseHelper.IsNonStatementCharacter(c)) { break; } else { statement.Insert(0, c); } } } beginOfStatement = i + 1; var originalBegin = beginOfStatement; for (int j = 0; j < statement.Length; j++) { var c = statement[j]; if (FortranParseHelper.IsWhiteSpace(c)) { beginOfStatement++; } else { break; } } return(statement.ToString().Substring(beginOfStatement - originalBegin)); }
private bool TryReadType(string memberName, SyntaxTree sourceAST, ref IMember parentMember) { //todo: we're not skipping comments in this code if (IsMemberExpected <Type>(parentMember) && TryReadElementString(memberName, false)) { var remainingLine = FortranParseHelper.GetStringUptoEndOfLineOrBeginOfComment(streamReader.Text, streamReader.ReadIndex - 1); var skip = false; if (remainingLine.IndexOf("(") >= 0) { //type use, not a type declaration } else { var indexOfDoubleDots = remainingLine.IndexOf("::"); if (indexOfDoubleDots >= 0) { streamReader.ReadIndex--; //read back one streamReader.ReadIndex += indexOfDoubleDots + 2; char c = streamReader.Text[streamReader.ReadIndex]; while (FortranParseHelper.IsWhiteSpace(c)) //skip whitespace { c = streamReader.Text[++streamReader.ReadIndex]; } } else { //expect whitespace if (!FortranParseHelper.IsWhiteSpace(streamReader.Text[streamReader.ReadIndex - 1])) { skip = true; } } if (!skip) { var name = streamReader.ReadElementName(); if (!String.IsNullOrEmpty(name)) { OnMemberFound <Type>(ref parentMember, name, sourceAST); return(true); } } } } return(TryReadEndOfMember <Type>(ref parentMember, memberName)); }
public IEnumerable <LocationInFile> FindInFileContents(MemberOrSearchTerm memberUsageToFind, string fileContents) { var results = new List <LocationInFile>(); //remove comments: var cleanedLines = FortranParseHelper.CleanLines(fileContents.Split('\n'), false, false).ToList(); int lineNr = 0; foreach (var line in cleanedLines) { lineNr++; SearchInLine(line, memberUsageToFind.Name, lineNr, results); } return(results); }
public IEnumerable <UsageResult> FindInFile(MemberOrSearchTerm memberUsageToFind, SyntaxTree syntaxTree) { var results = new List <UsageResult>(); var fileContents = syntaxTree.CodeFile.Contents; var locations = FindInFileContents(memberUsageToFind, fileContents); foreach (var location in locations) { var enclosingMember = FortranParseHelper.GetEnclosingMember(syntaxTree.Members, location.Line); if (enclosingMember != null && enclosingMember == memberUsageToFind.Member) { continue; //definition/declaration, not usage } results.Add(new UsageResult(syntaxTree, location, enclosingMember, location.LineStr)); } return(results); }
public string FindMethodAtOffset(string currentLine, int currentIndex) { var parenthesisLevel = 0; var functionEnd = -1; for (int i = currentIndex - 1; i >= 0; i--) { var c = currentLine[i]; if (c == ')') { parenthesisLevel++; } else if (c == '(') { parenthesisLevel--; if (parenthesisLevel == -1) { functionEnd = i; break; } } } if (functionEnd >= 0) { var lineWithFunctionName = currentLine.Substring(0, functionEnd).TrimEnd(); var methodName = ""; try { var beginOfMethodName = -1; methodName = FortranParseHelper.GetElementName(lineWithFunctionName, lineWithFunctionName.Length - 1, out beginOfMethodName); } catch (Exception e) { Log.Error(String.Format("GetElementName failed (line: {0})", lineWithFunctionName), e); } return(methodName); } return(null); }
private bool TryReadEndOfMember <T>(ref IMember parentMember, string memberName) { if (!(parentMember is T)) { return(false); } if (TryReadElementString("end " + memberName, true)) { HandleEndOfMember(ref parentMember); return(true); } //endsubroutine (for example) without space is also valid f90: if (TryReadElementString("end" + memberName, true)) { HandleEndOfMember(ref parentMember); return(true); } if (TryReadElementString("end", true)) { var remainingLine = FortranParseHelper.GetStringUptoEndOfLineOrBeginOfComment(streamReader.Text, streamReader.ReadIndex); if (String.IsNullOrEmpty(remainingLine)) { HandleEndOfMember(ref parentMember); return(true); } else { var trimmedLine = remainingLine.TrimStart(); var charsToSkip = remainingLine.Length - trimmedLine.Length; streamReader.ReadIndex += charsToSkip; if (TryReadElementString(memberName, true)) { HandleEndOfMember(ref parentMember); return(true); } } } return(false); }
public string ReadElementName() { bool nameStarted = false; var start = ReadIndex; for (ReadIndex = start; ReadIndex < Text.Length; ReadIndex++) { var c = Text[ReadIndex]; if (!nameStarted && c == ' ') //skip spaces in front of name { start++; continue; } nameStarted = true; if (FortranParseHelper.IsWhiteSpace(c)) //quick loop { //end of name break; } if (!FortranParseHelper.IsWordCharacter(c)) { //non valid name characters: end of name break; } } if (ReadIndex < Text.Length) { var name = Text.Substring(start, ReadIndex - start); if (!String.IsNullOrEmpty(name)) { ReadIndex--; } return(name); } return(""); }
public void ParseMethodSignature(IMethod method) { if (method.Parameters != null) { return; //already set } var lines = FortranParseHelper.CleanLinesAndMerge(FortranParseHelper.ExtractMemberLines(method), false, true); var firstLine = lines.FirstOrDefault(); if (firstLine == null) { throw new ArgumentException("Empty header"); } if (!firstLine.StartsWith(method.Name, StringComparison.InvariantCultureIgnoreCase)) { throw new ArgumentException("Signature does not start with method name"); } var parameterString = firstLine.Substring(method.Name.Length); var resultKeyword = " result"; var indexOfResult = parameterString.IndexOf(resultKeyword, StringComparison.InvariantCultureIgnoreCase); if (indexOfResult >= 0) { var resultString = parameterString.Substring(indexOfResult + resultKeyword.Length); parameterString = parameterString.Substring(0, indexOfResult); method.ResultVariableName = RemoveUndesiredCharacters(resultString).Trim(); } parameterString = RemoveUndesiredCharacters(parameterString); var parameters = parameterString.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries); var parameterList = new List <Variable>(); foreach (var parameter in parameters) { var parameterName = parameter.Trim(); if (String.IsNullOrEmpty(parameterName)) { continue; } var matchingDeclaration = FindDeclaration(method, parameterName); if (matchingDeclaration == null) { if (method.ImplicitNone) { throw new ArgumentException(String.Format("Could not find matching declaration in method {0} for parameter {1}, while implicit none is true.", method.Name, parameterName)); } } else { parameterList.Add(new Variable { Name = parameterName, Member = method, TypeString = matchingDeclaration.TypeString, IsBuildInType = matchingDeclaration.IsBuildInType }); } } method.SetParameters(parameterList); }
private static string RemoveBetweenSlashes(string input) { return(FortranParseHelper.RemoveBetweenCharacter(input, '/')); }
public void ParseDeclarationsAndUses(IMember member) { if (member.LocalVariables.Any() || member.Uses.Any()) { return; //already parsed (on file modification they are cleared) } member.ClearLocalVariables(); member.ClearUses(); var memberLines = FortranParseHelper.ExtractMemberLines(member); var cleanedLines = FortranParseHelper.CleanLines(memberLines, false, false).ToArray(); var mergedLines = FortranParseHelper.CleanLinesAndMerge(memberLines, true, true); var lineHint = 1; foreach (var line in mergedLines) { if (TryReadAndEat("#", line)) //preprocessor directives { continue; } if (TryReadAndEat("private", line)) //preprocessor directives { continue; } if (TryReadAndEat("public", line)) //preprocessor directives { continue; } if (TryReadAndEat("write", line)) //allowed?!?!?! { continue; } if (TryReadAndEat("implicit ", line)) { if (line.IndexOf("none", StringComparison.InvariantCultureIgnoreCase) >= 0) { member.ImplicitNone = true; } continue; } if (TryReadUses(member, line)) { continue; } if (TryReadVariableDeclaration(member, line, cleanedLines, ref lineHint)) { continue; } if (TryReadAndEat("parameter", line)) { continue; } if (TryReadAndEat("data", line)) { continue; } if (TryReadAndEat("common", line)) { continue; } if (TryReadAndEat("save", line)) { continue; } if (TryReadAndEat("intent", line)) { continue; } if (TryReadAndEat("include", line)) { continue; } //if we get here, it's the end of variable declarations because the line is non-empty and //non-commment, yet doesn't start with an expected string (variable, implicit, etc) break; } }
public bool SkipToNextPotentialCodeElement() { if (lastIndexVisited == ReadIndex) { ReadIndex++; //continue to next character if we already got here } var start = ReadIndex; for (ReadIndex = start; ReadIndex < Text.Length; ReadIndex++) { var c = Text[ReadIndex]; if (c == '\n') { LineNumber++; StartOfLineIndex = ReadIndex + 1; } if (FortranParseHelper.IsWhiteSpace(c)) { continue; //shortcut } if (!insideCharacterString && c == '"') { insideQuoteString = !insideQuoteString; //toggle continue; } if (!insideQuoteString && c == '\'') { insideCharacterString = !insideCharacterString; //toggle continue; } if (!insideCharacterString && !insideQuoteString) { //read comment if (c == '!') { SeekEndOfLine(); //skip comments continue; } if (Style == FortranStyle.Fortran77 && ReadIndex == StartOfLineIndex && (c == 'c' || c == 'C' || c == '*')) { SeekEndOfLine(); //skip comments (f77 style?) continue; } var previousCharWasWhitespace = (ReadIndex > 0) ? FortranParseHelper.IsWhiteSpace(Text[ReadIndex - 1]) : true; if (!previousCharWasWhitespace) //still inside a word { continue; } //this would improve performance and simply some things, but unfortunately the keywords //we're looking for are not always the first word on the line. For example the 'function' //keyword can be prefixed by a type. //if (beginOfLineOnly && lastVisitedLine == LineNumber) // continue; lastIndexVisited = ReadIndex; return(true); } } return(false); //eof }