public override void ExitFoxmethod([NotNull] XP.FoxmethodContext context) { context.SetSequencePoint(context.T.Start, context.end.Stop); var idName = context.Id.Get <SyntaxToken>(); var mods = context.Modifiers?.GetList <SyntaxToken>() ?? DefaultMethodModifiers(false, false, context.TypeParameters != null); var isExtern = mods.Any((int)SyntaxKind.ExternKeyword); var isAbstract = mods.Any((int)SyntaxKind.AbstractKeyword); var hasNoBody = isExtern || isAbstract; var mName = idName.Text; if (mName.EndsWith("_ACCESS", StringComparison.OrdinalIgnoreCase)) { mName = mName.Substring(0, mName.Length - "_ACCESS".Length); } else if (mName.EndsWith("_ASSIGN", StringComparison.OrdinalIgnoreCase)) { mName = mName.Substring(0, mName.Length - "_ASSIGN".Length); } idName = SyntaxFactory.MakeIdentifier(mName); bool isAccessAssign = this.isAccessAssign(context.RealType); var attributes = context.Attributes?.GetList <AttributeListSyntax>() ?? EmptyList <AttributeListSyntax>(); bool hasExtensionAttribute = false; if (isAccessAssign) { var vomods = _pool.Allocate(); vomods.Add(SyntaxFactory.MakeToken(SyntaxKind.PrivateKeyword)); if (mods.Any((int)SyntaxKind.StaticKeyword)) { vomods.Add(SyntaxFactory.MakeToken(SyntaxKind.StaticKeyword)); } if (mods.Any((int)SyntaxKind.UnsafeKeyword)) { vomods.Add(SyntaxFactory.MakeToken(SyntaxKind.UnsafeKeyword)); } mods = vomods.ToList <SyntaxToken>(); _pool.Free(vomods); } if (!isExtern) { isExtern = hasDllImport(attributes); hasNoBody = hasNoBody || isExtern; } if (isExtern && !mods.Any((int)SyntaxKind.ExternKeyword)) { // Add Extern Keyword to modifiers var m1 = _pool.Allocate(); m1.AddRange(mods); if (!m1.Any((int)SyntaxKind.ExternKeyword)) { m1.Add(SyntaxFactory.MakeToken(SyntaxKind.ExternKeyword)); } mods = m1.ToList <SyntaxToken>(); _pool.Free(m1); } var parameters = context.ParamList?.Get <ParameterListSyntax>() ?? EmptyParameterList(); var body = hasNoBody ? null : context.StmtBlk.Get <BlockSyntax>(); var returntype = context.Type?.Get <TypeSyntax>(); if (returntype == null) { if (context.RealType == XP.ASSIGN) { returntype = VoidType(); } else // method and access { returntype = _getMissingType(); returntype.XNode = context; } } else { returntype.XVoDecl = true; } var oldbody = body; ImplementClipperAndPSZ(context, ref attributes, ref parameters, ref body, ref returntype); if (body != oldbody) { context.StmtBlk.Put(body); } if (context.RealType == XP.ASSIGN) { // Assign does not need a return. // So do not add missing returns returntype = VoidType(); } else if (context.StmtBlk != null && !hasNoBody) { body = AddMissingReturnStatement(body, context.StmtBlk, returntype); } MemberDeclarationSyntax m = _syntaxFactory.MethodDeclaration( attributeLists: attributes, modifiers: mods, returnType: returntype, explicitInterfaceSpecifier: null, identifier: idName, typeParameterList: context.TypeParameters?.Get <TypeParameterListSyntax>(), parameterList: parameters, constraintClauses: MakeList <TypeParameterConstraintClauseSyntax>(context._ConstraintsClauses), body: body, expressionBody: null, // TODO: (grammar) expressionBody methods semicolonToken: (!hasNoBody && context.StmtBlk != null) ? null : SyntaxFactory.MakeToken(SyntaxKind.SemicolonToken)); if (hasExtensionAttribute) { m = m.WithAdditionalDiagnostics(new SyntaxDiagnosticInfo(ErrorCode.ERR_ExplicitExtension)); } bool separateMethod = false; context.Put(m); if (isAccessAssign && !separateMethod) { if (context.Data.HasClipperCallingConvention && context.CallingConvention != null) { m = m.WithAdditionalDiagnostics(new SyntaxDiagnosticInfo( ErrorCode.ERR_NoClipperCallingConventionForAccessAssign)); } context.Put(m); ClassEntities.Peek().AddVoPropertyAccessor(context, context.RealType, idName); } }
public override void ExitXppclassvars([NotNull] XP.XppclassvarsContext context) { // add class vars to current class // use the current visibility saved with declMethodVis // IS and IN are not supported, so produce warning // include [SHARED], [READONLY] [ASSIGNMENT HIDDEN | PROTECTED | EXPORTED] and [NOSAVE] modifiers // on top of the visibility modifier // The [Readonly] clause and [Assignment] clause are not supported yet // In as future build we will create a private backing Ivar and // Create a property with Getter and Setter with property visibility // to emulate the possible combinations of [ReadOnly] and Assignment and Visibility // The following table lists what should be done // ========================================================================. // | Visibility | // Assignment | Hidden | Protected | Exported | // ========================================================================. // Hidden | pri Get/pri Set | pro Get pri Set | pub Get pri Set | // Protected | | pro Get pro Set | pub Get pro Set | // Exported | - | | pub Get pub Set | // ========================================================================. // // The Readonly clause does something similar as the ASSIGNMENT. // For the following visibilities this results in: // Private Readonly is useless // Protected Readonly creates a Protected Getter and a hidden/Private Setter // Exported/Public ReadOnly creates a Public Getter and a Protected Setter // var varList = _pool.AllocateSeparated <VariableDeclaratorSyntax>(); // Check to see if the variables have not been also declared as property // when they are we do not generate variables var varType = context.DataType?.Get <TypeSyntax>() ?? _getMissingType(); varType.XVoDecl = true; var fieldList = new List <FieldDeclarationSyntax>(); var attributeLists = _pool.Allocate <AttributeListSyntax>(); if (context.Nosave != null) { GenerateAttributeList(attributeLists, SystemQualifiedNames.NonSerialized); } foreach (var id in context._Vars) { varList.Clear(); var name = id.GetText(); var variable = GenerateVariable(id.Get <SyntaxToken>()); varList.Add(variable); // calculate modifiers // each field is added separately so we can later decide which field to keep and which one to delete when they are duplicated by a var modifiers = decodeXppMemberModifiers(context.Visibility, false, context.Modifiers?._Tokens); if (varList.Count > 0) { var decl = _syntaxFactory.VariableDeclaration( type: varType, variables: varList); var fdecl = _syntaxFactory.FieldDeclaration( attributeLists: attributeLists, modifiers: modifiers, declaration: decl, semicolonToken: SyntaxFactory.MakeToken(SyntaxKind.SemicolonToken)); ClassEntities.Peek().Members.Add(fdecl); fieldList.Add(fdecl); } } context.PutList(MakeList <FieldDeclarationSyntax>(fieldList)); _pool.Free(varList); _pool.Free(attributeLists); }