Contents

Estilo de Codificação do Inkscape

Esta página documenta as convenções usadas no código-fonte do Inkscape. Por favor adote estas convenções quando escrever um novo código. Se você ver código que não está de acordo com elas, sinta-se livre para corrigí-lo!

Noções básicas: indentação, espaçamento e chaves

O código é indentado consistentemente usando quatro espaços. Tabulações não são permitidas em nenhuma parte do código. A única exceção é em arquivos makefiles e outros arquivos do sistema de construção onde os caracteres de tabulação são sintaticamente necessários.

As seguintes coisas são indentadas:

  • Corpo de instruções de controle: for, if, while, switch, etc.
  • Blocos de instruções livres, ou seja, abertura e fechamento de chaves que não seguem nenhuma instrução de controle. Estes são às vezes usados para limitar o tempo de vida de objetos.
  • Corpos de classes e funções.
  • Declarações de continuação da linha anterior.

As seguintes coisas não são indentadas:

  • Conteúdo de namespaces.
  • Rótulos Case e código que os segue.
  • Especificadores de controle de acesso.

O código é escrito usando chaves compactas, o que significa que a chave de abertura vai na mesma linha que a instrução de controle. A chave de fechamento de um bloco if vai na mesma linha que a seguinte palavra-chave else. No entanto, há uma exceção: se a condição de um if ou while ou o cabeçalho de um laço for são divididos em mais de uma linha, a chave de abertura vai em uma linha separada. Chaves são obrigatórias e não devem ser omitidas, mesmo quando o corpo do bloco tem apenas uma única linha. Para definições de função, a chave de abertura deve ir em uma linha separada, se a função é muito maior do que algumas linhas ou quando a lista de argumentos abrange mais do que uma única linha. A abertura de chaves em construtores com membros inicializadores deve ser feita em uma linha separada.

Espaços estão presentes nos seguintes locais:

  • Em torno de todos os operadores binários, incluindo as atribuições
  • Entre uma palavra-chave e parênteses
  • Entre um identificador ou palavra-chave e uma chave
  • Após vírgulas e ponto e vírgula que não terminam uma linha
  • Entre a palavra-chave do modelo e a lista de argumentos do modelo

Espaços estão ausentes nos seguintes locais:

  • Antes do ponto e vírgula e vírgulas
  • No lado interno de parênteses
  • Entre um nome de função e sua lista de argumentos
  • Entre operadores unários e seus operandos
  • Dentro de uma lista de argumentos vazia
  • Entre uma etiqueta e um dois-pontos
  • Em torno do operador de escopo ::

Membro inicializador de listas e listas de classes base que contêm mais de uma classe devem ser escritas usando indentação  Boost-style: cada classe ou membro vai em uma linha separada e é precedido por um espaço e pontuação adequada. Isto torna muito mais fácil a detecção de erros.

namespace Inkscape {
namespace UI {

Sandwich make_sandwich(int x);
int make_a_mess(float y);

} // namespace UI
} // namespace Inkscape

class Bunkum
    : public Nonsense
    , protected PublicSpeech
{
public:
    Bunkum()
        : _x(1024)
        , _y(42)
    {}
private:
    void _forget();
    int _x, _y;
};

template <typename Basket>
void fill_basket(Basket &b)
{
    switch (a) {
    case 1:
        do_one();
        break;

    case 2:
        do_two();
        break;

    default:
        break;
    }

    for (int i = 0; i < 30; ++i) {
        b << Inkscape::UI::make_sandwich();
    }
    return b;
}

Convenções de nomenclatura

Nomes de classe e namespace usam UpperCamelCase. Globais e funções públicas estáticas, variáveis de pilha e membros de classe (variáveis de classe) usam lower_snake_case. Funções de membro de classe (métodos) utilizam lowerCamelCase. Membros protegidos e de classe privada são prefixados com um sublinhado. Macros e constantes usam UPPER_SNAKE_CASE. Parâmetros de modelo que são tipos usam UpperCamelCase, enquanto aqueles que são inteiros usam UPPER_SNAKE_CASE, como constantes. Tipo de prefixos, notação húngara, etc. não são permitidos. Use sufixos significativos se você precisar para remover a ambiguidade, por exemplo, text_raw e text_escaped.

Nomes de variáveis devem ser substantivos. Nomes de função devem ser verbos, com exceção de métodos acessores de obtenção de valor (getter), que podem ser substantivos. Por exemplo, uma propriedade de classe chamada position  teria o método acessor de definição de valor como setPosition() e o getter como position().

Convenções de nome de arquivo

Todos os arquivos que fazem parte da fonte do Inkscape devem usar minúsculas-com-hifens. Arquivos de C++ devem ter a extensão .cpp, enquanto arquivos de cabeçalho devem ter a extensão .h. Não são permitidos espaços, letras maiusculas e caracteres de sublinhado. Usar números em nomes de arquivo não é recomendado.

Colocação de const

O qualificador const vincula-se à direita, não à esquerda. Este é um fato muitas vezes esquecido, portanto, todos devem ter isso em mente, nós exigimos que o qualificador const seja escrito após o tipo.

