Global Metrics

path: .metrics.nargs.sum
old: 0.0
new: 32.0

path: .metrics.nargs.average
old: 0.0
new: 2.6666666666666665

path: .metrics.halstead.time
old: 196.11305029659937
new: 31439.096787487582

path: .metrics.halstead.purity_ratio
old: 2.607459159380536
new: 0.7794289565893762

path: .metrics.halstead.bugs
old: 0.07727957857877282
new: 2.2805545025693568

path: .metrics.halstead.estimated_program_length
old: 174.6997636784959
new: 1307.8817891569731

path: .metrics.halstead.effort
old: 3530.034905338788
new: 565903.7421747765

path: .metrics.halstead.volume
old: 356.5691823574533
new: 12663.688903691454

path: .metrics.halstead.n1
old: 15.0
new: 24.0

path: .metrics.halstead.N2
old: 33.0
new: 607.0

path: .metrics.halstead.difficulty
old: 9.9
new: 44.68711656441718

path: .metrics.halstead.vocabulary
old: 40.0
new: 187.0

path: .metrics.halstead.N1
old: 34.0
new: 1071.0

path: .metrics.halstead.level
old: 0.101010101010101
new: 0.022377814387699063

path: .metrics.halstead.n2
old: 25.0
new: 163.0

path: .metrics.halstead.length
old: 67.0
new: 1678.0

path: .metrics.nom.total
old: 1.0
new: 12.0

path: .metrics.nom.functions
old: 1.0
new: 12.0

path: .metrics.cognitive.sum
old: 0.0
new: 18.0

path: .metrics.cognitive.average
old: 0.0
new: 1.5

path: .metrics.nexits.average
old: 0.0
new: 1.6666666666666667

path: .metrics.nexits.sum
old: 0.0
new: 20.0

path: .metrics.loc.ploc
old: 24.0
new: 398.0

path: .metrics.loc.lloc
old: 0.0
new: 321.0

path: .metrics.loc.sloc
old: 40.0
new: 425.0

path: .metrics.loc.cloc
old: 9.0
new: 10.0

path: .metrics.loc.blank
old: 7.0
new: 17.0

path: .metrics.mi.mi_visual_studio
old: 46.1065530891741
new: 0.0

path: .metrics.mi.mi_sei
old: 72.38264570000842
new: -72.09484340503941

path: .metrics.mi.mi_original
old: 78.84220578248771
new: -18.715613523008884

path: .metrics.cyclomatic.average
old: 1.3333333333333333
new: 12.333333333333334

path: .metrics.cyclomatic.sum
old: 8.0
new: 185.0

Spaces Data

Minimal test - lines (25, 108)

path: .spaces[0].spaces[0].spaces[1].metrics.nexits.average
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.nexits.sum
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.n2
old: 20.0
new: 49.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 2.590034300569197
new: 0.8899310434553945

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 145.04192083187502
new: 333.72414129577294

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.time
old: 155.5882515139973
new: 2831.6326530612246

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.bugs
old: 0.06622850457145868
new: 0.4582315873693401

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.vocabulary
old: 35.0
new: 64.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.length
old: 56.0
new: 375.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.effort
old: 2800.5885272519517
new: 50969.38775510204

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.volume
old: 287.2398489489181
new: 2250.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.level
old: 0.10256410256410256
new: 0.044144144144144144

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.N1
old: 30.0
new: 227.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.N2
old: 26.0
new: 148.0

path: .spaces[0].spaces[0].spaces[1].metrics.halstead.difficulty
old: 9.75
new: 22.653061224489797

path: .spaces[0].spaces[0].spaces[1].metrics.nargs.average
old: 0.0
new: 3.0

path: .spaces[0].spaces[0].spaces[1].metrics.nargs.sum
old: 0.0
new: 3.0

path: .spaces[0].spaces[0].spaces[1].metrics.cognitive.sum
old: 0.0
new: 3.0

path: .spaces[0].spaces[0].spaces[1].metrics.cognitive.average
old: 0.0
new: 3.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.blank
old: 4.0
new: 0.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.ploc
old: 14.0
new: 83.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.lloc
old: 0.0
new: 77.0

path: .spaces[0].spaces[0].spaces[1].metrics.loc.sloc
old: 19.0
new: 84.0

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_sei
old: 76.19849835917883
new: 11.510124024216037

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 54.354641599516206
new: 30.785732914448136

