text:
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.

package com.intellij.psi.impl.source.codeStyle;

import com.intellij.application.options.CodeStyle;
import com.intellij.formatting.*;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.lang.*;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.*;
import com.intellij.psi.codeStyle.Indent;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.RecursiveTreeElementWalkingVisitor;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.CharTable;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class CodeStyleManagerImpl extends CodeStyleManager implements FormattingModeAwareIndentAdjuster {
  private static final Logger LOG = Logger.getInstance(CodeStyleManagerImpl.class);
  private static final ThreadLocal<ProcessingUnderProgressInfo> SEQUENTIAL_PROCESSING_ALLOWED
    = ThreadLocal.withInitial(() -> new ProcessingUnderProgressInfo());

  private final ThreadLocal<FormattingMode> myCurrentFormattingMode = ThreadLocal.withInitial(() -> FormattingMode.REFORMAT);

  private final Project myProject;
  @NonNls private static final String DUMMY_IDENTIFIER = "xxx";

  public CodeStyleManagerImpl(Project project) {
    myProject = project;
  }

  @Override
  @NotNull
  public Project getProject() {
    return myProject;
  }

  @Override
  @NotNull
  public PsiElement reformat(@NotNull PsiElement element) throws IncorrectOperationException {
    return reformat(element, false);
  }

  @Override
  @NotNull
  public PsiElement reformat(@NotNull PsiElement element, boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException {
    CheckUtil.checkWritable(element);
    if( !SourceTreeToPsiMap.hasTreeElement( element ) )
    {
      return element;
    }

    ASTNode treeElement = element.getNode();
    final PsiFile file = element.getContainingFile();
    final PsiElement formatted =
      new CodeFormatterFacade(getSettings(file), element.getLanguage(), canChangeWhiteSpacesOnly)
        .processElement(treeElement).getPsi();
    if (!canChangeWhiteSpacesOnly) {
      return postProcessElement(file, formatted);
    }
    return formatted;
  }

  private static PsiElement postProcessElement(@NotNull PsiFile file, @NotNull final PsiElement formatted) {
    PsiElement result = formatted;
    if (getSettings(file).FORMATTER_TAGS_ENABLED && formatted instanceof PsiFile) {
      postProcessEnabledRanges((PsiFile) formatted, formatted.getTextRange(), getSettings(file));
    }
    else {
      for (PostFormatProcessor postFormatProcessor : Extensions.getExtensions(PostFormatProcessor.EP_NAME)) {
        result = postFormatProcessor.processElement(result, getSettings(file));
      }
    }
    return result;
  }

  private static void postProcessText(@NotNull final PsiFile file, @NotNull final TextRange textRange) {
    if (!getSettings(file).FORMATTER_TAGS_ENABLED) {
      TextRange currentRange = textRange;
      for (final PostFormatProcessor myPostFormatProcessor : Extensions.getExtensions(PostFormatProcessor.EP_NAME)) {
        currentRange = myPostFormatProcessor.processText(file, currentRange, getSettings(file));
      }
    }
    else {
      postProcessEnabledRanges(file, textRange, getSettings(file));
    }
  }

  @Override
  public PsiElement reformatRange(@NotNull PsiElement element,
                                  int startOffset,
                                  int endOffset,
                                  boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException {
    return reformatRangeImpl(element, startOffset, endOffset, canChangeWhiteSpacesOnly);
  }

  @Override
  public PsiElement reformatRange(@NotNull PsiElement element, int startOffset, int endOffset)
    throws IncorrectOperationException {
    return reformatRangeImpl(element, startOffset, endOffset, false);

  }

  private static void transformAllChildren(final ASTNode file) {
    ((TreeElement)file).acceptTree(new RecursiveTreeElementWalkingVisitor() {
    });
  }

  @Override
  public void reformatText(@NotNull PsiFile file, int startOffset, int endOffset) throws IncorrectOperationException {
    reformatText(file, Collections.singleton(new TextRange(startOffset, endOffset)));
  }

  @Override
  public void reformatText(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges) throws IncorrectOperationException {
    reformatText(file, ranges, null);
  }

  @Override
  public void reformatTextWithContext(@NotNull PsiFile file,
                                      @NotNull ChangedRangesInfo info) throws IncorrectOperationException
  {
    FormatTextRanges formatRanges = new FormatTextRanges(info);
    reformatText(file, formatRanges, null, true);
  }

  public void reformatText(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges, @Nullable Editor editor) throws IncorrectOperationException {
    FormatTextRanges formatRanges = new FormatTextRanges();
    ranges.forEach((range) -> formatRanges.add(range, true));
    reformatText(file, formatRanges, editor, false);
  }

  private void reformatText(@NotNull PsiFile file,
                            @NotNull FormatTextRanges ranges,
                            @Nullable Editor editor,
                            boolean reformatContext) throws IncorrectOperationException
  {
    if (ranges.isEmpty()) {
      return;
    }
    boolean isFullReformat = ranges.isFullReformat(file);
    ApplicationManager.getApplication().assertWriteAccessAllowed();
    PsiDocumentManager.getInstance(getProject()).commitAllDocuments();

    CheckUtil.checkWritable(file);
    if (!SourceTreeToPsiMap.hasTreeElement(file)) {
      return;
    }

    ASTNode treeElement = SourceTreeToPsiMap.psiElementToTree(file);
    transformAllChildren(treeElement);

    final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(getSettings(file), file.getLanguage());
    codeFormatter.setReformatContext(reformatContext);

    LOG.assertTrue(file.isValid(), "File name: " + file.getName() + " , class: " + file.getClass().getSimpleName());

    if (editor == null) {
      editor = PsiUtilBase.findEditor(file);
    }

    CaretPositionKeeper caretKeeper = null;
    if (editor != null) {
      caretKeeper = new CaretPositionKeeper(editor, getSettings(file), file.getLanguage());
    }

    if (FormatterUtil.isFormatterCalledExplicitly()) {
      removeEndingWhiteSpaceFromEachRange(file, ranges);
    }

    final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(getProject());
    List<RangeFormatInfo> infos = new ArrayList<>();
    for (TextRange range : ranges.getTextRanges()) {
      final PsiElement start = findElementInTreeWithFormatterEnabled(file, range.getStartOffset());
      final PsiElement end = findElementInTreeWithFormatterEnabled(file, range.getEndOffset());
      if (start != null && !start.isValid()) {
        LOG.error("start=" + start + "; file=" + file);
      }
      if (end != null && !end.isValid()) {
        LOG.error("end=" + start + "; end=" + file);
      }
      boolean formatFromStart = range.getStartOffset() == 0;
      boolean formatToEnd = range.getEndOffset() == file.getTextLength();
      infos.add(new RangeFormatInfo(
        start == null ? null : smartPointerManager.createSmartPsiElementPointer(start),
        end == null ? null : smartPointerManager.createSmartPsiElementPointer(end),
        formatFromStart,
        formatToEnd
      ));
    }

    codeFormatter.processText(file, ranges, true);

    for (RangeFormatInfo info : infos) {
      final PsiElement startElement = info.startPointer == null ? null : info.startPointer.getElement();
      final PsiElement endElement = info.endPointer == null ? null : info.endPointer.getElement();
      if ((startElement != null || info.fromStart) && (endElement != null || info.toEnd)) {
        postProcessText(file, new TextRange(info.fromStart ? 0 : startElement.getTextRange().getStartOffset(),
                                            info.toEnd ? file.getTextLength() : endElement.getTextRange().getEndOffset()));
      }
      if (info.startPointer != null) smartPointerManager.removePointer(info.startPointer);
      if (info.endPointer != null) smartPointerManager.removePointer(info.endPointer);
    }

    if (caretKeeper != null) {
      caretKeeper.restoreCaretPosition();
    }
    if (editor instanceof EditorEx && isFullReformat) {
      //noinspection deprecation
      CodeStyleSettingsManager.getInstance(myProject).fireCodeStyleSettingsChanged(file);
    }
  }

  private static void removeEndingWhiteSpaceFromEachRange(@NotNull PsiFile file, @NotNull FormatTextRanges ranges) {
    for (FormatTextRange formatRange : ranges.getRanges()) {
      TextRange range = formatRange.getTextRange();

      final int rangeStart = range.getStartOffset();
      final int rangeEnd = range.getEndOffset();

      PsiElement lastElementInRange = findElementInTreeWithFormatterEnabled(file, rangeEnd);
      if (lastElementInRange instanceof PsiWhiteSpace && rangeStart < lastElementInRange.getTextRange().getStartOffset()) {
        PsiElement prev = lastElementInRange.getPrevSibling();
        if (prev != null) {
          int newEnd = prev.getTextRange().getEndOffset();
          formatRange.setTextRange(new TextRange(rangeStart, newEnd));
        }
      }
    }
  }

  private static PsiElement reformatRangeImpl(final @NotNull PsiElement element,
                                              final int startOffset,
                                              final int endOffset,
                                              boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException {
    LOG.assertTrue(element.isValid());
    CheckUtil.checkWritable(element);
    if( !SourceTreeToPsiMap.hasTreeElement( element ) )
    {
      return element;
    }

    ASTNode treeElement = element.getNode();
    final PsiFile file = element.getContainingFile();
    final CodeFormatterFacade codeFormatter = new CodeFormatterFacade(getSettings(file), element.getLanguage());
    final PsiElement formatted = codeFormatter.processRange(treeElement, startOffset, endOffset).getPsi();

    return canChangeWhiteSpacesOnly ? formatted : postProcessElement(file, formatted);
  }

  @Override
  public void reformatNewlyAddedElement(@NotNull final ASTNode parent, @NotNull final ASTNode addedElement) throws IncorrectOperationException {

    LOG.assertTrue(addedElement.getTreeParent() == parent, "addedElement must be added to parent");

    final PsiElement psiElement = parent.getPsi();

    PsiFile containingFile = psiElement.getContainingFile();
    final FileViewProvider fileViewProvider = containingFile.getViewProvider();
    if (fileViewProvider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
      containingFile = fileViewProvider.getPsi(fileViewProvider.getBaseLanguage());
    }
    assert containingFile != null;

    TextRange textRange = addedElement.getTextRange();
    final Document document = fileViewProvider.getDocument();
    if (document instanceof DocumentWindow) {
      containingFile = InjectedLanguageManager.getInstance(containingFile.getProject()).getTopLevelFile(containingFile);
      textRange = ((DocumentWindow)document).injectedToHost(textRange);
    }

    final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(containingFile);
    if (builder != null) {
      final FormattingModel model = CoreFormatterUtil.buildModel(builder, containingFile, getSettings(containingFile), FormattingMode.REFORMAT);
      FormatterEx.getInstanceEx().formatAroundRange(model, getSettings(containingFile), containingFile, textRange);
    }

    adjustLineIndent(containingFile, textRange);
  }

  @Override
  public int adjustLineIndent(@NotNull final PsiFile file, final int offset) throws IncorrectOperationException {
    return PostprocessReformattingAspect.getInstance(file.getProject()).disablePostprocessFormattingInside(
      () -> doAdjustLineIndentByOffset(file, offset, FormattingMode.ADJUST_INDENT));
  }

  @Nullable
  static PsiElement findElementInTreeWithFormatterEnabled(final PsiFile file, final int offset) {
    final PsiElement bottomost = file.findElementAt(offset);
    if (bottomost != null && LanguageFormatting.INSTANCE.forContext(bottomost) != null){
      return bottomost;
    }

    final Language fileLang = file.getLanguage();
    if (fileLang instanceof CompositeLanguage) {
      return file.getViewProvider().findElementAt(offset, fileLang);
    }

    return bottomost;
  }

  public int adjustLineIndent(@NotNull final Document document, final int offset, FormattingMode mode) {
    return PostprocessReformattingAspect.getInstance(getProject()).disablePostprocessFormattingInside(() -> {
      final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
      documentManager.commitDocument(document);

      PsiFile file = documentManager.getPsiFile(document);
      if (file == null) return offset;

      return doAdjustLineIndentByOffset(file, offset, mode);
    });
  }

  @Override
  public int adjustLineIndent(@NotNull Document document, int offset) {
    return adjustLineIndent(document, offset, FormattingMode.ADJUST_INDENT);
  }

  private int doAdjustLineIndentByOffset(@NotNull PsiFile file, int offset, FormattingMode mode) {
    final Integer result = new CodeStyleManagerRunnable<Integer>(this, mode) {
      @Override
      protected Integer doPerform(int offset, TextRange range) {
        return FormatterEx.getInstanceEx().adjustLineIndent(myModel, mySettings, myIndentOptions, offset, mySignificantRange);
      }

      @Override
      protected Integer computeValueInsidePlainComment(PsiFile file, int offset, Integer defaultValue) {
        return CharArrayUtil.shiftForward(file.getViewProvider().getContents(), offset, " \t");
      }

      @Override
      protected Integer adjustResultForInjected(Integer result, DocumentWindow documentWindow) {
        return result != null ? documentWindow.hostToInjected(result)
                              : null;
      }
    }.perform(file, offset, null, null);

    return result != null ? result : offset;
  }

  @Override
  public void adjustLineIndent(@NotNull PsiFile file, TextRange rangeToAdjust) throws IncorrectOperationException {
    new CodeStyleManagerRunnable<Object>(this, FormattingMode.ADJUST_INDENT) {
      @Override
      protected Object doPerform(int offset, TextRange range) {
        FormatterEx.getInstanceEx().adjustLineIndentsForRange(myModel, mySettings, myIndentOptions, range);
        return null;
      }
    }.perform(file, -1, rangeToAdjust, null);
  }

  @Override
  @Nullable
  public String getLineIndent(@NotNull PsiFile file, int offset) {
    return getLineIndent(file, offset, FormattingMode.ADJUST_INDENT);
  }

  @Override
  @Nullable
  public String getLineIndent(@NotNull PsiFile file, int offset, FormattingMode mode) {
    return new CodeStyleManagerRunnable<String>(this, mode) {
      @Override
      protected boolean useDocumentBaseFormattingModel() {
        return false;
      }

      @Override
      protected String doPerform(int offset, TextRange range) {
        return FormatterEx.getInstanceEx().getLineIndent(myModel, mySettings, myIndentOptions, offset, mySignificantRange);
      }
    }.perform(file, offset, null, null);
  }

  @Override
  @Nullable
  public String getLineIndent(@NotNull Document document, int offset) {
    PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
    if (file == null) return "";

    return getLineIndent(file, offset);
  }

  @Override
  @Deprecated
  public boolean isLineToBeIndented(@NotNull PsiFile file, int offset) {
    if (!SourceTreeToPsiMap.hasTreeElement(file)) {
      return false;
    }
    CharSequence chars = file.getViewProvider().getContents();
    int start = CharArrayUtil.shiftBackward(chars, offset - 1, " \t");
    if (start > 0 && chars.charAt(start) != '\n' && chars.charAt(start) != '\r') {
      return false;
    }
    int end = CharArrayUtil.shiftForward(chars, offset, " \t");
    if (end >= chars.length()) {
      return false;
    }
    ASTNode element = SourceTreeToPsiMap.psiElementToTree(findElementInTreeWithFormatterEnabled(file, end));
    if (element == null) {
      return false;
    }
    if (element.getElementType() == TokenType.WHITE_SPACE) {
      return false;
    }
    if (element.getElementType() == PlainTextTokenTypes.PLAIN_TEXT) {
      return false;
    }
    /*
    if( element.getElementType() instanceof IJspElementType )
    {
      return false;
    }
    */
    if (getSettings(file).getCommonSettings(file.getLanguage()).KEEP_FIRST_COLUMN_COMMENT && isCommentToken(element)) {
      if (IndentHelper.getInstance().getIndent(myProject, file.getFileType(), element, true) == 0) {
        return false;
      }
    }
    return true;
  }

  private static boolean isCommentToken(final ASTNode element) {
    final Language language = element.getElementType().getLanguage();
    final Commenter commenter = LanguageCommenters.INSTANCE.forLanguage(language);
    if (commenter instanceof CodeDocumentationAwareCommenter) {
      final CodeDocumentationAwareCommenter documentationAwareCommenter = (CodeDocumentationAwareCommenter)commenter;
      return element.getElementType() == documentationAwareCommenter.getBlockCommentTokenType() ||
             element.getElementType() == documentationAwareCommenter.getLineCommentTokenType();
    }
    return false;
  }

  private static boolean isWhiteSpaceSymbol(char c) {
    return c == ' ' || c == '\t' || c == '\n';
  }

  /**
   * Formatter trims line that contains white spaces symbols only, however, there is a possible case that we want
   * to preserve them for particular line
   * (e.g. for live template that defines line with whitespaces that contains $END$ marker: templateText   $END$).
   *

   * Current approach is to do the following:
   *

   *

   *
Insert dummy text at the end of the blank line which white space symbols should be preserved;

   *
Perform formatting;

   *
Remove dummy text;

   *

   *

   *

   * This method inserts that dummy comment (fallback to identifier {@code xxx}, see {@link CodeStyleManagerImpl#createDummy(PsiFile)})
   * if necessary.
   *

   * Note: it's expected that the whole white space region that contains given offset is processed in a way that all
   * {@link RangeMarker range markers} registered for the given offset are expanded to the whole white space region.
   * E.g. there is a possible case that particular range marker serves for defining formatting range, hence, its start/end offsets
   * are updated correspondingly after current method call and whole white space region is reformatted.
   *
   * @param file        target PSI file
   * @param document    target document
   * @param offset      offset that defines end boundary of the target line text fragment (start boundary is the first line's symbol)
   * @return            text range that points to the newly inserted dummy text if any; {@code null} otherwise
   * @throws IncorrectOperationException  if given file is read-only
   */
  @Nullable
  public static TextRange insertNewLineIndentMarker(@NotNull PsiFile file, @NotNull Document document, int offset) {
    CharSequence text = document.getImmutableCharSequence();
    if (offset <= 0 || offset >= text.length() || !isWhiteSpaceSymbol(text.charAt(offset))) {
      return null;
    }

    if (!isWhiteSpaceSymbol(text.charAt(offset - 1))) {
      return null; // no whitespaces before offset
    }

    int end = offset;
    for (; end < text.length(); end++) {
      if (text.charAt(end) == '\n') {
        break; // line is empty till the end
      }
      if (!isWhiteSpaceSymbol(text.charAt(end))) {
        return null;
      }
    }

    setSequentialProcessingAllowed(false);
    String dummy = createDummy(file);
    document.insertString(offset, dummy);
    return new TextRange(offset, offset + dummy.length());
  }

  @NotNull
  private static String createDummy(@NotNull PsiFile file) {
    Language language = file.getLanguage();
    PsiComment comment = null;
    try {
      comment = PsiParserFacade.SERVICE.getInstance(file.getProject()).createLineOrBlockCommentFromText(language, "");
    }
    catch (Throwable ignored) {
    }
    String text = comment != null ? comment.getText() : null;
    return text != null ? text : DUMMY_IDENTIFIER;
  }

  /**
   * Allows to check if given offset points to white space element within the given PSI file and return that white space
   * element in the case of positive answer.
   *
   * @param file    target file
   * @param offset  offset that might point to white space element within the given PSI file
   * @return        target white space element for the given offset within the given file (if any); {@code null} otherwise
   */
  @Nullable
  public static PsiElement findWhiteSpaceNode(@NotNull PsiFile file, int offset) {
    return doFindWhiteSpaceNode(file, offset).first;
  }

  @NotNull
  private static Pair<PsiElement, CharTable> doFindWhiteSpaceNode(@NotNull PsiFile file, int offset) {
    ASTNode astNode = SourceTreeToPsiMap.psiElementToTree(file);
    if (!(astNode instanceof FileElement)) {
      return new Pair<>(null, null);
    }
    PsiElement elementAt = InjectedLanguageManager.getInstance(file.getProject()).findInjectedElementAt(file, offset);
    final CharTable charTable = ((FileElement)astNode).getCharTable();
    if (elementAt == null) {
      elementAt = findElementInTreeWithFormatterEnabled(file, offset);
    }

    if( elementAt == null) {
      return new Pair<>(null, charTable);
    }
    ASTNode node = elementAt.getNode();
    if (node == null || node.getElementType() != TokenType.WHITE_SPACE) {
      return new Pair<>(null, charTable);
    }
    return Pair.create(elementAt, charTable);
  }

  @Override
  @Deprecated
  public Indent getIndent(String text, FileType fileType) {
    int indent = IndentHelperImpl.getIndent(CodeStyle.getSettings(myProject).getIndentOptions(fileType), text, true);
    int indentLevel = indent / IndentHelperImpl.INDENT_FACTOR;
    int spaceCount = indent - indentLevel * IndentHelperImpl.INDENT_FACTOR;
    return new IndentImpl(CodeStyle.getSettings(myProject), indentLevel, spaceCount, fileType);
  }

  @Override
  @Deprecated
  public String fillIndent(Indent indent, FileType fileType) {
    IndentImpl indent1 = (IndentImpl)indent;
    int indentLevel = indent1.getIndentLevel();
    int spaceCount = indent1.getSpaceCount();
    final CodeStyleSettings settings = CodeStyle.getSettings(myProject);
    if (indentLevel < 0) {
      spaceCount += indentLevel * settings.getIndentSize(fileType);
      indentLevel = 0;
      if (spaceCount < 0) {
        spaceCount = 0;
      }
    }
    else {
      if (spaceCount < 0) {
        int v = (-spaceCount + settings.getIndentSize(fileType) - 1) / settings.getIndentSize(fileType);
        indentLevel -= v;
        spaceCount += v * settings.getIndentSize(fileType);
        if (indentLevel < 0) {
          indentLevel = 0;
        }
      }
    }
    return IndentHelperImpl.fillIndent(myProject, fileType, indentLevel * IndentHelperImpl.INDENT_FACTOR + spaceCount);
  }

  @Override
  @Deprecated
  public Indent zeroIndent() {
    return new IndentImpl(CodeStyle.getSettings(myProject), 0, 0, null);
  }

  @NotNull
  private static CodeStyleSettings getSettings(@NotNull PsiFile file) {
    return CodeStyle.getSettings(file);
  }

  @Override
  public boolean isSequentialProcessingAllowed() {
    return SEQUENTIAL_PROCESSING_ALLOWED.get().isAllowed();
  }

  /**
   * Allows to define if {@link #isSequentialProcessingAllowed() sequential processing} should be allowed.
   *

   * Current approach is not allow to stop sequential processing for more than predefine amount of time (couple of seconds).
   * That means that call to this method with {@code 'true'} argument is not mandatory for successful processing even
   * if this method is called with {@code 'false'} argument before.
   *
   * @param allowed     flag that defines if {@link #isSequentialProcessingAllowed() sequential processing} should be allowed
   */
  public static void setSequentialProcessingAllowed(boolean allowed) {
    ProcessingUnderProgressInfo info = SEQUENTIAL_PROCESSING_ALLOWED.get();
    if (allowed) {
      info.decrement();
    }
    else {
      info.increment();
    }
  }

  private static class ProcessingUnderProgressInfo {

    private static final long DURATION_TIME = TimeUnit.MILLISECONDS.convert(5, TimeUnit.SECONDS);

    private int  myCount;
    private long myEndTime;

    public void increment() {
      if (myCount > 0 && System.currentTimeMillis() > myEndTime) {
        myCount = 0;
      }
      myCount++;
      myEndTime = System.currentTimeMillis() + DURATION_TIME;
    }

    public void decrement() {
      if (myCount <= 0) {
        return;
      }
      myCount--;
    }

    public boolean isAllowed() {
      return myCount <= 0 || System.currentTimeMillis() >= myEndTime;
    }
  }

  @Override
  public void performActionWithFormatterDisabled(final Runnable r) {
    performActionWithFormatterDisabled(() -> {
      r.run();
      return null;
    });
  }

  @Override
  public <T extends Throwable> void performActionWithFormatterDisabled(final ThrowableRunnable<T> r) throws T {
    final Throwable[] throwable = new Throwable[1];

    performActionWithFormatterDisabled(() -> {
      try {
        r.run();
      }
      catch (Throwable t) {
        throwable[0] = t;
      }
      return null;
    });

    if (throwable[0] != null) {
      //noinspection unchecked
      throw (T)throwable[0];
    }
  }

  @Override
  public <T> T performActionWithFormatterDisabled(final Computable<T> r) {
    return ((FormatterImpl)FormatterEx.getInstance()).runWithFormattingDisabled(() -> {
      final PostprocessReformattingAspect component = PostprocessReformattingAspect.getInstance(getProject());
      return component.disablePostprocessFormattingInside(r);
    });
  }

  private static class RangeFormatInfo{
    private final SmartPsiElementPointer startPointer;
    private final SmartPsiElementPointer endPointer;
    private final boolean                fromStart;
    private final boolean                toEnd;

    RangeFormatInfo(@Nullable SmartPsiElementPointer startPointer,
                    @Nullable SmartPsiElementPointer endPointer,
                    boolean fromStart,
                    boolean toEnd)
    {
      this.startPointer = startPointer;
      this.endPointer = endPointer;
      this.fromStart = fromStart;
      this.toEnd = toEnd;
    }
  }

  // There is a possible case that cursor is located at the end of the line that contains only white spaces. For example:
  //     public void foo() {
  //         <caret>
  //     }
  // Formatter removes such white spaces, i.e. keeps only line feed symbol. But we want to preserve caret position then.
  // So, if 'virtual space in editor' is enabled, we save target visual column. Caret indent is ensured otherwise
  private static class CaretPositionKeeper {
    Editor myEditor;
    Document myDocument;
    CaretModel myCaretModel;
    RangeMarker myBeforeCaretRangeMarker;
    String myCaretIndentToRestore;
    int myVisualColumnToRestore = -1;
    boolean myBlankLineIndentPreserved;

    CaretPositionKeeper(@NotNull Editor editor, @NotNull CodeStyleSettings settings, @NotNull Language language) {
      myEditor = editor;
      myCaretModel = editor.getCaretModel();
      myDocument = editor.getDocument();
      myBlankLineIndentPreserved = isBlankLineIndentPreserved(settings, language);

      int caretOffset = getCaretOffset();
      int lineStartOffset = getLineStartOffsetByTotalOffset(caretOffset);
      int lineEndOffset = getLineEndOffsetByTotalOffset(caretOffset);
      boolean shouldFixCaretPosition = rangeHasWhiteSpaceSymbolsOnly(myDocument.getCharsSequence(), lineStartOffset, lineEndOffset);

      if (shouldFixCaretPosition) {
        initRestoreInfo(caretOffset);
      }
    }

    private static boolean isBlankLineIndentPreserved(@NotNull CodeStyleSettings settings, @NotNull Language language) {
      CommonCodeStyleSettings langSettings = settings.getCommonSettings(language);
      CommonCodeStyleSettings.IndentOptions indentOptions = langSettings.getIndentOptions();
      return indentOptions != null && indentOptions.KEEP_INDENTS_ON_EMPTY_LINES;
    }

    private void initRestoreInfo(int caretOffset) {
      int lineStartOffset = getLineStartOffsetByTotalOffset(caretOffset);

      myVisualColumnToRestore = myCaretModel.getVisualPosition().column;
      myCaretIndentToRestore = myDocument.getText(TextRange.create(lineStartOffset, caretOffset));
      myBeforeCaretRangeMarker = myDocument.createRangeMarker(0, lineStartOffset);
    }

    public void restoreCaretPosition() {
      if (isVirtualSpaceEnabled()) {
        restoreVisualPosition();
      }
      else {
        restorePositionByIndentInsertion();
      }
    }

    private void restorePositionByIndentInsertion() {
      if (myBeforeCaretRangeMarker == null ||
          !myBeforeCaretRangeMarker.isValid() ||
          myCaretIndentToRestore == null ||
          myBlankLineIndentPreserved) {
        return;
      }
      int newCaretLineStartOffset = myBeforeCaretRangeMarker.getEndOffset();
      myBeforeCaretRangeMarker.dispose();
      if (myCaretModel.getVisualPosition().column == myVisualColumnToRestore) {
        return;
      }
      Project project = myEditor.getProject();
      if (project == null || PsiDocumentManager.getInstance(project).isDocumentBlockedByPsi(myDocument)) {
        return;
      }
      insertWhiteSpaceIndentIfNeeded(newCaretLineStartOffset);
    }

    private void restoreVisualPosition() {
      if (myVisualColumnToRestore < 0) {
        EditorUtil.runWithAnimationDisabled(myEditor, () -> myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE));
        return;
      }
      VisualPosition position = myCaretModel.getVisualPosition();
      if (myVisualColumnToRestore != position.column) {
        myCaretModel.moveToVisualPosition(new VisualPosition(position.line, myVisualColumnToRestore));
      }
    }

    private void insertWhiteSpaceIndentIfNeeded(int caretLineOffset) {
      int lineToInsertIndent = myDocument.getLineNumber(caretLineOffset);
      if (!lineContainsWhiteSpaceSymbolsOnly(lineToInsertIndent))
        return;

      int lineToInsertStartOffset = myDocument.getLineStartOffset(lineToInsertIndent);

      if (lineToInsertIndent != getCurrentCaretLine()) {
        myCaretModel.moveToOffset(lineToInsertStartOffset);
      }
      myDocument.replaceString(lineToInsertStartOffset, caretLineOffset, myCaretIndentToRestore);
    }

    private static boolean rangeHasWhiteSpaceSymbolsOnly(CharSequence text, int lineStartOffset, int lineEndOffset) {
      for (int i = lineStartOffset; i < lineEndOffset; i++) {
        char c = text.charAt(i);
        if (c != ' ' && c != '\t' && c != '\n') {
          return false;
        }
      }
      return true;
    }

    private boolean isVirtualSpaceEnabled() {
      return myEditor.getSettings().isVirtualSpace();
    }

    private int getLineStartOffsetByTotalOffset(int offset) {
      int line = myDocument.getLineNumber(offset);
      return myDocument.getLineStartOffset(line);
    }

    private int getLineEndOffsetByTotalOffset(int offset) {
      int line = myDocument.getLineNumber(offset);
      return myDocument.getLineEndOffset(line);
    }

    private int getCaretOffset() {
      int caretOffset = myCaretModel.getOffset();
      caretOffset = Math.max(Math.min(caretOffset, myDocument.getTextLength() - 1), 0);
      return caretOffset;
    }

    private boolean lineContainsWhiteSpaceSymbolsOnly(int lineNumber) {
      int startOffset = myDocument.getLineStartOffset(lineNumber);
      int endOffset = myDocument.getLineEndOffset(lineNumber);
      return rangeHasWhiteSpaceSymbolsOnly(myDocument.getCharsSequence(), startOffset, endOffset);
    }

    private int getCurrentCaretLine() {
      return myDocument.getLineNumber(myCaretModel.getOffset());
    }
  }

  private static void postProcessEnabledRanges(@NotNull final PsiFile file, @NotNull TextRange range, CodeStyleSettings settings) {
    List<TextRange> enabledRanges = new FormatterTagHandler(getSettings(file)).getEnabledRanges(file.getNode(), range);
    int delta = 0;
    for (TextRange enabledRange : enabledRanges) {
      enabledRange = enabledRange.shiftRight(delta);
      for (PostFormatProcessor processor : Extensions.getExtensions(PostFormatProcessor.EP_NAME)) {
        TextRange processedRange = processor.processText(file, enabledRange, settings);
        delta += processedRange.getLength() - enabledRange.getLength();
      }
    }
  }

  @Override
  public FormattingMode getCurrentFormattingMode() {
    return myCurrentFormattingMode.get();
  }

  void setCurrentFormattingMode(@NotNull FormattingMode mode) {
    myCurrentFormattingMode.set(mode);
  }

  @Override
  public int getSpacing(@NotNull PsiFile file, int offset) {
    FormattingModel model = createFormattingModel(file);
    return model == null ? -1 : FormatterEx.getInstance().getSpacingForBlockAtOffset(model, offset);
  }

  @Override
  public int getMinLineFeeds(@NotNull PsiFile file, int offset) {
    FormattingModel model = createFormattingModel(file);
    return model == null ? -1 : FormatterEx.getInstance().getMinLineFeedsBeforeBlockAtOffset(model, offset);
  }

  @Nullable
  private static FormattingModel createFormattingModel(@NotNull PsiFile file) {
    FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(file);
    if (builder == null) return null;
    CodeStyleSettings settings = CodeStyle.getSettings(file);
    return builder.createModel(file, settings);
  }

  @Override
  public void runWithDocCommentFormattingDisabled(@NotNull PsiFile file, @NotNull Runnable runnable) {
    DocCommentSettings docSettings = getDocCommentSettings(file);
    boolean currDocFormattingEnabled = docSettings.isDocFormattingEnabled();
    docSettings.setDocFormattingEnabled(false);
    try {
      runnable.run();
    }
    finally {
      docSettings.setDocFormattingEnabled(currDocFormattingEnabled);
    }
  }

  @NotNull
  public DocCommentSettings getDocCommentSettings(@NotNull PsiFile file) {
    Language language = file.getLanguage();
    LanguageCodeStyleSettingsProvider settingsProvider = LanguageCodeStyleSettingsProvider.forLanguage(language);
    if (settingsProvider != null) {
      return settingsProvider.getDocCommentSettings(CodeStyle.getSettings(file));
    }
    return DocCommentSettings.DEFAULTS;
  }
}


text:
<?php if($image->result()==null){ echo "
Oops.. No Image Display :)
";};?>
	<?php foreach ($image->result() as $row):?>

		<a class="detail_img" id="modal-detail" data-id='<?=$row->id_foto;?>' href="#modal-container-detail" role="button" class="btn" data-toggle="modal">

			<img class="img img-responsive" src="<?=base_url("upload/mini/$row->mini");?>">

	<?php endforeach;?>

							<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
								×
							</button>

									Deskripsi

									Kategori

									Tag

									Resolution

							<button type="button" class="btn btn-default" data-dismiss="modal">
								Close
							</button>

								Generate Link Donwload

							<button data-dismiss="modal" id="<?=$row->id_foto;?>" type="button" class="beli btn btn-warning">
								 Beli Paket
							</button>

redpajama_set_name: RedPajamaGithub


text:
var cdb = require('cartodb.js');

module.exports = cdb.core.Model.extend({

  initialize: function (attrs, opts) {
    if (!opts.columnOptionsFactory) throw new Error('columnOptionsFactory is required');

    this._columnOptionsFactory = opts.columnOptionsFactory;
  },

  updateSchema: function () {
    var columnOptions = this._columnOptionsFactory.create(this.get('column'), this._isDateType);
    var helpMsg = this._columnOptionsFactory.unavailableColumnsHelpMessage();

    this.schema = {
      title: {
        title: _t('editor.widgets.widgets-form.data.title'),
        type: 'Text',
        validators: ['required']
      },
      column: {
        title: _t('editor.widgets.widgets-form.data.column'),
        type: 'Select',
        help: helpMsg,
        options: columnOptions,
        editorAttrs: {
          disabled: this._columnOptionsFactory.areColumnsUnavailable()
        }
      },
      bins: {
        title: _t('editor.widgets.widgets-form.data.bins'),
        type: 'Number',
        validators: ['required', {
          type: 'interval',
          min: 0,
          max: 30
        }]
      }
    };
  },

  canSave: function () {
    return this.get('column');
  },

  _isDateType: function (m) {
    return m.get('type') === 'date';
  }

});


text:
module Rubix
  module ResponseSpecs
    def mock_response result={}, code=200
      response = mock("Net::HTTPResponse")
      response.stub!(:body).and_return({"jsonrpc" => "2.0", "result" => result}.to_json)
      response.stub!(:code).and_return(code.to_s)
      Rubix::Response.new(response)
    end

    def mock_error message='', code=200
      response = mock("Net::HTTPResponse")
      response.stub!(:body).and_return({"jsonrpc" => "2.0", "error" => message}.to_json)
      response.stub!(:code).and_return(code.to_s)
      Rubix::Response.new(response)
    end
  end
end


text:
<?php

namespace Anorgan\LaravelCache;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;
use Illuminate\Support\Collection;

/**
 * Class TagFinder
 * @package Anorgan\LaravelCache
 */
class TagFinder
{
    /**
     * @param Collection|Model $models
     * @return array
     */
    public function find($models)
    {
        if ($models instanceof Model) {

            // Ignore Pivot models
            if ($models instanceof Pivot) {
                return [];
            }

            $models = collect([$models]);
        }

        return array_values(array_unique($this->getTagsFromCollection($models)));
    }

    /**
     * @param Collection $collection
     * @return array
     */
    private function getTagsFromCollection(Collection $collection)
    {
        $tags = [];

        foreach ($collection as $model) {
            $tags = array_merge($tags, $this->getTags($model));
        }

        return $tags;
    }

    /**
     * @param Model $model
     * @return array
     */
    private function getTags(Model $model)
    {
        if ($model instanceof Pivot) {
            // Ignore Pivot models
            return [];
        }

        $tags = [
            $this->createTag($model),
        ];

        foreach ($model->getRelations() as $relation) {
            if ($relation instanceof Collection) {
                $tags = array_merge($tags, $this->getTagsFromCollection($relation));
            } elseif ($relation instanceof Pivot) {
                // Ignore Pivot models
                $tags = [];
            } elseif ($relation instanceof Model) {
                $tags = array_merge($tags, $this->getTags($relation));
            }
        }

        return $tags;
    }

    /**
     * @param Model $model
     * @return string
     */
    private function createTag(Model $model)
    {
        return sprintf('%s_%s', str_singular($model->getTable()), $model->getKey());
    }
}


text:
/******************************************************************************
 *
 *	Filename:		Tasks.h
 *
 *	Author:			Adam Johnson
 *
 *	Description:	A lightweight task scheduler.
 *
 *	Inspired by:	http://www.embedded.com/design/programming-languages-and-tools/4007578/A-six-step-process-for-migrating-embedded-C-into-a-C--object-oriented-framework
 *
 *	Terms of Use:	MIT License
 *
 *****************************************************************************/

#define MAX_TASKS	10					// maximum number of scheduled tasks

typedef void (*callbackPtr_t) (void);	// a type for function pointer

void    TasksInit(void);										// start
uint8_t TasksAdd(callbackPtr_t Callback, uint16_t msInterval);	// add task
uint8_t TasksDelete(callbackPtr_t Callback);					// delete task
void    TasksRun(void);											// run in main loop
void    TasksISR(void);											// run in interrupt


text:
package org.apache.kylin.metadata.tuple;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;

import org.junit.Test;

public class EmptyTupleIteratorTest {

    @Test
    public void testListAllTables() throws Exception {
        ITupleIterator it = ITupleIterator.EMPTY_TUPLE_ITERATOR;
        assertFalse(it.hasNext());
        assertNull(it.next());
        it.close(); // for coverage
    }

}


text:
package it.swim.servlet.profilo.azioni;

import it.swim.util.UtenteCollegatoUtil;

import java.io.IOException;
import java.util.List;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import exceptions.LoginException;

import sessionBeans.localInterfaces.GestioneCollaborazioniLocal;

/**
 * Servlet implementation class RilasciaFeedBackServlet
 */
public class RilasciaFeedBackServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	@EJB
	private GestioneCollaborazioniLocal collab;
	private Long idCollaborazione;
	/**
	 * @see HttpServlet#HttpServlet()
	 */
	public RilasciaFeedBackServlet() {

	}

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// ottengo l'email dell'utente collegato dalla sessione, appoggiandomi
		// ad una classe di utilita'
		String emailUtenteCollegato = (String) UtenteCollegatoUtil
				.getEmailUtenteCollegato(request);
		idCollaborazione=Long.parseLong(request.getParameter("idCollaborazione"));
		// se e' null e' perche' l'utente non e' collegato e allora devo fare il
		// redirect alla home
		if (emailUtenteCollegato == null) {
			response.sendRedirect("../../home");
			return;
		}
		getServletConfig()
				.getServletContext()
				.getRequestDispatcher(
						"/jsp/utenti/profilo/rilascioFeedBack.jsp")
				.forward(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		// ottengo l'email dell'utente collegato dalla sessione, appoggiandomi
		// ad una classe di utilita'
		String emailUtenteCollegato = (String) UtenteCollegatoUtil
				.getEmailUtenteCollegato(request);
		List<FileItem> items;
		int punteggioFeedBack = 0;
		String commento="";
		// se e' null e' perche' l'utente non e' collegato e allora devo fare il
		// redirect alla home

		if (emailUtenteCollegato == null) {
			response.sendRedirect("../../home");
			return;
		}

		try {
			items = new ServletFileUpload(new DiskFileItemFactory())
					.parseRequest(request);
			for (FileItem item : items) {
				if (item.isFormField()) {
					// Process regular form field (input
					// type="text|radio|checkbox|etc", select, etc).
					// ... (do your job here)
					if (item.getFieldName().equals("punteggioFeedBack")) {
						punteggioFeedBack = Integer.parseInt(item.getString()
								.trim());
					}
					if (item.getFieldName().equals("commentoFeedBack")) {
						commento = item.getString().trim();
					}
				}
			}
		} catch (FileUploadException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(punteggioFeedBack<1||punteggioFeedBack>5){
			request.setAttribute("erroreNelPunteggio", "Il punteggio deve essere compreso tra 1 e 5");
			getServletConfig().getServletContext().getRequestDispatcher("/jsp/utenti/profilo/rilascioFeedBack.jsp").forward(request, response);
			return;
		}
		if(commento.isEmpty()){
			commento="Non ci sono commenti rilasciati";
		}
		try {
			collab.rilasciaFeedback(idCollaborazione, punteggioFeedBack, commento);
		} catch (LoginException e) {
			// TODO Auto-generated catch block
			request.setAttribute("erroreNelPunteggio", "Collaborazione a cui aggiungere il feedBack non trovata");
			getServletConfig().getServletContext().getRequestDispatcher("/jsp/utenti/profilo/rilascioFeedBack.jsp").forward(request, response);
			return;
		}
		request.setAttribute("feedBackRilasciato", "Feedback rilasciato con successo");
		getServletConfig().getServletContext().getRequestDispatcher("/jsp/utenti/profilo/rilascioFeedBack.jsp").forward(request, response);

	}

}


text:
import * as React from 'react'
import classNames from 'classnames'

import { FileChange } from '../../models/status'
import { Octicon, OcticonSymbol } from '../octicons'
import { RichText } from '../lib/rich-text'
import { Repository } from '../../models/repository'
import { Commit } from '../../models/commit'
import { getAvatarUsersForCommit, IAvatarUser } from '../../models/avatar'
import { AvatarStack } from '../lib/avatar-stack'
import { CommitAttribution } from '../lib/commit-attribution'
import { Checkbox, CheckboxValue } from '../lib/checkbox'
import {
  enableGitTagsDisplay,
  enableSideBySideDiffs,
} from '../../lib/feature-flag'
import { Tokenizer, TokenResult } from '../../lib/text-token-parser'
import { wrapRichTextCommitMessage } from '../../lib/wrap-rich-text-commit-message'
import { DiffOptions } from '../diff/diff-options'

interface ICommitSummaryProps {
  readonly repository: Repository
  readonly commit: Commit
  readonly files: ReadonlyArray<FileChange>
  readonly emoji: Map<string, string>

  /**
   * Whether or not the commit body container should
   * be rendered expanded or not. In expanded mode the
   * commit body container takes over the diff view
   * allowing for full height, scrollable reading of
   * the commit message body.
   */
  readonly isExpanded: boolean

  readonly onExpandChanged: (isExpanded: boolean) => void

  readonly onDescriptionBottomChanged: (descriptionBottom: Number) => void

  readonly hideDescriptionBorder: boolean

  readonly hideWhitespaceInDiff: boolean

  /** Whether we should display side by side diffs. */
  readonly showSideBySideDiff: boolean
  readonly onHideWhitespaceInDiffChanged: (checked: boolean) => void

  /** Called when the user changes the side by side diffs setting. */
  readonly onShowSideBySideDiffChanged: (checked: boolean) => void

  /** Called when the user opens the diff options popover */
  readonly onDiffOptionsOpened: () => void
}

interface ICommitSummaryState {
  /**
   * The commit message summary, i.e. the first line in the commit message.
   * Note that this may differ from the body property in the commit object
   * passed through props, see the createState method for more details.
   */
  readonly summary: ReadonlyArray<TokenResult>

  /**
   * The commit message body, i.e. anything after the first line of text in the
   * commit message. Note that this may differ from the body property in the
   * commit object passed through props, see the createState method for more
   * details.
   */
  readonly body: ReadonlyArray<TokenResult>

  /**
   * Whether or not the commit body text overflows its container. Used in
   * conjunction with the isExpanded prop.
   */
  readonly isOverflowed: boolean

  /**
   * The avatars associated with this commit. Used when rendering
   * the avatar stack and calculated whenever the commit prop changes.
   */
  readonly avatarUsers: ReadonlyArray<IAvatarUser>
}

/**
 * Creates the state object for the CommitSummary component.
 *
 * Ensures that the commit summary never exceeds 72 characters and wraps it
 * into the commit body if it does.
 *
 * @param isOverflowed Whether or not the component should render the commit
 *                     body in expanded mode, see the documentation for the
 *                     isOverflowed state property.
 *
 * @param props        The current commit summary prop object.
 */
function createState(
  isOverflowed: boolean,
  props: ICommitSummaryProps
): ICommitSummaryState {
  const tokenizer = new Tokenizer(props.emoji, props.repository)

  const { summary, body } = wrapRichTextCommitMessage(
    props.commit.summary,
    props.commit.body,
    tokenizer
  )

  const avatarUsers = getAvatarUsersForCommit(
    props.repository.gitHubRepository,
    props.commit
  )

  return { isOverflowed, summary, body, avatarUsers }
}

/**
 * Helper function which determines if two commit objects
 * have the same commit summary and body.
 */
function messageEquals(x: Commit, y: Commit) {
  return x.summary === y.summary && x.body === y.body
}

export class CommitSummary extends React.Component<
  ICommitSummaryProps,
  ICommitSummaryState
> {
  private descriptionScrollViewRef: HTMLDivElement | null = null
  private readonly resizeObserver: ResizeObserver | null = null
  private updateOverflowTimeoutId: NodeJS.Immediate | null = null
  private descriptionRef: HTMLDivElement | null = null

  public constructor(props: ICommitSummaryProps) {
    super(props)

    this.state = createState(false, props)

    const ResizeObserverClass: typeof ResizeObserver = (window as any)
      .ResizeObserver

    if (ResizeObserverClass || false) {
      this.resizeObserver = new ResizeObserverClass(entries => {
        for (const entry of entries) {
          if (entry.target === this.descriptionScrollViewRef) {
            // We might end up causing a recursive update by updating the state
            // when we're reacting to a resize so we'll defer it until after
            // react is done with this frame.
            if (this.updateOverflowTimeoutId !== null) {
              clearImmediate(this.updateOverflowTimeoutId)
            }

            this.updateOverflowTimeoutId = setImmediate(this.onResized)
          }
        }
      })
    }
  }

  private onHideWhitespaceInDiffChanged = (
    event: React.FormEvent<HTMLInputElement>
  ) => {
    const value = event.currentTarget.checked
    this.props.onHideWhitespaceInDiffChanged(value)
  }

  private onResized = () => {
    if (this.descriptionRef) {
      const descriptionBottom = this.descriptionRef.getBoundingClientRect()
        .bottom
      this.props.onDescriptionBottomChanged(descriptionBottom)
    }

    if (this.props.isExpanded) {
      return
    }

    this.updateOverflow()
  }

  private onDescriptionScrollViewRef = (ref: HTMLDivElement | null) => {
    this.descriptionScrollViewRef = ref

    if (this.resizeObserver) {
      this.resizeObserver.disconnect()

      if (ref) {
        this.resizeObserver.observe(ref)
      } else {
        this.setState({ isOverflowed: false })
      }
    }
  }

  private onDescriptionRef = (ref: HTMLDivElement | null) => {
    this.descriptionRef = ref
  }

  private renderExpander() {
    if (
      !this.state.body.length ||
      (!this.props.isExpanded && !this.state.isOverflowed)
    ) {
      return null
    }

    const expanded = this.props.isExpanded
    const onClick = expanded ? this.onCollapse : this.onExpand
    const icon = expanded ? OcticonSymbol.fold : OcticonSymbol.unfold

    return (

        <Octicon symbol={icon} />
        {expanded ? 'Collapse' : 'Expand'}

    )
  }

  private onExpand = () => {
    this.props.onExpandChanged(true)
  }

  private onCollapse = () => {
    if (this.descriptionScrollViewRef) {
      this.descriptionScrollViewRef.scrollTop = 0
    }

    this.props.onExpandChanged(false)
  }

  private updateOverflow() {
    const scrollView = this.descriptionScrollViewRef
    if (scrollView) {
      this.setState({
        isOverflowed: scrollView.scrollHeight > scrollView.offsetHeight,
      })
    } else {
      if (this.state.isOverflowed) {
        this.setState({ isOverflowed: false })
      }
    }
  }

  public componentDidMount() {
    // No need to check if it overflows if we're expanded
    if (!this.props.isExpanded) {
      this.updateOverflow()
    }
  }

  public componentWillUpdate(nextProps: ICommitSummaryProps) {
    if (!messageEquals(nextProps.commit, this.props.commit)) {
      this.setState(createState(false, nextProps))
    }
  }

  public componentDidUpdate(
    prevProps: ICommitSummaryProps,
    prevState: ICommitSummaryState
  ) {
    // No need to check if it overflows if we're expanded
    if (!this.props.isExpanded) {
      // If the body has changed or we've just toggled the expanded
      // state we'll recalculate whether we overflow or not.
      if (prevState.body !== this.state.body || prevProps.isExpanded) {
        this.updateOverflow()
      }
    } else {
      // Clear overflow state if we're expanded, we don't need it.
      if (this.state.isOverflowed) {
        this.setState({ isOverflowed: false })
      }
    }
  }

  private renderDescription() {
    if (this.state.body.length === 0) {
      return null
    }

    return (

          <RichText
            className="commit-summary-description"
            emoji={this.props.emoji}
            repository={this.props.repository}
            text={this.state.body}
          />

        {this.renderExpander()}

    )
  }

  public render() {
    const fileCount = this.props.files.length
    const filesPlural = fileCount === 1 ? 'file' : 'files'
    const filesDescription = `${fileCount} changed ${filesPlural}`
    const shortSHA = this.props.commit.shortSha

    const className = classNames({
      expanded: this.props.isExpanded,
      collapsed: !this.props.isExpanded,
      'has-expander': this.props.isExpanded || this.state.isOverflowed,
      'hide-description-border': this.props.hideDescriptionBorder,
    })

    return (

          <RichText
            className="commit-summary-title"
            emoji={this.props.emoji}
            repository={this.props.repository}
            text={this.state.summary}
          />

              <AvatarStack users={this.state.avatarUsers} />
              <CommitAttribution
                gitHubRepository={this.props.repository.gitHubRepository}
                commit={this.props.commit}
              />

                <Octicon symbol={OcticonSymbol.gitCommit} />

              {shortSHA}

                <Octicon symbol={OcticonSymbol.diff} />

              {filesDescription}

            {this.renderTags()}

            {enableSideBySideDiffs() || (

                <Checkbox
                  label="Hide Whitespace"
                  value={
                    this.props.hideWhitespaceInDiff
                      ? CheckboxValue.On
                      : CheckboxValue.Off
                  }
                  onChange={this.onHideWhitespaceInDiffChanged}
                />

            )}

            {enableSideBySideDiffs() && (
              <>

                  <DiffOptions
                    onHideWhitespaceChangesChanged={
                      this.props.onHideWhitespaceInDiffChanged
                    }
                    hideWhitespaceChanges={this.props.hideWhitespaceInDiff}
                    showSideBySideDiff={this.props.showSideBySideDiff}
                    onShowSideBySideDiffChanged={
                      this.props.onShowSideBySideDiffChanged
                    }
                    onDiffOptionsOpened={this.props.onDiffOptionsOpened}
                  />

              </>
            )}

        {this.renderDescription()}

    )
  }

  private renderTags() {
    if (!enableGitTagsDisplay()) {
      return null
    }

    const tags = this.props.commit.tags || []

    if (tags.length === 0) {
      return null
    }

    return (

          <Octicon symbol={OcticonSymbol.tag} />

        {tags.join(', ')}

    )
  }
}


text:
package org.winterblade.minecraft.harmony.tileentities.matchers;

import net.minecraft.tileentity.TileEntity;
import org.winterblade.minecraft.harmony.api.BaseMatchResult;
import org.winterblade.minecraft.harmony.api.Component;
import org.winterblade.minecraft.harmony.api.PrioritizedObject;
import org.winterblade.minecraft.harmony.api.Priority;
import org.winterblade.minecraft.harmony.api.tileentities.ITileEntityMatcher;
import org.winterblade.minecraft.harmony.api.utility.CallbackMetadata;
import org.winterblade.minecraft.harmony.common.matchers.BaseScoreboardMatcher;

/**
 * Created by Matt on 6/4/2016.
 */
@Component(properties = {"minScore"})
@PrioritizedObject(priority = Priority.HIGH)
public class MinScoreboardMatcher extends BaseScoreboardMatcher implements ITileEntityMatcher {
    public MinScoreboardMatcher(ScoreboardMatchData score) {
        super(score.withMinValue());
    }

    @Override
    public BaseMatchResult isMatch(TileEntity tileEntity, CallbackMetadata metadata) {
        return matches(tileEntity.getWorld(), null);
    }
}


text:
using Microsoft.AspNet.Authorization;
using Microsoft.AspNet.Mvc;

namespace Ascon.Pilot.WebClient.Controllers
{
    /// <summary>
    /// Контроллер задач
    /// </summary>
    [Authorize]
    public class TasksController : Controller
    {
        /// <summary>
        /// Открытие представление Index
        /// </summary>
        /// <returns>представление Index</returns>
        // GET: /<controller>/
        public IActionResult Index()
        {
            return View();
        }
    }
}


text:
package com.haulmont.cuba.web.gui.components.filter.edit;

import com.haulmont.cuba.gui.WindowManager;
import com.haulmont.cuba.gui.components.Frame;
import com.haulmont.cuba.gui.components.filter.edit.FilterEditor;

public class WebFilterEditorCompanion implements FilterEditor.Companion {
    @Override
    public void showComponentName(WindowManager windowManager, String title, String message) {
        windowManager.showMessageDialog(title, message, Frame.MessageType.CONFIRMATION);
    }
}


text:
package support;

/**
 * Contains useful methods for working with {@link String}s.
 */
public final class StringHelper {
    /**
     * Prevent instantiation.
     */
    private StringHelper() {
    }

    /**
     * Indicates whether a specified String is null, empty, or consists only of white-space characters.
     *
     * @param s the String to test
     * @return true if the String is null, empty, or consists only of white-space characters, false otherwise
     */
    public static boolean isNullOrWhiteSpace(String s) {
        return s == null || (s.length() >= 0 && s.trim().length() <= 0);
    }

    /**
     * Indicates whether a specified String is null or empty.
     *
     * @param s the String to test
     * @return true if the String is null, empty, or consists only of white-space characters, false otherwise
     */
    public static boolean isNullOrEmpty(String s) {
        return s == null || s.length() <= 0;
    }
}


text:
using System.Collections.Generic;

namespace Clustering.SolutionModel.Nodes
{
    //Abstract class inhereted by both SolutionFolder and Solution, they can both contain solution items
    public abstract class SolutionItemContainer : Node
    {
        //Gives a flat list of all projects found in the solution
        public IEnumerable<ProjectNode> Projects()
        {
            foreach (var node in Children)
            {
                if (node is ProjectNode)
                {
                    yield return node as ProjectNode;
                }
                else if (node is SolutionFolderNode)
                {
                    foreach (var projNode in (node as SolutionFolderNode).Projects())
                    {
                        yield return projNode;
                    }
                }
            }
        }

        public SolutionItemContainer(string name, IEnumerable<Node> children) : base(name, children)
        {
        }
    }

    //Abstract class inhereted by both Namespace and Projec, they can both contain solution items
    /*public abstract class ClassContainer : Node
    {
        //Gives a flat list of all projects found in the solution
        public IEnumerable<ClassNode> Classes()
        {
            foreach (var node in Children)
            {
                if (node is ClassNode)
                {
                    yield return node as ClassNode;
                }
                else if (node is ClassContainer)
                {
                    foreach (var classNode in (node as ClassContainer).Classes())
                    {
                        yield return classNode;
                    }
                }
            }
        }

        public ClassContainer(string path, IEnumerable<Node> children, Node parent) : base(path, children, parent)
        {
        }
    }*/
}


text:
using System;
using Ligas.Core;
using Ligas.Domain.Tournament.Events;

namespace Ligas.Domain.Tournament
{
    public class TournamentView : IView
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string Description { get; set; }
    }

    public class TournamentsViewProjection : ViewProjection<TournamentView>,
        IEventHandler<TournamentCreated>,
        IEventHandler<TournamentDeleted>
    {
        public TournamentsViewProjection(IViewRepository<TournamentView> repository)
            : base(repository)
        {
        }

        public void On(TournamentCreated e)
        {
            Repository.Add(MapFrom(e));
        }

        public void On(TournamentDeleted e)
        {
            Repository.Delete(e.Id);
        }
    }
}


text:
package org.onlab.netty;

import java.io.IOException;

/**
 * Internal message representation with additional attributes
 * for supporting, synchronous request/reply behavior.
 */
public final class InternalMessage implements Message {

    public static final String REPLY_MESSAGE_TYPE = "NETTY_MESSAGING_REQUEST_REPLY";

    private long id;
    private Endpoint sender;
    private String type;
    private byte[] payload;
    private transient NettyMessagingService messagingService;

    // Must be created using the Builder.
    private InternalMessage() {}

    InternalMessage(long id, Endpoint sender, String type, byte[] payload) {
        this.id = id;
        this.sender = sender;
        this.type = type;
        this.payload = payload;
    }

    public long id() {
        return id;
    }

    public String type() {
        return type;
    }

    public Endpoint sender() {
        return sender;
    }

    @Override
    public byte[] payload() {
        return payload;
    }

    protected void setMessagingService(NettyMessagingService messagingService) {
        this.messagingService = messagingService;
    }

    @Override
    public void respond(byte[] data) throws IOException {
        Builder builder = new Builder(messagingService);
        InternalMessage message = builder.withId(this.id)
            .withSender(messagingService.localEp())
            .withPayload(data)
            .withType(REPLY_MESSAGE_TYPE)
            .build();
        messagingService.sendAsync(sender, message);
    }

    /**
     * Builder for InternalMessages.
     */
    public static final class Builder {
        private InternalMessage message;

        public Builder(NettyMessagingService messagingService) {
            message = new InternalMessage();
            message.messagingService = messagingService;
        }

        public Builder withId(long id) {
            message.id = id;
            return this;
        }

        public Builder withType(String type) {
            message.type = type;
            return this;
        }

        public Builder withSender(Endpoint sender) {
            message.sender = sender;
            return this;
        }
        public Builder withPayload(byte[] payload) {
            message.payload = payload;
            return this;
        }

        public InternalMessage build() {
            return message;
        }
    }
}


text:
[![](https://images.microbadger.com/badges/image/alexcheng/magento2.svg)](http://microbadger.com/images/alexcheng/magento2)

[![Docker build](http://dockeri.co/image/alexcheng/magento2)](https://hub.docker.com/r/alexcheng/magento2/)

[![Docker Repository on Quay](https://quay.io/repository/alexcheng1982/magento2/status "Docker Repository on Quay")](https://quay.io/repository/alexcheng1982/magento2)

This repo provides Docker images for different Magento 2 versions. Refer to [this page](https://hub.docker.com/r/alexcheng/magento2/tags/) to see all available tags. It uses the same convention as my [Docker image for Magento 1.x](https://github.com/alexcheng1982/docker-magento).

This docker image is based on my [docker-apache2-php7](https://github.com/alexcheng1982/docker-apache2-php7) image for Apache 2 and PHP 7. Please refer to the image label `php_version` for the actual PHP version. In general, Magento `2.1.x` uses latest PHP `7.0.x`, Magento `2.2.x` uses latest PHP `7.1.x`, and `2.3.x` uses latest PHP `7.2.x`. Please refer to the label `php_version` of the image to get the actual PHP version.

> This docker image is based on [phusion/baseimage-docker](https://github.com/phusion/baseimage-docker) with Ubuntu 18.04 LTS. The reason to use `phusion/baseimage-docker` is to support multiple processes, which is important to get cron jobs working in Mangento.

**Please note: this Docker image is for development and testing only, not ready for production use. Setting up a Magento 2 production server requires more configurations. Please refer to [official documentations](http://devdocs.magento.com/guides/v2.2/config-guide/deployment/). You can this image as the base to build customized images.**

## Magento 2 installation types

Magento 2 has three different ways to [install](http://devdocs.magento.com/guides/v2.0/install-gde/bk-install-guide.html), for users, integrators and developers. This Docker image uses **integrator** as the default installation type, so the **Web Setup Wizard** can be used. For each version, both integrator and developer installation types are available. The user installation type is not currently supported.

For example, Magento 2 version `2.2.2` has tag `2.2.2`, `2.2.2-integrator` and `2.2.2-developer`. `2.2.2` is the same as `2.2.2-integrator`.

Below are some basic instructions.

## Quick start

The easiest way to start Magento 2 with MySQL is using [Docker Compose](https://docs.docker.com/compose/). Just clone this repo and run following command in the root directory. The default `docker-compose.yml` uses MySQL and phpMyAdmin.

~~~
$ docker-compose up -d
~~~

For admin username and password, please refer to the file `env`. You can also change the file `env` to update those configurations. Below are the default configurations.

~~~
MYSQL_HOST=db
MYSQL_ROOT_PASSWORD=myrootpassword
MYSQL_USER=magento
MYSQL_PASSWORD=magento
MYSQL_DATABASE=magento

MAGENTO_LANGUAGE=en_GB
MAGENTO_TIMEZONE=Pacific/Auckland
MAGENTO_DEFAULT_CURRENCY=NZD
MAGENTO_URL=http://local.magento
MAGENTO_BACKEND_FRONTNAME=admin
MAGENTO_USE_SECURE=0
MAGENTO_BASE_URL_SECURE=0
MAGENTO_USE_SECURE_ADMIN=0

MAGENTO_ADMIN_FIRSTNAME=Admin
MAGENTO_ADMIN_LASTNAME=MyStore
MAGENTO_ADMIN_EMAIL=amdin@example.com
MAGENTO_ADMIN_USERNAME=admin
MAGENTO_ADMIN_PASSWORD=magentorocks1
~~~

For example, if you want to change the default currency, just update the variable `MAGENTO_DEFAULT_CURRENCY`, e.g. `MAGENTO_DEFAULT_CURRENCY=USD`.

To get all the possible values of `MAGENTO_LANGUAGE`, `MAGENTO_TIMEZONE` and `MAGENTO_DEFAULT_CURRENCY`, run the corresponding command shown below:

* `MAGENTO_LANGUAGE` - `bin/magento info:language:list`
* `MAGENTO_TIMEZONE` - `bin/magento info:timezone:list`
* `MAGENTO_DEFAULT_CURRENCY` - `bin/magento info:currency:list`

For example, to get all possible values of `MAGENTO_LANGUAGE`, run

```bash
$ docker run --rm -it alexcheng/magento2 bin/magento info:language:list
```

You can find all available options in the official [setup guide](http://devdocs.magento.com/guides/v2.0/install-gde/install/cli/install-cli-install.html#instgde-install-cli-magento). If you need more options, fork this repo and add them in `bin\install-magento`.

Please see the following video for a quick demo.

[![Use Magento 2 with Docker](https://img.youtube.com/vi/18tOf_cuQKg/hqdefault.jpg)](https://www.youtube.com/watch?v=18tOf_cuQKg "Use Magento 2 with Docker")

## Installation

After starting the container, you'll see the setup page of Magento 2. You can use the script `install-magento` to quickly install Magento 2. The installation script uses the variables in the `env` file.

### Magento 2

~~~
$ docker exec -it <container_name> install-magento
~~~

### Sample data

~~~
$ docker exec -it <container_name> install-sampledata
~~~

**Please note:** Sample data for Magento 2.2.2 doesn't work at the moment, see [this issue](https://github.com/alexcheng1982/docker-magento2/issues/11).

### Database

The default `docker-compose.yml` uses MySQL as the database and starts [phpMyAdmin](https://www.phpmyadmin.net/). The default URL for phpMyAdmin is `http://localhost:8580`. Use MySQL username and password to log in.

Magento starts support of MySQL 5.7 in version `2.1.2`. Before `2.1.2`, MySQL 5.6 should be used.

## FAQ

### How to keep installed Magento?

You can add a volume to folder `/var/www/html`, see the `docker-compose.yml` file.

```
volumes:
  - magento-data:/var/www/html
```

### Where is the database?

Magento 2 cannot run without a database. This image is for Magento 2 only. It doesn't contain MySQL server. MySQL server should be started in another container and linked with Magento 2 container. It's recommended to use Docker Compose to start both containers. You can also use [Kubernetes](https://kubernetes.io/) or other tools.

### Why accessing http://local.magento?

For development and testing in the local environment, using `localhost` as Magento 2 URL has some issues. The default `env` file use `http://local.magento` as the value of `MAGENTO_URL`. You need to [edit your `hosts` file](https://support.rackspace.com/how-to/modify-your-hosts-file/) to add the mapping from `local.magento` to `localhost`. You can use any domain names as long as it looks like a real domain, not `localhost`.

If `localhost` doesn't work, try using `127.0.0.1`.

```
127.0.0.1    local.magento
```

### How to update Magento 2 installation configurations?

Depends on how the container is used,

* When using the GUI setup page of Magento 2, update configurations in the UI.
* When using the script, update configurations in the `env` file.
* When starting Magento 2 as a standalone container, use `-e` to pass environment variables.

### Why getting access denied error after changing the default DB password?

If you change the default DB password in `env` file and get the access denied error when installing Magento 2, see [this issue comment](https://github.com/alexcheng1982/docker-magento2/issues/10#issuecomment-355382150).

## Develop and test using this Docker image

As I mentioned before, this Docker image is primarily used for development and testing. Depends on the tasks you are trying to do, there are different ways to use this Docker image.

### Extensions and themes

You can keep the extensions and themes directories on your local host machine, and use Docker Compose [volumes](https://docs.docker.com/compose/compose-file/#volumes) to install the extensions and themes. For example, if you have a theme in the directory `/dev/mytheme`, you can install it by specifying it in the `docker-composer.yml` file. Then you can see the theme in Magento admin UI.

```yml
version: '3.0'
services:
  web:
    image: alexcheng/magento2
    ports:
      - "80:80"
    links:
      - db
    env_file:
      - env
    volumes:
      - /dev/mytheme:/var/www/html/app/design/frontend/mytheme/default
  db:
    image: mysql:5.6.23
    volumes:
      - db-data:/var/lib/mysql/data
    env_file:
      - env
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    ports:
      - "8580:80"
    links:
      - db
volumes:
  db-data:
```

### Modify Magento core files

If you want to modify Magento core files, you cannot modify them directly in the container. Those changes will be lost. It's also not recommended to update Magento core files directly, which makes upgrading Magento a painful process. Actually, Docker makes the process much easier if you absolutely need to modify some core files. You can use volumes to overwrite files.

For example, if you want to overwrite the file `app/code/Magento/Catalog/Block/Product/Price.php`, you can copy the content to a new file in your local directory `/dev/mycode/magento_2_2` and make the changes, then use `volumes` to overwrite it.

```yml
volumes:
  - /dev/mycode/magento_2_2/app/code/Magento/Catalog/Block/Product/Price.php:/var/www/html/app/code/Magento/Catalog/Block/Product/Price.php
```

By using Docker, we can make sure that all your changes to Magento core files are kept in one place and tracked in source code repository. These changes are also correctly aligned with different Magento versions.

When deploying those changes to production servers, we can simply copy all files in the `/dev/mycode/magento_2_2` directory to Magento installation directory and overwrite existing files.

### Test Magento compatibilities

This Docker images has different tags for corresponding Magento versions, e.g. `2.2.1`, `2.2.2`. You can switch to different Magento versions very easily when testing extensions and themes.


text:
import coulomb.testing.CoulombSuite

class SpireQuantitySuite extends CoulombSuite:
    import spire.math.*
    import coulomb.*
    import coulomb.syntax.*

    import algebra.instances.all.given
    import coulomb.ops.algebra.spire.all.{*, given}

    import coulomb.units.si.{*, given}
    import coulomb.units.si.prefixes.{*, given}
    import coulomb.units.mksa.{*, given}
    import coulomb.units.us.{*, given}

    test("toValue") {
        import coulomb.policy.spire.strict.given

        1.withUnit[Meter].toValue[Int].assertQ[Int, Meter](1)
        1.withUnit[Meter].toValue[Long].assertQ[Long, Meter](1)
        1.withUnit[Meter].toValue[BigInt].assertQ[BigInt, Meter](1)
        1.withUnit[Meter].toValue[BigDecimal].assertQ[BigDecimal, Meter](1)
        1.withUnit[Meter].toValue[Rational].assertQ[Rational, Meter](1)
        1.withUnit[Meter].toValue[Algebraic].assertQ[Algebraic, Meter](1)
        1.withUnit[Meter].toValue[Real].assertQ[Real, Meter](1)

        1L.withUnit[Meter].toValue[Int].assertQ[Int, Meter](1)
        BigInt(1).withUnit[Meter].toValue[Long].assertQ[Long, Meter](1)
        1.withUnit[Meter].toValue[BigInt].assertQ[BigInt, Meter](1)

        assertCE("1d.withUnit[Meter].toValue[Int]")
        2.5d.withUnit[Meter].tToValue[Int].assertQ[Int, Meter](2)
        assertCE("Rational(1).withUnit[Meter].toValue[BigInt]")
        Rational(5, 2)
            .withUnit[Meter]
            .tToValue[BigInt]
            .assertQ[BigInt, Meter](2)
        assertCE("BigDecimal(1).withUnit[Meter].toValue[BigInt]")
        BigDecimal(2.5).withUnit[Meter].tToValue[Long].assertQ[Long, Meter](2)
    }

    test("toUnit") {
        import coulomb.policy.spire.strict.given

        Rational(1)
            .withUnit[Yard]
            .toUnit[Meter]
            .assertQ[Rational, Meter](Rational(9144, 10000))
        BigDecimal(1)
            .withUnit[Yard]
            .toUnit[Meter]
            .assertQ[BigDecimal, Meter](BigDecimal(0.9144))
        Algebraic(1)
            .withUnit[Yard]
            .toUnit[Meter]
            .assertQ[Algebraic, Meter](Algebraic(0.9144))
        Real(1)
            .withUnit[Yard]
            .toUnit[Meter]
            .assertQ[Real, Meter](Real(Rational(9144, 10000)))

        assertCE("BigInt(10).withUnit[Yard].toUnit[Meter]")
        BigInt(10).withUnit[Yard].tToUnit[Meter].assertQ[BigInt, Meter](9)
    }

    test("addition strict") {
        import coulomb.policy.spire.strict.given

        (Rational(1).withUnit[Meter] + Rational(1).withUnit[Meter])
            .assertQ[Rational, Meter](Rational(2))
        (BigInt(1).withUnit[Meter] + BigInt(1).withUnit[Meter])
            .assertQ[BigInt, Meter](BigInt(2))
        (BigDecimal(1).withUnit[Meter] + BigDecimal(1).withUnit[Meter])
            .assertQ[BigDecimal, Meter](BigDecimal(2))
        (Algebraic(1).withUnit[Meter] + Algebraic(1).withUnit[Meter])
            .assertQ[Algebraic, Meter](Algebraic(2))
        (Real(1).withUnit[Meter] + Real(1).withUnit[Meter])
            .assertQ[Real, Meter](Real(2))

        assertCE("Real(1).withUnit[Meter] + Rational(1).withUnit[Meter]")
        assertCE("Rational(1).withUnit[Meter] + Rational(1).withUnit[Yard]")

        (Real(1).withUnit[Meter].toValue[Rational] + Rational(1)
            .withUnit[Meter])
            .assertQ[Rational, Meter](Rational(2))
        (Rational(1).withUnit[Meter] + Rational(1).withUnit[Yard].toUnit[Meter])
            .assertQ[Rational, Meter](Rational(19144, 10000))
    }

    test("addition standard") {
        import coulomb.policy.spire.standard.given

        (Rational(1).withUnit[Meter] + Rational(1).withUnit[Meter])
            .assertQ[Rational, Meter](Rational(2))

        (Rational(1).withUnit[Meter] + Rational(1).withUnit[Yard])
            .assertQ[Rational, Meter](Rational(19144, 10000))
        (BigDecimal(1).withUnit[Meter] + BigDecimal(1).withUnit[Yard])
            .assertQ[BigDecimal, Meter](BigDecimal(1.9144))

        (1.withUnit[Meter] + BigInt(1).withUnit[Meter])
            .assertQ[BigInt, Meter](BigInt(2))
        (BigInt(1).withUnit[Meter] + 1.withUnit[Meter])
            .assertQ[BigInt, Meter](BigInt(2))
        (1f.withUnit[Meter] + BigDecimal(1).withUnit[Meter])
            .assertQ[BigDecimal, Meter](BigDecimal(2))
        (BigDecimal(1).withUnit[Meter] + 1f.withUnit[Meter])
            .assertQ[BigDecimal, Meter](BigDecimal(2))
        (1.withUnit[Meter] + Real(1).withUnit[Meter])
            .assertQ[Real, Meter](Real(2))
        (Real(1).withUnit[Meter] + 1.withUnit[Meter])
            .assertQ[Real, Meter](Real(2))

        (Rational(1).withUnit[Meter] + BigDecimal(1).withUnit[Yard])
            .assertQ[Rational, Meter](Rational(19144, 10000))
        (BigDecimal(1).withUnit[Meter] + Rational(1).withUnit[Yard])
            .assertQ[Rational, Meter](Rational(19144, 10000))

        assertCE("BigDecimal(1).withUnit[Meter] + BigDecimal.withUnit[Second]")

        assertCE("BigInt(1).withUnit[Meter] + BigInt(1).withUnit[Yard]")

        (BigInt(1).withUnit[Meter] + BigInt(1).withUnit[Yard].tToUnit[Meter])
            .assertQ[BigInt, Meter](BigInt(1))
    }

    test("tquot") {
        import coulomb.policy.spire.standard.given

        (BigInt(5).withUnit[Meter] `tquot` BigInt(2).withUnit[Second])
            .assertQ[BigInt, Meter / Second](BigInt(2))
    }

    test("pow") {
        import coulomb.policy.spire.standard.given

        Rational(2).withUnit[Meter].pow[0].assertQ[Rational, 1](Rational(1))
        Rational(2)
            .withUnit[Meter]
            .pow[2]
            .assertQ[Rational, Meter ^ 2](Rational(4))
        Rational(2)
            .withUnit[Meter]
            .pow[-1]
            .assertQ[Rational, 1 / Meter](Rational(1, 2))
        Rational(2)
            .withUnit[Meter]
            .pow[1 / 2]
            .assertQD[Rational, Meter ^ (1 / 2)](1.4142135623730951)
        Rational(2)
            .withUnit[Meter]
            .pow[-1 / 2]
            .assertQD[Rational, 1 / (Meter ^ (1 / 2))](0.7071067811865476)

        BigDecimal(2)
            .withUnit[Meter]
            .pow[1 / 2]
            .assertQD[BigDecimal, Meter ^ (1 / 2)](1.4142135623730951)
        Algebraic(2)
            .withUnit[Meter]
            .pow[1 / 2]
            .assertQD[Algebraic, Meter ^ (1 / 2)](1.4142135623730951)
        Real(2)
            .withUnit[Meter]
            .pow[1 / 2]
            .assertQD[Real, Meter ^ (1 / 2)](1.4142135623730951)

        BigInt(2).withUnit[Meter].pow[0].assertQ[BigInt, 1](1)
        BigInt(2).withUnit[Meter].pow[2].assertQ[BigInt, Meter ^ 2](4)
        assertCE("BigInt(2).withUnit[Meter].pow[-1]")
        assertCE("BigInt(2).withUnit[Meter].pow[1 / 2]")
        assertCE("BigInt(2).withUnit[Meter].pow[-1 / 2]")
    }

    test("tpow") {
        import coulomb.policy.spire.standard.given

        BigInt(10).withUnit[Meter].tpow[0].assertQ[BigInt, 1](BigInt(1))
        BigInt(10)
            .withUnit[Meter]
            .tpow[2]
            .assertQ[BigInt, Meter ^ 2](BigInt(100))
        BigInt(10)
            .withUnit[Meter]
            .tpow[-1]
            .assertQ[BigInt, 1 / Meter](BigInt(0))
        BigInt(10)
            .withUnit[Meter]
            .tpow[1 / 2]
            .assertQ[BigInt, Meter ^ (1 / 2)](BigInt(3))
        BigInt(10)
            .withUnit[Meter]
            .tpow[-1 / 2]
            .assertQ[BigInt, 1 / (Meter ^ (1 / 2))](BigInt(0))
    }

    test("mul and div by lifted unitless values") {
        import coulomb.policy.spire.standard.given
        import scala.language.implicitConversions

        val q = 2.withUnit[Meter]

        (Rational(2) * q).assertQ[Rational, Meter](4)
        (Rational(2) / q).assertQ[Rational, 1 / Meter](1)

        (q * Rational(2)).assertQ[Rational, Meter](4)
        (q / Rational(2)).assertQ[Rational, Meter](1)
    }

    test("< strict") {
        import coulomb.policy.spire.strict.given

        assertEquals(
            Rational(1).withUnit[Meter] < Rational(2).withUnit[Meter],
            true
        )
        assertEquals(
            BigDecimal(2).withUnit[Meter] < BigDecimal(1).withUnit[Meter],
            false
        )
        assertEquals(
            Algebraic(1).withUnit[Meter] < Algebraic(2).withUnit[Meter],
            true
        )
        assertEquals(Real(2).withUnit[Meter] < Real(1).withUnit[Meter], false)
        assertEquals(
            BigInt(1).withUnit[Meter] < BigInt(2).withUnit[Meter],
            true
        )
    }

    test("< standard") {
        import coulomb.policy.spire.standard.given

        assertEquals(
            Rational(1).withUnit[Yard] < Rational(1).withUnit[Meter],
            true
        )
        assertEquals(
            BigDecimal(1).withUnit[Meter] < BigDecimal(1).withUnit[Yard],
            false
        )
        assertEquals(
            Algebraic(1).withUnit[Yard] < Algebraic(1).withUnit[Meter],
            true
        )
        assertEquals(Real(1).withUnit[Meter] < Real(1).withUnit[Yard], false)

        assertEquals(
            Rational(1).withUnit[Yard] < BigInt(1).withUnit[Meter],
            true
        )
        assertEquals(
            BigDecimal(1).withUnit[Meter] < Rational(1).withUnit[Yard],
            false
        )
        assertEquals(
            Algebraic(1).withUnit[Yard] < Real(1).withUnit[Meter],
            true
        )
        assertEquals(
            Rational(1).withUnit[Meter] < BigDecimal(1).withUnit[Yard],
            false
        )
    }


text:
'use strict';

import nls = require('vs/nls');
import {IWorkbenchActionRegistry, Extensions} from 'vs/workbench/browser/actionRegistry';
import {Registry} from 'vs/platform/platform';
import {Action} from 'vs/base/common/actions';
import {Promise} from 'vs/base/common/winjs.base';
import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry';
import {IQuickOpenService} from 'vs/workbench/services/quickopen/common/quickOpenService';
import {IKeybindingService, IKeybindings} from 'vs/platform/keybinding/common/keybindingService';
import {SyncActionDescriptor} from 'vs/platform/actions/common/actions';
import {KeyMod, KeyCode} from 'vs/base/common/keyCodes';

// Trigger Quick Open
class GlobalQuickOpenAction extends Action {

	public static ID = 'workbench.action.quickOpen';
	public static LABEL = nls.localize('quickOpen', "Go to File...");

	constructor(id: string, label: string, @IQuickOpenService private quickOpenService: IQuickOpenService) {
		super(id, label);

		this.order = 100; // Allow other actions to position before or after
		this.class = 'quickopen';
	}

	public run(): Promise {
		this.quickOpenService.show(null);

		return Promise.as(true);
	}
}

// Open Previous Editor
class OpenPreviousEditorAction extends Action {

	public static ID = 'workbench.action.openPreviousEditor';
	public static LABEL = nls.localize('navigateEditorHistoryByInput', "Navigate History");

	constructor(
		id: string,
		label: string,
		@IQuickOpenService private quickOpenService: IQuickOpenService,
		@IKeybindingService private keybindingService: IKeybindingService
	) {
		super(id, label);
	}

	public run(): Promise {
		let keys = this.keybindingService.lookupKeybindings(this.id);

		this.quickOpenService.show(null, {
			keybindings: keys
		});

		return Promise.as(true);
	}
}

class BaseQuickOpenNavigateAction extends Action {
	private navigateNext: boolean;

	constructor(
		id: string,
		label: string,
		navigateNext: boolean,
		@IQuickOpenService private quickOpenService: IQuickOpenService,
		@IKeybindingService private keybindingService: IKeybindingService
	) {
		super(id, label);

		this.navigateNext = navigateNext;
	}

	public run(event?: any): Promise {
		let keys = this.keybindingService.lookupKeybindings(this.id);

		this.quickOpenService.quickNavigate({
			keybindings: keys
		}, this.navigateNext);

		return Promise.as(true);
	}
}

class QuickOpenNavigateNextAction extends BaseQuickOpenNavigateAction {

	public static ID = 'workbench.action.quickOpenNavigateNext';
	public static LABEL = nls.localize('quickNavigateNext', "Navigate Next in Quick Open");

	constructor(
		id: string,
		label: string,
		@IQuickOpenService quickOpenService: IQuickOpenService,
		@IKeybindingService keybindingService: IKeybindingService
	) {
		super(id, label, true, quickOpenService, keybindingService);
	}
}

class QuickOpenNavigatePreviousAction extends BaseQuickOpenNavigateAction {

	public static ID = 'workbench.action.quickOpenNavigatePrevious';
	public static LABEL = nls.localize('quickNavigatePrevious', "Navigate Previous in Quick Open");

	constructor(
		id: string,
		label: string,
		@IQuickOpenService quickOpenService: IQuickOpenService,
		@IKeybindingService keybindingService: IKeybindingService
	) {
		super(id, label, false, quickOpenService, keybindingService);
	}
}

const quickOpenKb: IKeybindings = {
	primary: KeyMod.CtrlCmd | KeyCode.KEY_P,
	secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E]
};

const QUICK_NAVIGATE_KEY = KeyCode.Tab;

const prevEditorKb: IKeybindings = {
	primary: KeyMod.CtrlCmd | QUICK_NAVIGATE_KEY,
	secondary: [KeyMod.CtrlCmd | KeyMod.Shift | QUICK_NAVIGATE_KEY],
	mac: {
		primary: KeyMod.WinCtrl | QUICK_NAVIGATE_KEY,
		secondary: [KeyMod.WinCtrl | KeyMod.Shift | QUICK_NAVIGATE_KEY]
	}
};

function navigateKeybinding(shift: boolean): IKeybindings {
	if (shift) {
		return {
			primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_P,
			secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_E, KeyMod.CtrlCmd | KeyMod.Shift | QUICK_NAVIGATE_KEY],
			mac: {
				primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_P,
				secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_E, KeyMod.WinCtrl | KeyMod.Shift | QUICK_NAVIGATE_KEY]
			}
		};
	} else {
		return {
			primary: KeyMod.CtrlCmd | KeyCode.KEY_P,
			secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E, KeyMod.CtrlCmd | QUICK_NAVIGATE_KEY],
			mac: {
				primary: KeyMod.CtrlCmd | KeyCode.KEY_P,
				secondary: [KeyMod.CtrlCmd | KeyCode.KEY_E, KeyMod.WinCtrl | QUICK_NAVIGATE_KEY]
			}
		};
	}
}

// Contribute Quick Open
let registry = <IWorkbenchActionRegistry>Registry.as(Extensions.WorkbenchActions);
registry.registerWorkbenchAction(new SyncActionDescriptor(GlobalQuickOpenAction, GlobalQuickOpenAction.ID, GlobalQuickOpenAction.LABEL, quickOpenKb));

// Contribute Quick Navigate
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenPreviousEditorAction, OpenPreviousEditorAction.ID, OpenPreviousEditorAction.LABEL, prevEditorKb));

// Contribute Quick Navigate in Quick Open
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenNavigateNextAction, QuickOpenNavigateNextAction.ID, QuickOpenNavigateNextAction.LABEL, navigateKeybinding(false), [{ key: 'inQuickOpen' }]));
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenNavigatePreviousAction, QuickOpenNavigatePreviousAction.ID, QuickOpenNavigatePreviousAction.LABEL, navigateKeybinding(true), [{ key: 'inQuickOpen' }], KeybindingsRegistry.WEIGHT.workbenchContrib(50)));


text:
package com.morristaedt.mirror.modules;

import android.os.AsyncTask;
import android.util.Log;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Lee on 4/24/2016.
 */
public class SeptaStationStatusModule {

    /** SeptaListener is called by android framework to bring up the Septa information
     *
     */
    public interface SeptaListener {
        void onNewUpdate(String SeptaUpdate);
    }

    /**
     * The getStationStatus returns the next departure in each direction for the selected station ID
     * @param StationID The septa station ID number or name
     * @param septaListener Brings up the septa view
     */
    public static void getStationStatus(final String StationID, final SeptaListener septaListener) {
        final String TAG = "SeptaAsyncModule"; //Use to log error message

        //Start UI thread for background operations
        new AsyncTask<Void, Void, String>() {
            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                septaListener.onNewUpdate(s);
            }

            @Override
            protected String doInBackground(Void... params) {
                try {

                    String sURL = "http://www3.septa.org/hackathon/Arrivals/" + StationID + "/1/";    // Connect to the URL
                    URL url = new URL(sURL);

                    //starts and opens a connection request
                    HttpURLConnection request = (HttpURLConnection)url.openConnection();
                    request.connect();

                    JsonParser jp = new JsonParser();
                    JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent())); //Convert the input stream to a json element
                    JsonObject rootObj = root.getAsJsonObject();

                    //Convert Array to JsonReader Object to determine exact name of first key
                    JsonReader jreader = new JsonReader(new StringReader(rootObj.toString()));
                    jreader.beginObject(); //Consumes the next token from the JSON stream and asserts that it is the beginning of a new object.
                    String septaTrainHeader = jreader.nextName();

                    //the next train to arrive from both northbound and southbound
                    JsonArray trainDetail = rootObj.getAsJsonArray(septaTrainHeader);
                    JsonObject northbound = trainDetail.get(0).getAsJsonObject().getAsJsonArray("Northbound").get(0).getAsJsonObject();
                    JsonObject southbound = trainDetail.get(1).getAsJsonObject().getAsJsonArray("Southbound").get(0).getAsJsonObject();

                    //replaces certain text in the septaTrainHeader
                    septaTrainHeader = septaTrainHeader.replace(": ", "\n as of ");

                    //gets the depart time of the JSON object
                    String northDepart = northbound.get("depart_time").getAsString();
                    //Cleans up double spaces
                    northDepart = northDepart.replace("  "," ");
                    //using regular expression to remove milliseconds from the time
                    northDepart = northDepart.replaceAll(":[0-9]{2}:[0-9]{3}"," ");
                    //gets the depart time from the json object
                    String southDepart = southbound.get("depart_time").getAsString();
                    //cleans up double spaces
                    southDepart = southDepart.replace("  "," ");
                    //using regular expression to remove milliseconds from the time
                    southDepart = southDepart.replaceAll(":[0-9]{2}:[0-9]{3}"," ");

                    //return user friendly string of text for display
                    return septaTrainHeader + "\n\n" +
                            "Next Northbound\n" +
                            "Leaving: " + northDepart + "\n" +
                            "Delay: " + northbound.get("status").getAsString() + "\n" +
                            "Destination: " + northbound.get("destination").getAsString() + "\n\n" +
                            "Next Southbound\n" +
                            "Leaving: " + southDepart + "\n" +
                            "Delay: " + southbound.get("status").getAsString() + "\n" +
                            "Destination: " + southbound.get("destination").getAsString();

                } catch (Exception err) {
                    Log.d(TAG, "Station status exception thrown: " + err);
                    return null;
                }
            }
        }.execute();
    }
}