#define SOME_MACRO(x) x
void call_global();
unsigned const IMPORTANT_CONSTANT = 42;

class Example {
public:
    void callPublic();
    static void call_public_static();
    int public_variable;
protected:
    void _callProtected();
    static void _call_protected_static();
    int _protected_variable;
private:
    void _callPrivate();
    static void _call_private_static();
    int _private_variable;
};

template <typename TypeParam, int INTEGER_PARAM>
void call_global_template(boost::array<TypeParam, INTEGER_PARAM> const &array);

Pré-processador

A compilação condicional usando o pré-processador é fortemente desencorajada, pois leva a podridão de código. Use-o somente quando for inevitável, por exemplo, quando uma dependência opcional é usada. Um caso especial é usar a compilação condicional para excluir um arquivo inteiro baseado na plataforma, o que é permitido.

Ao invés do código compilado condicionalmente, específico para cada plataforma, você deve priorizar escrever código portátil que funciona da mesma forma independentemente da plataforma. O uso das bibliotecas GLib e GTK+ pode ajudar muito neste aspecto. Se você deve usar código diferente dependendo da plataforma, tente encapsulá-lo em funções auxiliares, para que a quantidade de código que difere entre plataformas seja mantida ao mínimo.

Layout de arquivo

Os arquivos do Inkscape têm um layout fixo. Cada arquivo de código deve conter as coisas nesta ordem:

  1. Um comentário do Doxygen com uma breve descrição do que está no arquivo.
  2. Um comentário separado não-Doxygen com o autor e informações de licenciamento.
  3. Inclusão de condição de abertura (só nos cabeçalhos).
  4. Inclusão de cabeçalhos do sistema, por exemplo, #include <header>. Esses cabeçalhos devem ser ordenados alfabeticamente ou ordenados por dependências de biblioteca.
  5. Inclusão de cabeçalho interno, por exemplo, #include "header.h". Esses cabeçalhos devem ser ordenados alfabeticamente.
  6. O próprio código, no namespace Inkscape. Aqui a ordem é mais flexível, mas geralmente as declarações de funções globais devem vir depois das declarações de classe. A ordem das definições no arquivo .cpp deve corresponder a ordem das declarações no arquivo .h.
  7. Fechamento de condição.
  8. Um comentário no padrão modelines para Vim e Emacs, também utilizável por outros editores. Este bloco é o mesmo para todos os arquivos.

O código a seguir demonstra um pequeno arquivo de exemplo que está de acordo com o layout exigido.

/** @file
 * Selector component (click and rubberband)
 *//*
 * Authors:
 *   Krzysztof Kosiński <tweenk.pl@gmail.com>
 *
 * Copyright (C) 2009 Authors
 * Released under GNU GPL, read the file 'COPYING' for more information
 */

#ifndef SEEN_UI_TOOL_SELECTOR_H
#define SEEN_UI_TOOL_SELECTOR_H

#include <memory>
#include <gdk/gdk.h>
#include <2geom/rect.h>
#include "ui/tool/manipulator.h"

class SPDesktop;
class CtrlRect;

namespace Inkscape {
namespace UI {

class SelectorPoint;

class Selector : public Manipulator {
public:
    Selector(SPDesktop *d);
    virtual ~Selector();
    virtual bool event(SPEventContext *, GdkEvent *);
    
    sigc::signal<void, Geom::Rect const &, GdkEventButton*> signal_area;
    sigc::signal<void, Geom::Point const &, GdkEventButton*> signal_point;
private:
    SelectorPoint *_dragger;
    Geom::Point _start;
    CtrlRect *_rubber;
    gulong _connection;
    bool _cancel;
    friend class SelectorPoint;
};

} // namespace UI
} // namespace Inkscape

#endif

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace .0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim:filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99:

Formatadores de código fonte

A tarefa de manter os arquivos fontes em conformidade com o estilo de codificação pode ser simplificada usando formatadores de código-fonte automáticos.

Opções de Estilo Artísticas

O Estilo Artístico (astyle) é um formatador de código fonte C++. Você pode usá-lo para reformatar qualquer código-fonte que não esteja em conformidade. Para o estilo de codificação do Inkscape, coloque o seguinte no seu arquivo .astylerc:

--style=stroustrup
--indent=spaces=4
--indent-preprocessor
--indent-col1-comments
--pad-oper
--unpad-paren
--pad-header
--align-pointer=name
--align-reference=name
--add-brackets
--convert-tabs

O mesmo conteúdo está disponível no arquivo astylerc no repositório de código fonte do Inkscape, que você pode passar como argumento para a opção --options. Você também pode usar o equivalente por linha de comando.

astyle --options=astylerc
astyle -A4 -s4 -k3 -W3 -cjHpUwY

clang-format options

clang-format é um formatador de código-fonte fornecido como parte do compilador Clang, baseado em LLVM. Revisões recentes do Inkscape vem com um arquivo _clang-format por questões de conveniência, significa que clang-format deve pegar as configurações corretas de fora da caixa.