path: .spaces[0].spaces[0].spaces[1].metrics.mi.mi_original
old: 92.9464371351727
new: 52.64360328370631

path: .spaces[0].spaces[0].spaces[1].metrics.cyclomatic.average
old: 2.0
new: 28.0

path: .spaces[0].spaces[0].spaces[1].metrics.cyclomatic.sum
old: 4.0
new: 28.0

Code

LayoutDeviceIntMargin HeadlessThemeGTK::GetWidgetBorder(
    nsDeviceContext* aContext, nsIFrame* aFrame, StyleAppearance aAppearance) {
  LayoutDeviceIntMargin result;
  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      result.top = 6;
      result.right = 7;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::FocusOutline:
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      result.top = 5;
      result.right = 7;
      result.bottom = 5;
      result.left = 7;
      break;
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::ProgressBar:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::Textarea:
    case StyleAppearance::Menupopup:
    case StyleAppearance::MozGtkInfoBar:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 1;
      break;
    case StyleAppearance::Treeheadercell:
      result.top = 5;
      result.right = 7;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::Tab:
      result.top = 4;
      result.right = 7;
      result.bottom = 2;
      result.left = 7;
      break;
    case StyleAppearance::Tooltip:
      result.top = 6;
      result.right = 6;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::Menulist:
      result.top = 6;
      result.right = 22;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::MozMenulistArrowButton:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 0;
      break;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (IsRegularMenuItem(aFrame)) {
        break;
      }
      result.top = 3;
      result.right = 5;
      result.bottom = 3;
      result.left = 5;
      break;
    default:
      break;
  }
  return result;
}

Minimal test - lines (13, 424)

path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: 1.5

path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 0.0
new: 18.0

path: .spaces[0].spaces[0].metrics.loc.sloc
old: 25.0
new: 412.0

path: .spaces[0].spaces[0].metrics.loc.blank
old: 7.0
new: 16.0

path: .spaces[0].spaces[0].metrics.loc.lloc
old: 0.0
new: 321.0

path: .spaces[0].spaces[0].metrics.loc.cloc
old: 1.0
new: 4.0

path: .spaces[0].spaces[0].metrics.loc.ploc
old: 17.0
new: 392.0

path: .spaces[0].spaces[0].metrics.nom.functions
old: 1.0
new: 12.0

path: .spaces[0].spaces[0].metrics.nom.total
old: 1.0
new: 12.0

path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 6.0
new: 183.0

path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 1.5
new: 14.076923076923077

path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 2.6666666666666665

path: .spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 32.0

path: .spaces[0].spaces[0].metrics.nexits.sum
old: 0.0
new: 20.0

path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: 1.6666666666666667

path: .spaces[0].spaces[0].metrics.halstead.time
old: 175.20301393776725
new: 31885.762229215852

path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.1
new: 0.021871539313399777

path: .spaces[0].spaces[0].metrics.halstead.N1
old: 33.0
new: 1070.0

path: .spaces[0].spaces[0].metrics.halstead.effort
old: 3153.6542508798107
new: 573943.7201258853

path: .spaces[0].spaces[0].metrics.halstead.length
old: 61.0
new: 1672.0

path: .spaces[0].spaces[0].metrics.halstead.N2
old: 28.0
new: 602.0

path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.07168387336161613
new: 2.302104060438371

path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 10.0
new: 45.721518987341774

path: .spaces[0].spaces[0].metrics.halstead.n2
old: 21.0
new: 158.0

path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 150.84202481248175
new: 1264.03645822929

path: .spaces[0].spaces[0].metrics.halstead.n1
old: 15.0
new: 24.0

path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 2.4728200788931436
new: 0.7560026664050777

path: .spaces[0].spaces[0].metrics.halstead.volume
old: 315.36542508798107
new: 12553.03263841222

path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 36.0
new: 182.0

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 66.47019965548418
new: -75.01047763429192

path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 87.55480499742775
new: -17.706709570753034

path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 51.20164034937295
new: 0.0

Code

namespace widget {

NS_IMPL_ISUPPORTS_INHERITED(HeadlessThemeGTK, nsNativeTheme, nsITheme)

NS_IMETHODIMP
HeadlessThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
                                       StyleAppearance aAppearance,
                                       const nsRect& aRect,
                                       const nsRect& aDirtyRect) {
  return NS_OK;
}

