| // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'dart:ffi'; |
| |
| import 'package:ffigen/src/code_generator.dart'; |
| import 'package:ffigen/src/header_parser/data.dart'; |
| import 'package:ffigen/src/header_parser/sub_parsers/unnamed_enumdecl_parser.dart'; |
| import 'package:logging/logging.dart'; |
| |
| import '../clang_bindings/clang_bindings.dart' as clang_types; |
| import '../includer.dart'; |
| import '../utils.dart'; |
| |
| final _logger = Logger('ffigen.header_parser.enumdecl_parser'); |
| |
| Pointer< |
| NativeFunction< |
| Int32 Function( |
| clang_types.CXCursor, clang_types.CXCursor, Pointer<Void>)>>? |
| _enumCursorVisitorPtr; |
| |
| /// Holds temporary information regarding [EnumClass] while parsing. |
| class _ParsedEnum { |
| EnumClass? enumClass; |
| _ParsedEnum(); |
| } |
| |
| final _stack = Stack<_ParsedEnum>(); |
| |
| /// Parses an enum declaration. |
| EnumClass? parseEnumDeclaration( |
| clang_types.CXCursor cursor, { |
| /// Option to ignore declaration filter (Useful in case of extracting |
| /// declarations when they are passed/returned by an included function.) |
| bool ignoreFilter = false, |
| }) { |
| _stack.push(_ParsedEnum()); |
| |
| // Parse the cursor definition instead, if this is a forward declaration. |
| cursor = cursorIndex.getDefinition(cursor); |
| |
| final enumUsr = cursor.usr(); |
| final String enumName; |
| // Only set name using USR if the type is not Anonymous (i.e not inside |
| // any typedef and declared inplace inside another type). |
| if (clang.clang_Cursor_isAnonymous(cursor) == 0) { |
| // This gives the significant name, i.e name of the enum if defined or |
| // name of the first typedef declaration that refers to it. |
| enumName = enumUsr.split('@').last; |
| } else { |
| enumName = ''; |
| } |
| |
| if (enumName.isEmpty) { |
| _logger.fine('Saving anonymous enum.'); |
| saveUnNamedEnum(cursor); |
| } else if (ignoreFilter || shouldIncludeEnumClass(enumUsr, enumName)) { |
| _logger.fine('++++ Adding Enum: ${cursor.completeStringRepr()}'); |
| _stack.top.enumClass = EnumClass( |
| usr: enumUsr, |
| dartDoc: getCursorDocComment(cursor), |
| originalName: enumName, |
| name: config.enumClassDecl.renameUsingConfig(enumName), |
| ); |
| _addEnumConstant(cursor); |
| } |
| |
| return _stack.pop().enumClass; |
| } |
| |
| void _addEnumConstant(clang_types.CXCursor cursor) { |
| final resultCode = clang.clang_visitChildren( |
| cursor, |
| _enumCursorVisitorPtr ??= |
| Pointer.fromFunction(_enumCursorVisitor, exceptional_visitor_return), |
| nullptr, |
| ); |
| |
| visitChildrenResultChecker(resultCode); |
| } |
| |
| /// Visitor for a enum cursor [clang.CXCursorKind.CXCursor_EnumDecl]. |
| /// |
| /// Invoked on every enum directly under rootCursor. |
| /// Used for for extracting enum values. |
| int _enumCursorVisitor(clang_types.CXCursor cursor, clang_types.CXCursor parent, |
| Pointer<Void> clientData) { |
| try { |
| _logger.finest(' enumCursorVisitor: ${cursor.completeStringRepr()}'); |
| switch (clang.clang_getCursorKind(cursor)) { |
| case clang_types.CXCursorKind.CXCursor_EnumConstantDecl: |
| _addEnumConstantToEnumClass(cursor); |
| break; |
| case clang_types.CXCursorKind.CXCursor_UnexposedAttr: |
| // Ignore. |
| break; |
| default: |
| _logger.fine('invalid enum constant'); |
| } |
| } catch (e, s) { |
| _logger.severe(e); |
| _logger.severe(s); |
| rethrow; |
| } |
| return clang_types.CXChildVisitResult.CXChildVisit_Continue; |
| } |
| |
| /// Adds the parameter to func in [functiondecl_parser.dart]. |
| void _addEnumConstantToEnumClass(clang_types.CXCursor cursor) { |
| _stack.top.enumClass!.enumConstants.add( |
| EnumConstant( |
| dartDoc: getCursorDocComment( |
| cursor, |
| nesting.length + commentPrefix.length, |
| ), |
| originalName: cursor.spelling(), |
| name: config.enumClassDecl.renameMemberUsingConfig( |
| _stack.top.enumClass!.originalName, |
| cursor.spelling(), |
| ), |
| value: clang.clang_getEnumConstantDeclValue(cursor)), |
| ); |
| } |