protected CodeStatementCollection CreateMethodSignature(CodeTypeDeclaration tgtType, GMethod method, bool isProxy) { bool add = true; CodeStatementCollection tgtStatements; CodeTypeMember tgtMember; CodeMemberMethod tgtMethod = null; CodeMemberPropertyEx tgtProperty; CodeMemberPropertyEx tgtEvent; if (method.IsConstructor) { var tgtConstructor = new CodeConstructor(); tgtMethod = tgtConstructor; tgtMember = tgtMethod; tgtStatements = tgtMethod.Statements; if (!type.IsRootType) { tgtConstructor.BaseConstructorArgs.Add( new CodeCastExpression(TypeReference("net.sf.jni4net.jni.JNIEnv"), new CodePrimitiveExpression(null))); } } else if (method.IsField) { var p = new CodeMemberProperty(); tgtMember = p; tgtStatements = p.GetStatements; p.Name = method.CLRName; p.Type = method.ReturnType.CLRReference; } else if (method.IsEvent) { tgtEvent = new CodeMemberPropertyEx(); tgtEvent.Getter = method.CLRPropertyAdd; tgtEvent.Setter = method.CLRPropertyRemove; tgtEvent.Name = method.CLRName; if (method.UseExplicitInterface) { tgtEvent.PrivateImplementationType = method.DeclaringType.CLRReference; } foreach (CodeTypeMember m in tgtType.Members) { var member = m as CodeMemberPropertyEx; if (member != null) { if (member.Getter == method || member.Setter == method) { tgtEvent = member; add = false; break; } } } int count = method.Parameters.Count - 1; tgtEvent.Type = method.Parameters[count].CLRReference; if (add) { for (int i = 0; i < count; i++) { var tgtParameter = new CodeParameterDeclarationExpression(); tgtParameter.Name = method.ParameterNames[i]; tgtParameter.Type = method.Parameters[i].CLRReference; tgtEvent.Parameters.Add(tgtParameter); } tgtEvent.Comments.Add(new CodeCommentStatement("__event__")); } tgtMember = tgtEvent; if (method.IsCLRPropertyAdd) { tgtEvent.GetStatements.Add(new CodeCommentStatement("__add__")); tgtStatements = tgtEvent.GetStatements; } else { tgtEvent.SetStatements.Add(new CodeCommentStatement("__remove__")); tgtStatements = tgtEvent.SetStatements; } } else if (method.IsProperty) { tgtProperty = new CodeMemberPropertyEx(); tgtProperty.Setter = method.CLRPropertySetter; tgtProperty.Getter = method.CLRPropertyGetter; tgtProperty.Name = method.CLRName; if (method.UseExplicitInterface) { tgtProperty.PrivateImplementationType = method.DeclaringType.CLRReference; } foreach (CodeTypeMember m in tgtType.Members) { var member = m as CodeMemberPropertyEx; if (member != null) { if (member.Getter == method || member.Setter == method) { tgtProperty = member; add = false; break; } } } int count = method.Parameters.Count; if (!method.IsCLRPropertyGetter) { count--; } if (add) { for (int i = 0; i < count; i++) { var tgtParameter = new CodeParameterDeclarationExpression(); tgtParameter.Name = method.ParameterNames[i]; tgtParameter.Type = method.Parameters[i].CLRReference; tgtProperty.Parameters.Add(tgtParameter); } } if (method.IsCLRPropertyGetter) { tgtProperty.Type = method.ReturnType.CLRReference; tgtStatements = tgtProperty.GetStatements; } else { tgtProperty.Type = method.Parameters[count].CLRReference; tgtStatements = tgtProperty.SetStatements; } tgtMember = tgtProperty; } else { tgtMethod = new CodeMemberMethod(); tgtMethod.Name = method.CLRName; tgtMethod.ReturnType = method.ReturnType.CLRReference; tgtMember = tgtMethod; tgtStatements = tgtMethod.Statements; if (method.UseExplicitInterface) { tgtMethod.PrivateImplementationType = method.DeclaringType.CLRReference; } } if (!config.SkipSignatures && !isProxy) { Utils.AddAttribute(tgtMember, "net.sf.jni4net.attributes.JavaMethodAttribute", method.JVMSignature); } tgtMember.Attributes = method.Attributes; if (isProxy) { tgtMember.Attributes |= MemberAttributes.Final; } if (tgtMethod != null) { GenerateParameters(method, tgtMethod); } if (add) { tgtType.Members.Add(tgtMember); } return(tgtStatements); }
public CodeMemberPropertyEx ResolvePropertyDeclarationCache() { var lang = Language; if(_propertyDecl == null && EnclosingType != null) { CodeTypeDeclarationEx typedecl = EnclosingType; var members = from m in typedecl.GetInheritedMembers() let memberMethod = m as CodeMemberPropertyEx where memberMethod != null && memberMethod.Name.Equals(this.PropertyName, lang.NameComparisation) select memberMethod; if(members.Any()) _propertyDecl = members.First(); } if(_propertyDecl == null) { var doc = CodeDocumentItem; if(doc != null && !(EnclosingType is CodeTypeDeclarationRoot)) { //doc.AST.RootTypeUnSave != EnclosingType var members = from member in doc.AST.RootTypeUnSave.Members.Cast<CodeTypeMember>() let methodMember = member as CodeMemberPropertyEx where methodMember != null && methodMember.Name.Equals(this.PropertyName, lang.NameComparisation) select methodMember; if(members.Any()) _propertyDecl = members.First(); } } return _propertyDecl; }
protected CodeStatementCollection CreateMethodSignature(CodeTypeDeclaration tgtType, GMethod method, bool isProxy) { bool add = true; CodeStatementCollection tgtStatements; CodeTypeMember tgtMember; CodeMemberMethod tgtMethod = null; CodeMemberPropertyEx tgtProperty; CodeMemberPropertyEx tgtEvent; if (method.IsConstructor) { var tgtConstructor = new CodeConstructor(); tgtMethod = tgtConstructor; tgtMember = tgtMethod; tgtStatements = tgtMethod.Statements; if (!type.IsRootType) { tgtConstructor.BaseConstructorArgs.Add( new CodeCastExpression(TypeReference("net.sf.jni4net.jni.JNIEnv"), new CodePrimitiveExpression(null))); } } else if (method.IsField) { var p = new CodeMemberProperty(); tgtMember = p; tgtStatements = p.GetStatements; p.Name = method.CLRName; p.Type = method.ReturnType.CLRReference; } else if (method.IsEvent) { tgtEvent = new CodeMemberPropertyEx(); tgtEvent.Getter = method.CLRPropertyAdd; tgtEvent.Setter = method.CLRPropertyRemove; tgtEvent.Name = method.CLRName; if (method.UseExplicitInterface) { tgtEvent.PrivateImplementationType = method.DeclaringType.CLRReference; } foreach (CodeTypeMember m in tgtType.Members) { var member = m as CodeMemberPropertyEx; if (member != null) if (member.Getter == method || member.Setter == method) { tgtEvent = member; add = false; break; } } int count = method.Parameters.Count-1; tgtEvent.Type = method.Parameters[count].CLRReference; if (add) { for (int i = 0; i < count; i++) { var tgtParameter = new CodeParameterDeclarationExpression(); tgtParameter.Name = method.ParameterNames[i]; tgtParameter.Type = method.Parameters[i].CLRReference; tgtEvent.Parameters.Add(tgtParameter); } tgtEvent.Comments.Add(new CodeCommentStatement("__event__")); } tgtMember = tgtEvent; if (method.IsCLRPropertyAdd) { tgtEvent.GetStatements.Add(new CodeCommentStatement("__add__")); tgtStatements = tgtEvent.GetStatements; } else { tgtEvent.SetStatements.Add(new CodeCommentStatement("__remove__")); tgtStatements = tgtEvent.SetStatements; } } else if (method.IsProperty) { tgtProperty = new CodeMemberPropertyEx(); tgtProperty.Setter = method.CLRPropertySetter; tgtProperty.Getter = method.CLRPropertyGetter; tgtProperty.Name = method.CLRName; if (method.UseExplicitInterface) { tgtProperty.PrivateImplementationType = method.DeclaringType.CLRReference; } foreach (CodeTypeMember m in tgtType.Members) { var member = m as CodeMemberPropertyEx; if (member != null) if (member.Getter == method || member.Setter == method) { tgtProperty = member; add = false; break; } } int count = method.Parameters.Count; if (!method.IsCLRPropertyGetter) { count--; } if (add) { for (int i = 0; i < count; i++) { var tgtParameter = new CodeParameterDeclarationExpression(); tgtParameter.Name = method.ParameterNames[i]; tgtParameter.Type = method.Parameters[i].CLRReference; tgtProperty.Parameters.Add(tgtParameter); } } if (method.IsCLRPropertyGetter) { tgtProperty.Type = method.ReturnType.CLRReference; tgtStatements = tgtProperty.GetStatements; } else { tgtProperty.Type = method.Parameters[count].CLRReference; tgtStatements = tgtProperty.SetStatements; } tgtMember = tgtProperty; } else { tgtMethod = new CodeMemberMethod(); tgtMethod.Name = method.CLRName; tgtMethod.ReturnType = method.ReturnType.CLRReference; tgtMember = tgtMethod; tgtStatements = tgtMethod.Statements; if (method.UseExplicitInterface) { tgtMethod.PrivateImplementationType = method.DeclaringType.CLRReference; } } if (!config.SkipSignatures && !isProxy) { Utils.AddAttribute(tgtMember, "net.sf.jni4net.attributes.JavaMethodAttribute", method.JVMSignature); } tgtMember.Attributes = method.Attributes; if (isProxy) { tgtMember.Attributes |= MemberAttributes.Final; } if (tgtMethod != null) { GenerateParameters(method, tgtMethod); } if (add) { tgtType.Members.Add(tgtMember); } return tgtStatements; }
protected async Task CompileTokenFile(CancellationToken cancellationToken) { try { await TaskEx.Run(() => { _languageRoot = new CodeTypeDeclarationRoot() { Project = _document.Project }; CodeTypeDeclarationEx initialparent = _languageRoot; cancellationToken.ThrowIfCancellationRequested(); _dependingOnSave = this.DependingOn; #region Clean Up _document.Project.Solution.ErrorService.ClearAllErrorsFrom(_document, Errors.ErrorSource.ASTParser); _codeRangeManager.Clear(); #endregion #region Merge DependingOn Members if(_dependingOnSave == null) { // merge super base members _languageRoot.Members.AddRange(_root.Members); firstAfterNull = true; } else { //if(!_project.IsInUpdate) { // if(firstAfterNull) { // ignoreDependingOnce = true; // _dependingOnSave.CompileTokenFileAsync(); // firstAfterNull = false; // } // _dependingOnSave.WaitUntilUpdated(200); //} _languageRoot.Members.AddRange(_dependingOnSave.GetRootTypeSnapshot().Members); } #endregion var codeLineMap = _document.SegmentService.GetCodeSegmentLinesMap(); CodeTypeDeclaration parent = initialparent; Stack<CodeSegment> paramstack = new Stack<CodeSegment>(); int linecnt = 0; if(codeLineMap.Keys.Any()) linecnt = codeLineMap.Keys.Max(); CodeTokenLine line; Stack<CodeTypeDeclarationEx> parentHirarchy = new Stack<CodeTypeDeclarationEx>(); int bcc = 0; parentHirarchy.Push(initialparent); cancellationToken.ThrowIfCancellationRequested(); #region Parse for(int i = 0; i <= linecnt; i++) { cancellationToken.ThrowIfCancellationRequested(); if(codeLineMap.ContainsKey(i)) line = codeLineMap[i]; else continue; // is class definition?: #region Parse Class Definition var classkeywordSegment = line.CodeSegments[0].ThisOrNextOmit(whitespacetokenNewLines); if(classkeywordSegment != null && classkeywordSegment.Token == Token.KeyWord && classkeywordSegment.TokenString.Equals("class", StringComparison.CurrentCultureIgnoreCase)) { var classNameSegment = classkeywordSegment.FindNextOnSameLine(Token.Identifier); if(classNameSegment != null) { var next = classNameSegment.NextOmit(whitespacetokenNewLines); if(next != null) { CodeTypeDeclarationEx thisparent = parentHirarchy.Any() ? parentHirarchy.Peek() : _languageRoot; CodeTypeReferenceEx basecls = null; CodeSegment refBaseClass = null; if(next.Token == Token.KeyWord && next.TokenString.Equals("extends", StringComparison.InvariantCultureIgnoreCase)) { refBaseClass = next.NextOmit(whitespacetokenNewLines); if(refBaseClass != null) { if(refBaseClass.Token == Token.Identifier) { refBaseClass.CodeDOMObject = basecls = new CodeTypeReferenceEx(_document, refBaseClass.TokenString, thisparent); next = refBaseClass.NextOmit(whitespacetokenNewLines); } else { RegisterError(_document, next.Next, "Expected: Class Name Identifier"); next = next.NextOmit(whitespacetokenNewLines); } } else { if(next.Next != null && next.Next.Token != Token.BlockOpen) { RegisterError(_document, next.Next, "Expected: Class Name Identifier"); next = next.NextOmit(whitespacetokenNewLines); } } } if(next != null) { if(next.Token == Token.BlockOpen) { #region Add Class Declaration CodeSegment classBodyStart = next; var type = new CodeTypeDeclarationEx(_document, classNameSegment.TokenString) { IsClass = true, LinePragma = CreatePragma(classNameSegment, _document.FilePath), CodeDocumentItem = _document }; classNameSegment.CodeDOMObject = type; // check if this type was alread defined in this scope if(thisparent.GetInheritedMembers().Contains(type)) { RegisterError(_document, classNameSegment, "oh my dear, this class already exisits in the current scope!"); } else { #region Check & Resolve Baseclass if(basecls != null) { //check if we have a circual interhance tree var baseclassImpl = basecls.ResolveTypeDeclarationCache(); if(baseclassImpl != null && baseclassImpl.IsSubclassOf(new CodeTypeReferenceEx(_document, classNameSegment.TokenString, thisparent))) { //circular dependency detected!! RegisterError(_document, refBaseClass, "Woops you just produced a circular dependency in your inheritance tree!"); } else { if(basecls != null) type.BaseTypes.Add(basecls); else type.BaseTypes.Add(new CodeTypeReferenceEx(_document, "Object", thisparent) { ResolvedTypeDeclaration = _superBase }); } } #endregion // extract class documentation Comment var comment = ExtractComment(classkeywordSegment); if(comment != null) type.Comments.Add(comment); // Add it to the CodeDOM Tree thisparent.Members.Add(type); type.Parent = thisparent; } // Create a CodeRange Item int startOffset = classBodyStart.Range.Offset; var classBodyEnd = classBodyStart.FindClosingBracked(true); if(classBodyEnd != null) { int length = (classBodyEnd.Range.Offset - startOffset); _codeRangeManager.Add(new CodeRange(new SimpleSegment(startOffset, length), type)); } else { RegisterError(_document, classBodyStart, "Expected: " + Token.BlockClosed); } parentHirarchy.Push(type); bcc++; i = classBodyStart.LineNumber; // jumt to: class Foo { * <---| continue; #endregion } else { RegisterError(_document, next, "Expected: " + Token.BlockOpen); i = (next.Next != null) ? next.Next.LineNumber : next.LineNumber; } } } } } #endregion // adjust some asumptions the tokenizer has made if(parentHirarchy.Count > 1) { // if we are in a class body, we can't have a traditional command invoke foreach(var s in line.CodeSegments) if(s.Token == Token.TraditionalCommandInvoke) { s.Token = Token.Identifier; break; } } // is method definition?: #region Analyze for Method Definition var methodSegment = line.CodeSegments[0].ThisOrNextOmit(whitespacetokenNewLines); if(methodSegment != null && methodSegment.Token == Token.Identifier) { var methodSignatureStart = methodSegment.Next; if(methodSignatureStart != null && methodSignatureStart.Token == Token.LiteralBracketOpen) { var methodSignatureEnd = methodSignatureStart.FindClosingBracked(false); if(methodSignatureEnd != null) { var startMethodBody = methodSignatureEnd.NextOmit(whitespacetokenNewLinesComments); if(startMethodBody != null && startMethodBody.Token == Token.BlockOpen) { // jup we have a method definition here. // Method body starts at startMethodBody CodeTypeDeclarationEx thisparent = parentHirarchy.Any() ? parentHirarchy.Peek() : _languageRoot; bool hasDeclarationError = false; #region Generate Method Definition DOM var method = new CodeMemberMethodExAHK(_document) { Name = methodSegment.TokenString, LinePragma = CreatePragma(methodSegment, _document.FilePath), CodeDocumentItem = _document, ReturnType = new CodeTypeReferenceEx(_document, typeof(object)) }; methodSegment.CodeDOMObject = method; //check if this method is not already defined elsewere in current scope var equalmethods = from m in thisparent.Members.Cast<CodeTypeMember>() let meth = m as CodeMemberMethodExAHK where meth != null && !meth.IsBuildInType && meth.Equals(method) select meth; if(equalmethods.Any()) { RegisterError(_document, methodSegment, string.Format("The Methodename '{0}' is already used in the current scope!", method.Name)); hasDeclarationError = true; } else { // extract Method Comment var comment = ExtractComment(methodSegment); if(comment != null) method.Comments.Add(comment); // extract method params paramstack.Clear(); CodeSegment previous = methodSignatureStart; // get method params: while(true) { var current = previous.Next; if(current.Token == Token.Identifier || current.Token == Token.KeyWord) { paramstack.Push(current); } else if(current.Token == Token.ParameterDelemiter || current.Token == Token.LiteralBracketClosed) { // end of param reached: if(paramstack.Count == 1) { // thread one param as the untyped argument, type of Object method.Parameters.Add(new CodeParameterDeclarationExpressionEx(typeof(object), paramstack.Pop().TokenString) { Direction = FieldDirection.In }); } else if(paramstack.Count == 2) { CodeParameterDeclarationExpressionEx param; var second = paramstack.Pop(); var first = paramstack.Pop(); //handle byref -> if(first.Token == Token.KeyWord && first.TokenString.Equals(BY_REF, StringComparison.InvariantCultureIgnoreCase)) { param = new CodeParameterDeclarationExpressionEx(typeof(object), second.TokenString); param.Direction = FieldDirection.Ref; } else { param = new CodeParameterDeclarationExpressionEx( new CodeTypeReferenceEx(_document, first.TokenString, thisparent), paramstack.Pop().TokenString); } // thread two param as the type and argument method.Parameters.Add(param); } if(current.Token == Token.LiteralBracketClosed) break; } else if(current.Token == Token.NewLine){ break; } previous = current; } } #endregion // Method body ends at var endMethodBody = startMethodBody.FindClosingBracked(true); if(endMethodBody != null) { // get method statements method.Statements.AddRange( CollectAllCodeStatements(cancellationToken, thisparent, codeLineMap, startMethodBody.LineNumber + 1, endMethodBody.LineNumber)); // add it to the code DOM Tree if(!hasDeclarationError) { thisparent.Members.Add(method); method.DefiningType = thisparent; } // Create a CodeRange Item int startOffset = startMethodBody.Range.Offset; int length = (endMethodBody.Range.Offset - startOffset); _codeRangeManager.Add(new CodeRange(new SimpleSegment(startOffset, length), method)); // move the scanpointer to the method end: i = endMethodBody.LineNumber; continue; } else { RegisterError(_document, startMethodBody, "Missing: " + Token.BlockClosed); } } } } } #endregion // is class property / field #region Parse Class Properties / Fields if(parentHirarchy.Count > 1) { // we must be in a class to have method properties // extract keywords & Identifiers untill we reach // any otherToken - omit whitespaces List<CodeSegment> declarationStack = new List<CodeSegment>(); CodeSegment current = line.CodeSegments[0].ThisOrNextOmit(whitespacetokens); while(current != null) { if(current.Token == Token.WhiteSpace) { //ignore white spaces } else if(current.Token == Token.Identifier || current.Token == Token.KeyWord) { declarationStack.Add(current); } else { break; } current = current.Next; } switch(declarationStack.Count) { case 0: break; case 1: // instance field definition if(declarationStack[0].Token == Token.Identifier) { // this is an untyped instance class field declaration var propertyType = new CodeTypeReference(typeof(object)); var memberprop = new CodeMemberPropertyEx(_document) { Name = declarationStack[0].TokenString, Attributes = MemberAttributes.Public, Type = propertyType, LinePragma = CreatePragma(declarationStack[0], _document.FilePath) }; declarationStack[0].CodeDOMObject = memberprop; parentHirarchy.Peek().Members.Add(memberprop); } else { RegisterError(_document, declarationStack[0], string.Format("Unexpected Token: {0}", declarationStack[0].Token)); } break; case 2: // we have two members in the decalration stack // expected token flows // keyword - identifier: static Field, int Field // identifier - identifier: Car myTypedCarField // for the time beeing, AHK just supports static Field if(declarationStack[0].Token == Token.KeyWord && declarationStack[0].TokenString.Equals(MODIFIER_STATIC, StringComparison.InvariantCultureIgnoreCase)) { if(declarationStack[1].Token == Token.Identifier) { // this is an untyped static class field declaration var propertyType = new CodeTypeReference(typeof(object)); var memberprop = new CodeMemberPropertyEx(_document) { Name = declarationStack[1].TokenString, Attributes = MemberAttributes.Public | MemberAttributes.Static, Type = propertyType, LinePragma = CreatePragma(declarationStack[1], _document.FilePath) }; declarationStack[1].CodeDOMObject = memberprop; parentHirarchy.Peek().Members.Add(memberprop); } else { RegisterError(_document, declarationStack[0], string.Format("Expected: {0}", Token.Identifier)); } } else { RegisterError(_document, declarationStack[0], string.Format("Unexpected '{0}' in Class Body", declarationStack[0].TokenString)); } break; default: for(int ci = 0; ci < declarationStack.Count; ci++) { RegisterError(_document, declarationStack[ci], string.Format("To much declaration Members", declarationStack[0].Token)); } break; } } #endregion #region Parse Remaining Tokens if(codeLineMap.ContainsKey(i)) { var lineBlock = codeLineMap[i]; CodeTypeDeclarationEx thisparent = parentHirarchy.Any() ? parentHirarchy.Peek() : _languageRoot; foreach(var segment in lineBlock.CodeSegments) { cancellationToken.ThrowIfCancellationRequested(); if(segment.Token == Token.BlockOpen) { bcc++; } else if(segment.Token == Token.BlockClosed) { bcc--; if(parentHirarchy.Count - 2 == bcc) { if(parentHirarchy.Any()) parentHirarchy.Pop(); } } } _autoexec.Statements.AddRange( CollectAllCodeStatements(cancellationToken, thisparent, codeLineMap, i, i)); } else continue; #endregion } #endregion AnalyzeAST(cancellationToken); lock(_rootLanguageSnapshotLOCK) { _rootLanguageSnapshot = _languageRoot; } }); } catch(OperationCanceledException) { throw; } }