LayoutDeviceIntMargin HeadlessThemeGTK::GetWidgetBorder(
    nsDeviceContext* aContext, nsIFrame* aFrame, StyleAppearance aAppearance) {
  LayoutDeviceIntMargin result;
  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      result.top = 6;
      result.right = 7;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::FocusOutline:
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      result.top = 5;
      result.right = 7;
      result.bottom = 5;
      result.left = 7;
      break;
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::ProgressBar:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::Textarea:
    case StyleAppearance::Menupopup:
    case StyleAppearance::MozGtkInfoBar:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 1;
      break;
    case StyleAppearance::Treeheadercell:
      result.top = 5;
      result.right = 7;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::Tab:
      result.top = 4;
      result.right = 7;
      result.bottom = 2;
      result.left = 7;
      break;
    case StyleAppearance::Tooltip:
      result.top = 6;
      result.right = 6;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::Menulist:
      result.top = 6;
      result.right = 22;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::MozMenulistArrowButton:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 0;
      break;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (IsRegularMenuItem(aFrame)) {
        break;
      }
      result.top = 3;
      result.right = 5;
      result.bottom = 3;
      result.left = 5;
      break;
    default:
      break;
  }
  return result;
}

bool HeadlessThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
                                        nsIFrame* aFrame,
                                        StyleAppearance aAppearance,
                                        LayoutDeviceIntMargin* aResult) {
  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::Toolbarbutton:
    case StyleAppearance::Dualbutton:
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
    case StyleAppearance::MozMenulistArrowButton:
    case StyleAppearance::RangeThumb:
    case StyleAppearance::ButtonFocus:
      aResult->top = 0;
      aResult->right = 0;
      aResult->bottom = 0;
      aResult->left = 0;
      return true;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (!IsRegularMenuItem(aFrame)) {
        return false;
      }
      aResult->top = 3;
      aResult->right = 5;
      aResult->bottom = 3;
      aResult->left = 5;
      return true;
    default:
      break;
  }
  return false;
}

static const int32_t kMinimumScrollbarSize = 10;

// TODO: Should probably deal with scrollbar-width somehow.
auto HeadlessThemeGTK::GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
                                         Overlay) -> ScrollbarSizes {
  return {kMinimumScrollbarSize, kMinimumScrollbarSize};
}

NS_IMETHODIMP
HeadlessThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
                                       nsIFrame* aFrame,
                                       StyleAppearance aAppearance,
                                       LayoutDeviceIntSize* aResult,
                                       bool* aIsOverridable) {
  aResult->width = aResult->height = 0;
  *aIsOverridable = true;

  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Splitter:
      if (IsHorizontal(aFrame)) {
        aResult->width = 6;
        aResult->height = 0;
      } else {
        aResult->width = 0;
        aResult->height = 6;
      }
      *aIsOverridable = false;
      break;
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      aResult->width = 14;
      aResult->height = 12;
      break;
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
      aResult->width = 18;
      aResult->height = 18;
      break;
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::Resizer:
      aResult->width = 15;
      aResult->height = 15;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Separator:
      aResult->width = 12;
      aResult->height = 0;
      break;
    case StyleAppearance::Treetwisty:
    case StyleAppearance::Treetwistyopen:
      aResult->width = 8;
      aResult->height = 8;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Treeheadercell:
      aResult->width = 13;
      aResult->height = 11;
      break;
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
      aResult->width = 14;
      aResult->height = 13;
      break;
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
      aResult->width = 16;
      aResult->height = 16;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Spinner:
      aResult->width = 14;
      aResult->height = 26;
      break;
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      aResult->width = 0;
      aResult->height = 12;
      break;
    case StyleAppearance::ScrollbarHorizontal:
      aResult->width = 31;
      aResult->height = kMinimumScrollbarSize;
      break;
    case StyleAppearance::ScrollbarVertical:
      aResult->width = kMinimumScrollbarSize;
      aResult->height = 31;
      break;
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
      aResult->width = 10;
      aResult->height = 13;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
      aResult->width = 13;
      aResult->height = 10;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarthumbHorizontal:
      aResult->width = 31;
      aResult->height = 10;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarthumbVertical:
      aResult->width = 10;
      aResult->height = 31;
      *aIsOverridable = false;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::Menulist:
      aResult->width = 44;
      aResult->height = 27;
      break;
    case StyleAppearance::MozMenulistArrowButton:
      aResult->width = 29;
      aResult->height = 28;
      *aIsOverridable = false;
      break;
    case StyleAppearance::RangeThumb:
      aResult->width = 14;
      aResult->height = 18;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Menuseparator:
      aResult->width = 0;
      aResult->height = 8;
      *aIsOverridable = false;
      break;
    default:
      break;
  }
  return NS_OK;
}

