Written by Evgeny Klimenchenko ✏️
GitHub Copilot is the newest tool developed by GitHub to autocomplete code with the help of OpenAI.
Copilot generates smart code suggestions with context, such as docstrings, code comments, function names, or even file names. It then uses all this information to suggest code snippets that developers can easily accept by pressing the Tab key on a keyboard.
It understands Python, JavaScript, TypeScript, Ruby, and Go, as well as dozens of other languages because it’s “trained on billions of lines of public code,” per the Copilot website. And while it's currently still in its limited technical preview, those interested can sign up to join a waitlist to try it out.
In this article, we’ll explore Copilot’s main functionalities, how to build a simple application using only Copilot, and its pros and cons.
Copilot’s main features
Copilot’s main feature is its autocomplete function. When typing a function description, for example, Copilot completes the whole function before a user finishes. While this autocomplete is similar to other general autocomplete functionalities, Copilot goes a step beyond.
When continuing to write code and adding more comments, Copilot begins to understand the whole context of the code through its AI capabilities. With the context, it autocompletes comments mid-sentence.
For example, by adding a function, it generates a whole comment and a function; in this case, it figured out the last function should be a multiply function, as seen below.
Another cool feature of Copilot is the ability to see 10 full-page suggestions, instead of a single one-liner suggestion, and choosing which suits the code best.
To do that, press ^ + Return
on a Mac keyboard or Ctrl + Enter
on Windows to open a list of suggestions, as shown below.
Can you build an application with only GitHub Copilot?
With Copilot’s capabilities, I wanted to challenge myself to build a small application using only Copilot. For this challenge, I wanted to create a simple random quote application that also displays the sentiment of the quote.
To do this, I had a few rules to follow to see how much benefit I could receive from Copilot.
First, I could not search the internet if I encountered a problem, including using Stack Overflow or documentation. This let me see whether it was possible to solely rely on Copilot's suggestions to create working code.
The second rule was that I could not write any new code myself. I could, however, write comments, variables, names, and function names to trigger Copilot’s suggestions. Similarly, I could also make small edits to the suggested code.
And finally, I could trigger the list of Copilot suggestions and accept one, since this is a built-in feature.
Setting up the project
I chose Next.js and React to build this project since they are the tools I am most familiar with to help me better evaluate Copilot’s performance.
Since React makes it fairly painless for developers to build applications, and I wanted to see how Copilot would manage React components.
For Next.js, it provides a good starting point where I didn’t need to spend a lot of time setting everything up, and it has built-in back-end functions, making it useful to call different API endpoints without triggering CORS errors.
While Next.js might seem too powerful for this small project, there’s no need to install other dependencies beforehand and its integrated, easy-to-use API functions make it a good choice for this challenge.
Developing the API endpoints
Starting with developing API endpoints, I wanted a quote generator that returns a random quote on a GET
request and a sentiment analysis endpoint. The sentiment analysis endpoint needed to receive a string as a query parameter and return a sentiment.
Since I didn't know what format the return value would be, I let Copilot write it and see what it could return.
/api/get_quote
GET
request endpoint
To create two endpoints using Next.js, I created two files in the api
folder: get_quote.js
and get_sentiment.js
. Next.js could then create these endpoints based on the file names. All that was left is to define was the handler functions inside those files, and I let Copilot do that for me.
For the get_quote
endpoint, I wrote a comment and chose a good suggestion:
// get random quote from random API
Clicking the comment, Copilot responds with a list of different options to pick from.
The suggestion I selected was the following:
const getQuote = async () => {
const response = await fetch('https://quotes.rest/qod.json')
const quote = await response.json()
return quote.contents.quotes[0].quote
}
This suggestion worked. Almost all of the other suggestions that I checked were either broken or required an API key that I didn’t have. This could be because Copilot was trained on open source GitHub code, and some endpoints might be outdated already, which can be frustrating.
Also, this endpoint returns the quote of the day, which means for every call, I receive the same quote for the current day, which was not what I was expecting. Instead, for every endpoint call, I wanted to receive a different random quote.
For the second part of this endpoint, I needed to create a handler for the endpoint that calls the function Copilot already generated. The handler is the function that Next.js calls when the client requests the endpoint.
To do this, I declared the function with its name to see whether Copilot would suggest the correct implementation or not.
And Copilot surprised me again. Everything seemed correct.
First, it called the getQuote
function and returned the quote received from the web service. Then, it saved the quote to the constant and returned JSON to the client with the retrieved quote. The only thing I had to add was .status(200)
to send the 200
status code to the client.
/api/get_sentiment
GET
request endpoint
For the get_sentiment
function, I chose Copilot’s suggestion and didn’t have to change anything.
I input the following:
// determine if the text is positive or negative
Then, Copilot suggested the following code, which I used:
async function getSentiment(text) {
const response = await fetch(`http://text-processing.com/api/sentiment/`, {
method: "POST",
body: `text=${text}`,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
})
const json = await response.json()
return json.label
}
However, for the endpoint part, I had to add .status(200)
, similar to the get_quote
endpoint. Here is what I provided to Copilot:
export default async function handler(req
And then, Copilot suggested the following, which I selected:
export default async function handler(req, res) {
const sentiment = await getSentiment(req.query.text)
res.json({ sentiment })
}
Copilot managed to provide us with a working solution again, suggesting the right handler and calculating what the get_sentiment
handle function needed to return. This suggestion looks similar to the one we had previously.
Let's see how Copilot handled React component generation next.
React components
For the frontend, I needed a couple of specified React components and a React controller component with a button. The two specified components needed to display text: one for quote text and another for sentiment text.
Let's see how Copilot handled creating these React components.
QuoteTextBox
I began with the QuoteTextBox
component that would showcase a simple quote; I added the following comment to see what Copilot would suggest:
// React component to show a quote inside a div
const
Copilot suggested a simple function component, which I did not have to change at all.
const QuoteTextBox = (props) => {
const { quote } = props
return (
<div className="quote-text-box">
<p>{quote}</p>
</div>
)
}
export default QuoteTextBox
SentimentTextBox
To build the sentiment text box, I added the following comment:
// React component to show sentiment text inside a div
const
For this text box, it was a bit trickier to find the right suggestions, and I had to scroll through most of them until I found one that would work with my code:
const SentimentTextBox = (props) => {
// Get sentiment text from props
const sentimentText = props.sentimentText
// Return component
return (
<div className="sentiment-text-box">
{sentimentText}
</div>
)
}
// Export component
export default SentimentTextBox
It’s important to clearly understand what to expect from Copilot because it is only a tool, and developers can’t just rely on the first suggestion it gives.
I still needed to come back to this component to map what the API returns to readable text. For example, if the web service returns neg
, I needed to map it to Negative
.
Controller component with button
I also needed a controller component to manage all the logic. The first two React components I created just received data and rendered it on-screen, but the controller component needed to manage the API calls.
I started by inputting the following:
// React component that uses QuiteTextBox and SentimentTextBox and APIs to show quotes and sentiment with a button to generate new quotes.
const
Then, Copilot brought this suggestion:
const QuoteGenerator = ({quote, sentiment, onClick}) => {
return (
<div>
<QuoteTextBox quote={quote} sentiment={sentiment} />
<button onClick={onClick}>Generate New Quote</button>
<SentimentTextBox sentiment={sentiment} />
</div>
)
}
export default QuoteGenerator
The controller component suggested by Copilot appeared to be pretty basic; it lacked the API calls and didn’t use correct props for SentimentTextBox
. However, Copilot did provide the correct structure, it just needed some tweaks to finish it.
Then, I just needed to add functions to the controller component. Instead of passing quote
, sentiment
, and onClick
, I asked Copilot to generate them. I also needed some Hooks to store the sentiment and quote data received from calling the APIs.
For Hooks, Copilot figured out right away what I needed. To trigger the suggestion for the first Hook, I began typing a comment and Copilot suggested the correct Hook.
However, for the second Hook, I didn’t even need to type a comment. I accepted the first Hook suggestion, moved to the next line, and Copilot suggested the second Hook immediately.
While the endpoints were correct, I still needed to make some changes to make them work. I had to ask very specifically what I wanted, otherwise, Copilot started suggesting different web services.
I wanted it to just call endpoints that were already created. Furthermore, I need to specifically call the getSentiment
endpoint when I received a quote and map the sentiment to human-readable text.
And this is my final version after some minor changes from my side:
const QuoteGenerator = () => {
// Hook to store text in state
const [quoteText, setQuoteText] = React.useState('')
const [sentimentText, setSentimentText] = React.useState('')
// Function to get quotes from API /api/get-quote
const getQuote = () => {
fetch('/api/get-quote')
.then(response => response.json())
.then(json => {
setQuoteText(json.quote)
getSentiment(json.quote)
})
}
// Function to get sentiment from API /api/get-sentiment\
const getSentiment = (text) => {
fetch('/api/get-sentiment?text=' + text)
.then(response => response.json())
.then(json => {
setSentimentText(json.sentiment)
})
}
// Function to be called when user clicks on button to generate new quote
const onClick = () => {
getQuote()
}
const mapSentimentToText = {
'neg': 'Negative',
'pos': 'Positive',
'neutral': 'Neutral'
}
return (
<div>
<QuoteTextBox quote={quoteText} />
<SentimentTextBox sentimentText={mapSentimentToText[sentimentText]} />
<button onClick={onClick}>Generate New Quote</button>
</div>
)
}
export default QuoteGenerator
The final application
After experimenting with my simple quote-generating app, I found that Copilot gives enough help to create a simple application.
I didn't have high expectations and initially thought I would need to change a lot of code to make the application work.
However, Copilot surprised me. In some places, it gave me nonsense suggestions, but in other places, the suggestions were so good that I can't believe Copilot made them.
Copilot pros and cons
To recap my experience with Copilot, I’ve compiled the pros and cons of working with it so you can decide whether Copilot is something you can use daily or not.
Copilot pros
The main advantage of using Copilot is that it provides autocomplete on steroids. As an autocomplete tool, I believe it is currently the best on the market; there is nothing even close to as useful as Copilot.
Copilot also shows developers multiple ways to solve different problems that may not be so obvious. When in need of a code snippet, the 10 suggestions functionality is great and can often be used in place of Stack Overflow for efficiency.
In all, Copilot is fun to use. For all the tech geeks, it is something new to play around with and it makes daily work a bit more interesting.
Copilot cons
While its functionality provides greater efficiency, users must remember it’s a tool, not a human developer replacement. Because Copilot is not a panacea, users cannot solely rely on it for all their code. Most of its suggestions require changes to fit specific needs.
And finally, I noticed Copilot was suggesting to use React classes for small components with little logic instead of functional components with Hooks. Because it was trained on openly available code on GitHub, Copilot might provide some depreciated suggestions for coding.
Conclusion
GitHub Copilot is not something that can just listen to a project idea and code everything for you. It is also not taking over developer jobs, either. But it is something that can make coding easier.
GitHub Copilot is good with small tasks; when you start asking it something more complex, you often get nonsense. Nevertheless, it is a very good tool for both beginner and experienced developers alike.
Full visibility into production React apps
Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.
LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.
The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.
Modernize how you debug your React apps — start monitoring for free.
Top comments (0)