NS_IMETHODIMP
HeadlessThemeGTK::WidgetStateChanged(nsIFrame* aFrame,
                                     StyleAppearance aAppearance,
                                     nsAtom* aAttribute, bool* aShouldRepaint,
                                     const nsAttrValue* aOldValue) {
  return NS_OK;
}

NS_IMETHODIMP
HeadlessThemeGTK::ThemeChanged() { return NS_OK; }

static bool IsFrameContentNodeInNamespace(nsIFrame* aFrame,
                                          uint32_t aNamespace) {
  nsIContent* content = aFrame ? aFrame->GetContent() : nullptr;
  if (!content) return false;
  return content->IsInNamespace(aNamespace);
}

NS_IMETHODIMP_(bool)
HeadlessThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
                                      nsIFrame* aFrame,
                                      StyleAppearance aAppearance) {
  switch (aAppearance) {
    case StyleAppearance::Button:
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::FocusOutline:
    case StyleAppearance::Toolbox:
    case StyleAppearance::Toolbar:
    case StyleAppearance::Toolbarbutton:
    case StyleAppearance::Dualbutton:
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::Separator:
    case StyleAppearance::Toolbargripper:
    case StyleAppearance::Splitter:
    case StyleAppearance::Statusbar:
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Resizer:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treetwisty:
    case StyleAppearance::Treeheadercell:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::Treetwistyopen:
    case StyleAppearance::ProgressBar:
    case StyleAppearance::Progresschunk:
    case StyleAppearance::Tab:
    case StyleAppearance::Tabpanels:
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
    case StyleAppearance::Tooltip:
    case StyleAppearance::Spinner:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::NumberInput:
    case StyleAppearance::ScrollbarHorizontal:
    case StyleAppearance::ScrollbarVertical:
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
    case StyleAppearance::ScrollbartrackHorizontal:
    case StyleAppearance::ScrollbartrackVertical:
    case StyleAppearance::ScrollbarthumbHorizontal:
    case StyleAppearance::ScrollbarthumbVertical:
    case StyleAppearance::Textfield:
    case StyleAppearance::Textarea:
    case StyleAppearance::Menulist:
    case StyleAppearance::MenulistButton:
    case StyleAppearance::MenulistText:
    case StyleAppearance::Range:
    case StyleAppearance::RangeThumb:
    case StyleAppearance::CheckboxContainer:
    case StyleAppearance::RadioContainer:
    case StyleAppearance::CheckboxLabel:
    case StyleAppearance::RadioLabel:
    case StyleAppearance::ButtonFocus:
    case StyleAppearance::Window:
    case StyleAppearance::Dialog:
    case StyleAppearance::Menubar:
    case StyleAppearance::Menupopup:
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
    case StyleAppearance::Menuseparator:
    case StyleAppearance::Menuarrow:
    case StyleAppearance::MozGtkInfoBar:
      return !IsWidgetStyled(aPresContext, aFrame, aAppearance);
    case StyleAppearance::MozMenulistArrowButton:
      return (!aFrame ||
              IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
             !IsWidgetStyled(aPresContext, aFrame, aAppearance);
    default:
      break;
  }
  return false;
}

NS_IMETHODIMP_(bool)
HeadlessThemeGTK::WidgetIsContainer(StyleAppearance aAppearance) {
  if (aAppearance == StyleAppearance::MozMenulistArrowButton ||
      aAppearance == StyleAppearance::Radio ||
      aAppearance == StyleAppearance::RangeThumb ||
      aAppearance == StyleAppearance::Checkbox ||
      aAppearance == StyleAppearance::TabScrollArrowBack ||
      aAppearance == StyleAppearance::TabScrollArrowForward ||
      aAppearance == StyleAppearance::ButtonArrowUp ||
      aAppearance == StyleAppearance::ButtonArrowDown ||
      aAppearance == StyleAppearance::ButtonArrowNext ||
      aAppearance == StyleAppearance::ButtonArrowPrevious) {
    return false;
  }
  return true;
}

bool HeadlessThemeGTK::ThemeDrawsFocusForWidget(StyleAppearance aAppearance) {
  if (aAppearance == StyleAppearance::Menulist ||
      aAppearance == StyleAppearance::Button ||
      aAppearance == StyleAppearance::Treeheadercell) {
    return true;
  }
  return false;
}

bool HeadlessThemeGTK::ThemeNeedsComboboxDropmarker() { return false; }

}  // namespace widget

Minimal test - lines (18, 23)

path: .spaces[0].spaces[0].spaces[0].metrics.nom.functions
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.nom.total
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: null
new: 2.482149912200411

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 0.0
new: 463.4102741938456

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N1
old: 0.0
new: 13.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 0.0
new: 4.363636363636363

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 0.0
new: 25.745015232991424

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 1.0
new: 25.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.vocabulary
old: 1.0
new: 19.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.0
new: 0.019961316654982013

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n1
old: 0.0
new: 8.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 1.0
new: 12.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: null
new: 62.05374780501027

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: null
new: 0.22916666666666669

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n2
old: 1.0
new: 11.0

path: .spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 0.0
new: 106.19818783608964

path: .spaces[0].spaces[0].spaces[0].metrics.loc.ploc
old: 1.0
new: 6.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.sloc
old: 1.0
new: 6.0

path: .spaces[0].spaces[0].spaces[0].metrics.loc.lloc
old: 0.0
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: null
new: 117.4838999646514

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: null
new: 93.89440773068937

path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: null
new: 68.7040350670476

path: .spaces[0].spaces[0].spaces[0].metrics.nargs.average
old: null
new: 5.0

path: .spaces[0].spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 5.0

path: .spaces[0].spaces[0].spaces[0].metrics.cognitive.average
old: null
new: 0.0

path: .spaces[0].spaces[0].spaces[0].metrics.nexits.average
old: null
new: 1.0

path: .spaces[0].spaces[0].spaces[0].metrics.nexits.sum
old: 0.0
new: 1.0

Code

HeadlessThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
                                       StyleAppearance aAppearance,
                                       const nsRect& aRect,
                                       const nsRect& aDirtyRect) {
  return NS_OK;
}

Minimal test - lines (12, 425)

path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 1.5

path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 18.0

path: .spaces[0].metrics.mi.mi_original
old: 85.87067255730673
new: -18.02684883225085

path: .spaces[0].metrics.mi.mi_visual_studio
old: 50.21676757737236
new: 0.0

path: .spaces[0].metrics.mi.mi_sei
old: 69.35981308609165
new: -74.50174191288278

path: .spaces[0].metrics.nom.total
old: 1.0
new: 12.0

path: .spaces[0].metrics.nom.functions
old: 1.0
new: 12.0

path: .spaces[0].metrics.cyclomatic.average
old: 1.4
new: 13.142857142857142

path: .spaces[0].metrics.cyclomatic.sum
old: 7.0
new: 184.0

path: .spaces[0].metrics.nargs.average
old: 0.0
new: 2.6666666666666665

path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 32.0

path: .spaces[0].metrics.loc.blank
old: 6.0
new: 15.0

path: .spaces[0].metrics.loc.ploc
old: 19.0
new: 394.0

path: .spaces[0].metrics.loc.sloc
old: 27.0
new: 414.0

path: .spaces[0].metrics.loc.cloc
old: 2.0
new: 5.0

path: .spaces[0].metrics.loc.lloc
old: 0.0
new: 321.0

path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 20.0

path: .spaces[0].metrics.nexits.average
old: 0.0
new: 1.6666666666666667

path: .spaces[0].metrics.halstead.estimated_program_length
old: 156.71085454414833
new: 1272.7874899075202

path: .spaces[0].metrics.halstead.n1
old: 15.0
new: 24.0

path: .spaces[0].metrics.halstead.length
old: 63.0
new: 1674.0

path: .spaces[0].metrics.halstead.purity_ratio
old: 2.4874738816531483
new: 0.7603270549029392

path: .spaces[0].metrics.halstead.N1
old: 34.0
new: 1071.0

path: .spaces[0].metrics.halstead.level
old: 0.10114942528735632
new: 0.021973466003316747

path: .spaces[0].metrics.halstead.n2
old: 22.0
new: 159.0

path: .spaces[0].metrics.halstead.bugs
old: 0.07305640010809418
new: 2.298421214688122

path: .spaces[0].metrics.halstead.N2
old: 29.0
new: 603.0

path: .spaces[0].metrics.halstead.time
old: 180.25892611750177
new: 31809.277828764592

path: .spaces[0].metrics.halstead.difficulty
old: 9.886363636363637
new: 45.509433962264154

path: .spaces[0].metrics.halstead.vocabulary
old: 37.0
new: 183.0

path: .spaces[0].metrics.halstead.effort
old: 3244.6606701150313
new: 572567.0009177626

path: .spaces[0].metrics.halstead.volume
old: 328.19556203462383
new: 12581.281529287488

Code

namespace mozilla {
namespace widget {

NS_IMPL_ISUPPORTS_INHERITED(HeadlessThemeGTK, nsNativeTheme, nsITheme)

NS_IMETHODIMP
HeadlessThemeGTK::DrawWidgetBackground(gfxContext* aContext, nsIFrame* aFrame,
                                       StyleAppearance aAppearance,
                                       const nsRect& aRect,
                                       const nsRect& aDirtyRect) {
  return NS_OK;
}

LayoutDeviceIntMargin HeadlessThemeGTK::GetWidgetBorder(
    nsDeviceContext* aContext, nsIFrame* aFrame, StyleAppearance aAppearance) {
  LayoutDeviceIntMargin result;
  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      result.top = 6;
      result.right = 7;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::FocusOutline:
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      result.top = 5;
      result.right = 7;
      result.bottom = 5;
      result.left = 7;
      break;
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::ProgressBar:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::Textarea:
    case StyleAppearance::Menupopup:
    case StyleAppearance::MozGtkInfoBar:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 1;
      break;
    case StyleAppearance::Treeheadercell:
      result.top = 5;
      result.right = 7;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::Tab:
      result.top = 4;
      result.right = 7;
      result.bottom = 2;
      result.left = 7;
      break;
    case StyleAppearance::Tooltip:
      result.top = 6;
      result.right = 6;
      result.bottom = 6;
      result.left = 6;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::Menulist:
      result.top = 6;
      result.right = 22;
      result.bottom = 6;
      result.left = 7;
      break;
    case StyleAppearance::MozMenulistArrowButton:
      result.top = 1;
      result.right = 1;
      result.bottom = 1;
      result.left = 0;
      break;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (IsRegularMenuItem(aFrame)) {
        break;
      }
      result.top = 3;
      result.right = 5;
      result.bottom = 3;
      result.left = 5;
      break;
    default:
      break;
  }
  return result;
}

bool HeadlessThemeGTK::GetWidgetPadding(nsDeviceContext* aContext,
                                        nsIFrame* aFrame,
                                        StyleAppearance aAppearance,
                                        LayoutDeviceIntMargin* aResult) {
  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::Toolbarbutton:
    case StyleAppearance::Dualbutton:
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
    case StyleAppearance::MozMenulistArrowButton:
    case StyleAppearance::RangeThumb:
    case StyleAppearance::ButtonFocus:
      aResult->top = 0;
      aResult->right = 0;
      aResult->bottom = 0;
      aResult->left = 0;
      return true;
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
      if (!IsRegularMenuItem(aFrame)) {
        return false;
      }
      aResult->top = 3;
      aResult->right = 5;
      aResult->bottom = 3;
      aResult->left = 5;
      return true;
    default:
      break;
  }
  return false;
}

static const int32_t kMinimumScrollbarSize = 10;

// TODO: Should probably deal with scrollbar-width somehow.
auto HeadlessThemeGTK::GetScrollbarSizes(nsPresContext*, StyleScrollbarWidth,
                                         Overlay) -> ScrollbarSizes {
  return {kMinimumScrollbarSize, kMinimumScrollbarSize};
}

NS_IMETHODIMP
HeadlessThemeGTK::GetMinimumWidgetSize(nsPresContext* aPresContext,
                                       nsIFrame* aFrame,
                                       StyleAppearance aAppearance,
                                       LayoutDeviceIntSize* aResult,
                                       bool* aIsOverridable) {
  aResult->width = aResult->height = 0;
  *aIsOverridable = true;

  // The following values are generated from the Ubuntu GTK theme.
  switch (aAppearance) {
    case StyleAppearance::Splitter:
      if (IsHorizontal(aFrame)) {
        aResult->width = 6;
        aResult->height = 0;
      } else {
        aResult->width = 0;
        aResult->height = 6;
      }
      *aIsOverridable = false;
      break;
    case StyleAppearance::Button:
    case StyleAppearance::Toolbarbutton:
      aResult->width = 14;
      aResult->height = 12;
      break;
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
      aResult->width = 18;
      aResult->height = 18;
      break;
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::Resizer:
      aResult->width = 15;
      aResult->height = 15;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Separator:
      aResult->width = 12;
      aResult->height = 0;
      break;
    case StyleAppearance::Treetwisty:
    case StyleAppearance::Treetwistyopen:
      aResult->width = 8;
      aResult->height = 8;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Treeheadercell:
      aResult->width = 13;
      aResult->height = 11;
      break;
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
      aResult->width = 14;
      aResult->height = 13;
      break;
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
      aResult->width = 16;
      aResult->height = 16;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Spinner:
      aResult->width = 14;
      aResult->height = 26;
      break;
    case StyleAppearance::NumberInput:
    case StyleAppearance::Textfield:
      aResult->width = 0;
      aResult->height = 12;
      break;
    case StyleAppearance::ScrollbarHorizontal:
      aResult->width = 31;
      aResult->height = kMinimumScrollbarSize;
      break;
    case StyleAppearance::ScrollbarVertical:
      aResult->width = kMinimumScrollbarSize;
      aResult->height = 31;
      break;
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
      aResult->width = 10;
      aResult->height = 13;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
      aResult->width = 13;
      aResult->height = 10;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarthumbHorizontal:
      aResult->width = 31;
      aResult->height = 10;
      *aIsOverridable = false;
      break;
    case StyleAppearance::ScrollbarthumbVertical:
      aResult->width = 10;
      aResult->height = 31;
      *aIsOverridable = false;
      break;
    case StyleAppearance::MenulistButton:
    case StyleAppearance::Menulist:
      aResult->width = 44;
      aResult->height = 27;
      break;
    case StyleAppearance::MozMenulistArrowButton:
      aResult->width = 29;
      aResult->height = 28;
      *aIsOverridable = false;
      break;
    case StyleAppearance::RangeThumb:
      aResult->width = 14;
      aResult->height = 18;
      *aIsOverridable = false;
      break;
    case StyleAppearance::Menuseparator:
      aResult->width = 0;
      aResult->height = 8;
      *aIsOverridable = false;
      break;
    default:
      break;
  }
  return NS_OK;
}

NS_IMETHODIMP
HeadlessThemeGTK::WidgetStateChanged(nsIFrame* aFrame,
                                     StyleAppearance aAppearance,
                                     nsAtom* aAttribute, bool* aShouldRepaint,
                                     const nsAttrValue* aOldValue) {
  return NS_OK;
}

NS_IMETHODIMP
HeadlessThemeGTK::ThemeChanged() { return NS_OK; }

static bool IsFrameContentNodeInNamespace(nsIFrame* aFrame,
                                          uint32_t aNamespace) {
  nsIContent* content = aFrame ? aFrame->GetContent() : nullptr;
  if (!content) return false;
  return content->IsInNamespace(aNamespace);
}

NS_IMETHODIMP_(bool)
HeadlessThemeGTK::ThemeSupportsWidget(nsPresContext* aPresContext,
                                      nsIFrame* aFrame,
                                      StyleAppearance aAppearance) {
  switch (aAppearance) {
    case StyleAppearance::Button:
    case StyleAppearance::Radio:
    case StyleAppearance::Checkbox:
    case StyleAppearance::FocusOutline:
    case StyleAppearance::Toolbox:
    case StyleAppearance::Toolbar:
    case StyleAppearance::Toolbarbutton:
    case StyleAppearance::Dualbutton:
    case StyleAppearance::ToolbarbuttonDropdown:
    case StyleAppearance::ButtonArrowUp:
    case StyleAppearance::ButtonArrowDown:
    case StyleAppearance::ButtonArrowNext:
    case StyleAppearance::ButtonArrowPrevious:
    case StyleAppearance::Separator:
    case StyleAppearance::Toolbargripper:
    case StyleAppearance::Splitter:
    case StyleAppearance::Statusbar:
    case StyleAppearance::Statusbarpanel:
    case StyleAppearance::Resizerpanel:
    case StyleAppearance::Resizer:
    case StyleAppearance::Listbox:
    case StyleAppearance::Treeview:
    case StyleAppearance::Treetwisty:
    case StyleAppearance::Treeheadercell:
    case StyleAppearance::Treeheadersortarrow:
    case StyleAppearance::Treetwistyopen:
    case StyleAppearance::ProgressBar:
    case StyleAppearance::Progresschunk:
    case StyleAppearance::Tab:
    case StyleAppearance::Tabpanels:
    case StyleAppearance::TabScrollArrowBack:
    case StyleAppearance::TabScrollArrowForward:
    case StyleAppearance::Tooltip:
    case StyleAppearance::Spinner:
    case StyleAppearance::SpinnerUpbutton:
    case StyleAppearance::SpinnerDownbutton:
    case StyleAppearance::SpinnerTextfield:
    case StyleAppearance::NumberInput:
    case StyleAppearance::ScrollbarHorizontal:
    case StyleAppearance::ScrollbarVertical:
    case StyleAppearance::ScrollbarbuttonUp:
    case StyleAppearance::ScrollbarbuttonDown:
    case StyleAppearance::ScrollbarbuttonLeft:
    case StyleAppearance::ScrollbarbuttonRight:
    case StyleAppearance::ScrollbartrackHorizontal:
    case StyleAppearance::ScrollbartrackVertical:
    case StyleAppearance::ScrollbarthumbHorizontal:
    case StyleAppearance::ScrollbarthumbVertical:
    case StyleAppearance::Textfield:
    case StyleAppearance::Textarea:
    case StyleAppearance::Menulist:
    case StyleAppearance::MenulistButton:
    case StyleAppearance::MenulistText:
    case StyleAppearance::Range:
    case StyleAppearance::RangeThumb:
    case StyleAppearance::CheckboxContainer:
    case StyleAppearance::RadioContainer:
    case StyleAppearance::CheckboxLabel:
    case StyleAppearance::RadioLabel:
    case StyleAppearance::ButtonFocus:
    case StyleAppearance::Window:
    case StyleAppearance::Dialog:
    case StyleAppearance::Menubar:
    case StyleAppearance::Menupopup:
    case StyleAppearance::Menuitem:
    case StyleAppearance::Checkmenuitem:
    case StyleAppearance::Radiomenuitem:
    case StyleAppearance::Menuseparator:
    case StyleAppearance::Menuarrow:
    case StyleAppearance::MozGtkInfoBar:
      return !IsWidgetStyled(aPresContext, aFrame, aAppearance);
    case StyleAppearance::MozMenulistArrowButton:
      return (!aFrame ||
              IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XUL)) &&
             !IsWidgetStyled(aPresContext, aFrame, aAppearance);
    default:
      break;
  }
  return false;
}

NS_IMETHODIMP_(bool)
HeadlessThemeGTK::WidgetIsContainer(StyleAppearance aAppearance) {
  if (aAppearance == StyleAppearance::MozMenulistArrowButton ||
      aAppearance == StyleAppearance::Radio ||
      aAppearance == StyleAppearance::RangeThumb ||
      aAppearance == StyleAppearance::Checkbox ||
      aAppearance == StyleAppearance::TabScrollArrowBack ||
      aAppearance == StyleAppearance::TabScrollArrowForward ||
      aAppearance == StyleAppearance::ButtonArrowUp ||
      aAppearance == StyleAppearance::ButtonArrowDown ||
      aAppearance == StyleAppearance::ButtonArrowNext ||
      aAppearance == StyleAppearance::ButtonArrowPrevious) {
    return false;
  }
  return true;
}

bool HeadlessThemeGTK::ThemeDrawsFocusForWidget(StyleAppearance aAppearance) {
  if (aAppearance == StyleAppearance::Menulist ||
      aAppearance == StyleAppearance::Button ||
      aAppearance == StyleAppearance::Treeheadercell) {
    return true;
  }
  return false;
}

bool HeadlessThemeGTK::ThemeNeedsComboboxDropmarker() { return false; }

}  // namespace widget
}  // namespace mozilla